Sync usage with man page.
[netbsd-mini2440.git] / sys / miscfs / procfs / procfs_ctl.c
blobfbdded79abfd2f78046e4494957f1b945d7b719f
1 /* $NetBSD: procfs_ctl.c,v 1.46 2009/03/14 21:04:25 dsl Exp $ */
3 /*
4 * Copyright (c) 1993
5 * The Regents of the University of California. All rights reserved.
7 * This code is derived from software contributed to Berkeley by
8 * Jan-Simon Pendry.
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.
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.
34 * @(#)procfs_ctl.c 8.4 (Berkeley) 6/15/94
38 * Copyright (c) 1993 Jan-Simon Pendry
40 * This code is derived from software contributed to Berkeley by
41 * Jan-Simon Pendry.
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.
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.
71 * @(#)procfs_ctl.c 8.4 (Berkeley) 6/15/94
74 #include <sys/cdefs.h>
75 __KERNEL_RCSID(0, "$NetBSD: procfs_ctl.c,v 1.46 2009/03/14 21:04:25 dsl Exp $");
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>
90 #include <uvm/uvm_extern.h>
92 #include <miscfs/procfs/procfs.h>
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
100 static 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 },
110 static 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 },
131 static int procfs_control(struct lwp *, struct lwp *, int, int,
132 struct pfsnode *);
135 procfs_control(struct lwp *curl, struct lwp *l, int op, int sig, struct pfsnode *pfs)
137 struct proc *curp = curl->l_proc;
138 struct proc *p = l->l_proc;
139 int error = 0;
141 mutex_enter(proc_lock);
142 mutex_enter(p->p_lock);
144 switch (op) {
146 * Attach - attaches the target process for debugging
147 * by the calling process.
149 case PROCFS_CTL_ATTACH:
151 * You can't attach to a process if:
152 * (1) it's the process that's doing the attaching,
154 if (p->p_pid == curp->p_pid) {
155 error = EINVAL;
156 break;
160 * (2) it's already being traced, or
162 if (ISSET(p->p_slflag, PSL_TRACED)) {
163 error = EBUSY;
164 break;
168 * (3) the security model prevents it.
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;
175 break;
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.
183 * Note that the semantics of DETACH are different here
184 * from ptrace(2).
186 case PROCFS_CTL_DETACH:
187 case PROCFS_CTL_WAIT:
189 * You can't do what you want to the process if:
190 * (1) It's not being traced at all,
192 if (!ISSET(p->p_slflag, PSL_TRACED)) {
193 error = EPERM;
194 break;
198 * (2) it's being traced by ptrace(2) (which has
199 * different signal delivery semantics), or
201 if (!ISSET(p->p_slflag, PSL_FSTRACE)) {
202 error = EBUSY;
203 break;
207 * (3) it's not being traced by _you_.
209 if (p->p_pptr != curp)
210 error = EBUSY;
212 break;
214 default:
216 * You can't do what you want to the process if:
217 * (1) It's not being traced at all,
219 if (!ISSET(p->p_slflag, PSL_TRACED)) {
220 error = EPERM;
221 break;
225 * (2) it's being traced by ptrace(2) (which has
226 * different signal delivery semantics),
228 if (!ISSET(p->p_slflag, PSL_FSTRACE)) {
229 error = EBUSY;
230 break;
234 * (3) it's not being traced by _you_, or
236 if (p->p_pptr != curp) {
237 error = EBUSY;
238 break;
242 * (4) it's not currently stopped.
244 if (p->p_stat != SSTOP || !p->p_waited /* XXXSMP */)
245 error = EBUSY;
247 break;
250 if (error != 0) {
251 mutex_exit(p->p_lock);
252 mutex_exit(proc_lock);
253 return (error);
256 /* Do single-step fixup if needed. */
257 FIX_SSTEP(p);
259 switch (op) {
260 case PROCFS_CTL_ATTACH:
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.
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);
277 } else if (p->p_pptr->p_lock > p->p_lock) {
278 mutex_enter(p->p_pptr->p_lock);
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);
285 sig = SIGSTOP;
286 goto sendsig;
288 #ifdef PT_STEP
289 case PROCFS_CTL_STEP:
291 * Step. Let the target process execute a single instruction.
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
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);
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 */
316 sendsig:
317 /* Finally, deliver the requested signal (or none). */
318 lwp_lock(l);
319 if (l->l_stat == LSSTOP) {
320 p->p_xstat = 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);
331 mutex_exit(p->p_lock);
332 mutex_exit(proc_lock);
333 return (error);
335 case PROCFS_CTL_WAIT:
336 mutex_exit(p->p_lock);
337 mutex_exit(proc_lock);
340 * Wait for the target process to stop.
341 * XXXSMP WTF is this?
343 while (l->l_stat != LSSTOP && P_ZOMBIE(p)) {
344 error = tsleep(l, PWAIT|PCATCH, "procfsx", hz);
345 if (error)
346 break;
349 return (error);
351 default:
352 panic("procfs_ctl");
353 /* NOTREACHED */
356 mutex_exit(p->p_lock);
357 mutex_exit(proc_lock);
358 return (error);
362 procfs_doctl(
363 struct lwp *curl,
364 struct lwp *l,
365 struct pfsnode *pfs,
366 struct uio *uio
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;
375 if (uio->uio_rw != UIO_WRITE)
376 return (EOPNOTSUPP);
378 xlen = PROCFS_CTLLEN;
379 error = vfs_getuserstr(uio, msg, &xlen);
380 if (error)
381 return (error);
384 * Map signal names into signal generation
385 * or debug control. Unknown commands and/or signals
386 * return EOPNOTSUPP.
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.
392 error = EOPNOTSUPP;
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;
411 return (error);