1 /*-
2  * Copyright (c) 1993 Jan-Simon Pendry
3  * Copyright (c) 1993
4  *	The Regents of the University of California.  All rights reserved.
5  *
6  * This code is derived from software contributed to Berkeley by
7  * Jan-Simon Pendry.
8  *
9  * Redistribution and use in source and binary forms, with or without
10  * modification, are permitted provided that the following conditions
11  * are met:
12  * 1. Redistributions of source code must retain the above copyright
13  *    notice, this list of conditions and the following disclaimer.
14  * 2. Redistributions in binary form must reproduce the above copyright
15  *    notice, this list of conditions and the following disclaimer in the
16  *    documentation and/or other materials provided with the distribution.
17  * 4. Neither the name of the University nor the names of its contributors
18  *    may be used to endorse or promote products derived from this software
19  *    without specific prior written permission.
20  *
21  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
22  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
25  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31  * SUCH DAMAGE.
32  *
33  *	@(#)procfs_ctl.c	8.4 (Berkeley) 6/15/94
34  *
35  * From:
36  *	$Id: procfs_ctl.c,v 1.51 2003/12/07 17:40:00 des Exp $
37  * $FreeBSD: stable/10/sys/fs/procfs/procfs_ctl.c 287604 2015-09-09 23:39:30Z jhb $
38  */
39 
40 #include <sys/param.h>
41 #include <sys/systm.h>
42 #include <sys/lock.h>
43 #include <sys/mutex.h>
44 #include <sys/proc.h>
45 #include <sys/ptrace.h>
46 #include <sys/sbuf.h>
47 #include <sys/signalvar.h>
48 #include <sys/sx.h>
49 #include <sys/uio.h>
50 
51 #include <fs/pseudofs/pseudofs.h>
52 #include <fs/procfs/procfs.h>
53 
54 #include <vm/vm.h>
55 
56 /*
57  * True iff process (p) is in trace wait state
58  * relative to process (curp)
59  */
60 #define TRACE_WAIT_P(curp, p) \
61 	 (P_SHOULDSTOP(p) && \
62 	 (p)->p_pptr == (curp) && \
63 	 ((p)->p_flag & P_TRACED))
64 
65 #define PROCFS_CTL_ATTACH	1
66 #define PROCFS_CTL_DETACH	2
67 #define PROCFS_CTL_STEP		3
68 #define PROCFS_CTL_RUN		4
69 #define PROCFS_CTL_WAIT		5
70 
71 struct namemap {
72 	const char *nm_name;
73 	int nm_val;
74 };
75 
76 static struct namemap ctlnames[] = {
77 	/* special /proc commands */
78 	{ "attach",	PROCFS_CTL_ATTACH },
79 	{ "detach",	PROCFS_CTL_DETACH },
80 	{ "step",	PROCFS_CTL_STEP },
81 	{ "run",	PROCFS_CTL_RUN },
82 	{ "wait",	PROCFS_CTL_WAIT },
83 	{ 0 },
84 };
85 
86 static struct namemap signames[] = {
87 	/* regular signal names */
88 	{ "hup",	SIGHUP },	{ "int",	SIGINT },
89 	{ "quit",	SIGQUIT },	{ "ill",	SIGILL },
90 	{ "trap",	SIGTRAP },	{ "abrt",	SIGABRT },
91 	{ "iot",	SIGIOT },	{ "emt",	SIGEMT },
92 	{ "fpe",	SIGFPE },	{ "kill",	SIGKILL },
93 	{ "bus",	SIGBUS },	{ "segv",	SIGSEGV },
94 	{ "sys",	SIGSYS },	{ "pipe",	SIGPIPE },
95 	{ "alrm",	SIGALRM },	{ "term",	SIGTERM },
96 	{ "urg",	SIGURG },	{ "stop",	SIGSTOP },
97 	{ "tstp",	SIGTSTP },	{ "cont",	SIGCONT },
98 	{ "chld",	SIGCHLD },	{ "ttin",	SIGTTIN },
99 	{ "ttou",	SIGTTOU },	{ "io",		SIGIO },
100 	{ "xcpu",	SIGXCPU },	{ "xfsz",	SIGXFSZ },
101 	{ "vtalrm",	SIGVTALRM },	{ "prof",	SIGPROF },
102 	{ "winch",	SIGWINCH },	{ "info",	SIGINFO },
103 	{ "usr1",	SIGUSR1 },	{ "usr2",	SIGUSR2 },
104 	{ 0 },
105 };
106 
107 static int	procfs_control(struct thread *td, struct proc *p, int op);
108 
109 static int
procfs_control(struct thread * td,struct proc * p,int op)110 procfs_control(struct thread *td, struct proc *p, int op)
111 {
112 	int error = 0;
113 	struct thread *temp;
114 
115 	/*
116 	 * Attach - attaches the target process for debugging
117 	 * by the calling process.
118 	 */
119 	if (op == PROCFS_CTL_ATTACH) {
120 		sx_xlock(&proctree_lock);
121 		PROC_LOCK(p);
122 		if ((error = p_candebug(td, p)) != 0)
123 			goto out;
124 		if (p->p_flag & P_TRACED) {
125 			error = EBUSY;
126 			goto out;
127 		}
128 
129 		/* Can't trace yourself! */
130 		if (p->p_pid == td->td_proc->p_pid) {
131 			error = EINVAL;
132 			goto out;
133 		}
134 
135 		/*
136 		 * Go ahead and set the trace flag.
137 		 * Save the old parent (it's reset in
138 		 *   _DETACH, and also in kern_exit.c:wait4()
139 		 * Reparent the process so that the tracing
140 		 *   proc gets to see all the action.
141 		 * Stop the target.
142 		 */
143 		p->p_flag |= P_TRACED;
144 		faultin(p);
145 		p->p_xstat = 0;		/* XXX ? */
146 		p->p_oppid = p->p_pptr->p_pid;
147 		if (p->p_pptr != td->td_proc) {
148 			proc_reparent(p, td->td_proc);
149 		}
150 		kern_psignal(p, SIGSTOP);
151 out:
152 		PROC_UNLOCK(p);
153 		sx_xunlock(&proctree_lock);
154 		return (error);
155 	}
156 
157 	/*
158 	 * Authorization check: rely on normal debugging protection, except
159 	 * allow processes to disengage debugging on a process onto which
160 	 * they have previously attached, but no longer have permission to
161 	 * debug.
162 	 */
163 	PROC_LOCK(p);
164 	if (op != PROCFS_CTL_DETACH &&
165 	    ((error = p_candebug(td, p)))) {
166 		PROC_UNLOCK(p);
167 		return (error);
168 	}
169 
170 	/*
171 	 * Target process must be stopped, owned by (td) and
172 	 * be set up for tracing (P_TRACED flag set).
173 	 * Allow DETACH to take place at any time for sanity.
174 	 * Allow WAIT any time, of course.
175 	 */
176 	switch (op) {
177 	case PROCFS_CTL_DETACH:
178 	case PROCFS_CTL_WAIT:
179 		break;
180 
181 	default:
182 		if (!TRACE_WAIT_P(td->td_proc, p)) {
183 			PROC_UNLOCK(p);
184 			return (EBUSY);
185 		}
186 	}
187 
188 
189 #ifdef FIX_SSTEP
190 	/*
191 	 * do single-step fixup if needed
192 	 */
193 	FIX_SSTEP(FIRST_THREAD_IN_PROC(p));
194 #endif
195 
196 	/*
197 	 * Don't deliver any signal by default.
198 	 * To continue with a signal, just send
199 	 * the signal name to the ctl file
200 	 */
201 	p->p_xstat = 0;
202 
203 	switch (op) {
204 	/*
205 	 * Detach.  Cleans up the target process, reparent it if possible
206 	 * and set it running once more.
207 	 */
208 	case PROCFS_CTL_DETACH:
209 		/* if not being traced, then this is a painless no-op */
210 		if ((p->p_flag & P_TRACED) == 0) {
211 			PROC_UNLOCK(p);
212 			return (0);
213 		}
214 
215 		/* not being traced any more */
216 		p->p_flag &= ~(P_TRACED | P_STOPPED_TRACE);
217 
218 		/* remove pending SIGTRAP, else the process will die */
219 		sigqueue_delete_proc(p, SIGTRAP);
220 		FOREACH_THREAD_IN_PROC(p, temp)
221 			temp->td_dbgflags &= ~TDB_SUSPEND;
222 		PROC_UNLOCK(p);
223 
224 		/* give process back to original parent */
225 		sx_xlock(&proctree_lock);
226 		if (p->p_oppid != p->p_pptr->p_pid) {
227 			struct proc *pp;
228 
229 			pp = pfind(p->p_oppid);
230 			PROC_LOCK(p);
231 			if (pp) {
232 				PROC_UNLOCK(pp);
233 				proc_reparent(p, pp);
234 			}
235 		} else
236 			PROC_LOCK(p);
237 		p->p_oppid = 0;
238 		p->p_stops = 0;
239 		p->p_flag &= ~P_WAITED;	/* XXX ? */
240 		sx_xunlock(&proctree_lock);
241 
242 		wakeup(td->td_proc);	/* XXX for CTL_WAIT below ? */
243 
244 		break;
245 
246 	/*
247 	 * Step.  Let the target process execute a single instruction.
248 	 * What does it mean to single step a threaded program?
249 	 */
250 	case PROCFS_CTL_STEP:
251 		error = proc_sstep(FIRST_THREAD_IN_PROC(p));
252 		if (error) {
253 			PROC_UNLOCK(p);
254 			return (error);
255 		}
256 		break;
257 
258 	/*
259 	 * Run.  Let the target process continue running until a breakpoint
260 	 * or some other trap.
261 	 */
262 	case PROCFS_CTL_RUN:
263 		p->p_flag &= ~P_STOPPED_SIG;	/* this uses SIGSTOP */
264 		break;
265 
266 	/*
267 	 * Wait for the target process to stop.
268 	 * If the target is not being traced then just wait
269 	 * to enter
270 	 */
271 	case PROCFS_CTL_WAIT:
272 		if (p->p_flag & P_TRACED) {
273 			while (error == 0 &&
274 					(P_SHOULDSTOP(p)) &&
275 					(p->p_flag & P_TRACED) &&
276 					(p->p_pptr == td->td_proc))
277 				error = msleep(p, &p->p_mtx,
278 						PWAIT|PCATCH, "procfsx", 0);
279 			if (error == 0 && !TRACE_WAIT_P(td->td_proc, p))
280 				error = EBUSY;
281 		} else {
282 			while (error == 0 && P_SHOULDSTOP(p))
283 				error = msleep(p, &p->p_mtx,
284 						PWAIT|PCATCH, "procfs", 0);
285 		}
286 		PROC_UNLOCK(p);
287 		return (error);
288 	default:
289 		panic("procfs_control");
290 	}
291 
292 	PROC_SLOCK(p);
293 	thread_unsuspend(p); /* If it can run, let it do so. */
294 	PROC_SUNLOCK(p);
295 	PROC_UNLOCK(p);
296 	return (0);
297 }
298 
299 static struct namemap *
findname(struct namemap * nm,char * buf,int buflen)300 findname(struct namemap *nm, char *buf, int buflen)
301 {
302 
303 	for (; nm->nm_name; nm++)
304 		if (bcmp(buf, nm->nm_name, buflen+1) == 0)
305 			return (nm);
306 
307 	return (0);
308 }
309 
310 int
procfs_doprocctl(PFS_FILL_ARGS)311 procfs_doprocctl(PFS_FILL_ARGS)
312 {
313 	int error;
314 	struct namemap *nm;
315 
316 	if (uio == NULL || uio->uio_rw != UIO_WRITE)
317 		return (EOPNOTSUPP);
318 
319 	/*
320 	 * Map signal names into signal generation
321 	 * or debug control.  Unknown commands and/or signals
322 	 * return EOPNOTSUPP.
323 	 *
324 	 * Sending a signal while the process is being debugged
325 	 * also has the side effect of letting the target continue
326 	 * to run.  There is no way to single-step a signal delivery.
327 	 */
328 	error = EOPNOTSUPP;
329 
330 	sbuf_trim(sb);
331 	sbuf_finish(sb);
332 	nm = findname(ctlnames, sbuf_data(sb), sbuf_len(sb));
333 	if (nm) {
334 		printf("procfs: got a %s command\n", sbuf_data(sb));
335 		error = procfs_control(td, p, nm->nm_val);
336 	} else {
337 		nm = findname(signames, sbuf_data(sb), sbuf_len(sb));
338 		if (nm) {
339 			printf("procfs: got a sig%s\n", sbuf_data(sb));
340 			PROC_LOCK(p);
341 
342 			if (TRACE_WAIT_P(td->td_proc, p)) {
343 				p->p_xstat = nm->nm_val;
344 #ifdef FIX_SSTEP
345 				FIX_SSTEP(FIRST_THREAD_IN_PROC(p));
346 #endif
347 				p->p_flag &= ~P_STOPPED_SIG;
348 				PROC_SLOCK(p);
349 				thread_unsuspend(p);
350 				PROC_SUNLOCK(p);
351 			} else
352 				kern_psignal(p, nm->nm_val);
353 			PROC_UNLOCK(p);
354 			error = 0;
355 		}
356 	}
357 
358 	return (error);
359 }
360