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 
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 },
108 };
109 
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 },
129 };
130 
131 static int procfs_control(struct lwp *, struct lwp *, int, int,
132     struct pfsnode *);
133 
134 int
procfs_control(struct lwp * curl,struct lwp * l,int op,int sig,struct pfsnode * pfs)135 procfs_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 
361 int
procfs_doctl(struct lwp * curl,struct lwp * l,struct pfsnode * pfs,struct uio * uio)362 procfs_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