Module Name: src Committed By: pgoyette Date: Wed Nov 2 00:12:00 UTC 2016
Modified Files: src/sys/arch/i386/conf: INSTALL_FLOPPY src/sys/arch/i386/i386: process_machdep.c src/sys/arch/sh3/include: userret.h src/sys/arch/sh3/sh3: exception_vector.S process_machdep.c sh3_machdep.c src/sys/compat/netbsd32: netbsd32_ptrace.c src/sys/conf: files std src/sys/kern: files.kern init_main.c kern_stub.c sys_process.c syscalls.master src/sys/miscfs/procfs: files.procfs src/sys/modules: Makefile src/sys/sys: ptrace.h Added Files: src/sys/kern: sys_ptrace.c sys_ptrace_common.c src/sys/modules/ptrace: Makefile src/sys/modules/ptrace_common: Makefile Log Message: * Split sys/kern/sys_process.c into three parts: 1 - ptrace(2) syscall for native emulation 2 - common ptrace(2) syscall code (shared with compat_netbsd32) 3 - support routines that are shared with PROCFS and/or KTRACE * Add module glue for #1 and #2. Both modules will be built-in to the kernel if "options PTRACE" is included in the config file (this is the default, defined in sys/conf/std). * Mark the ptrace(2) syscall as modular in syscalls.master (generated files will be committed shortly). * Conditionalize all remaining portions of PTRACE code on a new kernel option PTRACE_HOOKS. XXX Instead of PROCFS depending on 'options PTRACE', we should probably just add a procfs attribute to the sys/kern/sys_process.c file's entry in files.kern, and add PROCFS to the "#if defineds" for process_domem(). It's really confusing to have two different ways of requiring this file. To generate a diff of this commit: cvs rdiff -u -r1.29 -r1.30 src/sys/arch/i386/conf/INSTALL_FLOPPY cvs rdiff -u -r1.85 -r1.86 src/sys/arch/i386/i386/process_machdep.c cvs rdiff -u -r1.13 -r1.14 src/sys/arch/sh3/include/userret.h cvs rdiff -u -r1.49 -r1.50 src/sys/arch/sh3/sh3/exception_vector.S cvs rdiff -u -r1.20 -r1.21 src/sys/arch/sh3/sh3/process_machdep.c cvs rdiff -u -r1.103 -r1.104 src/sys/arch/sh3/sh3/sh3_machdep.c cvs rdiff -u -r1.1 -r1.2 src/sys/compat/netbsd32/netbsd32_ptrace.c cvs rdiff -u -r1.1165 -r1.1166 src/sys/conf/files cvs rdiff -u -r1.21 -r1.22 src/sys/conf/std cvs rdiff -u -r1.12 -r1.13 src/sys/kern/files.kern cvs rdiff -u -r1.483 -r1.484 src/sys/kern/init_main.c cvs rdiff -u -r1.42 -r1.43 src/sys/kern/kern_stub.c cvs rdiff -u -r1.174 -r1.175 src/sys/kern/sys_process.c cvs rdiff -u -r0 -r1.1 src/sys/kern/sys_ptrace.c \ src/sys/kern/sys_ptrace_common.c cvs rdiff -u -r1.285 -r1.286 src/sys/kern/syscalls.master cvs rdiff -u -r1.9 -r1.10 src/sys/miscfs/procfs/files.procfs cvs rdiff -u -r1.181 -r1.182 src/sys/modules/Makefile cvs rdiff -u -r0 -r1.1 src/sys/modules/ptrace/Makefile cvs rdiff -u -r0 -r1.1 src/sys/modules/ptrace_common/Makefile cvs rdiff -u -r1.47 -r1.48 src/sys/sys/ptrace.h Please note that diffs are not public domain; they are subject to the copyright notices on the relevant files.
Modified files: Index: src/sys/arch/i386/conf/INSTALL_FLOPPY diff -u src/sys/arch/i386/conf/INSTALL_FLOPPY:1.29 src/sys/arch/i386/conf/INSTALL_FLOPPY:1.30 --- src/sys/arch/i386/conf/INSTALL_FLOPPY:1.29 Sat Sep 26 11:16:12 2015 +++ src/sys/arch/i386/conf/INSTALL_FLOPPY Wed Nov 2 00:11:59 2016 @@ -1,4 +1,4 @@ -# $NetBSD: INSTALL_FLOPPY,v 1.29 2015/09/26 11:16:12 maxv Exp $ +# $NetBSD: INSTALL_FLOPPY,v 1.30 2016/11/02 00:11:59 pgoyette Exp $ # # INSTALL - Installation kernel. # @@ -64,6 +64,7 @@ options PIPE_SOCKETPAIR # smaller, but no options EXEC_AOUT no options RFC2292 # Previous version of Adv. Sockets API for IPv6 +no options PTRACE_HOOKS no options PTRACE # Include ptrace(2) # Diagnostic/debugging support options Index: src/sys/arch/i386/i386/process_machdep.c diff -u src/sys/arch/i386/i386/process_machdep.c:1.85 src/sys/arch/i386/i386/process_machdep.c:1.86 --- src/sys/arch/i386/i386/process_machdep.c:1.85 Wed Feb 19 21:23:01 2014 +++ src/sys/arch/i386/i386/process_machdep.c Wed Nov 2 00:11:59 2016 @@ -1,4 +1,4 @@ -/* $NetBSD: process_machdep.c,v 1.85 2014/02/19 21:23:01 dsl Exp $ */ +/* $NetBSD: process_machdep.c,v 1.86 2016/11/02 00:11:59 pgoyette Exp $ */ /*- * Copyright (c) 1998, 2000, 2001, 2008 The NetBSD Foundation, Inc. @@ -52,7 +52,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: process_machdep.c,v 1.85 2014/02/19 21:23:01 dsl Exp $"); +__KERNEL_RCSID(0, "$NetBSD: process_machdep.c,v 1.86 2016/11/02 00:11:59 pgoyette Exp $"); #include "opt_vm86.h" #include "opt_ptrace.h" @@ -129,7 +129,7 @@ process_read_fpregs(struct lwp *l, struc return 0; } -#ifdef PTRACE +#ifdef PTRACE_HOOKS int process_write_regs(struct lwp *l, const struct reg *regs) { @@ -336,4 +336,4 @@ process_machdep_validxmmregs(struct proc return (i386_use_fxsave); } #endif /* __HAVE_PTRACE_MACHDEP */ -#endif /* PTRACE */ +#endif /* PTRACE_HOOKS */ Index: src/sys/arch/sh3/include/userret.h diff -u src/sys/arch/sh3/include/userret.h:1.13 src/sys/arch/sh3/include/userret.h:1.14 --- src/sys/arch/sh3/include/userret.h:1.13 Sun Jul 8 20:14:11 2012 +++ src/sys/arch/sh3/include/userret.h Wed Nov 2 00:11:59 2016 @@ -1,4 +1,4 @@ -/* $NetBSD: userret.h,v 1.13 2012/07/08 20:14:11 dsl Exp $ */ +/* $NetBSD: userret.h,v 1.14 2016/11/02 00:11:59 pgoyette Exp $ */ /* * Copyright (c) 1988 University of Utah. @@ -54,7 +54,7 @@ userret(struct lwp *l) /* Invoke MI userret code */ mi_userret(l); -#ifdef PTRACE +#ifdef PTRACE_HOOKS /* Check if lwp is being PT_STEP'ed */ if (l->l_md.md_flags & MDL_SSTEP) { struct trapframe *tf = l->l_md.md_regs; @@ -75,7 +75,7 @@ userret(struct lwp *l) } #endif } -#endif /* PTRACE */ +#endif /* PTRACE_HOOKS */ } #endif /* !_SH3_USERRET_H_ */ Index: src/sys/arch/sh3/sh3/exception_vector.S diff -u src/sys/arch/sh3/sh3/exception_vector.S:1.49 src/sys/arch/sh3/sh3/exception_vector.S:1.50 --- src/sys/arch/sh3/sh3/exception_vector.S:1.49 Fri Feb 4 04:14:25 2011 +++ src/sys/arch/sh3/sh3/exception_vector.S Wed Nov 2 00:11:59 2016 @@ -1,4 +1,4 @@ -/* $NetBSD: exception_vector.S,v 1.49 2011/02/04 04:14:25 uwe Exp $ */ +/* $NetBSD: exception_vector.S,v 1.50 2016/11/02 00:11:59 pgoyette Exp $ */ /*- * Copyright (c) 2002 The NetBSD Foundation, Inc. @@ -48,7 +48,7 @@ #define _ALIGN_TEXT .align 5 #include <sh3/asm.h> -__KERNEL_RCSID(0, "$NetBSD: exception_vector.S,v 1.49 2011/02/04 04:14:25 uwe Exp $") +__KERNEL_RCSID(0, "$NetBSD: exception_vector.S,v 1.50 2016/11/02 00:11:59 pgoyette Exp $") /* @@ -98,7 +98,7 @@ NENTRY(sh_vector_generic) /* general_exception(curlwp, tf, TEA); */ 1: mov r4, r8 -#if defined(PTRACE) || defined(DDB) +#if defined(PTRACE_HOOKS) || defined(DDB) mov #0, r2 MOV (BBRA, r1) mov.l r2, @(TF_UBC, r14) /* clear tf->tf_ubc */ @@ -115,7 +115,7 @@ NENTRY(sh_vector_generic) jsr @r0 mov r14, r5 -#if defined(PTRACE) || defined(DDB) +#if defined(PTRACE_HOOKS) || defined(DDB) mov.l @(TF_UBC, r14), r2 tst r2, r2 ! single-step == 0? bt .Lg_return_from_exception Index: src/sys/arch/sh3/sh3/process_machdep.c diff -u src/sys/arch/sh3/sh3/process_machdep.c:1.20 src/sys/arch/sh3/sh3/process_machdep.c:1.21 --- src/sys/arch/sh3/sh3/process_machdep.c:1.20 Sun Jul 8 20:14:12 2012 +++ src/sys/arch/sh3/sh3/process_machdep.c Wed Nov 2 00:11:59 2016 @@ -1,4 +1,4 @@ -/* $NetBSD: process_machdep.c,v 1.20 2012/07/08 20:14:12 dsl Exp $ */ +/* $NetBSD: process_machdep.c,v 1.21 2016/11/02 00:11:59 pgoyette Exp $ */ /* * Copyright (c) 1993 The Regents of the University of California. @@ -77,7 +77,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: process_machdep.c,v 1.20 2012/07/08 20:14:12 dsl Exp $"); +__KERNEL_RCSID(0, "$NetBSD: process_machdep.c,v 1.21 2016/11/02 00:11:59 pgoyette Exp $"); #include <sys/param.h> #include <sys/systm.h> @@ -101,7 +101,7 @@ static int process_machdep_write_regs40( #endif /* COMPAT_40 */ -#if defined(PTRACE) || defined(COREDUMP) +#if defined(PTRACE_HOOKS) || defined(COREDUMP) static inline struct trapframe * process_frame(struct lwp *l) @@ -141,10 +141,10 @@ process_read_regs(struct lwp *l, struct return (0); } -#endif /* PTRACE || COREDUMP */ +#endif /* PTRACE_HOOKS || COREDUMP */ -#ifdef PTRACE +#ifdef PTRACE_HOOKS int process_write_regs(struct lwp *l, const struct reg *regs) @@ -360,4 +360,4 @@ process_set_pc(struct lwp *l, void *addr return (0); } -#endif /* PTRACE */ +#endif /* PTRACE_HOOKS */ Index: src/sys/arch/sh3/sh3/sh3_machdep.c diff -u src/sys/arch/sh3/sh3/sh3_machdep.c:1.103 src/sys/arch/sh3/sh3/sh3_machdep.c:1.104 --- src/sys/arch/sh3/sh3/sh3_machdep.c:1.103 Sun Nov 22 18:44:25 2015 +++ src/sys/arch/sh3/sh3/sh3_machdep.c Wed Nov 2 00:11:59 2016 @@ -1,4 +1,4 @@ -/* $NetBSD: sh3_machdep.c,v 1.103 2015/11/22 18:44:25 tsutsui Exp $ */ +/* $NetBSD: sh3_machdep.c,v 1.104 2016/11/02 00:11:59 pgoyette Exp $ */ /*- * Copyright (c) 1996, 1997, 1998, 2002 The NetBSD Foundation, Inc. @@ -65,7 +65,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: sh3_machdep.c,v 1.103 2015/11/22 18:44:25 tsutsui Exp $"); +__KERNEL_RCSID(0, "$NetBSD: sh3_machdep.c,v 1.104 2016/11/02 00:11:59 pgoyette Exp $"); #include "opt_ddb.h" #include "opt_kgdb.h" @@ -194,7 +194,7 @@ sh_cpu_init(int arch, int product) uvm_setpagesize(); /* setup UBC channel A for single-stepping */ -#if defined(PTRACE) || defined(DDB) +#if defined(PTRACE_HOOKS) || defined(DDB) _reg_write_2(SH_(BBRA), 0); /* disable channel A */ _reg_write_2(SH_(BBRB), 0); /* disable channel B */ Index: src/sys/compat/netbsd32/netbsd32_ptrace.c diff -u src/sys/compat/netbsd32/netbsd32_ptrace.c:1.1 src/sys/compat/netbsd32/netbsd32_ptrace.c:1.2 --- src/sys/compat/netbsd32/netbsd32_ptrace.c:1.1 Wed Oct 19 09:44:01 2016 +++ src/sys/compat/netbsd32/netbsd32_ptrace.c Wed Nov 2 00:11:59 2016 @@ -1,4 +1,4 @@ -/* $NetBSD: netbsd32_ptrace.c,v 1.1 2016/10/19 09:44:01 skrll Exp $ */ +/* $NetBSD: netbsd32_ptrace.c,v 1.2 2016/11/02 00:11:59 pgoyette Exp $ */ /* * Copyright (c) 2016 The NetBSD Foundation, Inc. @@ -30,7 +30,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: netbsd32_ptrace.c,v 1.1 2016/10/19 09:44:01 skrll Exp $"); +__KERNEL_RCSID(0, "$NetBSD: netbsd32_ptrace.c,v 1.2 2016/11/02 00:11:59 pgoyette Exp $"); #if defined(_KERNEL_OPT) #include "opt_ptrace.h" @@ -193,7 +193,9 @@ static const struct syscall_package comp { 0, 0, NULL }, }; -MODULE(MODULE_CLASS_EXEC, compat_netbsd32_ptrace, "compat_netbsd32"); +#define DEPS "compat_netbsd32,ptrace_common" + +MODULE(MODULE_CLASS_EXEC, compat_netbsd32_ptrace, DEPS); static int compat_netbsd32_ptrace_modcmd(modcmd_t cmd, void *arg) Index: src/sys/conf/files diff -u src/sys/conf/files:1.1165 src/sys/conf/files:1.1166 --- src/sys/conf/files:1.1165 Tue Nov 1 22:54:33 2016 +++ src/sys/conf/files Wed Nov 2 00:11:59 2016 @@ -1,4 +1,4 @@ -# $NetBSD: files,v 1.1165 2016/11/01 22:54:33 pgoyette Exp $ +# $NetBSD: files,v 1.1166 2016/11/02 00:11:59 pgoyette Exp $ # @(#)files.newconf 7.5 (Berkeley) 5/10/93 version 20150846 @@ -21,7 +21,7 @@ defparam opt_param.h MAXUSERS defflag INSECURE defflag KTRACE defflag MBUFTRACE -defflag PTRACE +defflag opt_ptrace.h PTRACE PTRACE_HOOKS defflag COREDUMP defflag opt_modular.h MODULAR defflag opt_modular.h MODULAR_DEFAULT_AUTOLOAD Index: src/sys/conf/std diff -u src/sys/conf/std:1.21 src/sys/conf/std:1.22 --- src/sys/conf/std:1.21 Sat Nov 14 07:31:13 2015 +++ src/sys/conf/std Wed Nov 2 00:11:59 2016 @@ -1,4 +1,4 @@ -# $NetBSD: std,v 1.21 2015/11/14 07:31:13 pgoyette Exp $ +# $NetBSD: std,v 1.22 2016/11/02 00:11:59 pgoyette Exp $ # # standard MI 'options' # @@ -27,7 +27,8 @@ options VMSWAP # Swap device/file suppo options BUFQ_FCFS # First-come First-serve strategy options BUFQ_DISKSORT # Traditional min seek sort strategy options RFC2292 # Previous version of Adv. Sockets API for IPv6 -options PTRACE # Include ptrace(2) +options PTRACE # Include ptrace(2) syscall +options PTRACE_HOOKS # Include ptrace hooks options COREDUMP # allow processes to coredump. options AIO # POSIX asynchronous I/O options MQUEUE # POSIX message queues Index: src/sys/kern/files.kern diff -u src/sys/kern/files.kern:1.12 src/sys/kern/files.kern:1.13 --- src/sys/kern/files.kern:1.12 Fri Sep 16 03:10:45 2016 +++ src/sys/kern/files.kern Wed Nov 2 00:11:59 2016 @@ -1,4 +1,4 @@ -# $NetBSD: files.kern,v 1.12 2016/09/16 03:10:45 pgoyette Exp $ +# $NetBSD: files.kern,v 1.13 2016/11/02 00:11:59 pgoyette Exp $ # # kernel sources @@ -144,7 +144,9 @@ file kern/sys_mqueue.c mqueue file kern/sys_lwp.c kern file kern/sys_pipe.c !pipe_socketpair file kern/sys_pmc.c kern -file kern/sys_process.c ptrace | ktrace +file kern/sys_process.c ptrace_hooks | ktrace +file kern/sys_ptrace.c ptrace +file kern/sys_ptrace_common.c ptrace file kern/sys_pset.c kern file kern/sys_select.c kern file kern/sys_sig.c kern Index: src/sys/kern/init_main.c diff -u src/sys/kern/init_main.c:1.483 src/sys/kern/init_main.c:1.484 --- src/sys/kern/init_main.c:1.483 Sat Sep 17 12:09:22 2016 +++ src/sys/kern/init_main.c Wed Nov 2 00:11:59 2016 @@ -1,4 +1,4 @@ -/* $NetBSD: init_main.c,v 1.483 2016/09/17 12:09:22 maxv Exp $ */ +/* $NetBSD: init_main.c,v 1.484 2016/11/02 00:11:59 pgoyette Exp $ */ /*- * Copyright (c) 2008, 2009 The NetBSD Foundation, Inc. @@ -97,7 +97,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: init_main.c,v 1.483 2016/09/17 12:09:22 maxv Exp $"); +__KERNEL_RCSID(0, "$NetBSD: init_main.c,v 1.484 2016/11/02 00:11:59 pgoyette Exp $"); #include "opt_ddb.h" #include "opt_inet.h" @@ -190,9 +190,6 @@ extern void *_binary_splash_image_end; #endif #include <sys/kauth.h> #include <net80211/ieee80211_netbsd.h> -#ifdef PTRACE -#include <sys/ptrace.h> -#endif /* PTRACE */ #include <sys/cprng.h> #include <sys/syscall.h> @@ -563,11 +560,6 @@ main(void) ktrinit(); #endif -#ifdef PTRACE - /* Initialize ptrace. */ - ptrace_init(); -#endif /* PTRACE */ - machdep_init(); procinit_sysctl(); Index: src/sys/kern/kern_stub.c diff -u src/sys/kern/kern_stub.c:1.42 src/sys/kern/kern_stub.c:1.43 --- src/sys/kern/kern_stub.c:1.42 Fri Aug 28 07:18:39 2015 +++ src/sys/kern/kern_stub.c Wed Nov 2 00:11:59 2016 @@ -1,4 +1,4 @@ -/* $NetBSD: kern_stub.c,v 1.42 2015/08/28 07:18:39 knakahara Exp $ */ +/* $NetBSD: kern_stub.c,v 1.43 2016/11/02 00:11:59 pgoyette Exp $ */ /*- * Copyright (c) 2007, 2008 The NetBSD Foundation, Inc. @@ -62,10 +62,9 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: kern_stub.c,v 1.42 2015/08/28 07:18:39 knakahara Exp $"); +__KERNEL_RCSID(0, "$NetBSD: kern_stub.c,v 1.43 2016/11/02 00:11:59 pgoyette Exp $"); #ifdef _KERNEL_OPT -#include "opt_ptrace.h" #include "opt_ktrace.h" #endif @@ -87,14 +86,6 @@ bool default_bus_space_handle_is_equal(b bus_space_handle_t); /* - * Nonexistent system call-- signal process (may want to handle it). Flag - * error in case process won't see signal immediately (blocked or ignored). - */ -#ifndef PTRACE -__strong_alias(sys_ptrace,sys_nosys); -#endif /* PTRACE */ - -/* * ktrace stubs. ktruser() goes to enosys as we want to fail the syscall, * but not kill the process: utrace() is a debugging feature. */ Index: src/sys/kern/sys_process.c diff -u src/sys/kern/sys_process.c:1.174 src/sys/kern/sys_process.c:1.175 --- src/sys/kern/sys_process.c:1.174 Wed Oct 19 09:44:01 2016 +++ src/sys/kern/sys_process.c Wed Nov 2 00:11:59 2016 @@ -1,4 +1,4 @@ -/* $NetBSD: sys_process.c,v 1.174 2016/10/19 09:44:01 skrll Exp $ */ +/* $NetBSD: sys_process.c,v 1.175 2016/11/02 00:11:59 pgoyette Exp $ */ /*- * Copyright (c) 2008, 2009 The NetBSD Foundation, Inc. @@ -118,7 +118,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: sys_process.c,v 1.174 2016/10/19 09:44:01 skrll Exp $"); +__KERNEL_RCSID(0, "$NetBSD: sys_process.c,v 1.175 2016/11/02 00:11:59 pgoyette Exp $"); #ifdef _KERNEL_OPT #include "opt_ptrace.h" @@ -144,975 +144,7 @@ __KERNEL_RCSID(0, "$NetBSD: sys_process. #include <machine/reg.h> -#ifdef PTRACE - -# ifdef DEBUG -# define DPRINTF(a) uprintf a -# else -# define DPRINTF(a) -# endif - -static kauth_listener_t ptrace_listener; -#ifdef PTRACE -static int process_auxv_offset(struct proc *, struct uio *); -#endif - -static int -ptrace_listener_cb(kauth_cred_t cred, kauth_action_t action, void *cookie, - void *arg0, void *arg1, void *arg2, void *arg3) -{ - struct proc *p; - int result; - - result = KAUTH_RESULT_DEFER; - p = arg0; - - if (action != KAUTH_PROCESS_PTRACE) - return result; - - switch ((u_long)arg1) { - case PT_TRACE_ME: - case PT_ATTACH: - case PT_WRITE_I: - case PT_WRITE_D: - case PT_READ_I: - case PT_READ_D: - case PT_IO: -#ifdef PT_GETREGS - case PT_GETREGS: -#endif -#ifdef PT_SETREGS - case PT_SETREGS: -#endif -#ifdef PT_GETFPREGS - case PT_GETFPREGS: -#endif -#ifdef PT_SETFPREGS - case PT_SETFPREGS: -#endif - case PT_SET_EVENT_MASK: - case PT_GET_EVENT_MASK: - case PT_GET_PROCESS_STATE: -#ifdef __HAVE_PTRACE_MACHDEP - PTRACE_MACHDEP_REQUEST_CASES -#endif - if (kauth_cred_getuid(cred) != kauth_cred_getuid(p->p_cred) || - ISSET(p->p_flag, PK_SUGID)) { - break; - } - - result = KAUTH_RESULT_ALLOW; - - break; - -#ifdef PT_STEP - case PT_STEP: -#endif - case PT_CONTINUE: - case PT_KILL: - case PT_DETACH: - case PT_LWPINFO: - case PT_SYSCALL: - case PT_SYSCALLEMU: - case PT_DUMPCORE: - result = KAUTH_RESULT_ALLOW; - break; - - default: - break; - } - - return result; -} - -void -ptrace_init(void) -{ - - ptrace_listener = kauth_listen_scope(KAUTH_SCOPE_PROCESS, - ptrace_listener_cb, NULL); -} - -static int -ptrace_copyinpiod(struct ptrace_io_desc *piod, const void *addr) -{ - return copyin(addr, piod, sizeof(*piod)); -} - -static void -ptrace_copyoutpiod(const struct ptrace_io_desc *piod, void *addr) -{ - (void) copyout(piod, addr, sizeof(*piod)); -} - - -static struct ptrace_methods native_ptm = { - .ptm_copyinpiod = ptrace_copyinpiod, - .ptm_copyoutpiod = ptrace_copyoutpiod, - .ptm_doregs = process_doregs, - .ptm_dofpregs = process_dofpregs, -}; - -/* - * Process debugging system call. - */ -int -sys_ptrace(struct lwp *l, const struct sys_ptrace_args *uap, register_t *retval) -{ - /* { - syscallarg(int) req; - syscallarg(pid_t) pid; - syscallarg(void *) addr; - syscallarg(int) data; - } */ - - return do_ptrace(&native_ptm, l, SCARG(uap, req), SCARG(uap, pid), - SCARG(uap, addr), SCARG(uap, data), retval); -} - -int -do_ptrace(struct ptrace_methods *ptm, struct lwp *l, int req, pid_t pid, - void *addr, int data, register_t *retval) -{ - struct proc *p = l->l_proc; - struct lwp *lt; -#ifdef PT_STEP - struct lwp *lt2; -#endif - struct proc *t; /* target process */ - struct uio uio; - struct iovec iov; - struct ptrace_io_desc piod; - struct ptrace_event pe; - struct ptrace_state ps; - struct ptrace_lwpinfo pl; - struct vmspace *vm; - int error, write, tmp, pheld; - int signo = 0; - int resume_all; - ksiginfo_t ksi; - char *path; - int len = 0; - error = 0; - - /* - * If attaching or detaching, we need to get a write hold on the - * proclist lock so that we can re-parent the target process. - */ - mutex_enter(proc_lock); - - /* "A foolish consistency..." XXX */ - if (req == PT_TRACE_ME) { - t = p; - mutex_enter(t->p_lock); - } else { - /* Find the process we're supposed to be operating on. */ - t = proc_find(pid); - if (t == NULL) { - mutex_exit(proc_lock); - return ESRCH; - } - - /* XXX-elad */ - mutex_enter(t->p_lock); - error = kauth_authorize_process(l->l_cred, KAUTH_PROCESS_CANSEE, - t, KAUTH_ARG(KAUTH_REQ_PROCESS_CANSEE_ENTRY), NULL, NULL); - if (error) { - mutex_exit(proc_lock); - mutex_exit(t->p_lock); - return ESRCH; - } - } - - /* - * Grab a reference on the process to prevent it from execing or - * exiting. - */ - if (!rw_tryenter(&t->p_reflock, RW_READER)) { - mutex_exit(proc_lock); - mutex_exit(t->p_lock); - return EBUSY; - } - - /* Make sure we can operate on it. */ - switch (req) { - case PT_TRACE_ME: - /* Saying that you're being traced is always legal. */ - break; - - case PT_ATTACH: - /* - * You can't attach to a process if: - * (1) it's the process that's doing the attaching, - */ - if (t->p_pid == p->p_pid) { - error = EINVAL; - break; - } - - /* - * (2) it's a system process - */ - if (t->p_flag & PK_SYSTEM) { - error = EPERM; - break; - } - - /* - * (3) it's already being traced, or - */ - if (ISSET(t->p_slflag, PSL_TRACED)) { - error = EBUSY; - break; - } - - /* - * (4) the tracer is chrooted, and its root directory is - * not at or above the root directory of the tracee - */ - mutex_exit(t->p_lock); /* XXXSMP */ - tmp = proc_isunder(t, l); - mutex_enter(t->p_lock); /* XXXSMP */ - if (!tmp) { - error = EPERM; - break; - } - break; - - case PT_READ_I: - case PT_READ_D: - case PT_WRITE_I: - case PT_WRITE_D: - case PT_IO: -#ifdef PT_GETREGS - case PT_GETREGS: -#endif -#ifdef PT_SETREGS - case PT_SETREGS: -#endif -#ifdef PT_GETFPREGS - case PT_GETFPREGS: -#endif -#ifdef PT_SETFPREGS - case PT_SETFPREGS: -#endif -#ifdef __HAVE_PTRACE_MACHDEP - PTRACE_MACHDEP_REQUEST_CASES -#endif - /* - * You can't read/write the memory or registers of a process - * if the tracer is chrooted, and its root directory is not at - * or above the root directory of the tracee. - */ - mutex_exit(t->p_lock); /* XXXSMP */ - tmp = proc_isunder(t, l); - mutex_enter(t->p_lock); /* XXXSMP */ - if (!tmp) { - error = EPERM; - break; - } - /*FALLTHROUGH*/ - - case PT_CONTINUE: - case PT_KILL: - case PT_DETACH: - case PT_LWPINFO: - case PT_SYSCALL: - case PT_SYSCALLEMU: - case PT_DUMPCORE: -#ifdef PT_STEP - case PT_STEP: -#endif - case PT_SET_EVENT_MASK: - case PT_GET_EVENT_MASK: - case PT_GET_PROCESS_STATE: - /* - * You can't do what you want to the process if: - * (1) It's not being traced at all, - */ - if (!ISSET(t->p_slflag, PSL_TRACED)) { - error = EPERM; - break; - } - - /* - * (2) it's being traced by procfs (which has - * different signal delivery semantics), - */ - if (ISSET(t->p_slflag, PSL_FSTRACE)) { - DPRINTF(("file system traced\n")); - error = EBUSY; - break; - } - - /* - * (3) it's not being traced by _you_, or - */ - if (t->p_pptr != p) { - DPRINTF(("parent %d != %d\n", t->p_pptr->p_pid, - p->p_pid)); - error = EBUSY; - break; - } - - /* - * (4) it's not currently stopped. - */ - if (t->p_stat != SSTOP || !t->p_waited /* XXXSMP */) { - DPRINTF(("stat %d flag %d\n", t->p_stat, - !t->p_waited)); - error = EBUSY; - break; - } - break; - - default: /* It was not a legal request. */ - error = EINVAL; - break; - } - - if (error == 0) { - error = kauth_authorize_process(l->l_cred, - KAUTH_PROCESS_PTRACE, t, KAUTH_ARG(req), - NULL, NULL); - } - if (error == 0) { - lt = lwp_find_first(t); - if (lt == NULL) - error = ESRCH; - } - - if (error != 0) { - mutex_exit(proc_lock); - mutex_exit(t->p_lock); - rw_exit(&t->p_reflock); - return error; - } - - /* Do single-step fixup if needed. */ - FIX_SSTEP(t); - KASSERT(lt != NULL); - lwp_addref(lt); - - /* - * Which locks do we need held? XXX Ugly. - */ - switch (req) { -#ifdef PT_STEP - case PT_STEP: -#endif - case PT_CONTINUE: - case PT_DETACH: - case PT_KILL: - case PT_SYSCALL: - case PT_SYSCALLEMU: - case PT_ATTACH: - case PT_TRACE_ME: - pheld = 1; - break; - default: - mutex_exit(proc_lock); - mutex_exit(t->p_lock); - pheld = 0; - break; - } - - /* Now do the operation. */ - write = 0; - *retval = 0; - tmp = 0; - resume_all = 1; - - switch (req) { - case PT_TRACE_ME: - /* Just set the trace flag. */ - SET(t->p_slflag, PSL_TRACED); - t->p_opptr = t->p_pptr; - break; - - case PT_WRITE_I: /* XXX no separate I and D spaces */ - case PT_WRITE_D: -#if defined(__HAVE_RAS) - /* - * Can't write to a RAS - */ - if (ras_lookup(t, addr) != (void *)-1) { - error = EACCES; - break; - } -#endif - write = 1; - tmp = data; - /* FALLTHROUGH */ - - case PT_READ_I: /* XXX no separate I and D spaces */ - case PT_READ_D: - /* write = 0 done above. */ - iov.iov_base = (void *)&tmp; - iov.iov_len = sizeof(tmp); - uio.uio_iov = &iov; - uio.uio_iovcnt = 1; - uio.uio_offset = (off_t)(unsigned long)addr; - uio.uio_resid = sizeof(tmp); - uio.uio_rw = write ? UIO_WRITE : UIO_READ; - UIO_SETUP_SYSSPACE(&uio); - - error = process_domem(l, lt, &uio); - if (!write) - *retval = tmp; - break; - - case PT_IO: - error = ptm->ptm_copyinpiod(&piod, addr); - if (error) - break; - - iov.iov_base = piod.piod_addr; - iov.iov_len = piod.piod_len; - uio.uio_iov = &iov; - uio.uio_iovcnt = 1; - uio.uio_offset = (off_t)(unsigned long)piod.piod_offs; - uio.uio_resid = piod.piod_len; - - switch (piod.piod_op) { - case PIOD_READ_D: - case PIOD_READ_I: - uio.uio_rw = UIO_READ; - break; - case PIOD_WRITE_D: - case PIOD_WRITE_I: - /* - * Can't write to a RAS - */ - if (ras_lookup(t, addr) != (void *)-1) { - return EACCES; - } - uio.uio_rw = UIO_WRITE; - break; - case PIOD_READ_AUXV: - req = PT_READ_D; - uio.uio_rw = UIO_READ; - tmp = t->p_execsw->es_arglen * PROC_PTRSZ(t); - if (uio.uio_offset > tmp) - return EIO; - if (uio.uio_resid > tmp - uio.uio_offset) - uio.uio_resid = tmp - uio.uio_offset; - piod.piod_len = iov.iov_len = uio.uio_resid; - error = process_auxv_offset(t, &uio); - if (error) - return error; - break; - default: - error = EINVAL; - break; - } - if (error) - break; - error = proc_vmspace_getref(l->l_proc, &vm); - if (error) - break; - uio.uio_vmspace = vm; - - error = process_domem(l, lt, &uio); - piod.piod_len -= uio.uio_resid; - (void) ptm->ptm_copyoutpiod(&piod, addr); - - uvmspace_free(vm); - break; - - case PT_DUMPCORE: - if ((path = addr) != NULL) { - char *dst; - len = data; - - if (len < 0 || len >= MAXPATHLEN) { - error = EINVAL; - break; - } - dst = kmem_alloc(len + 1, KM_SLEEP); - if ((error = copyin(path, dst, len)) != 0) { - kmem_free(dst, len + 1); - break; - } - path = dst; - path[len] = '\0'; - } - error = (*coredump_vec)(lt, path); - if (path) - kmem_free(path, len + 1); - break; - -#ifdef PT_STEP - case PT_STEP: - /* - * From the 4.4BSD PRM: - * "Execution continues as in request PT_CONTINUE; however - * as soon as possible after execution of at least one - * instruction, execution stops again. [ ... ]" - */ -#endif - case PT_CONTINUE: - case PT_SYSCALL: - case PT_DETACH: - if (req == PT_SYSCALL) { - if (!ISSET(t->p_slflag, PSL_SYSCALL)) { - SET(t->p_slflag, PSL_SYSCALL); -#ifdef __HAVE_SYSCALL_INTERN - (*t->p_emul->e_syscall_intern)(t); -#endif - } - } else { - if (ISSET(t->p_slflag, PSL_SYSCALL)) { - CLR(t->p_slflag, PSL_SYSCALL); -#ifdef __HAVE_SYSCALL_INTERN - (*t->p_emul->e_syscall_intern)(t); -#endif - } - } - t->p_trace_enabled = trace_is_enabled(t); - - /* - * Pick up the LWPID, if supplied. There are two cases: - * data < 0 : step or continue single thread, lwp = -data - * data > 0 in PT_STEP : step this thread, continue others - * For operations other than PT_STEP, data > 0 means - * data is the signo to deliver to the process. - */ - tmp = data; - if (tmp >= 0) { -#ifdef PT_STEP - if (req == PT_STEP) - signo = 0; - else -#endif - { - signo = tmp; - tmp = 0; /* don't search for LWP */ - } - } else - tmp = -tmp; - - if (tmp > 0) { - if (req == PT_DETACH) { - error = EINVAL; - break; - } - lwp_delref2 (lt); - lt = lwp_find(t, tmp); - if (lt == NULL) { - error = ESRCH; - break; - } - lwp_addref(lt); - resume_all = 0; - signo = 0; - } - - /* - * From the 4.4BSD PRM: - * "The data argument is taken as a signal number and the - * child's execution continues at location addr as if it - * incurred that signal. Normally the signal number will - * be either 0 to indicate that the signal that caused the - * stop should be ignored, or that value fetched out of - * the process's image indicating which signal caused - * the stop. If addr is (int *)1 then execution continues - * from where it stopped." - */ - - /* Check that the data is a valid signal number or zero. */ - if (signo < 0 || signo >= NSIG) { - error = EINVAL; - break; - } - - /* If the address parameter is not (int *)1, set the pc. */ - if ((int *)addr != (int *)1) { - error = process_set_pc(lt, addr); - if (error != 0) - break; - } -#ifdef PT_STEP - /* - * Arrange for a single-step, if that's requested and possible. - * More precisely, set the single step status as requested for - * the requested thread, and clear it for other threads. - */ - LIST_FOREACH(lt2, &t->p_lwps, l_sibling) { - if (lt != lt2) { - lwp_lock(lt2); - process_sstep(lt2, 0); - lwp_unlock(lt2); - } - } - error = process_sstep(lt, req == PT_STEP); - if (error) - break; -#endif - if (req == PT_DETACH) { - CLR(t->p_slflag, PSL_TRACED|PSL_FSTRACE|PSL_SYSCALL); - - /* give process back to original parent or init */ - if (t->p_opptr != t->p_pptr) { - struct proc *pp = t->p_opptr; - proc_reparent(t, pp ? pp : initproc); - } - - /* not being traced any more */ - t->p_opptr = NULL; - } - sendsig: - t->p_fpid = 0; - /* Finally, deliver the requested signal (or none). */ - if (t->p_stat == SSTOP) { - /* - * Unstop the process. If it needs to take a - * signal, make all efforts to ensure that at - * an LWP runs to see it. - */ - t->p_xsig = signo; - if (resume_all) - proc_unstop(t); - else - lwp_unstop(lt); - } else if (signo != 0) { - KSI_INIT_EMPTY(&ksi); - ksi.ksi_signo = signo; - kpsignal2(t, &ksi); - } - break; - - case PT_SYSCALLEMU: - if (!ISSET(t->p_slflag, PSL_SYSCALL) || t->p_stat != SSTOP) { - error = EINVAL; - break; - } - SET(t->p_slflag, PSL_SYSCALLEMU); - break; - - case PT_KILL: - /* just send the process a KILL signal. */ - signo = SIGKILL; - goto sendsig; /* in PT_CONTINUE, above. */ - - case PT_ATTACH: - /* - * Go ahead and set the trace flag. - * Save the old parent (it's reset in - * _DETACH, and also in kern_exit.c:wait4() - * Reparent the process so that the tracing - * proc gets to see all the action. - * Stop the target. - */ - t->p_opptr = t->p_pptr; - if (t->p_pptr != p) { - struct proc *parent = t->p_pptr; - - if (parent->p_lock < t->p_lock) { - if (!mutex_tryenter(parent->p_lock)) { - mutex_exit(t->p_lock); - mutex_enter(parent->p_lock); - mutex_enter(t->p_lock); - } - } else if (parent->p_lock > t->p_lock) { - mutex_enter(parent->p_lock); - } - parent->p_slflag |= PSL_CHTRACED; - proc_reparent(t, p); - if (parent->p_lock != t->p_lock) - mutex_exit(parent->p_lock); - } - SET(t->p_slflag, PSL_TRACED); - signo = SIGSTOP; - goto sendsig; - - case PT_GET_EVENT_MASK: - if (data != sizeof(pe)) { - DPRINTF(("ptrace(%d): %d != %zu\n", req, - data, sizeof(pe))); - error = EINVAL; - break; - } - memset(&pe, 0, sizeof(pe)); - pe.pe_set_event = ISSET(t->p_slflag, PSL_TRACEFORK) ? - PTRACE_FORK : 0; - error = copyout(&pe, addr, sizeof(pe)); - break; - - case PT_SET_EVENT_MASK: - if (data != sizeof(pe)) { - DPRINTF(("ptrace(%d): %d != %zu\n", req, data, - sizeof(pe))); - error = EINVAL; - break; - } - if ((error = copyin(addr, &pe, sizeof(pe))) != 0) - return error; - if (pe.pe_set_event & PTRACE_FORK) - SET(t->p_slflag, PSL_TRACEFORK); - else - CLR(t->p_slflag, PSL_TRACEFORK); - break; - - case PT_GET_PROCESS_STATE: - if (data != sizeof(ps)) { - DPRINTF(("ptrace(%d): %d != %zu\n", req, data, - sizeof(ps))); - error = EINVAL; - break; - } - memset(&ps, 0, sizeof(ps)); - if (t->p_fpid) { - ps.pe_report_event = PTRACE_FORK; - ps.pe_other_pid = t->p_fpid; - } - error = copyout(&ps, addr, sizeof(ps)); - break; - - case PT_LWPINFO: - if (data != sizeof(pl)) { - DPRINTF(("ptrace(%d): %d != %zu\n", req, data, - sizeof(pl))); - error = EINVAL; - break; - } - error = copyin(addr, &pl, sizeof(pl)); - if (error) - break; - tmp = pl.pl_lwpid; - lwp_delref(lt); - mutex_enter(t->p_lock); - if (tmp == 0) - lt = lwp_find_first(t); - else { - lt = lwp_find(t, tmp); - if (lt == NULL) { - mutex_exit(t->p_lock); - error = ESRCH; - break; - } - lt = LIST_NEXT(lt, l_sibling); - } - while (lt != NULL && !lwp_alive(lt)) - lt = LIST_NEXT(lt, l_sibling); - pl.pl_lwpid = 0; - pl.pl_event = 0; - if (lt) { - lwp_addref(lt); - pl.pl_lwpid = lt->l_lid; - if (lt->l_lid == t->p_sigctx.ps_lwp) - pl.pl_event = PL_EVENT_SIGNAL; - } - mutex_exit(t->p_lock); - - error = copyout(&pl, addr, sizeof(pl)); - break; - -#ifdef PT_SETREGS - case PT_SETREGS: - write = 1; -#endif -#ifdef PT_GETREGS - case PT_GETREGS: - /* write = 0 done above. */ -#endif -#if defined(PT_SETREGS) || defined(PT_GETREGS) - tmp = data; - if (tmp != 0 && t->p_nlwps > 1) { - lwp_delref(lt); - mutex_enter(t->p_lock); - lt = lwp_find(t, tmp); - if (lt == NULL) { - mutex_exit(t->p_lock); - error = ESRCH; - break; - } - lwp_addref(lt); - mutex_exit(t->p_lock); - } - if (!process_validregs(lt)) - error = EINVAL; - else { - error = proc_vmspace_getref(p, &vm); - if (error) - break; - iov.iov_base = addr; - iov.iov_len = PROC_REGSZ(p); - uio.uio_iov = &iov; - uio.uio_iovcnt = 1; - uio.uio_offset = 0; - uio.uio_resid = iov.iov_len; - uio.uio_rw = write ? UIO_WRITE : UIO_READ; - uio.uio_vmspace = vm; - - error = ptm->ptm_doregs(l, lt, &uio); - uvmspace_free(vm); - } - break; -#endif - -#ifdef PT_SETFPREGS - case PT_SETFPREGS: - write = 1; -#endif -#ifdef PT_GETFPREGS - case PT_GETFPREGS: - /* write = 0 done above. */ -#endif -#if defined(PT_SETFPREGS) || defined(PT_GETFPREGS) - tmp = data; - if (tmp != 0 && t->p_nlwps > 1) { - lwp_delref(lt); - mutex_enter(t->p_lock); - lt = lwp_find(t, tmp); - if (lt == NULL) { - mutex_exit(t->p_lock); - error = ESRCH; - break; - } - lwp_addref(lt); - mutex_exit(t->p_lock); - } - if (!process_validfpregs(lt)) - error = EINVAL; - else { - error = proc_vmspace_getref(p, &vm); - if (error) - break; - iov.iov_base = addr; - iov.iov_len = PROC_FPREGSZ(p); - uio.uio_iov = &iov; - uio.uio_iovcnt = 1; - uio.uio_offset = 0; - uio.uio_resid = iov.iov_len; - uio.uio_rw = write ? UIO_WRITE : UIO_READ; - uio.uio_vmspace = vm; - - error = ptm->ptm_dofpregs(l, lt, &uio); - uvmspace_free(vm); - } - break; -#endif - -#ifdef __HAVE_PTRACE_MACHDEP - PTRACE_MACHDEP_REQUEST_CASES - error = ptrace_machdep_dorequest(l, lt, req, addr, data); - break; -#endif - } - - if (pheld) { - mutex_exit(t->p_lock); - mutex_exit(proc_lock); - } - if (lt != NULL) - lwp_delref(lt); - rw_exit(&t->p_reflock); - - return error; -} - -int -process_doregs(struct lwp *curl /*tracer*/, - struct lwp *l /*traced*/, - struct uio *uio) -{ -#if defined(PT_GETREGS) || defined(PT_SETREGS) - int error; - struct reg r; - char *kv; - int kl; - - if (uio->uio_offset < 0 || uio->uio_offset > (off_t)sizeof(r)) - return EINVAL; - - kl = sizeof(r); - kv = (char *)&r; - - kv += uio->uio_offset; - kl -= uio->uio_offset; - if ((size_t)kl > uio->uio_resid) - kl = uio->uio_resid; - - error = process_read_regs(l, &r); - if (error == 0) - error = uiomove(kv, kl, uio); - if (error == 0 && uio->uio_rw == UIO_WRITE) { - if (l->l_stat != LSSTOP) - error = EBUSY; - else - error = process_write_regs(l, &r); - } - - uio->uio_offset = 0; - return error; -#else - return EINVAL; -#endif -} - -int -process_validregs(struct lwp *l) -{ - -#if defined(PT_SETREGS) || defined(PT_GETREGS) - return (l->l_flag & LW_SYSTEM) == 0; -#else - return 0; -#endif -} - -int -process_dofpregs(struct lwp *curl /*tracer*/, - struct lwp *l /*traced*/, - struct uio *uio) -{ -#if defined(PT_GETFPREGS) || defined(PT_SETFPREGS) - int error; - struct fpreg r; - char *kv; - size_t kl; - - if (uio->uio_offset < 0 || uio->uio_offset > (off_t)sizeof(r)) - return EINVAL; - - kl = sizeof(r); - kv = (char *)&r; - - kv += uio->uio_offset; - kl -= uio->uio_offset; - if (kl > uio->uio_resid) - kl = uio->uio_resid; - - error = process_read_fpregs(l, &r, &kl); - if (error == 0) - error = uiomove(kv, kl, uio); - if (error == 0 && uio->uio_rw == UIO_WRITE) { - if (l->l_stat != LSSTOP) - error = EBUSY; - else - error = process_write_fpregs(l, &r, kl); - } - uio->uio_offset = 0; - return error; -#else - return EINVAL; -#endif -} - -int -process_validfpregs(struct lwp *l) -{ - -#if defined(PT_SETFPREGS) || defined(PT_GETFPREGS) - return (l->l_flag & LW_SYSTEM) == 0; -#else - return 0; -#endif -} -#endif /* PTRACE */ - -#if defined(KTRACE) || defined(PTRACE) +#if defined(KTRACE) || defined(PTRACE_HOOKS) int process_domem(struct lwp *curl /*tracer*/, struct lwp *l /*traced*/, @@ -1156,9 +188,7 @@ process_domem(struct lwp *curl /*tracer* #endif return error; } -#endif /* KTRACE || PTRACE */ -#if defined(KTRACE) || defined(PTRACE) void process_stoptrace(void) { @@ -1186,32 +216,16 @@ process_stoptrace(void) } mutex_exit(p->p_lock); } -#endif /* KTRACE || PTRACE */ +#endif /* KTRACE || PTRACE_HOOKS */ -#ifdef PTRACE -static int -process_auxv_offset(struct proc *p, struct uio *uio) +/* + * Dummy routine so that ptrace_common module will fail to load if this + * routine is not defined. + */ +#if defined(PTRACE_HOOKS) +void +ptrace_hooks(void) { - struct ps_strings pss; - int error; - off_t off = (off_t)p->p_psstrp; - if ((error = copyin_psstrings(p, &pss)) != 0) - return error; - - if (pss.ps_envstr == NULL) - return EIO; - - uio->uio_offset += (off_t)(vaddr_t)(pss.ps_envstr + pss.ps_nenvstr + 1); -#ifdef __MACHINE_STACK_GROWS_UP - if (uio->uio_offset < off) - return EIO; -#else - if (uio->uio_offset > off) - return EIO; - if ((uio->uio_offset + uio->uio_resid) > off) - uio->uio_resid = off - uio->uio_offset; -#endif - return 0; } #endif Index: src/sys/kern/syscalls.master diff -u src/sys/kern/syscalls.master:1.285 src/sys/kern/syscalls.master:1.286 --- src/sys/kern/syscalls.master:1.285 Sun Jul 3 14:24:59 2016 +++ src/sys/kern/syscalls.master Wed Nov 2 00:11:59 2016 @@ -1,4 +1,4 @@ - $NetBSD: syscalls.master,v 1.285 2016/07/03 14:24:59 christos Exp $ + $NetBSD: syscalls.master,v 1.286 2016/11/02 00:11:59 pgoyette Exp $ ; @(#)syscalls.master 8.2 (Berkeley) 1/13/94 @@ -100,11 +100,12 @@ 21 COMPAT_40 MODULAR compat \ { int|sys||mount(const char *type, const char *path, \ int flags, void *data); } -22 STD RUMP { int|sys||unmount(const char *path, int flags); } +22 STD RUMP { int|sys||unmount(const char *path, int flags); } 23 STD RUMP { int|sys||setuid(uid_t uid); } 24 NOERR RUMP { uid_t|sys||getuid_with_euid(void); } getuid 25 NOERR RUMP { uid_t|sys||geteuid(void); } -26 STD { int|sys||ptrace(int req, pid_t pid, void *addr, \ +26 STD MODULAR ptrace \ + { int|sys||ptrace(int req, pid_t pid, void *addr, \ int data); } 27 STD RUMP { ssize_t|sys||recvmsg(int s, struct msghdr *msg, \ int flags); } Index: src/sys/miscfs/procfs/files.procfs diff -u src/sys/miscfs/procfs/files.procfs:1.9 src/sys/miscfs/procfs/files.procfs:1.10 --- src/sys/miscfs/procfs/files.procfs:1.9 Sat Oct 11 06:42:20 2014 +++ src/sys/miscfs/procfs/files.procfs Wed Nov 2 00:12:00 2016 @@ -1,6 +1,6 @@ -# $NetBSD: files.procfs,v 1.9 2014/10/11 06:42:20 uebayasi Exp $ +# $NetBSD: files.procfs,v 1.10 2016/11/02 00:12:00 pgoyette Exp $ -deffs PROCFS: PTRACE +deffs PROCFS: PTRACE_HOOKS define procfs: vfs file miscfs/procfs/procfs_cmdline.c procfs Index: src/sys/modules/Makefile diff -u src/sys/modules/Makefile:1.181 src/sys/modules/Makefile:1.182 --- src/sys/modules/Makefile:1.181 Wed Oct 19 09:44:01 2016 +++ src/sys/modules/Makefile Wed Nov 2 00:12:00 2016 @@ -1,4 +1,4 @@ -# $NetBSD: Makefile,v 1.181 2016/10/19 09:44:01 skrll Exp $ +# $NetBSD: Makefile,v 1.182 2016/11/02 00:12:00 pgoyette Exp $ .include <bsd.own.mk> @@ -96,6 +96,8 @@ SUBDIR+= pf SUBDIR+= ppp_bsdcomp SUBDIR+= ppp_deflate SUBDIR+= procfs +SUBDIR+= ptrace +SUBDIR+= ptrace_common SUBDIR+= ptyfs SUBDIR+= puffs SUBDIR+= putter Index: src/sys/sys/ptrace.h diff -u src/sys/sys/ptrace.h:1.47 src/sys/sys/ptrace.h:1.48 --- src/sys/sys/ptrace.h:1.47 Wed Oct 19 09:44:01 2016 +++ src/sys/sys/ptrace.h Wed Nov 2 00:12:00 2016 @@ -1,4 +1,4 @@ -/* $NetBSD: ptrace.h,v 1.47 2016/10/19 09:44:01 skrll Exp $ */ +/* $NetBSD: ptrace.h,v 1.48 2016/11/02 00:12:00 pgoyette Exp $ */ /*- * Copyright (c) 1984, 1993 @@ -146,7 +146,9 @@ struct ptrace_methods { int (*ptm_dofpregs)(struct lwp *, struct lwp *, struct uio *); }; -void ptrace_init(void); +int ptrace_init(void); +int ptrace_fini(void); +void ptrace_hooks(void); int process_doregs(struct lwp *, struct lwp *, struct uio *); int process_validregs(struct lwp *); Added files: Index: src/sys/kern/sys_ptrace.c diff -u /dev/null src/sys/kern/sys_ptrace.c:1.1 --- /dev/null Wed Nov 2 00:12:00 2016 +++ src/sys/kern/sys_ptrace.c Wed Nov 2 00:11:59 2016 @@ -0,0 +1,296 @@ +/* $NetBSD: sys_ptrace.c,v 1.1 2016/11/02 00:11:59 pgoyette Exp $ */ + +/*- + * Copyright (c) 2008, 2009 The NetBSD Foundation, Inc. + * All rights reserved. + * + * This code is derived from software contributed to The NetBSD Foundation + * by Andrew Doran. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/*- + * Copyright (c) 1982, 1986, 1989, 1993 + * The Regents of the University of California. All rights reserved. + * (c) UNIX System Laboratories, Inc. + * All or some portions of this file are derived from material licensed + * to the University of California by American Telephone and Telegraph + * Co. or Unix System Laboratories, Inc. and are reproduced herein with + * the permission of UNIX System Laboratories, Inc. + * + * This code is derived from software contributed to Berkeley by + * Jan-Simon Pendry. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * from: @(#)sys_process.c 8.1 (Berkeley) 6/10/93 + */ + +/*- + * Copyright (c) 1993 Jan-Simon Pendry. + * Copyright (c) 1994 Christopher G. Demetriou. All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * Jan-Simon Pendry. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * from: @(#)sys_process.c 8.1 (Berkeley) 6/10/93 + */ + +/* + * References: + * (1) Bach's "The Design of the UNIX Operating System", + * (2) sys/miscfs/procfs from UCB's 4.4BSD-Lite distribution, + * (3) the "4.4BSD Programmer's Reference Manual" published + * by USENIX and O'Reilly & Associates. + * The 4.4BSD PRM does a reasonably good job of documenting what the various + * ptrace() requests should actually do, and its text is quoted several times + * in this file. + */ + +#include <sys/cdefs.h> +__KERNEL_RCSID(0, "$NetBSD: sys_ptrace.c,v 1.1 2016/11/02 00:11:59 pgoyette Exp $"); + +#ifdef _KERNEL_OPT +#include "opt_ptrace.h" +#endif + +#include <sys/param.h> +#include <sys/systm.h> +#include <sys/proc.h> +#include <sys/errno.h> +#include <sys/exec.h> +#include <sys/pax.h> +#include <sys/ptrace.h> +#include <sys/uio.h> +#include <sys/ras.h> +#include <sys/kmem.h> +#include <sys/kauth.h> +#include <sys/mount.h> +#include <sys/syscallargs.h> +#include <sys/syscallvar.h> +#include <sys/syscall.h> +#include <sys/module.h> + +#include <uvm/uvm_extern.h> + +#include <machine/reg.h> + +/* + * PTRACE methods + */ + +static int ptrace_copyinpiod(struct ptrace_io_desc *, const void *); +static void ptrace_copyoutpiod(const struct ptrace_io_desc *, void *); +static int ptrace_doregs(struct lwp *, struct lwp *, struct uio *); +static int ptrace_dofpregs(struct lwp *, struct lwp *, struct uio *); + +static int +ptrace_copyinpiod(struct ptrace_io_desc *piod, const void *addr) +{ + return copyin(addr, piod, sizeof(*piod)); +} + +static void +ptrace_copyoutpiod(const struct ptrace_io_desc *piod, void *addr) +{ + (void) copyout(piod, addr, sizeof(*piod)); +} + +int +ptrace_doregs(struct lwp *curl /*tracer*/, + struct lwp *l /*traced*/, + struct uio *uio) +{ +#if defined(PT_GETREGS) || defined(PT_SETREGS) + int error; + struct reg r; + char *kv; + int kl; + + if (uio->uio_offset < 0 || uio->uio_offset > (off_t)sizeof(r)) + return EINVAL; + + kl = sizeof(r); + kv = (char *)&r; + + kv += uio->uio_offset; + kl -= uio->uio_offset; + if ((size_t)kl > uio->uio_resid) + kl = uio->uio_resid; + + error = process_read_regs(l, &r); + if (error == 0) + error = uiomove(kv, kl, uio); + if (error == 0 && uio->uio_rw == UIO_WRITE) { + if (l->l_stat != LSSTOP) + error = EBUSY; + else + error = process_write_regs(l, &r); + } + + uio->uio_offset = 0; + return error; +#else + return EINVAL; +#endif +} + +int +ptrace_dofpregs(struct lwp *curl /*tracer*/, + struct lwp *l /*traced*/, + struct uio *uio) +{ +#if defined(PT_GETFPREGS) || defined(PT_SETFPREGS) + int error; + struct fpreg r; + char *kv; + size_t kl; + + if (uio->uio_offset < 0 || uio->uio_offset > (off_t)sizeof(r)) + return EINVAL; + + kl = sizeof(r); + kv = (char *)&r; + + kv += uio->uio_offset; + kl -= uio->uio_offset; + if (kl > uio->uio_resid) + kl = uio->uio_resid; + + error = process_read_fpregs(l, &r, &kl); + if (error == 0) + error = uiomove(kv, kl, uio); + if (error == 0 && uio->uio_rw == UIO_WRITE) { + if (l->l_stat != LSSTOP) + error = EBUSY; + else + error = process_write_fpregs(l, &r, kl); + } + uio->uio_offset = 0; + return error; +#else + return EINVAL; +#endif +} + +static struct ptrace_methods native_ptm = { + .ptm_copyinpiod = ptrace_copyinpiod, + .ptm_copyoutpiod = ptrace_copyoutpiod, + .ptm_doregs = ptrace_doregs, + .ptm_dofpregs = ptrace_dofpregs, +}; + +static const struct syscall_package ptrace_syscalls[] = { + { SYS_ptrace, 0, (sy_call_t *)sys_ptrace }, + { 0, 0, NULL }, +}; + +/* + * Process debugging system call. + */ +int +sys_ptrace(struct lwp *l, const struct sys_ptrace_args *uap, register_t *retval) +{ + /* { + syscallarg(int) req; + syscallarg(pid_t) pid; + syscallarg(void *) addr; + syscallarg(int) data; + } */ + + return do_ptrace(&native_ptm, l, SCARG(uap, req), SCARG(uap, pid), + SCARG(uap, addr), SCARG(uap, data), retval); +} + +#define DEPS "ptrace_common" + +MODULE(MODULE_CLASS_EXEC, ptrace, DEPS); + +static int +ptrace_modcmd(modcmd_t cmd, void *arg) +{ + int error; + + switch (cmd) { + case MODULE_CMD_INIT: + error = syscall_establish(&emul_netbsd, ptrace_syscalls); + break; + case MODULE_CMD_FINI: + error = syscall_disestablish(&emul_netbsd, ptrace_syscalls); + break; + default: + error = ENOTTY; + break; + } + return error; +} Index: src/sys/kern/sys_ptrace_common.c diff -u /dev/null src/sys/kern/sys_ptrace_common.c:1.1 --- /dev/null Wed Nov 2 00:12:00 2016 +++ src/sys/kern/sys_ptrace_common.c Wed Nov 2 00:11:59 2016 @@ -0,0 +1,1171 @@ +/* $NetBSD: sys_ptrace_common.c,v 1.1 2016/11/02 00:11:59 pgoyette Exp $ */ + +/*- + * Copyright (c) 2008, 2009 The NetBSD Foundation, Inc. + * All rights reserved. + * + * This code is derived from software contributed to The NetBSD Foundation + * by Andrew Doran. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/*- + * Copyright (c) 1982, 1986, 1989, 1993 + * The Regents of the University of California. All rights reserved. + * (c) UNIX System Laboratories, Inc. + * All or some portions of this file are derived from material licensed + * to the University of California by American Telephone and Telegraph + * Co. or Unix System Laboratories, Inc. and are reproduced herein with + * the permission of UNIX System Laboratories, Inc. + * + * This code is derived from software contributed to Berkeley by + * Jan-Simon Pendry. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * from: @(#)sys_process.c 8.1 (Berkeley) 6/10/93 + */ + +/*- + * Copyright (c) 1993 Jan-Simon Pendry. + * Copyright (c) 1994 Christopher G. Demetriou. All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * Jan-Simon Pendry. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * from: @(#)sys_process.c 8.1 (Berkeley) 6/10/93 + */ + +/* + * References: + * (1) Bach's "The Design of the UNIX Operating System", + * (2) sys/miscfs/procfs from UCB's 4.4BSD-Lite distribution, + * (3) the "4.4BSD Programmer's Reference Manual" published + * by USENIX and O'Reilly & Associates. + * The 4.4BSD PRM does a reasonably good job of documenting what the various + * ptrace() requests should actually do, and its text is quoted several times + * in this file. + */ + +#include <sys/cdefs.h> +__KERNEL_RCSID(0, "$NetBSD: sys_ptrace_common.c,v 1.1 2016/11/02 00:11:59 pgoyette Exp $"); + +#ifdef _KERNEL_OPT +#include "opt_ptrace.h" +#include "opt_ktrace.h" +#include "opt_pax.h" +#endif + +#include <sys/param.h> +#include <sys/systm.h> +#include <sys/proc.h> +#include <sys/errno.h> +#include <sys/exec.h> +#include <sys/pax.h> +#include <sys/ptrace.h> +#include <sys/uio.h> +#include <sys/ras.h> +#include <sys/kmem.h> +#include <sys/kauth.h> +#include <sys/mount.h> +#include <sys/syscallargs.h> +#include <sys/module.h> +#include <sys/condvar.h> +#include <sys/mutex.h> + +#include <uvm/uvm_extern.h> + +#include <machine/reg.h> + +#ifdef PTRACE + +# ifdef DEBUG +# define DPRINTF(a) uprintf a +# else +# define DPRINTF(a) +# endif + +static kauth_listener_t ptrace_listener; +static int process_auxv_offset(struct proc *, struct uio *); + +#if 0 +static int ptrace_cbref; +static kmutex_t ptrace_mtx; +static kcondvar_t ptrace_cv; +#endif + +static int +ptrace_listener_cb(kauth_cred_t cred, kauth_action_t action, void *cookie, + void *arg0, void *arg1, void *arg2, void *arg3) +{ + struct proc *p; + int result; + + result = KAUTH_RESULT_DEFER; + p = arg0; + +#if 0 + mutex_enter(&ptrace_mtx); + ptrace_cbref++; + mutex_exit(&ptrace_mtx); +#endif + if (action != KAUTH_PROCESS_PTRACE) + goto out; + + switch ((u_long)arg1) { + case PT_TRACE_ME: + case PT_ATTACH: + case PT_WRITE_I: + case PT_WRITE_D: + case PT_READ_I: + case PT_READ_D: + case PT_IO: +#ifdef PT_GETREGS + case PT_GETREGS: +#endif +#ifdef PT_SETREGS + case PT_SETREGS: +#endif +#ifdef PT_GETFPREGS + case PT_GETFPREGS: +#endif +#ifdef PT_SETFPREGS + case PT_SETFPREGS: +#endif + case PT_SET_EVENT_MASK: + case PT_GET_EVENT_MASK: + case PT_GET_PROCESS_STATE: +#ifdef __HAVE_PTRACE_MACHDEP + PTRACE_MACHDEP_REQUEST_CASES +#endif + if (kauth_cred_getuid(cred) != kauth_cred_getuid(p->p_cred) || + ISSET(p->p_flag, PK_SUGID)) { + break; + } + + result = KAUTH_RESULT_ALLOW; + + break; + +#ifdef PT_STEP + case PT_STEP: +#endif + case PT_CONTINUE: + case PT_KILL: + case PT_DETACH: + case PT_LWPINFO: + case PT_SYSCALL: + case PT_SYSCALLEMU: + case PT_DUMPCORE: + result = KAUTH_RESULT_ALLOW; + break; + + default: + break; + } + + out: +#if 0 + mutex_enter(&ptrace_mtx); + if (--ptrace_cbref == 0) + cv_broadcast(&ptrace_cv); + mutex_exit(&ptrace_mtx); +#endif + + return result; +} + +int +ptrace_init(void) +{ + +#if 0 + mutex_init(&ptrace_mtx, MUTEX_DEFAULT, IPL_NONE); + cv_init(&ptrace_cv, "ptracecb"); + ptrace_cbref = 0; +#endif + ptrace_listener = kauth_listen_scope(KAUTH_SCOPE_PROCESS, + ptrace_listener_cb, NULL); + return 0; +} + +int +ptrace_fini(void) +{ + + kauth_unlisten_scope(ptrace_listener); + +#if 0 + /* Make sure no-one is executing our kauth listener */ + + mutex_enter(&ptrace_mtx); + while (ptrace_cbref != 0) + cv_wait(&ptrace_cv, &ptrace_mtx); + mutex_exit(&ptrace_mtx); + mutex_destroy(&ptrace_mtx); + cv_destroy(&ptrace_cv); +#endif + + return 0; +} + +int +do_ptrace(struct ptrace_methods *ptm, struct lwp *l, int req, pid_t pid, + void *addr, int data, register_t *retval) +{ + struct proc *p = l->l_proc; + struct lwp *lt; +#ifdef PT_STEP + struct lwp *lt2; +#endif + struct proc *t; /* target process */ + struct uio uio; + struct iovec iov; + struct ptrace_io_desc piod; + struct ptrace_event pe; + struct ptrace_state ps; + struct ptrace_lwpinfo pl; + struct vmspace *vm; + int error, write, tmp, pheld; + int signo = 0; + int resume_all; + ksiginfo_t ksi; + char *path; + int len = 0; + error = 0; + + /* + * If attaching or detaching, we need to get a write hold on the + * proclist lock so that we can re-parent the target process. + */ + mutex_enter(proc_lock); + + /* "A foolish consistency..." XXX */ + if (req == PT_TRACE_ME) { + t = p; + mutex_enter(t->p_lock); + } else { + /* Find the process we're supposed to be operating on. */ + t = proc_find(pid); + if (t == NULL) { + mutex_exit(proc_lock); + return ESRCH; + } + + /* XXX-elad */ + mutex_enter(t->p_lock); + error = kauth_authorize_process(l->l_cred, KAUTH_PROCESS_CANSEE, + t, KAUTH_ARG(KAUTH_REQ_PROCESS_CANSEE_ENTRY), NULL, NULL); + if (error) { + mutex_exit(proc_lock); + mutex_exit(t->p_lock); + return ESRCH; + } + } + + /* + * Grab a reference on the process to prevent it from execing or + * exiting. + */ + if (!rw_tryenter(&t->p_reflock, RW_READER)) { + mutex_exit(proc_lock); + mutex_exit(t->p_lock); + return EBUSY; + } + + /* Make sure we can operate on it. */ + switch (req) { + case PT_TRACE_ME: + /* Saying that you're being traced is always legal. */ + break; + + case PT_ATTACH: + /* + * You can't attach to a process if: + * (1) it's the process that's doing the attaching, + */ + if (t->p_pid == p->p_pid) { + error = EINVAL; + break; + } + + /* + * (2) it's a system process + */ + if (t->p_flag & PK_SYSTEM) { + error = EPERM; + break; + } + + /* + * (3) it's already being traced, or + */ + if (ISSET(t->p_slflag, PSL_TRACED)) { + error = EBUSY; + break; + } + + /* + * (4) the tracer is chrooted, and its root directory is + * not at or above the root directory of the tracee + */ + mutex_exit(t->p_lock); /* XXXSMP */ + tmp = proc_isunder(t, l); + mutex_enter(t->p_lock); /* XXXSMP */ + if (!tmp) { + error = EPERM; + break; + } + break; + + case PT_READ_I: + case PT_READ_D: + case PT_WRITE_I: + case PT_WRITE_D: + case PT_IO: +#ifdef PT_GETREGS + case PT_GETREGS: +#endif +#ifdef PT_SETREGS + case PT_SETREGS: +#endif +#ifdef PT_GETFPREGS + case PT_GETFPREGS: +#endif +#ifdef PT_SETFPREGS + case PT_SETFPREGS: +#endif +#ifdef __HAVE_PTRACE_MACHDEP + PTRACE_MACHDEP_REQUEST_CASES +#endif + /* + * You can't read/write the memory or registers of a process + * if the tracer is chrooted, and its root directory is not at + * or above the root directory of the tracee. + */ + mutex_exit(t->p_lock); /* XXXSMP */ + tmp = proc_isunder(t, l); + mutex_enter(t->p_lock); /* XXXSMP */ + if (!tmp) { + error = EPERM; + break; + } + /*FALLTHROUGH*/ + + case PT_CONTINUE: + case PT_KILL: + case PT_DETACH: + case PT_LWPINFO: + case PT_SYSCALL: + case PT_SYSCALLEMU: + case PT_DUMPCORE: +#ifdef PT_STEP + case PT_STEP: +#endif + case PT_SET_EVENT_MASK: + case PT_GET_EVENT_MASK: + case PT_GET_PROCESS_STATE: + /* + * You can't do what you want to the process if: + * (1) It's not being traced at all, + */ + if (!ISSET(t->p_slflag, PSL_TRACED)) { + error = EPERM; + break; + } + + /* + * (2) it's being traced by procfs (which has + * different signal delivery semantics), + */ + if (ISSET(t->p_slflag, PSL_FSTRACE)) { + DPRINTF(("file system traced\n")); + error = EBUSY; + break; + } + + /* + * (3) it's not being traced by _you_, or + */ + if (t->p_pptr != p) { + DPRINTF(("parent %d != %d\n", t->p_pptr->p_pid, + p->p_pid)); + error = EBUSY; + break; + } + + /* + * (4) it's not currently stopped. + */ + if (t->p_stat != SSTOP || !t->p_waited /* XXXSMP */) { + DPRINTF(("stat %d flag %d\n", t->p_stat, + !t->p_waited)); + error = EBUSY; + break; + } + break; + + default: /* It was not a legal request. */ + error = EINVAL; + break; + } + + if (error == 0) { + error = kauth_authorize_process(l->l_cred, + KAUTH_PROCESS_PTRACE, t, KAUTH_ARG(req), + NULL, NULL); + } + if (error == 0) { + lt = lwp_find_first(t); + if (lt == NULL) + error = ESRCH; + } + + if (error != 0) { + mutex_exit(proc_lock); + mutex_exit(t->p_lock); + rw_exit(&t->p_reflock); + return error; + } + + /* Do single-step fixup if needed. */ + FIX_SSTEP(t); + KASSERT(lt != NULL); + lwp_addref(lt); + + /* + * Which locks do we need held? XXX Ugly. + */ + switch (req) { +#ifdef PT_STEP + case PT_STEP: +#endif + case PT_CONTINUE: + case PT_DETACH: + case PT_KILL: + case PT_SYSCALL: + case PT_SYSCALLEMU: + case PT_ATTACH: + case PT_TRACE_ME: + pheld = 1; + break; + default: + mutex_exit(proc_lock); + mutex_exit(t->p_lock); + pheld = 0; + break; + } + + /* Now do the operation. */ + write = 0; + *retval = 0; + tmp = 0; + resume_all = 1; + + switch (req) { + case PT_TRACE_ME: + /* Just set the trace flag. */ + SET(t->p_slflag, PSL_TRACED); + t->p_opptr = t->p_pptr; + break; + + case PT_WRITE_I: /* XXX no separate I and D spaces */ + case PT_WRITE_D: +#if defined(__HAVE_RAS) + /* + * Can't write to a RAS + */ + if (ras_lookup(t, addr) != (void *)-1) { + error = EACCES; + break; + } +#endif + write = 1; + tmp = data; + /* FALLTHROUGH */ + + case PT_READ_I: /* XXX no separate I and D spaces */ + case PT_READ_D: + /* write = 0 done above. */ + iov.iov_base = (void *)&tmp; + iov.iov_len = sizeof(tmp); + uio.uio_iov = &iov; + uio.uio_iovcnt = 1; + uio.uio_offset = (off_t)(unsigned long)addr; + uio.uio_resid = sizeof(tmp); + uio.uio_rw = write ? UIO_WRITE : UIO_READ; + UIO_SETUP_SYSSPACE(&uio); + + error = process_domem(l, lt, &uio); + if (!write) + *retval = tmp; + break; + + case PT_IO: + error = ptm->ptm_copyinpiod(&piod, addr); + if (error) + break; + + iov.iov_base = piod.piod_addr; + iov.iov_len = piod.piod_len; + uio.uio_iov = &iov; + uio.uio_iovcnt = 1; + uio.uio_offset = (off_t)(unsigned long)piod.piod_offs; + uio.uio_resid = piod.piod_len; + + switch (piod.piod_op) { + case PIOD_READ_D: + case PIOD_READ_I: + uio.uio_rw = UIO_READ; + break; + case PIOD_WRITE_D: + case PIOD_WRITE_I: + /* + * Can't write to a RAS + */ + if (ras_lookup(t, addr) != (void *)-1) { + return EACCES; + } + uio.uio_rw = UIO_WRITE; + break; + case PIOD_READ_AUXV: + req = PT_READ_D; + uio.uio_rw = UIO_READ; + tmp = t->p_execsw->es_arglen * PROC_PTRSZ(t); + if (uio.uio_offset > tmp) + return EIO; + if (uio.uio_resid > tmp - uio.uio_offset) + uio.uio_resid = tmp - uio.uio_offset; + piod.piod_len = iov.iov_len = uio.uio_resid; + error = process_auxv_offset(t, &uio); + if (error) + return error; + break; + default: + error = EINVAL; + break; + } + if (error) + break; + error = proc_vmspace_getref(l->l_proc, &vm); + if (error) + break; + uio.uio_vmspace = vm; + + error = process_domem(l, lt, &uio); + piod.piod_len -= uio.uio_resid; + (void) ptm->ptm_copyoutpiod(&piod, addr); + + uvmspace_free(vm); + break; + + case PT_DUMPCORE: + if ((path = addr) != NULL) { + char *dst; + len = data; + + if (len < 0 || len >= MAXPATHLEN) { + error = EINVAL; + break; + } + dst = kmem_alloc(len + 1, KM_SLEEP); + if ((error = copyin(path, dst, len)) != 0) { + kmem_free(dst, len + 1); + break; + } + path = dst; + path[len] = '\0'; + } + error = (*coredump_vec)(lt, path); + if (path) + kmem_free(path, len + 1); + break; + +#ifdef PT_STEP + case PT_STEP: + /* + * From the 4.4BSD PRM: + * "Execution continues as in request PT_CONTINUE; however + * as soon as possible after execution of at least one + * instruction, execution stops again. [ ... ]" + */ +#endif + case PT_CONTINUE: + case PT_SYSCALL: + case PT_DETACH: + if (req == PT_SYSCALL) { + if (!ISSET(t->p_slflag, PSL_SYSCALL)) { + SET(t->p_slflag, PSL_SYSCALL); +#ifdef __HAVE_SYSCALL_INTERN + (*t->p_emul->e_syscall_intern)(t); +#endif + } + } else { + if (ISSET(t->p_slflag, PSL_SYSCALL)) { + CLR(t->p_slflag, PSL_SYSCALL); +#ifdef __HAVE_SYSCALL_INTERN + (*t->p_emul->e_syscall_intern)(t); +#endif + } + } + t->p_trace_enabled = trace_is_enabled(t); + + /* + * Pick up the LWPID, if supplied. There are two cases: + * data < 0 : step or continue single thread, lwp = -data + * data > 0 in PT_STEP : step this thread, continue others + * For operations other than PT_STEP, data > 0 means + * data is the signo to deliver to the process. + */ + tmp = data; + if (tmp >= 0) { +#ifdef PT_STEP + if (req == PT_STEP) + signo = 0; + else +#endif + { + signo = tmp; + tmp = 0; /* don't search for LWP */ + } + } else + tmp = -tmp; + + if (tmp > 0) { + if (req == PT_DETACH) { + error = EINVAL; + break; + } + lwp_delref2 (lt); + lt = lwp_find(t, tmp); + if (lt == NULL) { + error = ESRCH; + break; + } + lwp_addref(lt); + resume_all = 0; + signo = 0; + } + + /* + * From the 4.4BSD PRM: + * "The data argument is taken as a signal number and the + * child's execution continues at location addr as if it + * incurred that signal. Normally the signal number will + * be either 0 to indicate that the signal that caused the + * stop should be ignored, or that value fetched out of + * the process's image indicating which signal caused + * the stop. If addr is (int *)1 then execution continues + * from where it stopped." + */ + + /* Check that the data is a valid signal number or zero. */ + if (signo < 0 || signo >= NSIG) { + error = EINVAL; + break; + } + + /* If the address parameter is not (int *)1, set the pc. */ + if ((int *)addr != (int *)1) { + error = process_set_pc(lt, addr); + if (error != 0) + break; + } +#ifdef PT_STEP + /* + * Arrange for a single-step, if that's requested and possible. + * More precisely, set the single step status as requested for + * the requested thread, and clear it for other threads. + */ + LIST_FOREACH(lt2, &t->p_lwps, l_sibling) { + if (lt != lt2) { + lwp_lock(lt2); + process_sstep(lt2, 0); + lwp_unlock(lt2); + } + } + error = process_sstep(lt, req == PT_STEP); + if (error) + break; +#endif + if (req == PT_DETACH) { + CLR(t->p_slflag, PSL_TRACED|PSL_FSTRACE|PSL_SYSCALL); + + /* give process back to original parent or init */ + if (t->p_opptr != t->p_pptr) { + struct proc *pp = t->p_opptr; + proc_reparent(t, pp ? pp : initproc); + } + + /* not being traced any more */ + t->p_opptr = NULL; + } + sendsig: + t->p_fpid = 0; + /* Finally, deliver the requested signal (or none). */ + if (t->p_stat == SSTOP) { + /* + * Unstop the process. If it needs to take a + * signal, make all efforts to ensure that at + * an LWP runs to see it. + */ + t->p_xsig = signo; + if (resume_all) + proc_unstop(t); + else + lwp_unstop(lt); + } else if (signo != 0) { + KSI_INIT_EMPTY(&ksi); + ksi.ksi_signo = signo; + kpsignal2(t, &ksi); + } + break; + + case PT_SYSCALLEMU: + if (!ISSET(t->p_slflag, PSL_SYSCALL) || t->p_stat != SSTOP) { + error = EINVAL; + break; + } + SET(t->p_slflag, PSL_SYSCALLEMU); + break; + + case PT_KILL: + /* just send the process a KILL signal. */ + signo = SIGKILL; + goto sendsig; /* in PT_CONTINUE, above. */ + + case PT_ATTACH: + /* + * Go ahead and set the trace flag. + * Save the old parent (it's reset in + * _DETACH, and also in kern_exit.c:wait4() + * Reparent the process so that the tracing + * proc gets to see all the action. + * Stop the target. + */ + t->p_opptr = t->p_pptr; + if (t->p_pptr != p) { + struct proc *parent = t->p_pptr; + + if (parent->p_lock < t->p_lock) { + if (!mutex_tryenter(parent->p_lock)) { + mutex_exit(t->p_lock); + mutex_enter(parent->p_lock); + mutex_enter(t->p_lock); + } + } else if (parent->p_lock > t->p_lock) { + mutex_enter(parent->p_lock); + } + parent->p_slflag |= PSL_CHTRACED; + proc_reparent(t, p); + if (parent->p_lock != t->p_lock) + mutex_exit(parent->p_lock); + } + SET(t->p_slflag, PSL_TRACED); + signo = SIGSTOP; + goto sendsig; + + case PT_GET_EVENT_MASK: + if (data != sizeof(pe)) { + DPRINTF(("ptrace(%d): %d != %zu\n", req, + data, sizeof(pe))); + error = EINVAL; + break; + } + memset(&pe, 0, sizeof(pe)); + pe.pe_set_event = ISSET(t->p_slflag, PSL_TRACEFORK) ? + PTRACE_FORK : 0; + error = copyout(&pe, addr, sizeof(pe)); + break; + + case PT_SET_EVENT_MASK: + if (data != sizeof(pe)) { + DPRINTF(("ptrace(%d): %d != %zu\n", req, data, + sizeof(pe))); + error = EINVAL; + break; + } + if ((error = copyin(addr, &pe, sizeof(pe))) != 0) + return error; + if (pe.pe_set_event & PTRACE_FORK) + SET(t->p_slflag, PSL_TRACEFORK); + else + CLR(t->p_slflag, PSL_TRACEFORK); + break; + + case PT_GET_PROCESS_STATE: + if (data != sizeof(ps)) { + DPRINTF(("ptrace(%d): %d != %zu\n", req, data, + sizeof(ps))); + error = EINVAL; + break; + } + memset(&ps, 0, sizeof(ps)); + if (t->p_fpid) { + ps.pe_report_event = PTRACE_FORK; + ps.pe_other_pid = t->p_fpid; + } + error = copyout(&ps, addr, sizeof(ps)); + break; + + case PT_LWPINFO: + if (data != sizeof(pl)) { + DPRINTF(("ptrace(%d): %d != %zu\n", req, data, + sizeof(pl))); + error = EINVAL; + break; + } + error = copyin(addr, &pl, sizeof(pl)); + if (error) + break; + tmp = pl.pl_lwpid; + lwp_delref(lt); + mutex_enter(t->p_lock); + if (tmp == 0) + lt = lwp_find_first(t); + else { + lt = lwp_find(t, tmp); + if (lt == NULL) { + mutex_exit(t->p_lock); + error = ESRCH; + break; + } + lt = LIST_NEXT(lt, l_sibling); + } + while (lt != NULL && !lwp_alive(lt)) + lt = LIST_NEXT(lt, l_sibling); + pl.pl_lwpid = 0; + pl.pl_event = 0; + if (lt) { + lwp_addref(lt); + pl.pl_lwpid = lt->l_lid; + if (lt->l_lid == t->p_sigctx.ps_lwp) + pl.pl_event = PL_EVENT_SIGNAL; + } + mutex_exit(t->p_lock); + + error = copyout(&pl, addr, sizeof(pl)); + break; + +#ifdef PT_SETREGS + case PT_SETREGS: + write = 1; +#endif +#ifdef PT_GETREGS + case PT_GETREGS: + /* write = 0 done above. */ +#endif +#if defined(PT_SETREGS) || defined(PT_GETREGS) + tmp = data; + if (tmp != 0 && t->p_nlwps > 1) { + lwp_delref(lt); + mutex_enter(t->p_lock); + lt = lwp_find(t, tmp); + if (lt == NULL) { + mutex_exit(t->p_lock); + error = ESRCH; + break; + } + lwp_addref(lt); + mutex_exit(t->p_lock); + } + if (!process_validregs(lt)) + error = EINVAL; + else { + error = proc_vmspace_getref(p, &vm); + if (error) + break; + iov.iov_base = addr; + iov.iov_len = PROC_REGSZ(p); + uio.uio_iov = &iov; + uio.uio_iovcnt = 1; + uio.uio_offset = 0; + uio.uio_resid = iov.iov_len; + uio.uio_rw = write ? UIO_WRITE : UIO_READ; + uio.uio_vmspace = vm; + + error = ptm->ptm_doregs(l, lt, &uio); + uvmspace_free(vm); + } + break; +#endif + +#ifdef PT_SETFPREGS + case PT_SETFPREGS: + write = 1; +#endif +#ifdef PT_GETFPREGS + case PT_GETFPREGS: + /* write = 0 done above. */ +#endif +#if defined(PT_SETFPREGS) || defined(PT_GETFPREGS) + tmp = data; + if (tmp != 0 && t->p_nlwps > 1) { + lwp_delref(lt); + mutex_enter(t->p_lock); + lt = lwp_find(t, tmp); + if (lt == NULL) { + mutex_exit(t->p_lock); + error = ESRCH; + break; + } + lwp_addref(lt); + mutex_exit(t->p_lock); + } + if (!process_validfpregs(lt)) + error = EINVAL; + else { + error = proc_vmspace_getref(p, &vm); + if (error) + break; + iov.iov_base = addr; + iov.iov_len = PROC_FPREGSZ(p); + uio.uio_iov = &iov; + uio.uio_iovcnt = 1; + uio.uio_offset = 0; + uio.uio_resid = iov.iov_len; + uio.uio_rw = write ? UIO_WRITE : UIO_READ; + uio.uio_vmspace = vm; + + error = ptm->ptm_dofpregs(l, lt, &uio); + uvmspace_free(vm); + } + break; +#endif + +#ifdef __HAVE_PTRACE_MACHDEP + PTRACE_MACHDEP_REQUEST_CASES + error = ptrace_machdep_dorequest(l, lt, req, addr, data); + break; +#endif + } + + if (pheld) { + mutex_exit(t->p_lock); + mutex_exit(proc_lock); + } + if (lt != NULL) + lwp_delref(lt); + rw_exit(&t->p_reflock); + + return error; +} + +int +process_doregs(struct lwp *curl /*tracer*/, + struct lwp *l /*traced*/, + struct uio *uio) +{ +#if defined(PT_GETREGS) || defined(PT_SETREGS) + int error; + struct reg r; + char *kv; + int kl; + + if (uio->uio_offset < 0 || uio->uio_offset > (off_t)sizeof(r)) + return EINVAL; + + kl = sizeof(r); + kv = (char *)&r; + + kv += uio->uio_offset; + kl -= uio->uio_offset; + if ((size_t)kl > uio->uio_resid) + kl = uio->uio_resid; + + error = process_read_regs(l, &r); + if (error == 0) + error = uiomove(kv, kl, uio); + if (error == 0 && uio->uio_rw == UIO_WRITE) { + if (l->l_stat != LSSTOP) + error = EBUSY; + else + error = process_write_regs(l, &r); + } + + uio->uio_offset = 0; + return error; +#else + return EINVAL; +#endif +} + +int +process_validregs(struct lwp *l) +{ + +#if defined(PT_SETREGS) || defined(PT_GETREGS) + return (l->l_flag & LW_SYSTEM) == 0; +#else + return 0; +#endif +} + +int +process_dofpregs(struct lwp *curl /*tracer*/, + struct lwp *l /*traced*/, + struct uio *uio) +{ +#if defined(PT_GETFPREGS) || defined(PT_SETFPREGS) + int error; + struct fpreg r; + char *kv; + size_t kl; + + if (uio->uio_offset < 0 || uio->uio_offset > (off_t)sizeof(r)) + return EINVAL; + + kl = sizeof(r); + kv = (char *)&r; + + kv += uio->uio_offset; + kl -= uio->uio_offset; + if (kl > uio->uio_resid) + kl = uio->uio_resid; + + error = process_read_fpregs(l, &r, &kl); + if (error == 0) + error = uiomove(kv, kl, uio); + if (error == 0 && uio->uio_rw == UIO_WRITE) { + if (l->l_stat != LSSTOP) + error = EBUSY; + else + error = process_write_fpregs(l, &r, kl); + } + uio->uio_offset = 0; + return error; +#else + return EINVAL; +#endif +} + +int +process_validfpregs(struct lwp *l) +{ + +#if defined(PT_SETFPREGS) || defined(PT_GETFPREGS) + return (l->l_flag & LW_SYSTEM) == 0; +#else + return 0; +#endif +} + +static int +process_auxv_offset(struct proc *p, struct uio *uio) +{ + struct ps_strings pss; + int error; + off_t off = (off_t)p->p_psstrp; + + if ((error = copyin_psstrings(p, &pss)) != 0) + return error; + + if (pss.ps_envstr == NULL) + return EIO; + + uio->uio_offset += (off_t)(vaddr_t)(pss.ps_envstr + pss.ps_nenvstr + 1); +#ifdef __MACHINE_STACK_GROWS_UP + if (uio->uio_offset < off) + return EIO; +#else + if (uio->uio_offset > off) + return EIO; + if ((uio->uio_offset + uio->uio_resid) > off) + uio->uio_resid = off - uio->uio_offset; +#endif + return 0; +} +#endif /* PTRACE */ + +MODULE(MODULE_CLASS_EXEC, ptrace_common, ""); + +static int +ptrace_common_modcmd(modcmd_t cmd, void *arg) +{ + int error; + + switch (cmd) { + case MODULE_CMD_INIT: + error = ptrace_init(); + break; + case MODULE_CMD_FINI: + error = ptrace_fini(); + break; + default: + ptrace_hooks(); + error = ENOTTY; + break; + } + return error; +} + Index: src/sys/modules/ptrace/Makefile diff -u /dev/null src/sys/modules/ptrace/Makefile:1.1 --- /dev/null Wed Nov 2 00:12:00 2016 +++ src/sys/modules/ptrace/Makefile Wed Nov 2 00:12:00 2016 @@ -0,0 +1,12 @@ +# $NetBSD: Makefile,v 1.1 2016/11/02 00:12:00 pgoyette Exp $ +# +.include "../Makefile.inc" + +.PATH: ${S}/kern + +CPPFLAGS+= -DPTRACE + +KMOD= ptrace +SRCS= sys_ptrace.c + +.include <bsd.kmodule.mk> Index: src/sys/modules/ptrace_common/Makefile diff -u /dev/null src/sys/modules/ptrace_common/Makefile:1.1 --- /dev/null Wed Nov 2 00:12:00 2016 +++ src/sys/modules/ptrace_common/Makefile Wed Nov 2 00:12:00 2016 @@ -0,0 +1,12 @@ +# $NetBSD: Makefile,v 1.1 2016/11/02 00:12:00 pgoyette Exp $ +# +.include "../Makefile.inc" + +.PATH: ${S}/kern + +CPPFLAGS+= -DPTRACE + +KMOD= ptrace_common +SRCS= sys_ptrace_common.c + +.include <bsd.kmodule.mk>