1139804Simp/*-
21945Sdg * Copyright (c) 1994, Sean Eric Fagan
31945Sdg * All rights reserved.
41541Srgrimes *
51541Srgrimes * Redistribution and use in source and binary forms, with or without
61541Srgrimes * modification, are permitted provided that the following conditions
71541Srgrimes * are met:
81541Srgrimes * 1. Redistributions of source code must retain the above copyright
91541Srgrimes *    notice, this list of conditions and the following disclaimer.
101541Srgrimes * 2. Redistributions in binary form must reproduce the above copyright
111541Srgrimes *    notice, this list of conditions and the following disclaimer in the
121541Srgrimes *    documentation and/or other materials provided with the distribution.
131541Srgrimes * 3. All advertising materials mentioning features or use of this software
141541Srgrimes *    must display the following acknowledgement:
151945Sdg *	This product includes software developed by Sean Eric Fagan.
161945Sdg * 4. The name of the author may not be used to endorse or promote products
171945Sdg *    derived from this software without specific prior written permission.
181541Srgrimes *
191945Sdg * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
201541Srgrimes * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
211541Srgrimes * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
221945Sdg * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
231541Srgrimes * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
241541Srgrimes * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
251541Srgrimes * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
261541Srgrimes * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
271541Srgrimes * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
281541Srgrimes * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
291541Srgrimes * SUCH DAMAGE.
301541Srgrimes */
311541Srgrimes
32116182Sobrien#include <sys/cdefs.h>
33116182Sobrien__FBSDID("$FreeBSD$");
34116182Sobrien
35147692Speter#include "opt_compat.h"
36147692Speter
371541Srgrimes#include <sys/param.h>
382112Swollman#include <sys/systm.h>
3976166Smarkm#include <sys/lock.h>
4076166Smarkm#include <sys/mutex.h>
41102946Siedowse#include <sys/syscallsubr.h>
42189282Skib#include <sys/sysent.h>
4312221Sbde#include <sys/sysproto.h>
44260208Sjhb#include <sys/priv.h>
451541Srgrimes#include <sys/proc.h>
46260208Sjhb#include <sys/procctl.h>
471945Sdg#include <sys/vnode.h>
481945Sdg#include <sys/ptrace.h>
4974927Sjhb#include <sys/sx.h>
50132089Sdavidxu#include <sys/malloc.h>
51138129Sdas#include <sys/signalvar.h>
521541Srgrimes
531945Sdg#include <machine/reg.h>
5476166Smarkm
55155634Swsalamon#include <security/audit/audit.h>
56155634Swsalamon
571945Sdg#include <vm/vm.h>
5812662Sdg#include <vm/pmap.h>
5984637Sdes#include <vm/vm_extern.h>
6012662Sdg#include <vm/vm_map.h>
6184637Sdes#include <vm/vm_kern.h>
6284637Sdes#include <vm/vm_object.h>
631945Sdg#include <vm/vm_page.h>
64199819Salc#include <vm/vm_pager.h>
65194766Skib#include <vm/vm_param.h>
661945Sdg
67205014Snwhitehorn#ifdef COMPAT_FREEBSD32
68147692Speter#include <sys/procfs.h>
69209688Skib#include <compat/freebsd32/freebsd32_signal.h>
70147692Speter
71147692Speterstruct ptrace_io_desc32 {
72147692Speter	int		piod_op;
73209390Sed	uint32_t	piod_offs;
74209390Sed	uint32_t	piod_addr;
75209390Sed	uint32_t	piod_len;
76147692Speter};
77203708Smarcel
78203708Smarcelstruct ptrace_vm_entry32 {
79203783Smarcel	int		pve_entry;
80203783Smarcel	int		pve_timestamp;
81203708Smarcel	uint32_t	pve_start;
82203708Smarcel	uint32_t	pve_end;
83203708Smarcel	uint32_t	pve_offset;
84203708Smarcel	u_int		pve_prot;
85203708Smarcel	u_int		pve_pathlen;
86203783Smarcel	int32_t		pve_fileid;
87203783Smarcel	u_int		pve_fsid;
88203708Smarcel	uint32_t	pve_path;
89203708Smarcel};
90203708Smarcel
91209688Skibstruct ptrace_lwpinfo32 {
92209688Skib	lwpid_t	pl_lwpid;	/* LWP described. */
93209688Skib	int	pl_event;	/* Event that stopped the LWP. */
94209688Skib	int	pl_flags;	/* LWP flags. */
95209688Skib	sigset_t	pl_sigmask;	/* LWP signal mask */
96209688Skib	sigset_t	pl_siglist;	/* LWP pending signal */
97209688Skib	struct siginfo32 pl_siginfo;	/* siginfo for signal */
98215679Sattilio	char	pl_tdname[MAXCOMLEN + 1];	/* LWP name. */
99217819Skib	int	pl_child_pid;		/* New child pid */
100209688Skib};
101209688Skib
102147692Speter#endif
103147692Speter
10491006Sbde/*
10591006Sbde * Functions implemented using PROC_ACTION():
10691006Sbde *
10791006Sbde * proc_read_regs(proc, regs)
10891006Sbde *	Get the current user-visible register set from the process
10991006Sbde *	and copy it into the regs structure (<machine/reg.h>).
11091006Sbde *	The process is stopped at the time read_regs is called.
11191006Sbde *
11291006Sbde * proc_write_regs(proc, regs)
11391006Sbde *	Update the current register set from the passed in regs
11491006Sbde *	structure.  Take care to avoid clobbering special CPU
11591006Sbde *	registers or privileged bits in the PSL.
11691006Sbde *	Depending on the architecture this may have fix-up work to do,
11791006Sbde *	especially if the IAR or PCW are modified.
11891006Sbde *	The process is stopped at the time write_regs is called.
11991006Sbde *
12091006Sbde * proc_read_fpregs, proc_write_fpregs
12191006Sbde *	deal with the floating point register set, otherwise as above.
12291006Sbde *
12391006Sbde * proc_read_dbregs, proc_write_dbregs
12491006Sbde *	deal with the processor debug register set, otherwise as above.
12591006Sbde *
12691006Sbde * proc_sstep(proc)
12791006Sbde *	Arrange for the process to trap after executing a single instruction.
12891006Sbde */
12991006Sbde
13091006Sbde#define	PROC_ACTION(action) do {					\
13185297Sdes	int error;							\
13285297Sdes									\
133113868Sjhb	PROC_LOCK_ASSERT(td->td_proc, MA_OWNED);			\
134172207Sjeff	if ((td->td_proc->p_flag & P_INMEM) == 0)			\
13591006Sbde		error = EIO;						\
13691006Sbde	else								\
13791006Sbde		error = (action);					\
13885297Sdes	return (error);							\
13991006Sbde} while(0)
140112389Sdes
14191006Sbdeint
14291006Sbdeproc_read_regs(struct thread *td, struct reg *regs)
14391006Sbde{
14491006Sbde
14591006Sbde	PROC_ACTION(fill_regs(td, regs));
14685297Sdes}
14785297Sdes
14891006Sbdeint
14991006Sbdeproc_write_regs(struct thread *td, struct reg *regs)
15091006Sbde{
15185297Sdes
15291006Sbde	PROC_ACTION(set_regs(td, regs));
15391006Sbde}
15491006Sbde
15584637Sdesint
15691006Sbdeproc_read_dbregs(struct thread *td, struct dbreg *dbregs)
15791006Sbde{
15891006Sbde
15991006Sbde	PROC_ACTION(fill_dbregs(td, dbregs));
16091006Sbde}
16191006Sbde
16291006Sbdeint
16391006Sbdeproc_write_dbregs(struct thread *td, struct dbreg *dbregs)
16491006Sbde{
16591006Sbde
16691006Sbde	PROC_ACTION(set_dbregs(td, dbregs));
16791006Sbde}
16891006Sbde
16991006Sbde/*
17091006Sbde * Ptrace doesn't support fpregs at all, and there are no security holes
17191006Sbde * or translations for fpregs, so we can just copy them.
17291006Sbde */
17391006Sbdeint
17491006Sbdeproc_read_fpregs(struct thread *td, struct fpreg *fpregs)
17591006Sbde{
17691006Sbde
17791006Sbde	PROC_ACTION(fill_fpregs(td, fpregs));
17891006Sbde}
17991006Sbde
18091006Sbdeint
18191006Sbdeproc_write_fpregs(struct thread *td, struct fpreg *fpregs)
18291006Sbde{
18391006Sbde
18491006Sbde	PROC_ACTION(set_fpregs(td, fpregs));
18591006Sbde}
18691006Sbde
187205014Snwhitehorn#ifdef COMPAT_FREEBSD32
188147692Speter/* For 32 bit binaries, we need to expose the 32 bit regs layouts. */
18991006Sbdeint
190147692Speterproc_read_regs32(struct thread *td, struct reg32 *regs32)
191147692Speter{
192147692Speter
193147692Speter	PROC_ACTION(fill_regs32(td, regs32));
194147692Speter}
195147692Speter
196147692Speterint
197147692Speterproc_write_regs32(struct thread *td, struct reg32 *regs32)
198147692Speter{
199147692Speter
200147692Speter	PROC_ACTION(set_regs32(td, regs32));
201147692Speter}
202147692Speter
203147692Speterint
204147692Speterproc_read_dbregs32(struct thread *td, struct dbreg32 *dbregs32)
205147692Speter{
206147692Speter
207147692Speter	PROC_ACTION(fill_dbregs32(td, dbregs32));
208147692Speter}
209147692Speter
210147692Speterint
211147692Speterproc_write_dbregs32(struct thread *td, struct dbreg32 *dbregs32)
212147692Speter{
213147692Speter
214147692Speter	PROC_ACTION(set_dbregs32(td, dbregs32));
215147692Speter}
216147692Speter
217147692Speterint
218147692Speterproc_read_fpregs32(struct thread *td, struct fpreg32 *fpregs32)
219147692Speter{
220147692Speter
221147692Speter	PROC_ACTION(fill_fpregs32(td, fpregs32));
222147692Speter}
223147692Speter
224147692Speterint
225147692Speterproc_write_fpregs32(struct thread *td, struct fpreg32 *fpregs32)
226147692Speter{
227147692Speter
228147692Speter	PROC_ACTION(set_fpregs32(td, fpregs32));
229147692Speter}
230147692Speter#endif
231147692Speter
232147692Speterint
23385297Sdesproc_sstep(struct thread *td)
23485297Sdes{
23585297Sdes
23691006Sbde	PROC_ACTION(ptrace_single_step(td));
23785297Sdes}
23885297Sdes
23985297Sdesint
24084637Sdesproc_rwmem(struct proc *p, struct uio *uio)
24184483Sdes{
24284637Sdes	vm_map_t map;
243199819Salc	vm_offset_t pageno;		/* page number */
24484637Sdes	vm_prot_t reqprot;
245216604Salc	int error, fault_flags, page_offset, writing;
2461945Sdg
24784637Sdes	/*
248155922Sjhb	 * Assert that someone has locked this vmspace.  (Should be
249155922Sjhb	 * curthread but we can't assert that.)  This keeps the process
250155922Sjhb	 * from exiting out from under us until this operation completes.
25184637Sdes	 */
252155922Sjhb	KASSERT(p->p_lock >= 1, ("%s: process %p (pid %d) not held", __func__,
253155922Sjhb	    p, p->p_pid));
254132684Salc
25584637Sdes	/*
25684637Sdes	 * The map we want...
25784637Sdes	 */
258155922Sjhb	map = &p->p_vmspace->vm_map;
2591945Sdg
260216604Salc	/*
261216604Salc	 * If we are writing, then we request vm_fault() to create a private
262216604Salc	 * copy of each page.  Since these copies will not be writeable by the
263216604Salc	 * process, we must explicity request that they be dirtied.
264216604Salc	 */
26584637Sdes	writing = uio->uio_rw == UIO_WRITE;
266199819Salc	reqprot = writing ? VM_PROT_COPY | VM_PROT_READ : VM_PROT_READ;
267216604Salc	fault_flags = writing ? VM_FAULT_DIRTY : VM_FAULT_NORMAL;
2688876Srgrimes
26984637Sdes	/*
27084637Sdes	 * Only map in one page at a time.  We don't have to, but it
27184637Sdes	 * makes things easier.  This way is trivial - right?
27284637Sdes	 */
27384637Sdes	do {
27484637Sdes		vm_offset_t uva;
27584637Sdes		u_int len;
27684637Sdes		vm_page_t m;
2778876Srgrimes
27884637Sdes		uva = (vm_offset_t)uio->uio_offset;
2791945Sdg
28084637Sdes		/*
28184637Sdes		 * Get the page number of this segment.
28284637Sdes		 */
28384637Sdes		pageno = trunc_page(uva);
28484637Sdes		page_offset = uva - pageno;
2851945Sdg
28684637Sdes		/*
28784637Sdes		 * How many bytes to copy
28884637Sdes		 */
28984637Sdes		len = min(PAGE_SIZE - page_offset, uio->uio_resid);
29084637Sdes
29184637Sdes		/*
292216604Salc		 * Fault and hold the page on behalf of the process.
29384637Sdes		 */
294216604Salc		error = vm_fault_hold(map, pageno, reqprot, fault_flags, &m);
295216604Salc		if (error != KERN_SUCCESS) {
296194766Skib			if (error == KERN_RESOURCE_SHORTAGE)
297194766Skib				error = ENOMEM;
298194766Skib			else
299194766Skib				error = EFAULT;
30084637Sdes			break;
3011945Sdg		}
3021945Sdg
30384637Sdes		/*
30484637Sdes		 * Now do the i/o move.
30584637Sdes		 */
306127386Salc		error = uiomove_fromphys(&m, page_offset, len, uio);
3071945Sdg
308198341Smarcel		/* Make the I-cache coherent for breakpoints. */
309216604Salc		if (writing && error == 0) {
310216604Salc			vm_map_lock_read(map);
311216604Salc			if (vm_map_check_protection(map, pageno, pageno +
312216604Salc			    PAGE_SIZE, VM_PROT_EXECUTE))
313216604Salc				vm_sync_icache(map, uva, len);
314216604Salc			vm_map_unlock_read(map);
315216604Salc		}
316198341Smarcel
31784637Sdes		/*
318118697Salc		 * Release the page.
31984637Sdes		 */
320207410Skmacy		vm_page_lock(m);
321118697Salc		vm_page_unhold(m);
322207410Skmacy		vm_page_unlock(m);
3231945Sdg
32484637Sdes	} while (error == 0 && uio->uio_resid > 0);
3251945Sdg
32684637Sdes	return (error);
3271945Sdg}
3281945Sdg
329203696Smarcelstatic int
330203696Smarcelptrace_vm_entry(struct thread *td, struct proc *p, struct ptrace_vm_entry *pve)
331203696Smarcel{
332203783Smarcel	struct vattr vattr;
333203696Smarcel	vm_map_t map;
334203696Smarcel	vm_map_entry_t entry;
335203696Smarcel	vm_object_t obj, tobj, lobj;
336203783Smarcel	struct vmspace *vm;
337203696Smarcel	struct vnode *vp;
338203696Smarcel	char *freepath, *fullpath;
339203696Smarcel	u_int pathlen;
340203783Smarcel	int error, index, vfslocked;
341203696Smarcel
342203783Smarcel	error = 0;
343203783Smarcel	obj = NULL;
344203783Smarcel
345203783Smarcel	vm = vmspace_acquire_ref(p);
346203783Smarcel	map = &vm->vm_map;
347203783Smarcel	vm_map_lock_read(map);
348203783Smarcel
349203783Smarcel	do {
350203783Smarcel		entry = map->header.next;
351203783Smarcel		index = 0;
352203783Smarcel		while (index < pve->pve_entry && entry != &map->header) {
353203696Smarcel			entry = entry->next;
354203783Smarcel			index++;
355203783Smarcel		}
356203783Smarcel		if (index != pve->pve_entry) {
357203783Smarcel			error = EINVAL;
358203783Smarcel			break;
359203783Smarcel		}
360203783Smarcel		while (entry != &map->header &&
361203783Smarcel		    (entry->eflags & MAP_ENTRY_IS_SUB_MAP) != 0) {
362203783Smarcel			entry = entry->next;
363203783Smarcel			index++;
364203783Smarcel		}
365203783Smarcel		if (entry == &map->header) {
366203783Smarcel			error = ENOENT;
367203783Smarcel			break;
368203783Smarcel		}
369203696Smarcel
370203783Smarcel		/* We got an entry. */
371203783Smarcel		pve->pve_entry = index + 1;
372203783Smarcel		pve->pve_timestamp = map->timestamp;
373203783Smarcel		pve->pve_start = entry->start;
374203783Smarcel		pve->pve_end = entry->end - 1;
375203783Smarcel		pve->pve_offset = entry->offset;
376203783Smarcel		pve->pve_prot = entry->protection;
377203696Smarcel
378203783Smarcel		/* Backing object's path needed? */
379203783Smarcel		if (pve->pve_pathlen == 0)
380203783Smarcel			break;
381203696Smarcel
382203783Smarcel		pathlen = pve->pve_pathlen;
383203783Smarcel		pve->pve_pathlen = 0;
384203696Smarcel
385203783Smarcel		obj = entry->object.vm_object;
386203783Smarcel		if (obj != NULL)
387203783Smarcel			VM_OBJECT_LOCK(obj);
388203783Smarcel	} while (0);
389203696Smarcel
390203783Smarcel	vm_map_unlock_read(map);
391203783Smarcel	vmspace_free(vm);
392203783Smarcel
393203788Smarcel	pve->pve_fsid = VNOVAL;
394203788Smarcel	pve->pve_fileid = VNOVAL;
395203788Smarcel
396203783Smarcel	if (error == 0 && obj != NULL) {
397203783Smarcel		lobj = obj;
398203783Smarcel		for (tobj = obj; tobj != NULL; tobj = tobj->backing_object) {
399203783Smarcel			if (tobj != obj)
400203783Smarcel				VM_OBJECT_LOCK(tobj);
401203783Smarcel			if (lobj != obj)
402203783Smarcel				VM_OBJECT_UNLOCK(lobj);
403203783Smarcel			lobj = tobj;
404203783Smarcel			pve->pve_offset += tobj->backing_object_offset;
405203783Smarcel		}
406203696Smarcel		vp = (lobj->type == OBJT_VNODE) ? lobj->handle : NULL;
407203696Smarcel		if (vp != NULL)
408203696Smarcel			vref(vp);
409203696Smarcel		if (lobj != obj)
410203696Smarcel			VM_OBJECT_UNLOCK(lobj);
411203696Smarcel		VM_OBJECT_UNLOCK(obj);
412203696Smarcel
413203783Smarcel		if (vp != NULL) {
414203783Smarcel			freepath = NULL;
415203783Smarcel			fullpath = NULL;
416203783Smarcel			vn_fullpath(td, vp, &fullpath, &freepath);
417203783Smarcel			vfslocked = VFS_LOCK_GIANT(vp->v_mount);
418203783Smarcel			vn_lock(vp, LK_SHARED | LK_RETRY);
419203783Smarcel			if (VOP_GETATTR(vp, &vattr, td->td_ucred) == 0) {
420203783Smarcel				pve->pve_fileid = vattr.va_fileid;
421203783Smarcel				pve->pve_fsid = vattr.va_fsid;
422203783Smarcel			}
423203783Smarcel			vput(vp);
424203783Smarcel			VFS_UNLOCK_GIANT(vfslocked);
425203696Smarcel
426203783Smarcel			if (fullpath != NULL) {
427203783Smarcel				pve->pve_pathlen = strlen(fullpath) + 1;
428203783Smarcel				if (pve->pve_pathlen <= pathlen) {
429203783Smarcel					error = copyout(fullpath, pve->pve_path,
430203783Smarcel					    pve->pve_pathlen);
431203783Smarcel				} else
432203783Smarcel					error = ENAMETOOLONG;
433203783Smarcel			}
434203783Smarcel			if (freepath != NULL)
435203783Smarcel				free(freepath, M_TEMP);
436203783Smarcel		}
437203783Smarcel	}
438203696Smarcel
439203783Smarcel	return (error);
440203783Smarcel}
441203783Smarcel
442205014Snwhitehorn#ifdef COMPAT_FREEBSD32
443203783Smarcelstatic int
444203783Smarcelptrace_vm_entry32(struct thread *td, struct proc *p,
445203783Smarcel    struct ptrace_vm_entry32 *pve32)
446203783Smarcel{
447203783Smarcel	struct ptrace_vm_entry pve;
448203783Smarcel	int error;
449203783Smarcel
450203783Smarcel	pve.pve_entry = pve32->pve_entry;
451203783Smarcel	pve.pve_pathlen = pve32->pve_pathlen;
452203783Smarcel	pve.pve_path = (void *)(uintptr_t)pve32->pve_path;
453203783Smarcel
454203783Smarcel	error = ptrace_vm_entry(td, p, &pve);
455203783Smarcel	if (error == 0) {
456203783Smarcel		pve32->pve_entry = pve.pve_entry;
457203783Smarcel		pve32->pve_timestamp = pve.pve_timestamp;
458203783Smarcel		pve32->pve_start = pve.pve_start;
459203783Smarcel		pve32->pve_end = pve.pve_end;
460203783Smarcel		pve32->pve_offset = pve.pve_offset;
461203783Smarcel		pve32->pve_prot = pve.pve_prot;
462203783Smarcel		pve32->pve_fileid = pve.pve_fileid;
463203783Smarcel		pve32->pve_fsid = pve.pve_fsid;
464203696Smarcel	}
465203783Smarcel
466203783Smarcel	pve32->pve_pathlen = pve.pve_pathlen;
467203696Smarcel	return (error);
468203696Smarcel}
469209688Skib
470209688Skibstatic void
471209688Skibptrace_lwpinfo_to32(const struct ptrace_lwpinfo *pl,
472209688Skib    struct ptrace_lwpinfo32 *pl32)
473209688Skib{
474209688Skib
475209688Skib	pl32->pl_lwpid = pl->pl_lwpid;
476209688Skib	pl32->pl_event = pl->pl_event;
477209688Skib	pl32->pl_flags = pl->pl_flags;
478209688Skib	pl32->pl_sigmask = pl->pl_sigmask;
479209688Skib	pl32->pl_siglist = pl->pl_siglist;
480209688Skib	siginfo_to_siginfo32(&pl->pl_siginfo, &pl32->pl_siginfo);
481215679Sattilio	strcpy(pl32->pl_tdname, pl->pl_tdname);
482217819Skib	pl32->pl_child_pid = pl->pl_child_pid;
483209688Skib}
484205014Snwhitehorn#endif /* COMPAT_FREEBSD32 */
485203696Smarcel
4861541Srgrimes/*
4871541Srgrimes * Process debugging system call.
4881541Srgrimes */
48912221Sbde#ifndef _SYS_SYSPROTO_H_
4901541Srgrimesstruct ptrace_args {
4911541Srgrimes	int	req;
4921541Srgrimes	pid_t	pid;
4931541Srgrimes	caddr_t	addr;
4941541Srgrimes	int	data;
4951541Srgrimes};
49612221Sbde#endif
4971945Sdg
498205014Snwhitehorn#ifdef COMPAT_FREEBSD32
499114028Sjhb/*
500147692Speter * This CPP subterfuge is to try and reduce the number of ifdefs in
501147692Speter * the body of the code.
502147692Speter *   COPYIN(uap->addr, &r.reg, sizeof r.reg);
503147692Speter * becomes either:
504147692Speter *   copyin(uap->addr, &r.reg, sizeof r.reg);
505147692Speter * or
506147692Speter *   copyin(uap->addr, &r.reg32, sizeof r.reg32);
507147692Speter * .. except this is done at runtime.
508147692Speter */
509147692Speter#define	COPYIN(u, k, s)		wrap32 ? \
510147692Speter	copyin(u, k ## 32, s ## 32) : \
511147692Speter	copyin(u, k, s)
512147692Speter#define	COPYOUT(k, u, s)	wrap32 ? \
513147692Speter	copyout(k ## 32, u, s ## 32) : \
514147692Speter	copyout(k, u, s)
515147692Speter#else
516147692Speter#define	COPYIN(u, k, s)		copyin(u, k, s)
517147692Speter#define	COPYOUT(k, u, s)	copyout(k, u, s)
518147692Speter#endif
5191549Srgrimesint
520225617Skmacysys_ptrace(struct thread *td, struct ptrace_args *uap)
5211541Srgrimes{
52291007Sbde	/*
52391007Sbde	 * XXX this obfuscation is to reduce stack usage, but the register
52491007Sbde	 * structs may be too large to put on the stack anyway.
52591007Sbde	 */
52684637Sdes	union {
52792395Sdes		struct ptrace_io_desc piod;
528132016Smarcel		struct ptrace_lwpinfo pl;
529203696Smarcel		struct ptrace_vm_entry pve;
53091007Sbde		struct dbreg dbreg;
53191007Sbde		struct fpreg fpreg;
53291007Sbde		struct reg reg;
533205014Snwhitehorn#ifdef COMPAT_FREEBSD32
534147692Speter		struct dbreg32 dbreg32;
535147692Speter		struct fpreg32 fpreg32;
536147692Speter		struct reg32 reg32;
537147692Speter		struct ptrace_io_desc32 piod32;
538209688Skib		struct ptrace_lwpinfo32 pl32;
539203708Smarcel		struct ptrace_vm_entry32 pve32;
540147692Speter#endif
54184637Sdes	} r;
542102946Siedowse	void *addr;
543102946Siedowse	int error = 0;
544205014Snwhitehorn#ifdef COMPAT_FREEBSD32
545147692Speter	int wrap32 = 0;
546102946Siedowse
547189282Skib	if (SV_CURPROC_FLAG(SV_ILP32))
548147692Speter		wrap32 = 1;
549147692Speter#endif
550195104Srwatson	AUDIT_ARG_PID(uap->pid);
551195104Srwatson	AUDIT_ARG_CMD(uap->req);
552195104Srwatson	AUDIT_ARG_VALUE(uap->data);
553102946Siedowse	addr = &r;
554102946Siedowse	switch (uap->req) {
555102946Siedowse	case PT_GETREGS:
556102946Siedowse	case PT_GETFPREGS:
557102946Siedowse	case PT_GETDBREGS:
558132016Smarcel	case PT_LWPINFO:
559102946Siedowse		break;
560102946Siedowse	case PT_SETREGS:
561147692Speter		error = COPYIN(uap->addr, &r.reg, sizeof r.reg);
562102946Siedowse		break;
563102946Siedowse	case PT_SETFPREGS:
564147692Speter		error = COPYIN(uap->addr, &r.fpreg, sizeof r.fpreg);
565102946Siedowse		break;
566102946Siedowse	case PT_SETDBREGS:
567147692Speter		error = COPYIN(uap->addr, &r.dbreg, sizeof r.dbreg);
568102946Siedowse		break;
569102946Siedowse	case PT_IO:
570147692Speter		error = COPYIN(uap->addr, &r.piod, sizeof r.piod);
571102946Siedowse		break;
572203696Smarcel	case PT_VM_ENTRY:
573203696Smarcel		error = COPYIN(uap->addr, &r.pve, sizeof r.pve);
574203696Smarcel		break;
575102946Siedowse	default:
576102946Siedowse		addr = uap->addr;
577118932Smarcel		break;
578102946Siedowse	}
579102946Siedowse	if (error)
580102946Siedowse		return (error);
581102946Siedowse
582102946Siedowse	error = kern_ptrace(td, uap->req, uap->pid, addr, uap->data);
583102946Siedowse	if (error)
584102946Siedowse		return (error);
585102946Siedowse
586102946Siedowse	switch (uap->req) {
587203696Smarcel	case PT_VM_ENTRY:
588203696Smarcel		error = COPYOUT(&r.pve, uap->addr, sizeof r.pve);
589203696Smarcel		break;
590102946Siedowse	case PT_IO:
591147692Speter		error = COPYOUT(&r.piod, uap->addr, sizeof r.piod);
592102946Siedowse		break;
593102946Siedowse	case PT_GETREGS:
594147692Speter		error = COPYOUT(&r.reg, uap->addr, sizeof r.reg);
595102946Siedowse		break;
596102946Siedowse	case PT_GETFPREGS:
597147692Speter		error = COPYOUT(&r.fpreg, uap->addr, sizeof r.fpreg);
598102946Siedowse		break;
599102946Siedowse	case PT_GETDBREGS:
600147692Speter		error = COPYOUT(&r.dbreg, uap->addr, sizeof r.dbreg);
601102946Siedowse		break;
602132016Smarcel	case PT_LWPINFO:
603132016Smarcel		error = copyout(&r.pl, uap->addr, uap->data);
604132016Smarcel		break;
605102946Siedowse	}
606102946Siedowse
607102946Siedowse	return (error);
608102946Siedowse}
609147692Speter#undef COPYIN
610147692Speter#undef COPYOUT
611102946Siedowse
612205014Snwhitehorn#ifdef COMPAT_FREEBSD32
613147692Speter/*
614147692Speter *   PROC_READ(regs, td2, addr);
615147692Speter * becomes either:
616147692Speter *   proc_read_regs(td2, addr);
617147692Speter * or
618147692Speter *   proc_read_regs32(td2, addr);
619147692Speter * .. except this is done at runtime.  There is an additional
620147692Speter * complication in that PROC_WRITE disallows 32 bit consumers
621147692Speter * from writing to 64 bit address space targets.
622147692Speter */
623147692Speter#define	PROC_READ(w, t, a)	wrap32 ? \
624147692Speter	proc_read_ ## w ## 32(t, a) : \
625147692Speter	proc_read_ ## w (t, a)
626147692Speter#define	PROC_WRITE(w, t, a)	wrap32 ? \
627147692Speter	(safe ? proc_write_ ## w ## 32(t, a) : EINVAL ) : \
628147692Speter	proc_write_ ## w (t, a)
629147692Speter#else
630147692Speter#define	PROC_READ(w, t, a)	proc_read_ ## w (t, a)
631147692Speter#define	PROC_WRITE(w, t, a)	proc_write_ ## w (t, a)
632147692Speter#endif
633147692Speter
634102946Siedowseint
635102946Siedowsekern_ptrace(struct thread *td, int req, pid_t pid, void *addr, int data)
636102946Siedowse{
637102946Siedowse	struct iovec iov;
638102946Siedowse	struct uio uio;
63994665Salfred	struct proc *curp, *p, *pp;
640131450Sdavidxu	struct thread *td2 = NULL;
641147692Speter	struct ptrace_io_desc *piod = NULL;
642132016Smarcel	struct ptrace_lwpinfo *pl;
643132089Sdavidxu	int error, write, tmp, num;
64494556Sjhb	int proctree_locked = 0;
645132089Sdavidxu	lwpid_t tid = 0, *buf;
646205014Snwhitehorn#ifdef COMPAT_FREEBSD32
647147692Speter	int wrap32 = 0, safe = 0;
648147692Speter	struct ptrace_io_desc32 *piod32 = NULL;
649209688Skib	struct ptrace_lwpinfo32 *pl32 = NULL;
650209688Skib	struct ptrace_lwpinfo plr;
651147692Speter#endif
6521541Srgrimes
65394665Salfred	curp = td->td_proc;
65494665Salfred
655102946Siedowse	/* Lock proctree before locking the process. */
656102946Siedowse	switch (req) {
65794556Sjhb	case PT_TRACE_ME:
65894556Sjhb	case PT_ATTACH:
65994556Sjhb	case PT_STEP:
66094556Sjhb	case PT_CONTINUE:
661120937Srobert	case PT_TO_SCE:
662120937Srobert	case PT_TO_SCX:
663143820Sdas	case PT_SYSCALL:
664217819Skib	case PT_FOLLOW_FORK:
66594556Sjhb	case PT_DETACH:
66694556Sjhb		sx_xlock(&proctree_lock);
66794556Sjhb		proctree_locked = 1;
66894556Sjhb		break;
66994556Sjhb	default:
67095165Smarcel		break;
67194556Sjhb	}
672112389Sdes
67348430Speter	write = 0;
674102946Siedowse	if (req == PT_TRACE_ME) {
67594556Sjhb		p = td->td_proc;
67675893Sjhb		PROC_LOCK(p);
67775893Sjhb	} else {
678131450Sdavidxu		if (pid <= PID_MAX) {
679131450Sdavidxu			if ((p = pfind(pid)) == NULL) {
680131450Sdavidxu				if (proctree_locked)
681131450Sdavidxu					sx_xunlock(&proctree_lock);
682131450Sdavidxu				return (ESRCH);
683131450Sdavidxu			}
684131450Sdavidxu		} else {
685213642Sdavidxu			td2 = tdfind(pid, -1);
686213642Sdavidxu			if (td2 == NULL) {
687131450Sdavidxu				if (proctree_locked)
688131450Sdavidxu					sx_xunlock(&proctree_lock);
689131450Sdavidxu				return (ESRCH);
690131450Sdavidxu			}
691213642Sdavidxu			p = td2->td_proc;
692131450Sdavidxu			tid = pid;
693131450Sdavidxu			pid = p->p_pid;
69494556Sjhb		}
6951945Sdg	}
696195104Srwatson	AUDIT_ARG_PROCESS(p);
697155922Sjhb
698155922Sjhb	if ((p->p_flag & P_WEXIT) != 0) {
699155922Sjhb		error = ESRCH;
700155922Sjhb		goto fail;
701155922Sjhb	}
702100418Srwatson	if ((error = p_cansee(td, p)) != 0)
70394556Sjhb		goto fail;
70484637Sdes
70596886Sjhb	if ((error = p_candebug(td, p)) != 0)
70694556Sjhb		goto fail;
70794556Sjhb
70813607Speter	/*
70991007Sbde	 * System processes can't be debugged.
71084637Sdes	 */
71184637Sdes	if ((p->p_flag & P_SYSTEM) != 0) {
71294556Sjhb		error = EINVAL;
71394556Sjhb		goto fail;
71484637Sdes	}
715112389Sdes
716131450Sdavidxu	if (tid == 0) {
717153697Sdavidxu		if ((p->p_flag & P_STOPPED_TRACE) != 0) {
718153697Sdavidxu			KASSERT(p->p_xthread != NULL, ("NULL p_xthread"));
719153697Sdavidxu			td2 = p->p_xthread;
720153697Sdavidxu		} else {
721153697Sdavidxu			td2 = FIRST_THREAD_IN_PROC(p);
722153697Sdavidxu		}
723131450Sdavidxu		tid = td2->td_tid;
724131450Sdavidxu	}
725131450Sdavidxu
726205014Snwhitehorn#ifdef COMPAT_FREEBSD32
72784637Sdes	/*
728147692Speter	 * Test if we're a 32 bit client and what the target is.
729147692Speter	 * Set the wrap controls accordingly.
730147692Speter	 */
731189282Skib	if (SV_CURPROC_FLAG(SV_ILP32)) {
732217896Sdchagin		if (SV_PROC_FLAG(td2->td_proc, SV_ILP32))
733147692Speter			safe = 1;
734147692Speter		wrap32 = 1;
735147692Speter	}
736147692Speter#endif
737147692Speter	/*
73813607Speter	 * Permissions check
73913607Speter	 */
740102946Siedowse	switch (req) {
74113607Speter	case PT_TRACE_ME:
74213607Speter		/* Always legal. */
74313607Speter		break;
7441945Sdg
74513607Speter	case PT_ATTACH:
74613607Speter		/* Self */
74794556Sjhb		if (p->p_pid == td->td_proc->p_pid) {
74894556Sjhb			error = EINVAL;
74994556Sjhb			goto fail;
75075893Sjhb		}
75113607Speter
75213607Speter		/* Already traced */
75373917Sjhb		if (p->p_flag & P_TRACED) {
75494556Sjhb			error = EBUSY;
75594556Sjhb			goto fail;
75673917Sjhb		}
75713607Speter
75894665Salfred		/* Can't trace an ancestor if you're being traced. */
75994665Salfred		if (curp->p_flag & P_TRACED) {
76094665Salfred			for (pp = curp->p_pptr; pp != NULL; pp = pp->p_pptr) {
76194665Salfred				if (pp == p) {
76294665Salfred					error = EINVAL;
76394665Salfred					goto fail;
76494665Salfred				}
76594665Salfred			}
76694665Salfred		}
76794665Salfred
76894665Salfred
76913607Speter		/* OK */
77013607Speter		break;
77113607Speter
772132089Sdavidxu	case PT_CLEARSTEP:
773132089Sdavidxu		/* Allow thread to clear single step for itself */
774132089Sdavidxu		if (td->td_tid == tid)
775132089Sdavidxu			break;
776132089Sdavidxu
777132089Sdavidxu		/* FALLTHROUGH */
778118932Smarcel	default:
77913607Speter		/* not being traced... */
78073917Sjhb		if ((p->p_flag & P_TRACED) == 0) {
78194556Sjhb			error = EPERM;
78294556Sjhb			goto fail;
78373917Sjhb		}
78413607Speter
78513607Speter		/* not being traced by YOU */
78694556Sjhb		if (p->p_pptr != td->td_proc) {
78794556Sjhb			error = EBUSY;
78894556Sjhb			goto fail;
78970317Sjake		}
79013607Speter
79113607Speter		/* not currently stopped */
792153697Sdavidxu		if ((p->p_flag & (P_STOPPED_SIG | P_STOPPED_TRACE)) == 0 ||
793153697Sdavidxu		    p->p_suspcount != p->p_numthreads  ||
794132089Sdavidxu		    (p->p_flag & P_WAITED) == 0) {
79594556Sjhb			error = EBUSY;
79694556Sjhb			goto fail;
79769506Sjhb		}
79813607Speter
799153697Sdavidxu		if ((p->p_flag & P_STOPPED_TRACE) == 0) {
800153697Sdavidxu			static int count = 0;
801153697Sdavidxu			if (count++ == 0)
802153697Sdavidxu				printf("P_STOPPED_TRACE not set.\n");
803153697Sdavidxu		}
804153697Sdavidxu
80513607Speter		/* OK */
80613607Speter		break;
8071945Sdg	}
80813607Speter
809155922Sjhb	/* Keep this process around until we finish this request. */
810155922Sjhb	_PHOLD(p);
811155922Sjhb
81213607Speter#ifdef FIX_SSTEP
81313607Speter	/*
81413607Speter	 * Single step fixup ala procfs
81513607Speter	 */
816155922Sjhb	FIX_SSTEP(td2);
8171945Sdg#endif
81813607Speter
8191541Srgrimes	/*
82013607Speter	 * Actually do the requests
8211541Srgrimes	 */
8221945Sdg
82383366Sjulian	td->td_retval[0] = 0;
82413607Speter
825102946Siedowse	switch (req) {
82613607Speter	case PT_TRACE_ME:
82713607Speter		/* set my trace flag and "owner" so it can read/write me */
8281945Sdg		p->p_flag |= P_TRACED;
829247077Skib		if (p->p_flag & P_PPWAIT)
830247077Skib			p->p_flag |= P_PPTRACE;
83113607Speter		p->p_oppid = p->p_pptr->p_pid;
832155922Sjhb		break;
8331945Sdg
83413607Speter	case PT_ATTACH:
83513607Speter		/* security check done above */
836223212Sobrien		/*
837223212Sobrien		 * It would be nice if the tracing relationship was separate
838223212Sobrien		 * from the parent relationship but that would require
839223212Sobrien		 * another set of links in the proc struct or for "wait"
840223212Sobrien		 * to scan the entire proc table.  To make life easier,
841223212Sobrien		 * we just re-parent the process we're trying to trace.
842223212Sobrien		 * The old parent is remembered so we can put things back
843223212Sobrien		 * on a "detach".
844223212Sobrien		 */
84513607Speter		p->p_flag |= P_TRACED;
84613607Speter		p->p_oppid = p->p_pptr->p_pid;
847223088Sobrien		if (p->p_pptr != td->td_proc) {
84894556Sjhb			proc_reparent(p, td->td_proc);
849223088Sobrien		}
850102946Siedowse		data = SIGSTOP;
85113607Speter		goto sendsig;	/* in PT_CONTINUE below */
85213607Speter
853132089Sdavidxu	case PT_CLEARSTEP:
854132089Sdavidxu		error = ptrace_clear_single_step(td2);
855155922Sjhb		break;
856132089Sdavidxu
857132089Sdavidxu	case PT_SETSTEP:
858132089Sdavidxu		error = ptrace_single_step(td2);
859155922Sjhb		break;
860132089Sdavidxu
861132089Sdavidxu	case PT_SUSPEND:
862183911Sdavidxu		td2->td_dbgflags |= TDB_SUSPEND;
863170307Sjeff		thread_lock(td2);
864183911Sdavidxu		td2->td_flags |= TDF_NEEDSUSPCHK;
865170307Sjeff		thread_unlock(td2);
866155922Sjhb		break;
867132089Sdavidxu
868132089Sdavidxu	case PT_RESUME:
869183911Sdavidxu		td2->td_dbgflags &= ~TDB_SUSPEND;
870155922Sjhb		break;
871132089Sdavidxu
872217819Skib	case PT_FOLLOW_FORK:
873217819Skib		if (data)
874217819Skib			p->p_flag |= P_FOLLOWFORK;
875217819Skib		else
876217819Skib			p->p_flag &= ~P_FOLLOWFORK;
877217819Skib		break;
878217819Skib
87913607Speter	case PT_STEP:
88013607Speter	case PT_CONTINUE:
881120937Srobert	case PT_TO_SCE:
882120937Srobert	case PT_TO_SCX:
883143820Sdas	case PT_SYSCALL:
8841945Sdg	case PT_DETACH:
885118749Snectar		/* Zero means do not send any signal */
886118749Snectar		if (data < 0 || data > _SIG_MAXSIG) {
88794556Sjhb			error = EINVAL;
888155922Sjhb			break;
88994556Sjhb		}
89013607Speter
891120937Srobert		switch (req) {
892120937Srobert		case PT_STEP:
89390391Speter			error = ptrace_single_step(td2);
894155922Sjhb			if (error)
895155922Sjhb				goto out;
896120937Srobert			break;
897208555Sjhb		case PT_CONTINUE:
898120937Srobert		case PT_TO_SCE:
899120937Srobert		case PT_TO_SCX:
900120937Srobert		case PT_SYSCALL:
901208555Sjhb			if (addr != (void *)1) {
902208555Sjhb				error = ptrace_set_pc(td2,
903208555Sjhb				    (u_long)(uintfptr_t)addr);
904208555Sjhb				if (error)
905208555Sjhb					goto out;
906208555Sjhb			}
907208555Sjhb			switch (req) {
908208555Sjhb			case PT_TO_SCE:
909208555Sjhb				p->p_stops |= S_PT_SCE;
910208555Sjhb				break;
911208555Sjhb			case PT_TO_SCX:
912208555Sjhb				p->p_stops |= S_PT_SCX;
913208555Sjhb				break;
914208555Sjhb			case PT_SYSCALL:
915208555Sjhb				p->p_stops |= S_PT_SCE | S_PT_SCX;
916208555Sjhb				break;
917208555Sjhb			}
918120937Srobert			break;
919208555Sjhb		case PT_DETACH:
92013607Speter			/* reset process parent */
92113607Speter			if (p->p_oppid != p->p_pptr->p_pid) {
92213607Speter				struct proc *pp;
92313607Speter
924152214Sdavidxu				PROC_LOCK(p->p_pptr);
925152214Sdavidxu				sigqueue_take(p->p_ksi);
926152214Sdavidxu				PROC_UNLOCK(p->p_pptr);
927152214Sdavidxu
92894556Sjhb				PROC_UNLOCK(p);
92913607Speter				pp = pfind(p->p_oppid);
93091140Stanimura				if (pp == NULL)
93191140Stanimura					pp = initproc;
93291140Stanimura				else
93376274Sjhb					PROC_UNLOCK(pp);
93476274Sjhb				PROC_LOCK(p);
93576274Sjhb				proc_reparent(p, pp);
936125993Struckman				if (pp == initproc)
937125993Struckman					p->p_sigparent = SIGCHLD;
93894556Sjhb			}
939223088Sobrien			p->p_oppid = 0;
940217819Skib			p->p_flag &= ~(P_TRACED | P_WAITED | P_FOLLOWFORK);
94173917Sjhb
94213607Speter			/* should we send SIGCHLD? */
943152214Sdavidxu			/* childproc_continued(p); */
944208555Sjhb			break;
94513607Speter		}
94613607Speter
94713607Speter	sendsig:
948155922Sjhb		if (proctree_locked) {
94994556Sjhb			sx_xunlock(&proctree_lock);
950155922Sjhb			proctree_locked = 0;
951155922Sjhb		}
952153697Sdavidxu		p->p_xstat = data;
953153697Sdavidxu		p->p_xthread = NULL;
954153697Sdavidxu		if ((p->p_flag & (P_STOPPED_SIG | P_STOPPED_TRACE)) != 0) {
955172485Sjeff			/* deliver or queue signal */
956183911Sdavidxu			td2->td_dbgflags &= ~TDB_XSIG;
957172485Sjeff			td2->td_xsig = data;
958172485Sjeff
959132089Sdavidxu			if (req == PT_DETACH) {
960132089Sdavidxu				struct thread *td3;
961170307Sjeff				FOREACH_THREAD_IN_PROC(p, td3) {
962183911Sdavidxu					td3->td_dbgflags &= ~TDB_SUSPEND;
963170307Sjeff				}
964132089Sdavidxu			}
965132089Sdavidxu			/*
966132089Sdavidxu			 * unsuspend all threads, to not let a thread run,
967132089Sdavidxu			 * you should use PT_SUSPEND to suspend it before
968132089Sdavidxu			 * continuing process.
969132089Sdavidxu			 */
970184667Sdavidxu			PROC_SLOCK(p);
971153697Sdavidxu			p->p_flag &= ~(P_STOPPED_TRACE|P_STOPPED_SIG|P_WAITED);
972103216Sjulian			thread_unsuspend(p);
973184667Sdavidxu			PROC_SUNLOCK(p);
974172485Sjeff		} else {
975172485Sjeff			if (data)
976225617Skmacy				kern_psignal(p, data);
977153697Sdavidxu		}
978155922Sjhb		break;
9791945Sdg
9801945Sdg	case PT_WRITE_I:
9811945Sdg	case PT_WRITE_D:
982202882Skib		td2->td_dbgflags |= TDB_USERWR;
98313607Speter		write = 1;
984102412Scharnier		/* FALLTHROUGH */
98513607Speter	case PT_READ_I:
98613607Speter	case PT_READ_D:
98794556Sjhb		PROC_UNLOCK(p);
98899880Stmm		tmp = 0;
98913607Speter		/* write = 0 set above */
990102946Siedowse		iov.iov_base = write ? (caddr_t)&data : (caddr_t)&tmp;
99113607Speter		iov.iov_len = sizeof(int);
99213607Speter		uio.uio_iov = &iov;
99313607Speter		uio.uio_iovcnt = 1;
994102946Siedowse		uio.uio_offset = (off_t)(uintptr_t)addr;
99513607Speter		uio.uio_resid = sizeof(int);
99691007Sbde		uio.uio_segflg = UIO_SYSSPACE;	/* i.e.: the uap */
99713607Speter		uio.uio_rw = write ? UIO_WRITE : UIO_READ;
99883366Sjulian		uio.uio_td = td;
99984637Sdes		error = proc_rwmem(p, &uio);
100014925Speter		if (uio.uio_resid != 0) {
100114925Speter			/*
100284637Sdes			 * XXX proc_rwmem() doesn't currently return ENOSPC,
100314925Speter			 * so I think write() can bogusly return 0.
100414925Speter			 * XXX what happens for short writes?  We don't want
100514925Speter			 * to write partial data.
100684637Sdes			 * XXX proc_rwmem() returns EPERM for other invalid
100714925Speter			 * addresses.  Convert this to EINVAL.  Does this
100814925Speter			 * clobber returns of EPERM for other reasons?
100914925Speter			 */
101014925Speter			if (error == 0 || error == ENOSPC || error == EPERM)
101114925Speter				error = EINVAL;	/* EOF */
101214925Speter		}
101399880Stmm		if (!write)
101499880Stmm			td->td_retval[0] = tmp;
1015155922Sjhb		PROC_LOCK(p);
1016155922Sjhb		break;
10171945Sdg
101892395Sdes	case PT_IO:
1019205014Snwhitehorn#ifdef COMPAT_FREEBSD32
1020147692Speter		if (wrap32) {
1021147692Speter			piod32 = addr;
1022147692Speter			iov.iov_base = (void *)(uintptr_t)piod32->piod_addr;
1023147692Speter			iov.iov_len = piod32->piod_len;
1024147692Speter			uio.uio_offset = (off_t)(uintptr_t)piod32->piod_offs;
1025147692Speter			uio.uio_resid = piod32->piod_len;
1026147692Speter		} else
1027147692Speter#endif
1028147692Speter		{
1029147692Speter			piod = addr;
1030147692Speter			iov.iov_base = piod->piod_addr;
1031147692Speter			iov.iov_len = piod->piod_len;
1032147692Speter			uio.uio_offset = (off_t)(uintptr_t)piod->piod_offs;
1033147692Speter			uio.uio_resid = piod->piod_len;
1034147692Speter		}
103592395Sdes		uio.uio_iov = &iov;
103692395Sdes		uio.uio_iovcnt = 1;
103792395Sdes		uio.uio_segflg = UIO_USERSPACE;
103892395Sdes		uio.uio_td = td;
1039205014Snwhitehorn#ifdef COMPAT_FREEBSD32
1040147692Speter		tmp = wrap32 ? piod32->piod_op : piod->piod_op;
1041147692Speter#else
1042147692Speter		tmp = piod->piod_op;
1043147692Speter#endif
1044147692Speter		switch (tmp) {
104592395Sdes		case PIOD_READ_D:
104692395Sdes		case PIOD_READ_I:
104792395Sdes			uio.uio_rw = UIO_READ;
104892395Sdes			break;
104992395Sdes		case PIOD_WRITE_D:
105092395Sdes		case PIOD_WRITE_I:
1051202882Skib			td2->td_dbgflags |= TDB_USERWR;
105292395Sdes			uio.uio_rw = UIO_WRITE;
105392395Sdes			break;
105492395Sdes		default:
1055155922Sjhb			error = EINVAL;
1056155922Sjhb			goto out;
105792395Sdes		}
1058155922Sjhb		PROC_UNLOCK(p);
105992395Sdes		error = proc_rwmem(p, &uio);
1060205014Snwhitehorn#ifdef COMPAT_FREEBSD32
1061147692Speter		if (wrap32)
1062147692Speter			piod32->piod_len -= uio.uio_resid;
1063147692Speter		else
1064147692Speter#endif
1065147692Speter			piod->piod_len -= uio.uio_resid;
1066155922Sjhb		PROC_LOCK(p);
1067155922Sjhb		break;
106892395Sdes
10691945Sdg	case PT_KILL:
1070102946Siedowse		data = SIGKILL;
107113607Speter		goto sendsig;	/* in PT_CONTINUE above */
107213607Speter
107313607Speter	case PT_SETREGS:
1074202882Skib		td2->td_dbgflags |= TDB_USERWR;
1075147692Speter		error = PROC_WRITE(regs, td2, addr);
1076155922Sjhb		break;
107784637Sdes
10781945Sdg	case PT_GETREGS:
1079147692Speter		error = PROC_READ(regs, td2, addr);
1080155922Sjhb		break;
108113607Speter
108213607Speter	case PT_SETFPREGS:
1083202882Skib		td2->td_dbgflags |= TDB_USERWR;
1084147692Speter		error = PROC_WRITE(fpregs, td2, addr);
1085155922Sjhb		break;
108684637Sdes
108713607Speter	case PT_GETFPREGS:
1088147692Speter		error = PROC_READ(fpregs, td2, addr);
1089155922Sjhb		break;
109013607Speter
109148691Sjlemon	case PT_SETDBREGS:
1092202882Skib		td2->td_dbgflags |= TDB_USERWR;
1093147692Speter		error = PROC_WRITE(dbregs, td2, addr);
1094155922Sjhb		break;
109592369Sdes
109648691Sjlemon	case PT_GETDBREGS:
1097147692Speter		error = PROC_READ(dbregs, td2, addr);
1098155922Sjhb		break;
109948691Sjlemon
1100132016Smarcel	case PT_LWPINFO:
1101209688Skib		if (data <= 0 ||
1102209688Skib#ifdef COMPAT_FREEBSD32
1103209688Skib		    (!wrap32 && data > sizeof(*pl)) ||
1104209688Skib		    (wrap32 && data > sizeof(*pl32))) {
1105209688Skib#else
1106209688Skib		    data > sizeof(*pl)) {
1107209688Skib#endif
1108155922Sjhb			error = EINVAL;
1109155922Sjhb			break;
1110155922Sjhb		}
1111209688Skib#ifdef COMPAT_FREEBSD32
1112209688Skib		if (wrap32) {
1113209688Skib			pl = &plr;
1114209688Skib			pl32 = addr;
1115209688Skib		} else
1116209688Skib#endif
1117132016Smarcel		pl = addr;
1118153697Sdavidxu		pl->pl_lwpid = td2->td_tid;
1119239555Skib		pl->pl_event = PL_EVENT_NONE;
1120209688Skib		pl->pl_flags = 0;
1121209688Skib		if (td2->td_dbgflags & TDB_XSIG) {
1122132089Sdavidxu			pl->pl_event = PL_EVENT_SIGNAL;
1123209688Skib			if (td2->td_dbgksi.ksi_signo != 0 &&
1124209688Skib#ifdef COMPAT_FREEBSD32
1125209688Skib			    ((!wrap32 && data >= offsetof(struct ptrace_lwpinfo,
1126209688Skib			    pl_siginfo) + sizeof(pl->pl_siginfo)) ||
1127209688Skib			    (wrap32 && data >= offsetof(struct ptrace_lwpinfo32,
1128209688Skib			    pl_siginfo) + sizeof(struct siginfo32)))
1129209688Skib#else
1130209688Skib			    data >= offsetof(struct ptrace_lwpinfo, pl_siginfo)
1131209688Skib			    + sizeof(pl->pl_siginfo)
1132209688Skib#endif
1133209688Skib			){
1134209688Skib				pl->pl_flags |= PL_FLAG_SI;
1135209688Skib				pl->pl_siginfo = td2->td_dbgksi.ksi_info;
1136209688Skib			}
1137209688Skib		}
1138209688Skib		if ((pl->pl_flags & PL_FLAG_SI) == 0)
1139209688Skib			bzero(&pl->pl_siginfo, sizeof(pl->pl_siginfo));
1140208453Skib		if (td2->td_dbgflags & TDB_SCE)
1141208453Skib			pl->pl_flags |= PL_FLAG_SCE;
1142208453Skib		else if (td2->td_dbgflags & TDB_SCX)
1143208453Skib			pl->pl_flags |= PL_FLAG_SCX;
1144208453Skib		if (td2->td_dbgflags & TDB_EXEC)
1145208453Skib			pl->pl_flags |= PL_FLAG_EXEC;
1146217819Skib		if (td2->td_dbgflags & TDB_FORK) {
1147217819Skib			pl->pl_flags |= PL_FLAG_FORKED;
1148217819Skib			pl->pl_child_pid = td2->td_dbg_forked;
1149217819Skib		}
1150231865Skib		if (td2->td_dbgflags & TDB_CHILD)
1151231865Skib			pl->pl_flags |= PL_FLAG_CHILD;
1152155381Sdavidxu		pl->pl_sigmask = td2->td_sigmask;
1153155381Sdavidxu		pl->pl_siglist = td2->td_siglist;
1154215679Sattilio		strcpy(pl->pl_tdname, td2->td_name);
1155209688Skib#ifdef COMPAT_FREEBSD32
1156209688Skib		if (wrap32)
1157209688Skib			ptrace_lwpinfo_to32(pl, pl32);
1158209688Skib#endif
1159155922Sjhb		break;
1160132016Smarcel
1161132089Sdavidxu	case PT_GETNUMLWPS:
1162132089Sdavidxu		td->td_retval[0] = p->p_numthreads;
1163155922Sjhb		break;
1164132089Sdavidxu
1165132089Sdavidxu	case PT_GETLWPLIST:
1166132089Sdavidxu		if (data <= 0) {
1167155922Sjhb			error = EINVAL;
1168155922Sjhb			break;
1169132089Sdavidxu		}
1170132089Sdavidxu		num = imin(p->p_numthreads, data);
1171132089Sdavidxu		PROC_UNLOCK(p);
1172132089Sdavidxu		buf = malloc(num * sizeof(lwpid_t), M_TEMP, M_WAITOK);
1173132089Sdavidxu		tmp = 0;
1174132089Sdavidxu		PROC_LOCK(p);
1175132089Sdavidxu		FOREACH_THREAD_IN_PROC(p, td2) {
1176132089Sdavidxu			if (tmp >= num)
1177132089Sdavidxu				break;
1178132089Sdavidxu			buf[tmp++] = td2->td_tid;
1179132089Sdavidxu		}
1180132089Sdavidxu		PROC_UNLOCK(p);
1181132089Sdavidxu		error = copyout(buf, addr, tmp * sizeof(lwpid_t));
1182132089Sdavidxu		free(buf, M_TEMP);
1183132089Sdavidxu		if (!error)
1184163345Strhodes			td->td_retval[0] = tmp;
1185155922Sjhb		PROC_LOCK(p);
1186155922Sjhb		break;
1187132089Sdavidxu
1188203696Smarcel	case PT_VM_TIMESTAMP:
1189203696Smarcel		td->td_retval[0] = p->p_vmspace->vm_map.timestamp;
1190203696Smarcel		break;
1191203696Smarcel
1192203696Smarcel	case PT_VM_ENTRY:
1193203783Smarcel		PROC_UNLOCK(p);
1194205014Snwhitehorn#ifdef COMPAT_FREEBSD32
1195203783Smarcel		if (wrap32)
1196203783Smarcel			error = ptrace_vm_entry32(td, p, addr);
1197203783Smarcel		else
1198203708Smarcel#endif
1199203696Smarcel		error = ptrace_vm_entry(td, p, addr);
1200203696Smarcel		PROC_LOCK(p);
1201203696Smarcel		break;
1202203696Smarcel
12031945Sdg	default:
1204118932Smarcel#ifdef __HAVE_PTRACE_MACHDEP
1205118932Smarcel		if (req >= PT_FIRSTMACH) {
1206127034Sjhb			PROC_UNLOCK(p);
1207118932Smarcel			error = cpu_ptrace(td2, req, addr, data);
1208155922Sjhb			PROC_LOCK(p);
1209155922Sjhb		} else
1210118932Smarcel#endif
1211155922Sjhb			/* Unknown request. */
1212155922Sjhb			error = EINVAL;
12131945Sdg		break;
12141945Sdg	}
12151945Sdg
1216155922Sjhbout:
1217155922Sjhb	/* Drop our hold on this process now that the request has completed. */
1218155922Sjhb	_PRELE(p);
121994556Sjhbfail:
122094556Sjhb	PROC_UNLOCK(p);
122194556Sjhb	if (proctree_locked)
122294556Sjhb		sx_xunlock(&proctree_lock);
122394556Sjhb	return (error);
12241541Srgrimes}
1225147692Speter#undef PROC_READ
1226147692Speter#undef PROC_WRITE
12271541Srgrimes
122831564Ssef/*
122984637Sdes * Stop a process because of a debugging event;
123031564Ssef * stay stopped until p->p_step is cleared
123131564Ssef * (cleared by PIOCCONT in procfs).
123231564Ssef */
123331564Ssefvoid
123484637Sdesstopevent(struct proc *p, unsigned int event, unsigned int val)
123571567Sjhb{
123671567Sjhb
1237113635Sjhb	PROC_LOCK_ASSERT(p, MA_OWNED);
123831564Ssef	p->p_step = 1;
123931564Ssef	do {
124031564Ssef		p->p_xstat = val;
1241132089Sdavidxu		p->p_xthread = NULL;
124231564Ssef		p->p_stype = event;	/* Which event caused the stop? */
124331564Ssef		wakeup(&p->p_stype);	/* Wake up any PIOCWAIT'ing procs */
124471567Sjhb		msleep(&p->p_step, &p->p_mtx, PWAIT, "stopevent", 0);
124531564Ssef	} while (p->p_step);
124631564Ssef}
1247260208Sjhb
1248260208Sjhbstatic int
1249260208Sjhbprotect_setchild(struct thread *td, struct proc *p, int flags)
1250260208Sjhb{
1251260208Sjhb
1252260208Sjhb	PROC_LOCK_ASSERT(p, MA_OWNED);
1253260208Sjhb	if (p->p_flag & P_SYSTEM || p_cansee(td, p) != 0)
1254260208Sjhb		return (0);
1255260208Sjhb	if (flags & PPROT_SET) {
1256260208Sjhb		p->p_flag |= P_PROTECTED;
1257260208Sjhb		if (flags & PPROT_INHERIT)
1258260208Sjhb			p->p_flag2 |= P2_INHERIT_PROTECTED;
1259260208Sjhb	} else {
1260260208Sjhb		p->p_flag &= ~P_PROTECTED;
1261260208Sjhb		p->p_flag2 &= ~P2_INHERIT_PROTECTED;
1262260208Sjhb	}
1263260208Sjhb	return (1);
1264260208Sjhb}
1265260208Sjhb
1266260208Sjhbstatic int
1267260208Sjhbprotect_setchildren(struct thread *td, struct proc *top, int flags)
1268260208Sjhb{
1269260208Sjhb	struct proc *p;
1270260208Sjhb	int ret;
1271260208Sjhb
1272260208Sjhb	p = top;
1273260208Sjhb	ret = 0;
1274260208Sjhb	sx_assert(&proctree_lock, SX_LOCKED);
1275260208Sjhb	for (;;) {
1276260208Sjhb		ret |= protect_setchild(td, p, flags);
1277260208Sjhb		PROC_UNLOCK(p);
1278260208Sjhb		/*
1279260208Sjhb		 * If this process has children, descend to them next,
1280260208Sjhb		 * otherwise do any siblings, and if done with this level,
1281260208Sjhb		 * follow back up the tree (but not past top).
1282260208Sjhb		 */
1283260208Sjhb		if (!LIST_EMPTY(&p->p_children))
1284260208Sjhb			p = LIST_FIRST(&p->p_children);
1285260208Sjhb		else for (;;) {
1286260208Sjhb			if (p == top) {
1287260208Sjhb				PROC_LOCK(p);
1288260208Sjhb				return (ret);
1289260208Sjhb			}
1290260208Sjhb			if (LIST_NEXT(p, p_sibling)) {
1291260208Sjhb				p = LIST_NEXT(p, p_sibling);
1292260208Sjhb				break;
1293260208Sjhb			}
1294260208Sjhb			p = p->p_pptr;
1295260208Sjhb		}
1296260208Sjhb		PROC_LOCK(p);
1297260208Sjhb	}
1298260208Sjhb}
1299260208Sjhb
1300260208Sjhbstatic int
1301260208Sjhbprotect_set(struct thread *td, struct proc *p, int flags)
1302260208Sjhb{
1303260208Sjhb	int error, ret;
1304260208Sjhb
1305260208Sjhb	switch (PPROT_OP(flags)) {
1306260208Sjhb	case PPROT_SET:
1307260208Sjhb	case PPROT_CLEAR:
1308260208Sjhb		break;
1309260208Sjhb	default:
1310260208Sjhb		return (EINVAL);
1311260208Sjhb	}
1312260208Sjhb
1313260208Sjhb	if ((PPROT_FLAGS(flags) & ~(PPROT_DESCEND | PPROT_INHERIT)) != 0)
1314260208Sjhb		return (EINVAL);
1315260208Sjhb
1316260208Sjhb	error = priv_check(td, PRIV_VM_MADV_PROTECT);
1317260208Sjhb	if (error)
1318260208Sjhb		return (error);
1319260208Sjhb
1320260208Sjhb	if (flags & PPROT_DESCEND)
1321260208Sjhb		ret = protect_setchildren(td, p, flags);
1322260208Sjhb	else
1323260208Sjhb		ret = protect_setchild(td, p, flags);
1324260208Sjhb	if (ret == 0)
1325260208Sjhb		return (EPERM);
1326260208Sjhb	return (0);
1327260208Sjhb}
1328260208Sjhb
1329260208Sjhb#ifndef _SYS_SYSPROTO_H_
1330260208Sjhbstruct procctl_args {
1331260208Sjhb	idtype_t idtype;
1332260208Sjhb	id_t	id;
1333260208Sjhb	int	com;
1334260208Sjhb	void	*data;
1335260208Sjhb};
1336260208Sjhb#endif
1337260208Sjhb/* ARGSUSED */
1338260208Sjhbint
1339260208Sjhbsys_procctl(struct thread *td, struct procctl_args *uap)
1340260208Sjhb{
1341260208Sjhb	int error, flags;
1342260208Sjhb	void *data;
1343260208Sjhb
1344260208Sjhb	switch (uap->com) {
1345260208Sjhb	case PROC_SPROTECT:
1346260208Sjhb		error = copyin(uap->data, &flags, sizeof(flags));
1347260208Sjhb		if (error)
1348260208Sjhb			return (error);
1349260208Sjhb		data = &flags;
1350260208Sjhb		break;
1351260208Sjhb	default:
1352260208Sjhb		return (EINVAL);
1353260208Sjhb	}
1354260208Sjhb
1355260208Sjhb	return (kern_procctl(td, uap->idtype, uap->id, uap->com, data));
1356260208Sjhb}
1357260208Sjhb
1358260208Sjhbstatic int
1359260208Sjhbkern_procctl_single(struct thread *td, struct proc *p, int com, void *data)
1360260208Sjhb{
1361260208Sjhb
1362260208Sjhb	PROC_LOCK_ASSERT(p, MA_OWNED);
1363260208Sjhb	switch (com) {
1364260208Sjhb	case PROC_SPROTECT:
1365260208Sjhb		return (protect_set(td, p, *(int *)data));
1366260208Sjhb	default:
1367260208Sjhb		return (EINVAL);
1368260208Sjhb	}
1369260208Sjhb}
1370260208Sjhb
1371260208Sjhbint
1372260208Sjhbkern_procctl(struct thread *td, idtype_t idtype, id_t id, int com, void *data)
1373260208Sjhb{
1374260208Sjhb	struct pgrp *pg;
1375260208Sjhb	struct proc *p;
1376260208Sjhb	int error, first_error, ok;
1377260208Sjhb
1378260208Sjhb	sx_slock(&proctree_lock);
1379260208Sjhb	switch (idtype) {
1380260208Sjhb	case P_PID:
1381260208Sjhb		p = pfind(id);
1382260208Sjhb		if (p == NULL) {
1383260208Sjhb			error = ESRCH;
1384260208Sjhb			break;
1385260208Sjhb		}
1386260208Sjhb		if (p->p_state == PRS_NEW)
1387260208Sjhb			error = ESRCH;
1388260208Sjhb		else
1389260208Sjhb			error = p_cansee(td, p);
1390260208Sjhb		if (error == 0)
1391260208Sjhb			error = kern_procctl_single(td, p, com, data);
1392260208Sjhb		PROC_UNLOCK(p);
1393260208Sjhb		break;
1394260208Sjhb	case P_PGID:
1395260208Sjhb		/*
1396260208Sjhb		 * Attempt to apply the operation to all members of the
1397260208Sjhb		 * group.  Ignore processes in the group that can't be
1398260208Sjhb		 * seen.  Ignore errors so long as at least one process is
1399260208Sjhb		 * able to complete the request successfully.
1400260208Sjhb		 */
1401260208Sjhb		pg = pgfind(id);
1402260208Sjhb		if (pg == NULL) {
1403260208Sjhb			error = ESRCH;
1404260208Sjhb			break;
1405260208Sjhb		}
1406260208Sjhb		PGRP_UNLOCK(pg);
1407260208Sjhb		ok = 0;
1408260208Sjhb		first_error = 0;
1409260208Sjhb		LIST_FOREACH(p, &pg->pg_members, p_pglist) {
1410260208Sjhb			PROC_LOCK(p);
1411260208Sjhb			if (p->p_state == PRS_NEW || p_cansee(td, p) != 0) {
1412260208Sjhb				PROC_UNLOCK(p);
1413260208Sjhb				continue;
1414260208Sjhb			}
1415260208Sjhb			error = kern_procctl_single(td, p, com, data);
1416260208Sjhb			PROC_UNLOCK(p);
1417260208Sjhb			if (error == 0)
1418260208Sjhb				ok = 1;
1419260208Sjhb			else if (first_error == 0)
1420260208Sjhb				first_error = error;
1421260208Sjhb		}
1422260208Sjhb		if (ok)
1423260208Sjhb			error = 0;
1424260208Sjhb		else if (first_error != 0)
1425260208Sjhb			error = first_error;
1426260208Sjhb		else
1427260208Sjhb			/*
1428260208Sjhb			 * Was not able to see any processes in the
1429260208Sjhb			 * process group.
1430260208Sjhb			 */
1431260208Sjhb			error = ESRCH;
1432260208Sjhb		break;
1433260208Sjhb	default:
1434260208Sjhb		error = EINVAL;
1435260208Sjhb		break;
1436260208Sjhb	}
1437260208Sjhb	sx_sunlock(&proctree_lock);
1438260208Sjhb	return (error);
1439260208Sjhb}
1440