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