|
|
1.1 root 1: /*
2: * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
3: *
4: * @APPLE_LICENSE_HEADER_START@
5: *
6: * Portions Copyright (c) 1999 Apple Computer, Inc. All Rights
7: * Reserved. This file contains Original Code and/or Modifications of
8: * Original Code as defined in and that are subject to the Apple Public
9: * Source License Version 1.1 (the "License"). You may not use this file
10: * except in compliance with the License. Please obtain a copy of the
11: * License at http://www.apple.com/publicsource and read it before using
12: * this file.
13: *
14: * The Original Code and all software distributed under the License are
15: * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER
16: * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
17: * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
18: * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the
19: * License for the specific language governing rights and limitations
20: * under the License.
21: *
22: * @APPLE_LICENSE_HEADER_END@
23: */
24:
25: /* $NetBSD: procfs_ctl.c,v 1.12 1994/06/29 06:34:46 cgd Exp $ */
26:
27: /*
28: * Copyright (c) 1993 Jan-Simon Pendry
29: * Copyright (c) 1993
30: * The Regents of the University of California. All rights reserved.
31: *
32: * This code is derived from software contributed to Berkeley by
33: * Jan-Simon Pendry.
34: *
35: * Redistribution and use in source and binary forms, with or without
36: * modification, are permitted provided that the following conditions
37: * are met:
38: * 1. Redistributions of source code must retain the above copyright
39: * notice, this list of conditions and the following disclaimer.
40: * 2. Redistributions in binary form must reproduce the above copyright
41: * notice, this list of conditions and the following disclaimer in the
42: * documentation and/or other materials provided with the distribution.
43: * 3. All advertising materials mentioning features or use of this software
44: * must display the following acknowledgement:
45: * This product includes software developed by the University of
46: * California, Berkeley and its contributors.
47: * 4. Neither the name of the University nor the names of its contributors
48: * may be used to endorse or promote products derived from this software
49: * without specific prior written permission.
50: *
51: * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
52: * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
53: * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
54: * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
55: * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
56: * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
57: * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
58: * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
59: * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
60: * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
61: * SUCH DAMAGE.
62: *
63: * @(#)procfs_ctl.c 8.4 (Berkeley) 6/15/94
64: */
65:
66: #include <sys/param.h>
67: #include <sys/systm.h>
68: #include <sys/time.h>
69: #include <sys/kernel.h>
70: #include <sys/proc.h>
71: #include <sys/vnode.h>
72: #include <sys/ioctl.h>
73: #include <sys/tty.h>
74: #include <sys/resource.h>
75: #include <sys/resourcevar.h>
76: #include <sys/ptrace.h>
77: #include <miscfs/procfs/procfs.h>
78:
79: /*
80: * True iff process (p) is in trace wait state
81: * relative to process (curp)
82: */
83: #define TRACE_WAIT_P(curp, p) \
84: ((p)->p_stat == SSTOP && \
85: (p)->p_pptr == (curp) && \
86: ((p)->p_flag & P_TRACED))
87:
88: #define PROCFS_CTL_ATTACH 1
89: #define PROCFS_CTL_DETACH 2
90: #define PROCFS_CTL_STEP 3
91: #define PROCFS_CTL_RUN 4
92: #define PROCFS_CTL_WAIT 5
93:
94: static vfs_namemap_t ctlnames[] = {
95: /* special /proc commands */
96: { "attach", PROCFS_CTL_ATTACH },
97: { "detach", PROCFS_CTL_DETACH },
98: { "step", PROCFS_CTL_STEP },
99: { "run", PROCFS_CTL_RUN },
100: { "wait", PROCFS_CTL_WAIT },
101: { 0 },
102: };
103:
104: static vfs_namemap_t signames[] = {
105: /* regular signal names */
106: { "hup", SIGHUP }, { "int", SIGINT },
107: { "quit", SIGQUIT }, { "ill", SIGILL },
108: { "trap", SIGTRAP }, { "abrt", SIGABRT },
109: { "iot", SIGIOT }, { "emt", SIGEMT },
110: { "fpe", SIGFPE }, { "kill", SIGKILL },
111: { "bus", SIGBUS }, { "segv", SIGSEGV },
112: { "sys", SIGSYS }, { "pipe", SIGPIPE },
113: { "alrm", SIGALRM }, { "term", SIGTERM },
114: { "urg", SIGURG }, { "stop", SIGSTOP },
115: { "tstp", SIGTSTP }, { "cont", SIGCONT },
116: { "chld", SIGCHLD }, { "ttin", SIGTTIN },
117: { "ttou", SIGTTOU }, { "io", SIGIO },
118: { "xcpu", SIGXCPU }, { "xfsz", SIGXFSZ },
119: { "vtalrm", SIGVTALRM }, { "prof", SIGPROF },
120: { "winch", SIGWINCH }, { "info", SIGINFO },
121: { "usr1", SIGUSR1 }, { "usr2", SIGUSR2 },
122: { 0 },
123: };
124:
125: static int
126: procfs_control(curp, p, op)
127: struct proc *curp;
128: struct proc *p;
129: int op;
130: {
131: int error;
132:
133: /*
134: * Attach - attaches the target process for debugging
135: * by the calling process.
136: */
137: if (op == PROCFS_CTL_ATTACH) {
138: /* check whether already being traced */
139: if (p->p_flag & P_TRACED)
140: return (EBUSY);
141:
142: /* can't trace yourself! */
143: if (p->p_pid == curp->p_pid)
144: return (EINVAL);
145:
146: /*
147: * Go ahead and set the trace flag.
148: * Save the old parent (it's reset in
149: * _DETACH, and also in kern_exit.c:wait4()
150: * Reparent the process so that the tracing
151: * proc gets to see all the action.
152: * Stop the target.
153: */
154: p->p_flag |= P_TRACED;
155: p->p_xstat = 0; /* XXX ? */
156: if (p->p_pptr != curp) {
157: p->p_oppid = p->p_pptr->p_pid;
158: proc_reparent(p, curp);
159: }
160: psignal(p, SIGSTOP);
161: return (0);
162: }
163:
164: /*
165: * Target process must be stopped, owned by (curp) and
166: * be set up for tracing (P_TRACED flag set).
167: * Allow DETACH to take place at any time for sanity.
168: * Allow WAIT any time, of course.
169: */
170: switch (op) {
171: case PROCFS_CTL_DETACH:
172: case PROCFS_CTL_WAIT:
173: break;
174:
175: default:
176: if (!TRACE_WAIT_P(curp, p))
177: return (EBUSY);
178: }
179:
180: /*
181: * do single-step fixup if needed
182: */
183: FIX_SSTEP(p);
184:
185: /*
186: * Don't deliver any signal by default.
187: * To continue with a signal, just send
188: * the signal name to the ctl file
189: */
190: p->p_xstat = 0;
191:
192: switch (op) {
193: /*
194: * Detach. Cleans up the target process, reparent it if possible
195: * and set it running once more.
196: */
197: case PROCFS_CTL_DETACH:
198: /* if not being traced, then this is a painless no-op */
199: if ((p->p_flag & P_TRACED) == 0)
200: return (0);
201:
202: /* not being traced any more */
203: p->p_flag &= ~P_TRACED;
204:
205: /* give process back to original parent */
206: if (p->p_oppid != p->p_pptr->p_pid) {
207: struct proc *pp;
208:
209: pp = pfind(p->p_oppid);
210: if (pp)
211: proc_reparent(p, pp);
212: }
213:
214: p->p_oppid = 0;
215: p->p_flag &= ~P_WAITED; /* XXX ? */
216: wakeup((caddr_t) curp); /* XXX for CTL_WAIT below ? */
217:
218: break;
219:
220: /*
221: * Step. Let the target process execute a single instruction.
222: */
223: case PROCFS_CTL_STEP:
224: if (error = process_sstep(p, 1))
225: return (error);
226: break;
227:
228: /*
229: * Run. Let the target process continue running until a breakpoint
230: * or some other trap.
231: */
232: case PROCFS_CTL_RUN:
233: break;
234:
235: /*
236: * Wait for the target process to stop.
237: * If the target is not being traced then just wait
238: * to enter
239: */
240: case PROCFS_CTL_WAIT:
241: error = 0;
242: if (p->p_flag & P_TRACED) {
243: while (error == 0 &&
244: (p->p_stat != SSTOP) &&
245: (p->p_flag & P_TRACED) &&
246: (p->p_pptr == curp)) {
247: error = tsleep((caddr_t) p,
248: PWAIT|PCATCH, "procfsx", 0);
249: }
250: if (error == 0 && !TRACE_WAIT_P(curp, p))
251: error = EBUSY;
252: } else {
253: while (error == 0 && p->p_stat != SSTOP) {
254: error = tsleep((caddr_t) p,
255: PWAIT|PCATCH, "procfs", 0);
256: }
257: }
258: return (error);
259:
260: default:
261: panic("procfs_control");
262: }
263:
264: if (p->p_stat == SSTOP)
265: setrunnable(p);
266: return (0);
267: }
268:
269: int
270: procfs_doctl(curp, p, pfs, uio)
271: struct proc *curp;
272: struct pfsnode *pfs;
273: struct uio *uio;
274: struct proc *p;
275: {
276: int xlen;
277: int error;
278: char msg[PROCFS_CTLLEN+1];
279: vfs_namemap_t *nm;
280:
281: if (uio->uio_rw != UIO_WRITE)
282: return (EOPNOTSUPP);
283:
284: xlen = PROCFS_CTLLEN;
285: error = vfs_getuserstr(uio, msg, &xlen);
286: if (error)
287: return (error);
288:
289: /*
290: * Map signal names into signal generation
291: * or debug control. Unknown commands and/or signals
292: * return EOPNOTSUPP.
293: *
294: * Sending a signal while the process is being debugged
295: * also has the side effect of letting the target continue
296: * to run. There is no way to single-step a signal delivery.
297: */
298: error = EOPNOTSUPP;
299:
300: nm = vfs_findname(ctlnames, msg, xlen);
301: if (nm) {
302: error = procfs_control(curp, p, nm->nm_val);
303: } else {
304: nm = vfs_findname(signames, msg, xlen);
305: if (nm) {
306: if (TRACE_WAIT_P(curp, p)) {
307: p->p_xstat = nm->nm_val;
308: FIX_SSTEP(p);
309: setrunnable(p);
310: } else {
311: psignal(p, nm->nm_val);
312: }
313: error = 0;
314: }
315: }
316:
317: return (error);
318: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.