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