1/* $NetBSD: procfs_ctl.c,v 1.48 2016/04/04 20:47:57 christos Exp $ */
2
3/*
4 * Copyright (c) 1993
5 * The Regents of the University of California. All rights reserved.
6 *
7 * This code is derived from software contributed to Berkeley by
8 * Jan-Simon Pendry.
9 *
10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions
12 * are met:
13 * 1. Redistributions of source code must retain the above copyright
14 * notice, this list of conditions and the following disclaimer.
15 * 2. Redistributions in binary form must reproduce the above copyright
16 * notice, this list of conditions and the following disclaimer in the
17 * documentation and/or other materials provided with the distribution.
18 * 3. Neither the name of the University nor the names of its contributors
19 * may be used to endorse or promote products derived from this software
20 * without specific prior written permission.
21 *
22 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
23 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
24 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
25 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
26 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
27 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
28 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
29 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
30 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
31 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
32 * SUCH DAMAGE.
33 *
34 * @(#)procfs_ctl.c 8.4 (Berkeley) 6/15/94
35 */
36
37/*
38 * Copyright (c) 1993 Jan-Simon Pendry
39 *
40 * This code is derived from software contributed to Berkeley by
41 * Jan-Simon Pendry.
42 *
43 * Redistribution and use in source and binary forms, with or without
44 * modification, are permitted provided that the following conditions
45 * are met:
46 * 1. Redistributions of source code must retain the above copyright
47 * notice, this list of conditions and the following disclaimer.
48 * 2. Redistributions in binary form must reproduce the above copyright
49 * notice, this list of conditions and the following disclaimer in the
50 * documentation and/or other materials provided with the distribution.
51 * 3. All advertising materials mentioning features or use of this software
52 * must display the following acknowledgement:
53 * This product includes software developed by the University of
54 * California, Berkeley and its contributors.
55 * 4. Neither the name of the University nor the names of its contributors
56 * may be used to endorse or promote products derived from this software
57 * without specific prior written permission.
58 *
59 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
60 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
61 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
62 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
63 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
64 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
65 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
66 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
67 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
68 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
69 * SUCH DAMAGE.
70 *
71 * @(#)procfs_ctl.c 8.4 (Berkeley) 6/15/94
72 */
73
74#include <sys/cdefs.h>
75__KERNEL_RCSID(0, "$NetBSD: procfs_ctl.c,v 1.48 2016/04/04 20:47:57 christos Exp $");
76
77#include <sys/param.h>
78#include <sys/systm.h>
79#include <sys/time.h>
80#include <sys/kernel.h>
81#include <sys/proc.h>
82#include <sys/vnode.h>
83#include <sys/ioctl.h>
84#include <sys/tty.h>
85#include <sys/resource.h>
86#include <sys/resourcevar.h>
87#include <sys/signalvar.h>
88#include <sys/kauth.h>
89
90#include <uvm/uvm_extern.h>
91
92#include <miscfs/procfs/procfs.h>
93
94#define PROCFS_CTL_ATTACH 1
95#define PROCFS_CTL_DETACH 2
96#define PROCFS_CTL_STEP 3
97#define PROCFS_CTL_RUN 4
98#define PROCFS_CTL_WAIT 5
99
100static const vfs_namemap_t ctlnames[] = {
101 /* special /proc commands */
102 { "attach", PROCFS_CTL_ATTACH },
103 { "detach", PROCFS_CTL_DETACH },
104 { "step", PROCFS_CTL_STEP },
105 { "run", PROCFS_CTL_RUN },
106 { "wait", PROCFS_CTL_WAIT },
107 { NULL, 0 },
108};
109
110static const vfs_namemap_t signames[] = {
111 /* regular signal names */
112 { "hup", SIGHUP }, { "int", SIGINT },
113 { "quit", SIGQUIT }, { "ill", SIGILL },
114 { "trap", SIGTRAP }, { "abrt", SIGABRT },
115 { "iot", SIGIOT }, { "emt", SIGEMT },
116 { "fpe", SIGFPE }, { "kill", SIGKILL },
117 { "bus", SIGBUS }, { "segv", SIGSEGV },
118 { "sys", SIGSYS }, { "pipe", SIGPIPE },
119 { "alrm", SIGALRM }, { "term", SIGTERM },
120 { "urg", SIGURG }, { "stop", SIGSTOP },
121 { "tstp", SIGTSTP }, { "cont", SIGCONT },
122 { "chld", SIGCHLD }, { "ttin", SIGTTIN },
123 { "ttou", SIGTTOU }, { "io", SIGIO },
124 { "xcpu", SIGXCPU }, { "xfsz", SIGXFSZ },
125 { "vtalrm", SIGVTALRM }, { "prof", SIGPROF },
126 { "winch", SIGWINCH }, { "info", SIGINFO },
127 { "usr1", SIGUSR1 }, { "usr2", SIGUSR2 },
128 { NULL, 0 },
129};
130
131static int procfs_control(struct lwp *, struct lwp *, int, int,
132 struct pfsnode *);
133
134int
135procfs_control(struct lwp *curl, struct lwp *l, int op, int sig, struct pfsnode *pfs)
136{
137 struct proc *curp = curl->l_proc;
138 struct proc *p = l->l_proc;
139 int error = 0;
140
141 mutex_enter(proc_lock);
142 mutex_enter(p->p_lock);
143
144 switch (op) {
145 /*
146 * Attach - attaches the target process for debugging
147 * by the calling process.
148 */
149 case PROCFS_CTL_ATTACH:
150 /*
151 * You can't attach to a process if:
152 * (1) it's the process that's doing the attaching,
153 */
154 if (p->p_pid == curp->p_pid) {
155 error = EINVAL;
156 break;
157 }
158
159 /*
160 * (2) it's already being traced, or
161 */
162 if (ISSET(p->p_slflag, PSL_TRACED)) {
163 error = EBUSY;
164 break;
165 }
166
167 /*
168 * (3) the security model prevents it.
169 */
170 if ((error = kauth_authorize_process(curl->l_cred,
171 KAUTH_PROCESS_PROCFS, p, pfs,
172 KAUTH_ARG(KAUTH_REQ_PROCESS_PROCFS_CTL), NULL)) != 0)
173 break;
174
175 break;
176
177 /*
178 * Target process must be stopped, owned by (curp) and
179 * be set up for tracing (PSL_TRACED flag set).
180 * Allow DETACH to take place at any time for sanity.
181 * Allow WAIT any time, of course.
182 *
183 * Note that the semantics of DETACH are different here
184 * from ptrace(2).
185 */
186 case PROCFS_CTL_DETACH:
187 case PROCFS_CTL_WAIT:
188 /*
189 * You can't do what you want to the process if:
190 * (1) It's not being traced at all,
191 */
192 if (!ISSET(p->p_slflag, PSL_TRACED)) {
193 error = EPERM;
194 break;
195 }
196
197 /*
198 * (2) it's being traced by ptrace(2) (which has
199 * different signal delivery semantics), or
200 */
201 if (!ISSET(p->p_slflag, PSL_FSTRACE)) {
202 error = EBUSY;
203 break;
204 }
205
206 /*
207 * (3) it's not being traced by _you_.
208 */
209 if (p->p_pptr != curp)
210 error = EBUSY;
211
212 break;
213
214 default:
215 /*
216 * You can't do what you want to the process if:
217 * (1) It's not being traced at all,
218 */
219 if (!ISSET(p->p_slflag, PSL_TRACED)) {
220 error = EPERM;
221 break;
222 }
223
224 /*
225 * (2) it's being traced by ptrace(2) (which has
226 * different signal delivery semantics),
227 */
228 if (!ISSET(p->p_slflag, PSL_FSTRACE)) {
229 error = EBUSY;
230 break;
231 }
232
233 /*
234 * (3) it's not being traced by _you_, or
235 */
236 if (p->p_pptr != curp) {
237 error = EBUSY;
238 break;
239 }
240
241 /*
242 * (4) it's not currently stopped.
243 */
244 if (p->p_stat != SSTOP || !p->p_waited /* XXXSMP */)
245 error = EBUSY;
246
247 break;
248 }
249
250 if (error != 0) {
251 mutex_exit(p->p_lock);
252 mutex_exit(proc_lock);
253 return (error);
254 }
255
256 /* Do single-step fixup if needed. */
257 FIX_SSTEP(p);
258
259 switch (op) {
260 case PROCFS_CTL_ATTACH:
261 /*
262 * Go ahead and set the trace flag.
263 * Save the old parent (it's reset in
264 * _DETACH, and also in kern_exit.c:wait4()
265 * Reparent the process so that the tracing
266 * proc gets to see all the action.
267 * Stop the target.
268 */
269 SET(p->p_slflag, PSL_TRACED|PSL_FSTRACE);
270 p->p_opptr = p->p_pptr;
271 if (p->p_pptr != curp) {
272 if (p->p_pptr->p_lock < p->p_lock) {
273 if (!mutex_tryenter(p->p_pptr->p_lock)) {
274 mutex_exit(p->p_lock);
275 mutex_enter(p->p_pptr->p_lock);
276 }
277 } else if (p->p_pptr->p_lock > p->p_lock) {
278 mutex_enter(p->p_pptr->p_lock);
279 }
280 p->p_pptr->p_slflag |= PSL_CHTRACED;
281 proc_reparent(p, curp);
282 if (p->p_pptr->p_lock != p->p_lock)
283 mutex_exit(p->p_pptr->p_lock);
284 }
285 sig = SIGSTOP;
286 goto sendsig;
287
288#ifdef PT_STEP
289 case PROCFS_CTL_STEP:
290 /*
291 * Step. Let the target process execute a single instruction.
292 */
293#endif
294 case PROCFS_CTL_RUN:
295 case PROCFS_CTL_DETACH:
296#ifdef PT_STEP
297 /* XXXAD locking? */
298 error = process_sstep(l, op == PROCFS_CTL_STEP);
299 if (error)
300 break;
301#endif
302
303 if (op == PROCFS_CTL_DETACH) {
304 /* give process back to original parent */
305 if (p->p_opptr != p->p_pptr) {
306 struct proc *pp = p->p_opptr;
307 proc_reparent(p, pp ? pp : initproc);
308 }
309
310 /* not being traced any more */
311 p->p_opptr = NULL;
312 CLR(p->p_slflag, PSL_TRACED|PSL_FSTRACE);
313 p->p_waited = 0; /* XXXSMP */
314 }
315
316 sendsig:
317 /* Finally, deliver the requested signal (or none). */
318 lwp_lock(l);
319 if (l->l_stat == LSSTOP) {
320 p->p_xsig = sig;
321 /* setrunnable() will release the lock. */
322 setrunnable(l);
323 } else {
324 lwp_unlock(l);
325 if (sig != 0) {
326 mutex_exit(p->p_lock);
327 psignal(p, sig);
328 mutex_enter(p->p_lock);
329 }
330 }
331 mutex_exit(p->p_lock);
332 mutex_exit(proc_lock);
333 return (error);
334
335 case PROCFS_CTL_WAIT:
336 mutex_exit(p->p_lock);
337 mutex_exit(proc_lock);
338
339 /*
340 * Wait for the target process to stop.
341 * XXXSMP WTF is this?
342 */
343 while (l->l_stat != LSSTOP && P_ZOMBIE(p)) {
344 error = tsleep(l, PWAIT|PCATCH, "procfsx", hz);
345 if (error)
346 break;
347 }
348
349 return (error);
350
351 default:
352 panic("procfs_ctl");
353 /* NOTREACHED */
354 }
355
356 mutex_exit(p->p_lock);
357 mutex_exit(proc_lock);
358 return (error);
359}
360
361int
362procfs_doctl(
363 struct lwp *curl,
364 struct lwp *l,
365 struct pfsnode *pfs,
366 struct uio *uio
367)
368{
369 struct proc *p = l->l_proc;
370 char msg[PROCFS_CTLLEN+1];
371 const vfs_namemap_t *nm;
372 int error;
373 int xlen;
374
375 if (uio->uio_rw != UIO_WRITE)
376 return (EOPNOTSUPP);
377
378 xlen = PROCFS_CTLLEN;
379 error = vfs_getuserstr(uio, msg, &xlen);
380 if (error)
381 return (error);
382
383 /*
384 * Map signal names into signal generation
385 * or debug control. Unknown commands and/or signals
386 * return EOPNOTSUPP.
387 *
388 * Sending a signal while the process is being debugged
389 * also has the side effect of letting the target continue
390 * to run. There is no way to single-step a signal delivery.
391 */
392 error = EOPNOTSUPP;
393
394 nm = vfs_findname(ctlnames, msg, xlen);
395 if (nm) {
396 error = procfs_control(curl, l, nm->nm_val, 0, pfs);
397 } else {
398 nm = vfs_findname(signames, msg, xlen);
399 if (nm) {
400 if (ISSET(p->p_slflag, PSL_TRACED) &&
401 p->p_pptr == p)
402 error = procfs_control(curl, l, PROCFS_CTL_RUN,
403 nm->nm_val, pfs);
404 else {
405 psignal(p, nm->nm_val);
406 error = 0;
407 }
408 }
409 }
410
411 return (error);
412}
413