Module Name: src Committed By: martin Date: Thu Apr 12 13:42:49 UTC 2018
Modified Files: src/bin/ps [netbsd-8]: ps.1 src/doc [netbsd-8]: TODO.ptrace src/sbin/mount_procfs [netbsd-8]: mount_procfs.8 src/share/man/man9 [netbsd-8]: kauth.9 src/sys/compat/linux/arch/arm [netbsd-8]: linux_ptrace.c src/sys/compat/linux/arch/i386 [netbsd-8]: linux_ptrace.c src/sys/compat/linux/arch/powerpc [netbsd-8]: linux_ptrace.c src/sys/compat/netbsd32 [netbsd-8]: netbsd32.h netbsd32_ptrace.c netbsd32_signal.c src/sys/kern [netbsd-8]: kern_exit.c kern_proc.c kern_sig.c sys_ptrace.c sys_ptrace_common.c src/sys/miscfs/procfs [netbsd-8]: files.procfs procfs.h procfs_subr.c procfs_vfsops.c procfs_vnops.c src/sys/modules/procfs [netbsd-8]: Makefile src/sys/sys [netbsd-8]: kauth.h proc.h ptrace.h sysctl.h Removed Files: src/sys/miscfs/procfs [netbsd-8]: procfs_ctl.c Log Message: Pull up following revision(s) (requested by kamil in ticket #713): sys/modules/procfs/Makefile: revision 1.4 sys/miscfs/procfs/procfs_vfsops.c: revision 1.98 bin/ps/ps.1: revision 1.108 sys/compat/linux/arch/i386/linux_ptrace.c: revision 1.32 sys/miscfs/procfs/procfs_vnops.c: revision 1.198 sys/kern/sys_ptrace_common.c: revision 1.23 sys/kern/sys_ptrace_common.c: revision 1.24 sbin/mount_procfs/mount_procfs.8: revision 1.36 sys/kern/sys_ptrace_common.c: revision 1.25 sys/kern/sys_ptrace.c: revision 1.5 sys/compat/linux/arch/powerpc/linux_ptrace.c: revision 1.30 sys/sys/proc.h: revision 1.342 sys/kern/sys_ptrace_common.c: revision 1.26 sys/miscfs/procfs/procfs_ctl.c: file removal sys/kern/sys_ptrace_common.c: revision 1.27 sys/miscfs/procfs/procfs_subr.c: revision 1.109 sys/kern/sys_ptrace_common.c: revision 1.28 sys/secmodel/extensions/secmodel_extensions.c: revision 1.8 sys/kern/sys_ptrace_common.c: revision 1.29 sys/sys/ptrace.h: revision 1.62 sys/compat/netbsd32/netbsd32_signal.c: revision 1.45 share/man/man9/kauth.9: revision 1.109 sys/miscfs/procfs/files.procfs: revision 1.12 sys/compat/netbsd32/netbsd32.h: revision 1.115 sys/miscfs/procfs/procfs.h: revision 1.72 sys/compat/netbsd32/netbsd32_ptrace.c: revision 1.5 sys/kern/kern_sig.c: revision 1.337 sys/sys/kauth.h: revision 1.75 sys/sys/sysctl.h: revision 1.224 sys/kern/sys_ptrace_common.c: revision 1.30 sys/kern/sys_ptrace_common.c: revision 1.31 sys/kern/sys_ptrace_common.c: revision 1.32 sys/kern/sys_ptrace_common.c: revision 1.33 sys/compat/linux/arch/arm/linux_ptrace.c: revision 1.20 sys/kern/sys_ptrace_common.c: revision 1.34 sys/kern/sys_ptrace_common.c: revision 1.36 sys/kern/kern_proc.c: revision 1.207 sys/kern/kern_exit.c: revision 1.269 doc/TODO.ptrace: revision 1.29 Make {s,g}et{db,fp,}regs work again for PK_32 processes XXX: pullup-8 add disgusting magic to handle compat_netbsd32 as a module. use process_*reg32 instead of struct *reg32. Remove the filesystem tracing feature This is a legacy interface from 4.4BSD, and it was introduced to overcome shortcomings of ptrace(2) at that time, which are no longer relevant (performance). Today /proc/#/ctl offers a narrow subset of ptrace(2) commands and is not applicable for modern applications use beyond simplistic tracing scenarios. This removal will simplify kernel internals. Users will still be able to use all the other /proc files. This change won't affect other procfs files neither Linux compat features within mount_procfs(8). /proc/#/ctl isn't available on Linux. Remove: - /proc/#/ctl from mount_procfs(8) - P_FSTRACE note from the documentation of ps(1) - /proc/#/ctl and filesystem tracing documentation from mount_procfs(8) - KAUTH_REQ_PROCESS_PROCFS_CTL documentation from kauth(9) - source code file miscfs/procfs/procfs_ctl.c - PFSctl and procfs_doctl() from sys/miscfs/procfs/procfs.h - KAUTH_REQ_PROCESS_PROCFS_CTL from sys/sys/kauth.h - PSL_FSTRACE (0x00010000) from sys/sys/proc.h - P_FSTRACE (0x00010000) from sys/sys/sysctl.h Reduce code complexity after removal of this functionality. Update TODO.ptrace accordingly: remove two entries about /proc tracing. Do not keep legacy notes as comments in the headers about removed PSL_FSTRACE / P_FSTRACE, as this interface had little number of users (close or equal to zero). Proposed on tech-kern@. All filesystem tracing utility users are encouraged to switch to ptrace(2). Sponsored by <The NetBSD Foundation> untangle the mess: - factor out common code - break each ptrace subcall to its own sub-function .. more to come ... - reduce ifdef ugliness by moving it up top. - factor out PT_IO and make PT_{READ,WRITE}_{I,D} use it - factor out PT_DUMPCORE - factor out sendsig code .. more to come ... handle siginfo requests for ptrace32 ptrace: Partially undo PT_{READ,WRITE}_{I,D} and unbreak these commands The refactored code did not work and was generating EFAULT. Sponsored by <The NetBSD Foundation> Merge the code back; the problem was that since we are reading/writing to a kernel address for PT_{READ,WRITE}_{I,D} we need the kernel vmspace. provide separate read and write functions to accomodate register functions that need a size argument. don't ignore error from copyout_piod Use the proper process (the tracee) to get information about lwps and registers and the tracer for vmspace. Add new sysctl(3) entry: security.models.extensions.user_set_dbregs Model this new sysctl(3) entry after "user_set_cpu_affinity" in the same level of sysctl(3) switches. Allow to read unconditionally Debug Registers (no change here). This is convenient as even if a user of a debugger does not use hardware assisted watchpoints/breakpoints, a debugger can still prompt these values to store in an internal cache with context of registers. Reading them should have no security concerns. Add a paranoid MI switch that prohibits by default setting these registers by a regular user (non-superuser). Make this switch disabled by default. There are enough reserved bits out there to allow using them unconditionally on hardened hosts. Features shipped with Debug Registers are optional features in debuggers. There is no reduction in elementary functionality. Reviewed by <christos> Sponsored by <The NetBSD Foundation> To generate a diff of this commit: cvs rdiff -u -r1.106 -r1.106.6.1 src/bin/ps/ps.1 cvs rdiff -u -r1.28 -r1.28.4.1 src/doc/TODO.ptrace cvs rdiff -u -r1.34 -r1.34.38.1 src/sbin/mount_procfs/mount_procfs.8 cvs rdiff -u -r1.107 -r1.107.4.1 src/share/man/man9/kauth.9 cvs rdiff -u -r1.19 -r1.19.10.1 src/sys/compat/linux/arch/arm/linux_ptrace.c cvs rdiff -u -r1.31 -r1.31.10.1 src/sys/compat/linux/arch/i386/linux_ptrace.c cvs rdiff -u -r1.29 -r1.29.10.1 \ src/sys/compat/linux/arch/powerpc/linux_ptrace.c cvs rdiff -u -r1.114 -r1.114.8.1 src/sys/compat/netbsd32/netbsd32.h cvs rdiff -u -r1.4 -r1.4.6.1 src/sys/compat/netbsd32/netbsd32_ptrace.c cvs rdiff -u -r1.43 -r1.43.8.1 src/sys/compat/netbsd32/netbsd32_signal.c cvs rdiff -u -r1.268 -r1.268.8.1 src/sys/kern/kern_exit.c cvs rdiff -u -r1.206.6.2 -r1.206.6.3 src/sys/kern/kern_proc.c cvs rdiff -u -r1.336.4.1 -r1.336.4.2 src/sys/kern/kern_sig.c cvs rdiff -u -r1.4 -r1.4.6.1 src/sys/kern/sys_ptrace.c cvs rdiff -u -r1.22.2.1 -r1.22.2.2 src/sys/kern/sys_ptrace_common.c cvs rdiff -u -r1.11 -r1.11.6.1 src/sys/miscfs/procfs/files.procfs cvs rdiff -u -r1.71 -r1.71.6.1 src/sys/miscfs/procfs/procfs.h cvs rdiff -u -r1.48 -r0 src/sys/miscfs/procfs/procfs_ctl.c cvs rdiff -u -r1.108 -r1.108.6.1 src/sys/miscfs/procfs/procfs_subr.c cvs rdiff -u -r1.97 -r1.97.6.1 src/sys/miscfs/procfs/procfs_vfsops.c cvs rdiff -u -r1.197.2.1 -r1.197.2.2 src/sys/miscfs/procfs/procfs_vnops.c cvs rdiff -u -r1.3 -r1.3.6.1 src/sys/modules/procfs/Makefile cvs rdiff -u -r1.73.10.1 -r1.73.10.2 src/sys/sys/kauth.h cvs rdiff -u -r1.340 -r1.340.6.1 src/sys/sys/proc.h cvs rdiff -u -r1.60.6.1 -r1.60.6.2 src/sys/sys/ptrace.h cvs rdiff -u -r1.223 -r1.223.6.1 src/sys/sys/sysctl.h Please note that diffs are not public domain; they are subject to the copyright notices on the relevant files.
Modified files: Index: src/bin/ps/ps.1 diff -u src/bin/ps/ps.1:1.106 src/bin/ps/ps.1:1.106.6.1 --- src/bin/ps/ps.1:1.106 Fri Dec 2 21:59:03 2016 +++ src/bin/ps/ps.1 Thu Apr 12 13:42:48 2018 @@ -1,4 +1,4 @@ -.\" $NetBSD: ps.1,v 1.106 2016/12/02 21:59:03 christos Exp $ +.\" $NetBSD: ps.1,v 1.106.6.1 2018/04/12 13:42:48 martin Exp $ .\" .\" Copyright (c) 1980, 1990, 1991, 1993, 1994 .\" The Regents of the University of California. All rights reserved. @@ -308,7 +308,6 @@ the include file .It Dv "P_EXEC" Ta No "0x00004000 process called" Xr execve 2 .It Dv "P_OWEUPC" Ta No "0x00008000 owe process an addupc() call at next ast" .\" the routine addupc is not documented in the man pages -.It Dv "P_FSTRACE" Ta No "0x00010000 tracing via file system" .It Dv "P_NOCLDWAIT" Ta No "0x00020000 no zombies when children die" .It Dv "P_32" Ta No "0x00040000 32-bit process (used on 64-bit kernels)" .It Dv "P_BIGLOCK" Ta No "0x00080000 process needs kernel ``big lock'' to run" Index: src/doc/TODO.ptrace diff -u src/doc/TODO.ptrace:1.28 src/doc/TODO.ptrace:1.28.4.1 --- src/doc/TODO.ptrace:1.28 Sat Apr 8 01:08:36 2017 +++ src/doc/TODO.ptrace Thu Apr 12 13:42:49 2018 @@ -1,4 +1,4 @@ -$NetBSD: TODO.ptrace,v 1.28 2017/04/08 01:08:36 kamil Exp $ +$NetBSD: TODO.ptrace,v 1.28.4.1 2018/04/12 13:42:49 martin Exp $ Items we (currently) plan to finish in the ptrace(2) field: @@ -8,11 +8,6 @@ Items we (currently) plan to finish in t - reiterate over FreeBSD tests and add missing ones if applicable - add PT_DUMPCORE tests in the ATF framework - add ATF tests for PT_WRITE_I and PIOD_WRITE_I - test mprotect restrictions - - add tests for the procfs interface covering all functions available on the - same level as ptrace(2) - - remove 4.4BSD tracing with /proc, restrict /proc to Linux compat, to be - superseded with kevent tracing, the original purpose of /proc debugging is - long gone (performance issues with PT_WRITE_* and PT_READ_*) - research kevent support for tracing a process over a file descriptor, this means alternative to wait(2)-based events with passing events over the kqueue API - signal handlers are global per application and they clash with Index: src/sbin/mount_procfs/mount_procfs.8 diff -u src/sbin/mount_procfs/mount_procfs.8:1.34 src/sbin/mount_procfs/mount_procfs.8:1.34.38.1 --- src/sbin/mount_procfs/mount_procfs.8:1.34 Tue Feb 24 12:45:37 2009 +++ src/sbin/mount_procfs/mount_procfs.8 Thu Apr 12 13:42:49 2018 @@ -1,4 +1,4 @@ -.\" $NetBSD: mount_procfs.8,v 1.34 2009/02/24 12:45:37 pooka Exp $ +.\" $NetBSD: mount_procfs.8,v 1.34.38.1 2018/04/12 13:42:49 martin Exp $ .\" .\" Copyright (c) 1992, 1993 .\" The Regents of the University of California. All rights reserved. @@ -90,38 +90,6 @@ This file is readonly and returns null-t corresponding to the process' command line arguments. For a system or zombie process, this file contains only a string with the name of the process. -.It Pa ctl -a writeonly file which supports a variety of control operations. -Control commands are written as strings to the -.Pa ctl -file. -The control commands are: -.Bl -tag -width detach -compact -.It attach -stops the target process and arranges for the sending -process to become the debug control process. -.It detach -continue execution of the target process and -remove it from control by the debug process. -.It run -continue running the target process until -a signal is delivered, a breakpoint is hit, or the -target process exits. -.It step -single step the target process, with no signal delivery. -.It wait -wait for the target process to stop. -The target process must be stopped before -any of the run, step, or signal commands are allowed. -.El -.Pp -The string can also be the name of a signal, lower case -and without the -.Dv SIG -prefix, -in which case that signal is delivered to the process -(see -.Xr sigaction 2 ) . .It Pa cwd A symbolic link that points to the current working directory of the process. @@ -226,29 +194,10 @@ is the effective group id) all comma separated. .El .El -.Pp -In a normal debugging environment, -where the target is fork/exec'd by the debugger, -the debugger should fork and the child should stop -itself (with a self-inflicted -.Dv SIGSTOP -for example). -The parent should issue a -.Dv wait -and then an -.Dv attach -command via the appropriate -.Pa ctl -file. -The child process will receive a -.Dv SIGTRAP -immediately after the call to exec (see -.Xr execve 2 ) . .Sh FILES .Bl -tag -width /proc/curproc -compact .It Pa /proc/# .It Pa /proc/#/cmdline -.It Pa /proc/#/ctl .It Pa /proc/#/cwd .It Pa /proc/#/exe .It Pa /proc/#/file Index: src/share/man/man9/kauth.9 diff -u src/share/man/man9/kauth.9:1.107 src/share/man/man9/kauth.9:1.107.4.1 --- src/share/man/man9/kauth.9:1.107 Sat Mar 18 19:01:01 2017 +++ src/share/man/man9/kauth.9 Thu Apr 12 13:42:49 2018 @@ -1,4 +1,4 @@ -.\" $NetBSD: kauth.9,v 1.107 2017/03/18 19:01:01 riastradh Exp $ +.\" $NetBSD: kauth.9,v 1.107.4.1 2018/04/12 13:42:49 martin Exp $ .\" .\" Copyright (c) 2005, 2006 Elad Efrat <e...@netbsd.org> .\" All rights reserved. @@ -553,7 +553,6 @@ is the for the target element in the target process, and .Ar arg2 is the access type, which can be either -.Dv KAUTH_REQ_PROCESS_PROCFS_CTL , .Dv KAUTH_REQ_PROCESS_PROCFS_READ , .Dv KAUTH_REQ_PROCESS_PROCFS_RW , or Index: src/sys/compat/linux/arch/arm/linux_ptrace.c diff -u src/sys/compat/linux/arch/arm/linux_ptrace.c:1.19 src/sys/compat/linux/arch/arm/linux_ptrace.c:1.19.10.1 --- src/sys/compat/linux/arch/arm/linux_ptrace.c:1.19 Tue Oct 13 08:24:35 2015 +++ src/sys/compat/linux/arch/arm/linux_ptrace.c Thu Apr 12 13:42:49 2018 @@ -1,4 +1,4 @@ -/* $NetBSD: linux_ptrace.c,v 1.19 2015/10/13 08:24:35 pgoyette Exp $ */ +/* $NetBSD: linux_ptrace.c,v 1.19.10.1 2018/04/12 13:42:49 martin Exp $ */ /*- * Copyright (c) 1999 The NetBSD Foundation, Inc. @@ -31,7 +31,7 @@ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: linux_ptrace.c,v 1.19 2015/10/13 08:24:35 pgoyette Exp $"); +__KERNEL_RCSID(0, "$NetBSD: linux_ptrace.c,v 1.19.10.1 2018/04/12 13:42:49 martin Exp $"); #include <sys/param.h> #include <sys/mount.h> @@ -157,8 +157,7 @@ linux_sys_ptrace_arch(struct lwp *l, con * 3. It is not being traced by _you_, or * 4. It is not currently stopped. */ - if (ISSET(t->p_slflag, PSL_FSTRACE) || t->p_pptr != p || - t->p_stat != SSTOP || !t->p_waited) { + if (t->p_pptr != p || t->p_stat != SSTOP || !t->p_waited) { mutex_exit(t->p_lock); mutex_exit(proc_lock); error = EBUSY; Index: src/sys/compat/linux/arch/i386/linux_ptrace.c diff -u src/sys/compat/linux/arch/i386/linux_ptrace.c:1.31 src/sys/compat/linux/arch/i386/linux_ptrace.c:1.31.10.1 --- src/sys/compat/linux/arch/i386/linux_ptrace.c:1.31 Tue Oct 13 08:24:35 2015 +++ src/sys/compat/linux/arch/i386/linux_ptrace.c Thu Apr 12 13:42:48 2018 @@ -1,4 +1,4 @@ -/* $NetBSD: linux_ptrace.c,v 1.31 2015/10/13 08:24:35 pgoyette Exp $ */ +/* $NetBSD: linux_ptrace.c,v 1.31.10.1 2018/04/12 13:42:48 martin Exp $ */ /*- * Copyright (c) 1999 The NetBSD Foundation, Inc. @@ -30,7 +30,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: linux_ptrace.c,v 1.31 2015/10/13 08:24:35 pgoyette Exp $"); +__KERNEL_RCSID(0, "$NetBSD: linux_ptrace.c,v 1.31.10.1 2018/04/12 13:42:48 martin Exp $"); #include <sys/param.h> #include <sys/mount.h> @@ -197,13 +197,10 @@ linux_sys_ptrace_arch(struct lwp *l, con goto out; } /* - * 2. It is being traced by procfs (which has different signal - * delivery semantics), - * 3. It is not being traced by _you_, or - * 4. It is not currently stopped. + * 2. It is not being traced by _you_, or + * 3. It is not currently stopped. */ - if (ISSET(t->p_slflag, PSL_FSTRACE) || t->p_pptr != p || - t->p_stat != SSTOP || !t->p_waited) { + if (t->p_pptr != p || t->p_stat != SSTOP || !t->p_waited) { mutex_exit(t->p_lock); mutex_exit(proc_lock); error = EBUSY; Index: src/sys/compat/linux/arch/powerpc/linux_ptrace.c diff -u src/sys/compat/linux/arch/powerpc/linux_ptrace.c:1.29 src/sys/compat/linux/arch/powerpc/linux_ptrace.c:1.29.10.1 --- src/sys/compat/linux/arch/powerpc/linux_ptrace.c:1.29 Tue Oct 13 08:24:35 2015 +++ src/sys/compat/linux/arch/powerpc/linux_ptrace.c Thu Apr 12 13:42:49 2018 @@ -1,4 +1,4 @@ -/* $NetBSD: linux_ptrace.c,v 1.29 2015/10/13 08:24:35 pgoyette Exp $ */ +/* $NetBSD: linux_ptrace.c,v 1.29.10.1 2018/04/12 13:42:49 martin Exp $ */ /*- * Copyright (c) 1999, 2001 The NetBSD Foundation, Inc. @@ -30,7 +30,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: linux_ptrace.c,v 1.29 2015/10/13 08:24:35 pgoyette Exp $"); +__KERNEL_RCSID(0, "$NetBSD: linux_ptrace.c,v 1.29.10.1 2018/04/12 13:42:49 martin Exp $"); #include <sys/param.h> #include <sys/mount.h> @@ -174,13 +174,10 @@ linux_sys_ptrace_arch(struct lwp *l, con goto out; } /* - * 2. It is being traced by procfs (which has different signal - * delivery semantics), - * 3. It is not being traced by _you_, or - * 4. It is not currently stopped. + * 2. It is not being traced by _you_, or + * 3. It is not currently stopped. */ - if (ISSET(t->p_slflag, PSL_FSTRACE) || t->p_pptr != p || - t->p_stat != SSTOP || !t->p_waited) { + if (t->p_pptr != p || t->p_stat != SSTOP || !t->p_waited) { mutex_exit(t->p_lock); mutex_exit(proc_lock); error = EBUSY; Index: src/sys/compat/netbsd32/netbsd32.h diff -u src/sys/compat/netbsd32/netbsd32.h:1.114 src/sys/compat/netbsd32/netbsd32.h:1.114.8.1 --- src/sys/compat/netbsd32/netbsd32.h:1.114 Sun Nov 13 13:52:41 2016 +++ src/sys/compat/netbsd32/netbsd32.h Thu Apr 12 13:42:49 2018 @@ -1,4 +1,4 @@ -/* $NetBSD: netbsd32.h,v 1.114 2016/11/13 13:52:41 rin Exp $ */ +/* $NetBSD: netbsd32.h,v 1.114.8.1 2018/04/12 13:42:49 martin Exp $ */ /* * Copyright (c) 1998, 2001, 2008, 2015 Matthew R. Green @@ -292,6 +292,13 @@ struct netbsd32_ptrace_io_desc { actual count (out) */ }; +struct netbsd32_ptrace_siginfo { + siginfo32_t psi_siginfo; /* signal information structure */ + lwpid_t psi_lwpid; /* destination LWP of the signal + * value 0 means the whole process + * (route signal to all LWPs) */ +}; + /* from <sys/quotactl.h> */ typedef netbsd32_pointer_t netbsd32_quotactlargsp_t; struct netbsd32_quotactlargs { @@ -1121,6 +1128,8 @@ vaddr_t netbsd32_vm_default_addr(struct void netbsd32_adjust_limits(struct proc *); void netbsd32_si_to_si32(siginfo32_t *, const siginfo_t *); +void netbsd32_si32_to_si(siginfo_t *, const siginfo32_t *); + void netbsd32_ksi32_to_ksi(struct _ksiginfo *si, const struct __ksiginfo32 *si32); #ifdef KTRACE Index: src/sys/compat/netbsd32/netbsd32_ptrace.c diff -u src/sys/compat/netbsd32/netbsd32_ptrace.c:1.4 src/sys/compat/netbsd32/netbsd32_ptrace.c:1.4.6.1 --- src/sys/compat/netbsd32/netbsd32_ptrace.c:1.4 Thu Feb 23 03:34:22 2017 +++ src/sys/compat/netbsd32/netbsd32_ptrace.c Thu Apr 12 13:42:49 2018 @@ -1,4 +1,4 @@ -/* $NetBSD: netbsd32_ptrace.c,v 1.4 2017/02/23 03:34:22 kamil Exp $ */ +/* $NetBSD: netbsd32_ptrace.c,v 1.4.6.1 2018/04/12 13:42:49 martin 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.4 2017/02/23 03:34:22 kamil Exp $"); +__KERNEL_RCSID(0, "$NetBSD: netbsd32_ptrace.c,v 1.4.6.1 2018/04/12 13:42:49 martin Exp $"); #if defined(_KERNEL_OPT) #include "opt_ptrace.h" @@ -54,18 +54,14 @@ extern struct emul emul_netbsd32; * PTRACE methods */ -static int netbsd32_copyinpiod(struct ptrace_io_desc *, const void *); -static void netbsd32_copyoutpiod(const struct ptrace_io_desc *, void *); -static int netbsd32_doregs(struct lwp *, struct lwp *, struct uio *); -static int netbsd32_dofpregs(struct lwp *, struct lwp *, struct uio *); -static int netbsd32_dodbregs(struct lwp *, struct lwp *, struct uio *); - - static int -netbsd32_copyinpiod(struct ptrace_io_desc *piod, const void *addr) +netbsd32_copyin_piod(struct ptrace_io_desc *piod, const void *addr, size_t len) { struct netbsd32_ptrace_io_desc piod32; + if (len != 0 && sizeof(piod32) != len) + return EINVAL; + int error = copyin(addr, &piod32, sizeof(piod32)); if (error) return error; @@ -77,18 +73,49 @@ netbsd32_copyinpiod(struct ptrace_io_des return 0; } -static void -netbsd32_copyoutpiod(const struct ptrace_io_desc *piod, void *addr) +static int +netbsd32_copyout_piod(const struct ptrace_io_desc *piod, void *addr, size_t len) { struct netbsd32_ptrace_io_desc piod32; + if (len != 0 && sizeof(piod32) != len) + return EINVAL; + piod32.piod_op = piod->piod_op; NETBSD32PTR32(piod32.piod_offs, piod->piod_offs); NETBSD32PTR32(piod32.piod_addr, piod->piod_addr); piod32.piod_len = (netbsd32_size_t)piod->piod_len; - (void) copyout(&piod32, addr, sizeof(piod32)); + return copyout(&piod32, addr, sizeof(piod32)); } +static int +netbsd32_copyin_siginfo(struct ptrace_siginfo *psi, const void *addr, size_t len) +{ + struct netbsd32_ptrace_siginfo psi32; + + if (sizeof(psi32) != len) + return EINVAL; + + int error = copyin(addr, &psi32, sizeof(psi32)); + if (error) + return error; + psi->psi_lwpid = psi32.psi_lwpid; + netbsd32_si32_to_si(&psi->psi_siginfo, &psi32.psi_siginfo); + return 0; +} + +static int +netbsd32_copyout_siginfo(const struct ptrace_siginfo *psi, void *addr, size_t len) +{ + struct netbsd32_ptrace_siginfo psi32; + + if (sizeof(psi32) != len) + return EINVAL; + + psi32.psi_lwpid = psi->psi_lwpid; + netbsd32_si_to_si32(&psi32.psi_siginfo, &psi->psi_siginfo); + return copyout(&psi32, addr, sizeof(psi32)); +} static int netbsd32_doregs(struct lwp *curl /*tracer*/, @@ -205,8 +232,10 @@ netbsd32_dodbregs(struct lwp *curl /*tra } static struct ptrace_methods netbsd32_ptm = { - .ptm_copyinpiod = netbsd32_copyinpiod, - .ptm_copyoutpiod = netbsd32_copyoutpiod, + .ptm_copyin_piod = netbsd32_copyin_piod, + .ptm_copyout_piod = netbsd32_copyout_piod, + .ptm_copyin_siginfo = netbsd32_copyin_siginfo, + .ptm_copyout_siginfo = netbsd32_copyout_siginfo, .ptm_doregs = netbsd32_doregs, .ptm_dofpregs = netbsd32_dofpregs, .ptm_dodbregs = netbsd32_dodbregs Index: src/sys/compat/netbsd32/netbsd32_signal.c diff -u src/sys/compat/netbsd32/netbsd32_signal.c:1.43 src/sys/compat/netbsd32/netbsd32_signal.c:1.43.8.1 --- src/sys/compat/netbsd32/netbsd32_signal.c:1.43 Sun Sep 18 05:16:21 2016 +++ src/sys/compat/netbsd32/netbsd32_signal.c Thu Apr 12 13:42:49 2018 @@ -1,4 +1,4 @@ -/* $NetBSD: netbsd32_signal.c,v 1.43 2016/09/18 05:16:21 christos Exp $ */ +/* $NetBSD: netbsd32_signal.c,v 1.43.8.1 2018/04/12 13:42:49 martin Exp $ */ /* * Copyright (c) 1998, 2001 Matthew R. Green @@ -27,7 +27,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: netbsd32_signal.c,v 1.43 2016/09/18 05:16:21 christos Exp $"); +__KERNEL_RCSID(0, "$NetBSD: netbsd32_signal.c,v 1.43.8.1 2018/04/12 13:42:49 martin Exp $"); #if defined(_KERNEL_OPT) #include "opt_ktrace.h" @@ -313,6 +313,49 @@ netbsd32_si_to_si32(siginfo32_t *si32, c } void +netbsd32_si32_to_si(siginfo_t *si, const siginfo32_t *si32) +{ + memset(si, 0, sizeof (*si)); + si->si_signo = si32->si_signo; + si->si_code = si32->si_code; + si->si_errno = si32->si_errno; + + switch (si->si_signo) { + case 0: /* SA */ + si->si_value.sival_int = si32->si_value.sival_int; + break; + case SIGILL: + case SIGBUS: + case SIGSEGV: + case SIGFPE: + case SIGTRAP: + si->si_addr = (void *)(uintptr_t)si32->si_addr; + si->si_trap = si32->si_trap; + break; + case SIGALRM: + case SIGVTALRM: + case SIGPROF: + default: + si->si_pid = si32->si_pid; + si->si_uid = si32->si_uid; + si->si_value.sival_int = si32->si_value.sival_int; + break; + case SIGCHLD: + si->si_pid = si32->si_pid; + si->si_uid = si32->si_uid; + si->si_status = si32->si_status; + si->si_utime = si32->si_utime; + si->si_stime = si32->si_stime; + break; + case SIGURG: + case SIGIO: + si->si_band = si32->si_band; + si->si_fd = si32->si_fd; + break; + } +} + +void getucontext32(struct lwp *l, ucontext32_t *ucp) { struct proc *p = l->l_proc; Index: src/sys/kern/kern_exit.c diff -u src/sys/kern/kern_exit.c:1.268 src/sys/kern/kern_exit.c:1.268.8.1 --- src/sys/kern/kern_exit.c:1.268 Mon Jan 9 00:31:30 2017 +++ src/sys/kern/kern_exit.c Thu Apr 12 13:42:48 2018 @@ -1,4 +1,4 @@ -/* $NetBSD: kern_exit.c,v 1.268 2017/01/09 00:31:30 kamil Exp $ */ +/* $NetBSD: kern_exit.c,v 1.268.8.1 2018/04/12 13:42:48 martin Exp $ */ /*- * Copyright (c) 1998, 1999, 2006, 2007, 2008 The NetBSD Foundation, Inc. @@ -67,7 +67,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: kern_exit.c,v 1.268 2017/01/09 00:31:30 kamil Exp $"); +__KERNEL_RCSID(0, "$NetBSD: kern_exit.c,v 1.268.8.1 2018/04/12 13:42:48 martin Exp $"); #include "opt_ktrace.h" #include "opt_dtrace.h" @@ -469,7 +469,7 @@ exit1(struct lwp *l, int exitcode, int s if (__predict_false(child->p_slflag & PSL_TRACED)) { mutex_enter(p->p_lock); child->p_slflag &= - ~(PSL_TRACED|PSL_FSTRACE|PSL_SYSCALL); + ~(PSL_TRACED|PSL_SYSCALL); mutex_exit(p->p_lock); if (child->p_opptr != child->p_pptr) { struct proc *t = child->p_opptr; @@ -526,8 +526,7 @@ exit1(struct lwp *l, int exitcode, int s /* Reload parent pointer, since p may have been reparented above */ new_parent = p->p_pptr; - if (__predict_false((p->p_slflag & PSL_FSTRACE) == 0 && - p->p_exitsig != 0)) { + if (__predict_false(p->p_exitsig != 0)) { exit_psignal(p, new_parent, &ksi); kpsignal(new_parent, &ksi, NULL); } @@ -1159,7 +1158,7 @@ proc_free(struct proc *p, struct wrusage */ if ((p->p_slflag & PSL_TRACED) != 0 && p->p_opptr != parent) { mutex_enter(p->p_lock); - p->p_slflag &= ~(PSL_TRACED|PSL_FSTRACE|PSL_SYSCALL); + p->p_slflag &= ~(PSL_TRACED|PSL_SYSCALL); mutex_exit(p->p_lock); parent = (p->p_opptr == NULL) ? initproc : p->p_opptr; proc_reparent(p, parent); Index: src/sys/kern/kern_proc.c diff -u src/sys/kern/kern_proc.c:1.206.6.2 src/sys/kern/kern_proc.c:1.206.6.3 --- src/sys/kern/kern_proc.c:1.206.6.2 Sun Apr 1 08:45:43 2018 +++ src/sys/kern/kern_proc.c Thu Apr 12 13:42:48 2018 @@ -1,4 +1,4 @@ -/* $NetBSD: kern_proc.c,v 1.206.6.2 2018/04/01 08:45:43 martin Exp $ */ +/* $NetBSD: kern_proc.c,v 1.206.6.3 2018/04/12 13:42:48 martin Exp $ */ /*- * Copyright (c) 1999, 2006, 2007, 2008 The NetBSD Foundation, Inc. @@ -62,7 +62,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: kern_proc.c,v 1.206.6.2 2018/04/01 08:45:43 martin Exp $"); +__KERNEL_RCSID(0, "$NetBSD: kern_proc.c,v 1.206.6.3 2018/04/12 13:42:48 martin Exp $"); #ifdef _KERNEL_OPT #include "opt_kstack.h" @@ -1560,7 +1560,6 @@ static const u_int sysctl_sflagmap[] = { static const u_int sysctl_slflagmap[] = { PSL_TRACED, P_TRACED, - PSL_FSTRACE, P_FSTRACE, PSL_CHTRACED, P_CHTRACED, PSL_SYSCALL, P_SYSCALL, 0 Index: src/sys/kern/kern_sig.c diff -u src/sys/kern/kern_sig.c:1.336.4.1 src/sys/kern/kern_sig.c:1.336.4.2 --- src/sys/kern/kern_sig.c:1.336.4.1 Thu Dec 21 19:41:15 2017 +++ src/sys/kern/kern_sig.c Thu Apr 12 13:42:48 2018 @@ -1,4 +1,4 @@ -/* $NetBSD: kern_sig.c,v 1.336.4.1 2017/12/21 19:41:15 snj Exp $ */ +/* $NetBSD: kern_sig.c,v 1.336.4.2 2018/04/12 13:42:48 martin Exp $ */ /*- * Copyright (c) 2006, 2007, 2008 The NetBSD Foundation, Inc. @@ -70,7 +70,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: kern_sig.c,v 1.336.4.1 2017/12/21 19:41:15 snj Exp $"); +__KERNEL_RCSID(0, "$NetBSD: kern_sig.c,v 1.336.4.2 2018/04/12 13:42:48 martin Exp $"); #include "opt_ptrace.h" #include "opt_dtrace.h" @@ -1737,8 +1737,7 @@ issignal(struct lwp *l) /* Emulation-specific handling of signal trace */ if (p->p_emul->e_tracesig == NULL || (*p->p_emul->e_tracesig)(p, signo) == 0) - sigswitch(!(p->p_slflag & PSL_FSTRACE), 0, - signo); + sigswitch(1, 0, signo); /* Check for a signal from the debugger. */ if ((signo = sigchecktrace()) == 0) Index: src/sys/kern/sys_ptrace.c diff -u src/sys/kern/sys_ptrace.c:1.4 src/sys/kern/sys_ptrace.c:1.4.6.1 --- src/sys/kern/sys_ptrace.c:1.4 Thu Feb 23 03:34:22 2017 +++ src/sys/kern/sys_ptrace.c Thu Apr 12 13:42:48 2018 @@ -1,4 +1,4 @@ -/* $NetBSD: sys_ptrace.c,v 1.4 2017/02/23 03:34:22 kamil Exp $ */ +/* $NetBSD: sys_ptrace.c,v 1.4.6.1 2018/04/12 13:42:48 martin Exp $ */ /*- * Copyright (c) 2008, 2009 The NetBSD Foundation, Inc. @@ -118,7 +118,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: sys_ptrace.c,v 1.4 2017/02/23 03:34:22 kamil Exp $"); +__KERNEL_RCSID(0, "$NetBSD: sys_ptrace.c,v 1.4.6.1 2018/04/12 13:42:48 martin Exp $"); #ifdef _KERNEL_OPT #include "opt_ptrace.h" @@ -149,24 +149,47 @@ __KERNEL_RCSID(0, "$NetBSD: sys_ptrace.c * 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_copyinpiod(struct ptrace_io_desc *piod, const void *addr) +ptrace_copyin_piod(struct ptrace_io_desc *piod, const void *addr, size_t len) { + if (len != 0 && sizeof(*piod) != len) + return EINVAL; + return copyin(addr, piod, sizeof(*piod)); } -static void -ptrace_copyoutpiod(const struct ptrace_io_desc *piod, void *addr) +static int +ptrace_copyout_piod(const struct ptrace_io_desc *piod, void *addr, size_t len) +{ + if (len != 0 && sizeof(*piod) != len) + return EINVAL; + + return copyout(piod, addr, sizeof(*piod)); +} + +static int +ptrace_copyin_siginfo(struct ptrace_siginfo *psi, const void *addr, size_t len) { - (void) copyout(piod, addr, sizeof(*piod)); + if (sizeof(*psi) != len) + return EINVAL; + + return copyin(addr, psi, sizeof(*psi)); +} + +static int +ptrace_copyout_siginfo(const struct ptrace_siginfo *psi, void *addr, size_t len) +{ + if (sizeof(*psi) != len) + return EINVAL; + + return copyout(psi, addr, sizeof(*psi)); } static struct ptrace_methods native_ptm = { - .ptm_copyinpiod = ptrace_copyinpiod, - .ptm_copyoutpiod = ptrace_copyoutpiod, + .ptm_copyin_piod = ptrace_copyin_piod, + .ptm_copyout_piod = ptrace_copyout_piod, + .ptm_copyin_siginfo = ptrace_copyin_siginfo, + .ptm_copyout_siginfo = ptrace_copyout_siginfo, .ptm_doregs = process_doregs, .ptm_dofpregs = process_dofpregs, .ptm_dodbregs = process_dodbregs, Index: src/sys/kern/sys_ptrace_common.c diff -u src/sys/kern/sys_ptrace_common.c:1.22.2.1 src/sys/kern/sys_ptrace_common.c:1.22.2.2 --- src/sys/kern/sys_ptrace_common.c:1.22.2.1 Tue Mar 6 09:52:09 2018 +++ src/sys/kern/sys_ptrace_common.c Thu Apr 12 13:42:48 2018 @@ -1,4 +1,4 @@ -/* $NetBSD: sys_ptrace_common.c,v 1.22.2.1 2018/03/06 09:52:09 martin Exp $ */ +/* $NetBSD: sys_ptrace_common.c,v 1.22.2.2 2018/04/12 13:42:48 martin Exp $ */ /*- * Copyright (c) 2008, 2009 The NetBSD Foundation, Inc. @@ -118,12 +118,18 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: sys_ptrace_common.c,v 1.22.2.1 2018/03/06 09:52:09 martin Exp $"); +__KERNEL_RCSID(0, "$NetBSD: sys_ptrace_common.c,v 1.22.2.2 2018/04/12 13:42:48 martin Exp $"); #ifdef _KERNEL_OPT #include "opt_ptrace.h" #include "opt_ktrace.h" #include "opt_pax.h" +#include "opt_compat_netbsd32.h" +#endif + +#if defined(__HAVE_COMPAT_NETBSD32) && !defined(COMPAT_NETBSD32) \ + && !defined(_RUMPKERNEL) +#define COMPAT_NETBSD32 #endif #include <sys/param.h> @@ -164,12 +170,57 @@ static kmutex_t ptrace_mtx; static kcondvar_t ptrace_cv; #endif +#ifdef PT_GETREGS +# define case_PT_GETREGS case PT_GETREGS: +#else +# define case_PT_GETREGS +#endif + +#ifdef PT_SETREGS +# define case_PT_SETREGS case PT_SETREGS: +#else +# define case_PT_SETREGS +#endif + +#ifdef PT_GETFPREGS +# define case_PT_GETFPREGS case PT_GETFPREGS: +#else +# define case_PT_GETFPREGS +#endif + +#ifdef PT_SETFPREGS +# define case_PT_SETFPREGS case PT_SETFPREGS: +#else +# define case_PT_SETFPREGS +#endif + +#ifdef PT_GETDBREGS +# define case_PT_GETDBREGS case PT_GETDBREGS: +#else +# define case_PT_GETDBREGS +#endif + +#ifdef PT_SETDBREGS +# define case_PT_SETDBREGS case PT_SETDBREGS: +#else +# define case_PT_SETDBREGS +#endif + +#if defined(PT_SETREGS) || defined(PT_GETREGS) || \ + defined(PT_SETFPREGS) || defined(PT_GETFOREGS) || \ + defined(PT_SETDBREGS) || defined(PT_GETDBREGS) +# define PT_REGISTERS +#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; +#ifdef PT_SETDBREGS + extern int user_set_dbregs; +#endif result = KAUTH_RESULT_DEFER; p = arg0; @@ -183,6 +234,13 @@ ptrace_listener_cb(kauth_cred_t cred, ka goto out; switch ((u_long)arg1) { +#ifdef PT_SETDBREGS + case_PT_SETDBREGS + if (kauth_cred_getuid(cred) != 0 && user_set_dbregs == 0) { + result = KAUTH_RESULT_DENY; + break; + } +#endif case PT_TRACE_ME: case PT_ATTACH: case PT_WRITE_I: @@ -190,24 +248,11 @@ ptrace_listener_cb(kauth_cred_t cred, ka 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 -#ifdef PT_GETDBREGS - case PT_GETDBREGS: -#endif -#ifdef PT_SETDBREGS - case PT_SETDBREGS: -#endif + case_PT_GETREGS + case_PT_SETREGS + case_PT_GETFPREGS + case_PT_SETFPREGS + case_PT_GETDBREGS case PT_SET_EVENT_MASK: case PT_GET_EVENT_MASK: case PT_GET_PROCESS_STATE: @@ -291,139 +336,94 @@ ptrace_fini(void) return 0; } -int -do_ptrace(struct ptrace_methods *ptm, struct lwp *l, int req, pid_t pid, - void *addr, int data, register_t *retval) +static struct proc * +ptrace_find(struct lwp *l, int req, pid_t pid) { - struct proc *p = l->l_proc; - struct lwp *lt; - struct lwp *lt2; - 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 ptrace_siginfo psi; - 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); + struct proc *t; /* "A foolish consistency..." XXX */ if (req == PT_TRACE_ME) { - t = p; + t = l->l_proc; 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; - } + return t; + } - /* 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; - } + /* Find the process we're supposed to be operating on. */ + t = proc_find(pid); + if (t == NULL) + return NULL; + + /* XXX-elad */ + mutex_enter(t->p_lock); + int error = kauth_authorize_process(l->l_cred, KAUTH_PROCESS_CANSEE, + t, KAUTH_ARG(KAUTH_REQ_PROCESS_CANSEE_ENTRY), NULL, NULL); + if (error) { + mutex_exit(t->p_lock); + return NULL; } + return t; +} +static int +ptrace_allowed(struct lwp *l, int req, struct proc *t, struct proc *p) +{ /* * 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); + if (!rw_tryenter(&t->p_reflock, RW_READER)) return EBUSY; - } /* Make sure we can operate on it. */ switch (req) { - case PT_TRACE_ME: + case PT_TRACE_ME: /* Saying that you're being traced is always legal. */ - break; + return 0; - case PT_ATTACH: + 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; - } + if (t->p_pid == p->p_pid) + return EINVAL; /* * (2) it's a system process */ - if (t->p_flag & PK_SYSTEM) { - error = EPERM; - break; - } + if (t->p_flag & PK_SYSTEM) + return EPERM; /* * (3) it's already being traced, or */ - if (ISSET(t->p_slflag, PSL_TRACED)) { - error = EBUSY; - break; - } + if (ISSET(t->p_slflag, PSL_TRACED)) + return EBUSY; /* * (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); + int tmp = proc_isunder(t, l); mutex_enter(t->p_lock); /* XXXSMP */ - if (!tmp) { - error = EPERM; - break; - } - break; + if (!tmp) + return EPERM; + return 0; - case PT_READ_I: - case PT_READ_D: - case PT_WRITE_I: - case PT_WRITE_D: - case PT_IO: - case PT_SET_SIGINFO: - case PT_GET_SIGINFO: -#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 PT_GETDBREGS - case PT_GETDBREGS: -#endif -#ifdef PT_SETDBREGS - case PT_SETDBREGS: -#endif + case PT_READ_I: + case PT_READ_D: + case PT_WRITE_I: + case PT_WRITE_D: + case PT_IO: + case PT_SET_SIGINFO: + case PT_GET_SIGINFO: + case_PT_GETREGS + case_PT_SETREGS + case_PT_GETFPREGS + case_PT_SETFPREGS + case_PT_GETDBREGS + case_PT_SETDBREGS #ifdef __HAVE_PTRACE_MACHDEP PTRACE_MACHDEP_REQUEST_CASES #endif @@ -435,90 +435,563 @@ do_ptrace(struct ptrace_methods *ptm, st mutex_exit(t->p_lock); /* XXXSMP */ tmp = proc_isunder(t, l); mutex_enter(t->p_lock); /* XXXSMP */ - if (!tmp) { - error = EPERM; - break; - } + if (!tmp) + return EPERM; /*FALLTHROUGH*/ - case PT_CONTINUE: - case PT_KILL: - case PT_DETACH: - case PT_LWPINFO: - case PT_SYSCALL: - case PT_SYSCALLEMU: - case PT_DUMPCORE: + 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: - case PT_SETSTEP: - case PT_CLEARSTEP: -#endif - case PT_SET_EVENT_MASK: - case PT_GET_EVENT_MASK: - case PT_GET_PROCESS_STATE: - case PT_RESUME: - case PT_SUSPEND: + case PT_STEP: + case PT_SETSTEP: + case PT_CLEARSTEP: +#endif + case PT_SET_EVENT_MASK: + case PT_GET_EVENT_MASK: + case PT_GET_PROCESS_STATE: + case PT_RESUME: + case PT_SUSPEND: /* * 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; - } + if (!ISSET(t->p_slflag, PSL_TRACED)) + return EPERM; /* - * (3) it's not being traced by _you_, or + * (2) 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; + return EBUSY; } /* - * (4) it's not currently stopped. + * (3) 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; + return EBUSY; } - break; + return 0; default: /* It was not a legal request. */ + return EINVAL; + } +} + +static int +ptrace_needs_hold(int req) +{ + 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: + case PT_GET_SIGINFO: + case PT_SET_SIGINFO: + return 1; + default: + return 0; + } +} + +static int +ptrace_update_lwp(struct proc *t, struct lwp **lt, lwpid_t lid) +{ + if (lid == 0 || lid == (*lt)->l_lid || t->p_nlwps == 1) + return 0; + + lwp_delref(*lt); + + mutex_enter(t->p_lock); + *lt = lwp_find(t, lid); + if (*lt == NULL) { + mutex_exit(t->p_lock); + return ESRCH; + } + + if ((*lt)->l_flag & LW_SYSTEM) { + *lt = NULL; + return EINVAL; + } + + lwp_addref(*lt); + mutex_exit(t->p_lock); + + return 0; +} + +static int +ptrace_get_siginfo(struct proc *t, struct ptrace_methods *ptm, void *addr, + size_t data) +{ + struct ptrace_siginfo psi; + + psi.psi_siginfo._info = t->p_sigctx.ps_info; + psi.psi_lwpid = t->p_sigctx.ps_lwp; + + return ptm->ptm_copyout_siginfo(&psi, addr, data); +} + +static int +ptrace_set_siginfo(struct proc *t, struct lwp **lt, struct ptrace_methods *ptm, + void *addr, size_t data) +{ + struct ptrace_siginfo psi; + + int error = ptm->ptm_copyin_siginfo(&psi, addr, data); + if (error) + return error; + + /* Check that the data is a valid signal number or zero. */ + if (psi.psi_siginfo.si_signo < 0 || psi.psi_siginfo.si_signo >= NSIG) + return EINVAL; + + if ((error = ptrace_update_lwp(t, lt, psi.psi_lwpid)) != 0) + return error; + + t->p_sigctx.ps_faked = true; + t->p_sigctx.ps_info = psi.psi_siginfo._info; + t->p_sigctx.ps_lwp = psi.psi_lwpid; + return 0; +} + +static int +ptrace_get_event_mask(struct proc *t, void *addr, size_t data) +{ + struct ptrace_event pe; + + if (data != sizeof(pe)) { + DPRINTF(("%s: %zu != %zu\n", __func__, data, sizeof(pe))); + return EINVAL; + } + memset(&pe, 0, sizeof(pe)); + pe.pe_set_event = ISSET(t->p_slflag, PSL_TRACEFORK) ? + PTRACE_FORK : 0; + pe.pe_set_event |= ISSET(t->p_slflag, PSL_TRACEVFORK) ? + PTRACE_VFORK : 0; + pe.pe_set_event |= ISSET(t->p_slflag, PSL_TRACEVFORK_DONE) ? + PTRACE_VFORK_DONE : 0; + pe.pe_set_event |= ISSET(t->p_slflag, PSL_TRACELWP_CREATE) ? + PTRACE_LWP_CREATE : 0; + pe.pe_set_event |= ISSET(t->p_slflag, PSL_TRACELWP_EXIT) ? + PTRACE_LWP_EXIT : 0; + return copyout(&pe, addr, sizeof(pe)); +} + +static int +ptrace_set_event_mask(struct proc *t, void *addr, size_t data) +{ + struct ptrace_event pe; + int error; + + if (data != sizeof(pe)) { + DPRINTF(("%s: %zu != %zu\n", __func__, data, sizeof(pe))); + return EINVAL; + } + 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); +#if notyet + if (pe.pe_set_event & PTRACE_VFORK) + SET(t->p_slflag, PSL_TRACEVFORK); + else + CLR(t->p_slflag, PSL_TRACEVFORK); +#else + if (pe.pe_set_event & PTRACE_VFORK) + return ENOTSUP; +#endif + if (pe.pe_set_event & PTRACE_VFORK_DONE) + SET(t->p_slflag, PSL_TRACEVFORK_DONE); + else + CLR(t->p_slflag, PSL_TRACEVFORK_DONE); + if (pe.pe_set_event & PTRACE_LWP_CREATE) + SET(t->p_slflag, PSL_TRACELWP_CREATE); + else + CLR(t->p_slflag, PSL_TRACELWP_CREATE); + if (pe.pe_set_event & PTRACE_LWP_EXIT) + SET(t->p_slflag, PSL_TRACELWP_EXIT); + else + CLR(t->p_slflag, PSL_TRACELWP_EXIT); + return 0; +} + +static int +ptrace_get_process_state(struct proc *t, void *addr, size_t data) +{ + struct ptrace_state ps; + + if (data != sizeof(ps)) { + DPRINTF(("%s: %zu != %zu\n", __func__, data, sizeof(ps))); + return EINVAL; + } + memset(&ps, 0, sizeof(ps)); + + if (t->p_fpid) { + ps.pe_report_event = PTRACE_FORK; + ps.pe_other_pid = t->p_fpid; + } else if (t->p_vfpid) { + ps.pe_report_event = PTRACE_VFORK; + ps.pe_other_pid = t->p_vfpid; + } else if (t->p_vfpid_done) { + ps.pe_report_event = PTRACE_VFORK_DONE; + ps.pe_other_pid = t->p_vfpid_done; + } else if (t->p_lwp_created) { + ps.pe_report_event = PTRACE_LWP_CREATE; + ps.pe_lwp = t->p_lwp_created; + } else if (t->p_lwp_exited) { + ps.pe_report_event = PTRACE_LWP_EXIT; + ps.pe_lwp = t->p_lwp_exited; + } + return copyout(&ps, addr, sizeof(ps)); +} + +static int +ptrace_lwpinfo(struct proc *t, struct lwp **lt, void *addr, size_t data) +{ + struct ptrace_lwpinfo pl; + + if (data != sizeof(pl)) { + DPRINTF(("%s: %zu != %zu\n", __func__, data, sizeof(pl))); + return EINVAL; + } + int error = copyin(addr, &pl, sizeof(pl)); + if (error) + return error; + + lwpid_t 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); + return ESRCH; + } + *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_flag & LW_WSUSPEND) + pl.pl_event = PL_EVENT_SUSPENDED; + /* + * If we match the lwp, or it was sent to every lwp, + * we set PL_EVENT_SIGNAL. + * XXX: ps_lwp == 0 means everyone and noone, so + * check ps_signo too. + */ + else if ((*lt)->l_lid == t->p_sigctx.ps_lwp + || (t->p_sigctx.ps_lwp == 0 && + t->p_sigctx.ps_info._signo)) + pl.pl_event = PL_EVENT_SIGNAL; + } + mutex_exit(t->p_lock); + + return copyout(&pl, addr, sizeof(pl)); +} + +static int +ptrace_startstop(struct proc *t, struct lwp **lt, int rq, void *addr, + size_t data) +{ + int error; + + if ((error = ptrace_update_lwp(t, lt, data)) != 0) + return error; + + lwp_lock(*lt); + if (rq == PT_SUSPEND) + (*lt)->l_flag |= LW_WSUSPEND; + else + (*lt)->l_flag &= ~LW_WSUSPEND; + lwp_unlock(*lt); + return 0; +} + +#ifdef PT_REGISTERS +static int +ptrace_uio_dir(int req) +{ + switch (req) { + case_PT_GETREGS + case_PT_GETFPREGS + case_PT_GETDBREGS + return UIO_READ; + case_PT_SETREGS + case_PT_SETFPREGS + case_PT_SETDBREGS + return UIO_WRITE; + default: + return -1; + } +} + +static int +ptrace_regs(struct lwp *l, struct lwp **lt, int rq, struct ptrace_methods *ptm, + void *addr, size_t data) +{ + int error; + struct proc *t = (*lt)->l_proc; + struct vmspace *vm; + + if ((error = ptrace_update_lwp(t, lt, data)) != 0) + return error; + + int dir = ptrace_uio_dir(rq); + size_t size; + int (*func)(struct lwp *, struct lwp *, struct uio *); + + switch (rq) { +#if defined(PT_SETREGS) || defined(PT_GETREGS) + case_PT_GETREGS + case_PT_SETREGS + if (!process_validregs(*lt)) + return EINVAL; + size = PROC_REGSZ(t); + func = ptm->ptm_doregs; + break; +#endif +#if defined(PT_SETFPREGS) || defined(PT_GETFPREGS) + case_PT_GETFPREGS + case_PT_SETFPREGS + if (!process_validfpregs(*lt)) + return EINVAL; + size = PROC_FPREGSZ(t); + func = ptm->ptm_dofpregs; + break; +#endif +#if defined(PT_SETDBREGS) || defined(PT_GETDBREGS) + case_PT_GETDBREGS + case_PT_SETDBREGS + if (!process_validdbregs(*lt)) + return EINVAL; + size = PROC_DBREGSZ(t); + func = ptm->ptm_dodbregs; + break; +#endif + default: + return EINVAL; + } + + error = proc_vmspace_getref(l->l_proc, &vm); + if (error) + return error; + + struct uio uio; + struct iovec iov; + + iov.iov_base = addr; + iov.iov_len = size; + uio.uio_iov = &iov; + uio.uio_iovcnt = 1; + uio.uio_offset = 0; + uio.uio_resid = iov.iov_len; + uio.uio_rw = dir; + uio.uio_vmspace = vm; + + error = (*func)(l, *lt, &uio); + uvmspace_free(vm); + return error; +} +#endif + +static int +ptrace_sendsig(struct proc *t, struct lwp *lt, int signo, int resume_all) +{ + ksiginfo_t ksi; + + t->p_fpid = 0; + t->p_vfpid = 0; + t->p_vfpid_done = 0; + t->p_lwp_created = 0; + t->p_lwp_exited = 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); + return 0; + } + + KSI_INIT_EMPTY(&ksi); + if (t->p_sigctx.ps_faked) { + if (signo != t->p_sigctx.ps_info._signo) + return EINVAL; + t->p_sigctx.ps_faked = false; + ksi.ksi_info = t->p_sigctx.ps_info; + ksi.ksi_lid = t->p_sigctx.ps_lwp; + } else if (signo == 0) { + return 0; + } else { + ksi.ksi_signo = signo; + } + + kpsignal2(t, &ksi); + return 0; +} + +static int +ptrace_dumpcore(struct lwp *lt, char *path, size_t len) +{ + int error; + if (path != NULL) { + + if (len >= MAXPATHLEN) + return EINVAL; + + char *src = path; + path = kmem_alloc(len + 1, KM_SLEEP); + error = copyin(src, path, len); + if (error) + goto out; + path[len] = '\0'; + } + error = (*coredump_vec)(lt, path); +out: + if (path) + kmem_free(path, len + 1); + return error; +} + +static int +ptrace_doio(struct lwp *l, struct proc *t, struct lwp *lt, + struct ptrace_io_desc *piod, void *addr, bool sysspace) +{ + struct uio uio; + struct iovec iov; + int error, tmp; + + error = 0; + 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: + uio.uio_rw = UIO_READ; + tmp = t->p_execsw->es_arglen; + 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); + break; + default: 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) + return error; + + if (sysspace) { + uio.uio_vmspace = vmspace_kernel(); + } else { + error = proc_vmspace_getref(l->l_proc, &uio.uio_vmspace); + if (error) + return error; } - if (error != 0) { - mutex_exit(proc_lock); - mutex_exit(t->p_lock); - rw_exit(&t->p_reflock); + error = process_domem(l, lt, &uio); + if (!sysspace) + uvmspace_free(uio.uio_vmspace); + if (error) return error; + piod->piod_len -= uio.uio_resid; + 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 = NULL; + struct lwp *lt2; + struct proc *t; /* target process */ + struct ptrace_io_desc piod; + int error, write, tmp, pheld; + int signo = 0; + int resume_all; + 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); + + t = ptrace_find(l, req, pid); + if (t == NULL) { + mutex_exit(proc_lock); + return ESRCH; + } + + pheld = 1; + if ((error = ptrace_allowed(l, req, t, p)) != 0) + goto out; + + if ((error = kauth_authorize_process(l->l_cred, + KAUTH_PROCESS_PTRACE, t, KAUTH_ARG(req), NULL, NULL)) != 0) + goto out; + + if ((lt = lwp_find_first(t)) == NULL) { + error = ESRCH; + goto out; } /* Do single-step fixup if needed. */ @@ -529,24 +1002,9 @@ do_ptrace(struct ptrace_methods *ptm, st /* * 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); + if ((pheld = ptrace_needs_hold(req)) == 0) { mutex_exit(t->p_lock); - pheld = 0; - break; + mutex_exit(proc_lock); } /* Now do the operation. */ @@ -556,124 +1014,43 @@ do_ptrace(struct ptrace_methods *ptm, st resume_all = 1; switch (req) { - case PT_TRACE_ME: + 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 + case PT_WRITE_I: /* XXX no separate I and D spaces */ + case PT_WRITE_D: 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); + case PT_READ_I: /* XXX no separate I and D spaces */ + case PT_READ_D: + piod.piod_addr = &tmp; + piod.piod_len = sizeof(tmp); + piod.piod_offs = addr; + piod.piod_op = write ? PIOD_WRITE_D : PIOD_READ_D; + if ((error = ptrace_doio(l, t, lt, &piod, addr, true)) != 0) + break; 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; - 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); - break; - default: - error = EINVAL; - break; - } - if (error) + case PT_IO: + if ((error = ptm->ptm_copyin_piod(&piod, addr, data)) != 0) break; - error = proc_vmspace_getref(l->l_proc, &vm); - if (error) + if ((error = ptrace_doio(l, t, lt, &piod, addr, false)) != 0) 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); + error = ptm->ptm_copyout_piod(&piod, addr, data); 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); + case PT_DUMPCORE: + error = ptrace_dumpcore(lt, addr, data); break; #ifdef PT_STEP - case PT_STEP: + case PT_STEP: /* * From the 4.4BSD PRM: * "Execution continues as in request PT_CONTINUE; however @@ -681,9 +1058,9 @@ do_ptrace(struct ptrace_methods *ptm, st * instruction, execution stops again. [ ... ]" */ #endif - case PT_CONTINUE: - case PT_SYSCALL: - case PT_DETACH: + 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); @@ -813,7 +1190,7 @@ do_ptrace(struct ptrace_methods *ptm, st break; #endif if (req == PT_DETACH) { - CLR(t->p_slflag, PSL_TRACED|PSL_FSTRACE|PSL_SYSCALL); + CLR(t->p_slflag, PSL_TRACED|PSL_SYSCALL); /* give process back to original parent or init */ if (t->p_opptr != t->p_pptr) { @@ -831,41 +1208,10 @@ do_ptrace(struct ptrace_methods *ptm, st CLR(lt->l_pflag, LP_SINGLESTEP); } sendsig: - t->p_fpid = 0; - t->p_vfpid = 0; - t->p_vfpid_done = 0; - t->p_lwp_created = 0; - t->p_lwp_exited = 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 (t->p_sigctx.ps_faked) { - if (signo != t->p_sigctx.ps_info._signo) { - error = EINVAL; - break; - } - t->p_sigctx.ps_faked = false; - KSI_INIT_EMPTY(&ksi); - ksi.ksi_info = t->p_sigctx.ps_info; - ksi.ksi_lid = t->p_sigctx.ps_lwp; - kpsignal2(t, &ksi); - } else if (signo != 0) { - KSI_INIT_EMPTY(&ksi); - ksi.ksi_signo = signo; - kpsignal2(t, &ksi); - } + error = ptrace_sendsig(t, lt, signo, resume_all); break; - case PT_SYSCALLEMU: + case PT_SYSCALLEMU: if (!ISSET(t->p_slflag, PSL_SYSCALL) || t->p_stat != SSTOP) { error = EINVAL; break; @@ -874,41 +1220,27 @@ do_ptrace(struct ptrace_methods *ptm, st break; #ifdef PT_STEP - case PT_SETSTEP: + case PT_SETSTEP: write = 1; - case PT_CLEARSTEP: + case PT_CLEARSTEP: /* write = 0 done above. */ + if ((error = ptrace_update_lwp(t, <, data)) != 0) + break; - 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 (ISSET(lt->l_flag, LW_SYSTEM)) - error = EINVAL; - else if (write) + if (write) SET(lt->l_pflag, LP_SINGLESTEP); else CLR(lt->l_pflag, LP_SINGLESTEP); break; #endif - case PT_KILL: + case PT_KILL: /* just send the process a KILL signal. */ signo = SIGKILL; goto sendsig; /* in PT_CONTINUE, above. */ - case PT_ATTACH: + case PT_ATTACH: /* * Go ahead and set the trace flag. * Save the old parent (it's reset in @@ -921,360 +1253,43 @@ do_ptrace(struct ptrace_methods *ptm, st 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; - pe.pe_set_event |= ISSET(t->p_slflag, PSL_TRACEVFORK) ? - PTRACE_VFORK : 0; - pe.pe_set_event |= ISSET(t->p_slflag, PSL_TRACEVFORK_DONE) ? - PTRACE_VFORK_DONE : 0; - pe.pe_set_event |= ISSET(t->p_slflag, PSL_TRACELWP_CREATE) ? - PTRACE_LWP_CREATE : 0; - pe.pe_set_event |= ISSET(t->p_slflag, PSL_TRACELWP_EXIT) ? - PTRACE_LWP_EXIT : 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); -#if notyet - if (pe.pe_set_event & PTRACE_VFORK) - SET(t->p_slflag, PSL_TRACEVFORK); - else - CLR(t->p_slflag, PSL_TRACEVFORK); -#else - if (pe.pe_set_event & PTRACE_VFORK) { - error = ENOTSUP; - break; - } -#endif - if (pe.pe_set_event & PTRACE_VFORK_DONE) - SET(t->p_slflag, PSL_TRACEVFORK_DONE); - else - CLR(t->p_slflag, PSL_TRACEVFORK_DONE); - if (pe.pe_set_event & PTRACE_LWP_CREATE) - SET(t->p_slflag, PSL_TRACELWP_CREATE); - else - CLR(t->p_slflag, PSL_TRACELWP_CREATE); - if (pe.pe_set_event & PTRACE_LWP_EXIT) - SET(t->p_slflag, PSL_TRACELWP_EXIT); - else - CLR(t->p_slflag, PSL_TRACELWP_EXIT); - 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; - } else if (t->p_vfpid) { - ps.pe_report_event = PTRACE_VFORK; - ps.pe_other_pid = t->p_vfpid; - } else if (t->p_vfpid_done) { - ps.pe_report_event = PTRACE_VFORK_DONE; - ps.pe_other_pid = t->p_vfpid_done; - } else if (t->p_lwp_created) { - ps.pe_report_event = PTRACE_LWP_CREATE; - ps.pe_lwp = t->p_lwp_created; - } else if (t->p_lwp_exited) { - ps.pe_report_event = PTRACE_LWP_EXIT; - ps.pe_lwp = t->p_lwp_exited; - } - error = copyout(&ps, addr, sizeof(ps)); + case PT_GET_EVENT_MASK: + error = ptrace_get_event_mask(t, addr, data); 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_flag & LW_WSUSPEND) - pl.pl_event = PL_EVENT_SUSPENDED; - /* - * If we match the lwp, or it was sent to every lwp, - * we set PL_EVENT_SIGNAL. - * XXX: ps_lwp == 0 means everyone and noone, so - * check ps_signo too. - */ - else if (lt->l_lid == t->p_sigctx.ps_lwp - || (t->p_sigctx.ps_lwp == 0 && - t->p_sigctx.ps_info._signo)) - pl.pl_event = PL_EVENT_SIGNAL; - } - mutex_exit(t->p_lock); - - error = copyout(&pl, addr, sizeof(pl)); + case PT_SET_EVENT_MASK: + error = ptrace_set_event_mask(t, addr, data); break; - case PT_SET_SIGINFO: - if (data != sizeof(psi)) { - DPRINTF(("ptrace(%d): %d != %zu\n", req, data, - sizeof(psi))); - error = EINVAL; - break; - } - - error = copyin(addr, &psi, sizeof(psi)); - if (error) - break; - - /* Check that the data is a valid signal number or zero. */ - if (psi.psi_siginfo.si_signo < 0 || - psi.psi_siginfo.si_signo >= NSIG) { - error = EINVAL; - break; - } - - tmp = psi.psi_lwpid; - if (tmp != 0) - lwp_delref(lt); - - mutex_enter(t->p_lock); - - if (tmp != 0) { - lt = lwp_find(t, tmp); - if (lt == NULL) { - mutex_exit(t->p_lock); - error = ESRCH; - break; - } - lwp_addref(lt); - } - - t->p_sigctx.ps_faked = true; - t->p_sigctx.ps_info = psi.psi_siginfo._info; - t->p_sigctx.ps_lwp = psi.psi_lwpid; - mutex_exit(t->p_lock); + case PT_GET_PROCESS_STATE: + error = ptrace_get_process_state(t, addr, data); break; - case PT_GET_SIGINFO: - if (data != sizeof(psi)) { - DPRINTF(("ptrace(%d): %d != %zu\n", req, data, - sizeof(psi))); - error = EINVAL; - break; - } - mutex_enter(t->p_lock); - psi.psi_siginfo._info = t->p_sigctx.ps_info; - psi.psi_lwpid = t->p_sigctx.ps_lwp; - mutex_exit(t->p_lock); - - error = copyout(&psi, addr, sizeof(psi)); - if (error) - break; - + case PT_LWPINFO: + error = ptrace_lwpinfo(t, <, addr, data); break; - case PT_RESUME: - write = 1; - - case PT_SUSPEND: - /* write = 0 done above. */ - - 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 (lt->l_flag & LW_SYSTEM) { - error = EINVAL; - } else { - lwp_lock(lt); - if (write == 0) - lt->l_flag |= LW_WSUSPEND; - else - lt->l_flag &= ~LW_WSUSPEND; - lwp_unlock(lt); - } + case PT_SET_SIGINFO: + error = ptrace_set_siginfo(t, <, ptm, addr, data); 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); - } + case PT_GET_SIGINFO: + error = ptrace_get_siginfo(t, ptm, addr, data); break; -#endif - -#ifdef PT_SETFPREGS - case PT_SETFPREGS: - write = 1; - /*FALLTHROUGH*/ -#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); - } + case PT_RESUME: + case PT_SUSPEND: + error = ptrace_startstop(t, <, req, addr, data); break; -#endif - -#ifdef PT_SETDBREGS - case PT_SETDBREGS: - write = 1; - /*FALLTHROUGH*/ -#endif -#ifdef PT_GETDBREGS - case PT_GETDBREGS: - /* write = 0 done above. */ -#endif -#if defined(PT_SETDBREGS) || defined(PT_GETDBREGS) - 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_validdbregs(lt)) - error = EINVAL; - else { - error = proc_vmspace_getref(p, &vm); - if (error) - break; - iov.iov_base = addr; - iov.iov_len = PROC_DBREGSZ(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_dodbregs(l, lt, &uio); - uvmspace_free(vm); - } +#ifdef PT_REGISTERS + case_PT_SETREGS + case_PT_GETREGS + case_PT_SETFPREGS + case_PT_GETFPREGS + case_PT_SETDBREGS + case_PT_GETDBREGS + error = ptrace_regs(l, <, req, ptm, addr, data); break; #endif @@ -1285,6 +1300,7 @@ do_ptrace(struct ptrace_methods *ptm, st #endif } +out: if (pheld) { mutex_exit(t->p_lock); mutex_exit(proc_lock); @@ -1296,40 +1312,71 @@ do_ptrace(struct ptrace_methods *ptm, st return error; } -int -process_doregs(struct lwp *curl /*tracer*/, - struct lwp *l /*traced*/, - struct uio *uio) +typedef int (*regrfunc_t)(struct lwp *, void *, size_t *); +typedef int (*regwfunc_t)(struct lwp *, void *, size_t); + +#ifdef PT_REGISTERS +static int +proc_regio(struct lwp *l, struct uio *uio, size_t ks, regrfunc_t r, + regwfunc_t w) { -#if defined(PT_GETREGS) || defined(PT_SETREGS) + char buf[1024]; int error; - struct reg r; char *kv; - int kl; + size_t kl; - if (uio->uio_offset < 0 || uio->uio_offset > (off_t)sizeof(r)) + if (ks > sizeof(buf)) + return E2BIG; + + if (uio->uio_offset < 0 || uio->uio_offset > (off_t)ks) return EINVAL; - kl = sizeof(r); - kv = (char *)&r; + kv = buf + uio->uio_offset; + kl = ks - uio->uio_offset; - kv += uio->uio_offset; - kl -= uio->uio_offset; - if ((size_t)kl > uio->uio_resid) + if (kl > uio->uio_resid) kl = uio->uio_resid; - error = process_read_regs(l, &r); + error = (*r)(l, buf, &ks); 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); + error = (*w)(l, buf, ks); } uio->uio_offset = 0; return error; +} +#endif + +int +process_doregs(struct lwp *curl /*tracer*/, + struct lwp *l /*traced*/, + struct uio *uio) +{ +#if defined(PT_GETREGS) || defined(PT_SETREGS) + size_t s; + regrfunc_t r; + regwfunc_t w; + +#ifdef COMPAT_NETBSD32 + const bool pk32 = (l->l_proc->p_flag & PK_32) != 0; + + if (__predict_false(pk32)) { + s = sizeof(process_reg32); + r = (regrfunc_t)process_read_regs32; + w = (regwfunc_t)process_write_regs32; + } else +#endif + { + s = sizeof(struct reg); + r = (regrfunc_t)process_read_regs; + w = (regwfunc_t)process_write_regs; + } + return proc_regio(l, uio, s, r, w); #else return EINVAL; #endif @@ -1352,33 +1399,25 @@ process_dofpregs(struct lwp *curl /*trac 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); + size_t s; + regrfunc_t r; + regwfunc_t w; + +#ifdef COMPAT_NETBSD32 + const bool pk32 = (l->l_proc->p_flag & PK_32) != 0; + + if (__predict_false(pk32)) { + s = sizeof(process_fpreg32); + r = (regrfunc_t)process_read_fpregs32; + w = (regwfunc_t)process_write_fpregs32; + } else +#endif + { + s = sizeof(struct fpreg); + r = (regrfunc_t)process_read_fpregs; + w = (regwfunc_t)process_write_fpregs; } - uio->uio_offset = 0; - return error; + return proc_regio(l, uio, s, r, w); #else return EINVAL; #endif @@ -1401,33 +1440,25 @@ process_dodbregs(struct lwp *curl /*trac struct uio *uio) { #if defined(PT_GETDBREGS) || defined(PT_SETDBREGS) - int error; - struct dbreg 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_dbregs(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_dbregs(l, &r, kl); + size_t s; + regrfunc_t r; + regwfunc_t w; + +#ifdef COMPAT_NETBSD32 + const bool pk32 = (l->l_proc->p_flag & PK_32) != 0; + + if (__predict_false(pk32)) { + s = sizeof(process_dbreg32); + r = (regrfunc_t)process_read_dbregs32; + w = (regwfunc_t)process_write_dbregs32; + } else +#endif + { + s = sizeof(struct dbreg); + r = (regrfunc_t)process_read_dbregs; + w = (regwfunc_t)process_write_dbregs; } - uio->uio_offset = 0; - return error; + return proc_regio(l, uio, s, r, w); #else return EINVAL; #endif Index: src/sys/miscfs/procfs/files.procfs diff -u src/sys/miscfs/procfs/files.procfs:1.11 src/sys/miscfs/procfs/files.procfs:1.11.6.1 --- src/sys/miscfs/procfs/files.procfs:1.11 Thu Mar 30 20:16:29 2017 +++ src/sys/miscfs/procfs/files.procfs Thu Apr 12 13:42:48 2018 @@ -1,11 +1,10 @@ -# $NetBSD: files.procfs,v 1.11 2017/03/30 20:16:29 christos Exp $ +# $NetBSD: files.procfs,v 1.11.6.1 2018/04/12 13:42:48 martin Exp $ deffs PROCFS: PTRACE_HOOKS define procfs: vfs file miscfs/procfs/procfs_auxv.c procfs file miscfs/procfs/procfs_cmdline.c procfs -file miscfs/procfs/procfs_ctl.c procfs file miscfs/procfs/procfs_fd.c procfs file miscfs/procfs/procfs_fpregs.c procfs file miscfs/procfs/procfs_linux.c procfs Index: src/sys/miscfs/procfs/procfs.h diff -u src/sys/miscfs/procfs/procfs.h:1.71 src/sys/miscfs/procfs/procfs.h:1.71.6.1 --- src/sys/miscfs/procfs/procfs.h:1.71 Thu Mar 30 20:16:29 2017 +++ src/sys/miscfs/procfs/procfs.h Thu Apr 12 13:42:48 2018 @@ -1,4 +1,4 @@ -/* $NetBSD: procfs.h,v 1.71 2017/03/30 20:16:29 christos Exp $ */ +/* $NetBSD: procfs.h,v 1.71.6.1 2018/04/12 13:42:48 martin Exp $ */ /* * Copyright (c) 1993 @@ -88,7 +88,6 @@ typedef enum { PFSmem, /* the process's memory image */ PFSregs, /* the process's register set */ PFSfpregs, /* the process's FP register set */ - PFSctl, /* process control */ PFSstat, /* process status (if -o linux) */ PFSstatus, /* process status */ PFSnote, /* process notifier */ @@ -136,7 +135,6 @@ struct pfsnode { }; #define PROCFS_NOTELEN 64 /* max length of a note (/proc/$pid/note) */ -#define PROCFS_CTLLEN 8 /* max length of a ctl msg (/proc/$pid/ctl */ #define PROCFS_MAXNAMLEN 255 #endif /* _KERNEL */ @@ -203,8 +201,6 @@ int procfs_dofpregs(struct lwp *, struct struct uio *); int procfs_domem(struct lwp *, struct lwp *, struct pfsnode *, struct uio *); -int procfs_doctl(struct lwp *, struct lwp *, struct pfsnode *, - struct uio *); int procfs_do_pid_stat(struct lwp *, struct lwp *, struct pfsnode *, struct uio *); int procfs_dostatus(struct lwp *, struct lwp *, struct pfsnode *, Index: src/sys/miscfs/procfs/procfs_subr.c diff -u src/sys/miscfs/procfs/procfs_subr.c:1.108 src/sys/miscfs/procfs/procfs_subr.c:1.108.6.1 --- src/sys/miscfs/procfs/procfs_subr.c:1.108 Sat Apr 1 19:35:57 2017 +++ src/sys/miscfs/procfs/procfs_subr.c Thu Apr 12 13:42:48 2018 @@ -1,4 +1,4 @@ -/* $NetBSD: procfs_subr.c,v 1.108 2017/04/01 19:35:57 riastradh Exp $ */ +/* $NetBSD: procfs_subr.c,v 1.108.6.1 2018/04/12 13:42:48 martin Exp $ */ /*- * Copyright (c) 2006, 2007, 2008 The NetBSD Foundation, Inc. @@ -102,7 +102,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: procfs_subr.c,v 1.108 2017/04/01 19:35:57 riastradh Exp $"); +__KERNEL_RCSID(0, "$NetBSD: procfs_subr.c,v 1.108.6.1 2018/04/12 13:42:48 martin Exp $"); #include <sys/param.h> #include <sys/systm.h> @@ -200,10 +200,6 @@ procfs_rw(void *v) error = procfs_dofpregs(curl, l, pfs, uio); break; - case PFSctl: - error = procfs_doctl(curl, l, pfs, uio); - break; - case PFSstatus: error = procfs_dostatus(curl, l, pfs, uio); break; Index: src/sys/miscfs/procfs/procfs_vfsops.c diff -u src/sys/miscfs/procfs/procfs_vfsops.c:1.97 src/sys/miscfs/procfs/procfs_vfsops.c:1.97.6.1 --- src/sys/miscfs/procfs/procfs_vfsops.c:1.97 Thu Mar 30 20:16:29 2017 +++ src/sys/miscfs/procfs/procfs_vfsops.c Thu Apr 12 13:42:48 2018 @@ -1,4 +1,4 @@ -/* $NetBSD: procfs_vfsops.c,v 1.97 2017/03/30 20:16:29 christos Exp $ */ +/* $NetBSD: procfs_vfsops.c,v 1.97.6.1 2018/04/12 13:42:48 martin Exp $ */ /* * Copyright (c) 1993 @@ -76,7 +76,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: procfs_vfsops.c,v 1.97 2017/03/30 20:16:29 christos Exp $"); +__KERNEL_RCSID(0, "$NetBSD: procfs_vfsops.c,v 1.97.6.1 2018/04/12 13:42:48 martin Exp $"); #if defined(_KERNEL_OPT) #include "opt_compat_netbsd.h" @@ -379,7 +379,6 @@ procfs_loadvnode(struct mount *mp, struc vp->v_type = VREG; break; - case PFSctl: /* /proc/N/ctl = --w------ */ case PFSnote: /* /proc/N/note = --w------ */ case PFSnotepg: /* /proc/N/notepg = --w------ */ pfs->pfs_mode = S_IWUSR; @@ -491,21 +490,15 @@ procfs_listener_cb(kauth_cred_t cred, ka { struct proc *p; struct pfsnode *pfs; - enum kauth_process_req req; int result; result = KAUTH_RESULT_DEFER; p = arg0; pfs = arg1; - req = (enum kauth_process_req)(unsigned long)arg2; if (action != KAUTH_PROCESS_PROCFS) return result; - /* Privileged; let secmodel handle that. */ - if (req == KAUTH_REQ_PROCESS_PROCFS_CTL) - return result; - switch (pfs->pfs_type) { case PFSregs: case PFSfpregs: Index: src/sys/miscfs/procfs/procfs_vnops.c diff -u src/sys/miscfs/procfs/procfs_vnops.c:1.197.2.1 src/sys/miscfs/procfs/procfs_vnops.c:1.197.2.2 --- src/sys/miscfs/procfs/procfs_vnops.c:1.197.2.1 Sun Apr 8 06:10:24 2018 +++ src/sys/miscfs/procfs/procfs_vnops.c Thu Apr 12 13:42:48 2018 @@ -1,4 +1,4 @@ -/* $NetBSD: procfs_vnops.c,v 1.197.2.1 2018/04/08 06:10:24 snj Exp $ */ +/* $NetBSD: procfs_vnops.c,v 1.197.2.2 2018/04/12 13:42:48 martin Exp $ */ /*- * Copyright (c) 2006, 2007, 2008 The NetBSD Foundation, Inc. @@ -105,7 +105,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: procfs_vnops.c,v 1.197.2.1 2018/04/08 06:10:24 snj Exp $"); +__KERNEL_RCSID(0, "$NetBSD: procfs_vnops.c,v 1.197.2.2 2018/04/12 13:42:48 martin Exp $"); #include <sys/param.h> #include <sys/systm.h> @@ -164,7 +164,6 @@ static const struct proc_target { { DT_REG, N("mem"), PFSmem, NULL }, { DT_REG, N("regs"), PFSregs, procfs_validregs }, { DT_REG, N("fpregs"), PFSfpregs, procfs_validfpregs }, - { DT_REG, N("ctl"), PFSctl, NULL }, { DT_REG, N("stat"), PFSstat, procfs_validfile_linux }, { DT_REG, N("status"), PFSstatus, NULL }, { DT_REG, N("note"), PFSnote, NULL }, @@ -742,7 +741,6 @@ procfs_getattr(void *v) if (procp->p_flag & PK_SUGID) vap->va_mode &= ~(S_IRUSR|S_IWUSR); /* FALLTHROUGH */ - case PFSctl: case PFSstatus: case PFSstat: case PFSnote: @@ -888,7 +886,6 @@ procfs_getattr(void *v) break; #endif - case PFSctl: case PFSstatus: case PFSstat: case PFSnote: Index: src/sys/modules/procfs/Makefile diff -u src/sys/modules/procfs/Makefile:1.3 src/sys/modules/procfs/Makefile:1.3.6.1 --- src/sys/modules/procfs/Makefile:1.3 Thu Mar 30 20:16:42 2017 +++ src/sys/modules/procfs/Makefile Thu Apr 12 13:42:48 2018 @@ -1,4 +1,4 @@ -# $NetBSD: Makefile,v 1.3 2017/03/30 20:16:42 christos Exp $ +# $NetBSD: Makefile,v 1.3.6.1 2018/04/12 13:42:48 martin Exp $ .include "../Makefile.inc" @@ -10,7 +10,7 @@ .endif KMOD= procfs -SRCS= procfs_ctl.c procfs_note.c procfs_status.c procfs_subr.c \ +SRCS= procfs_note.c procfs_status.c procfs_subr.c \ procfs_vfsops.c procfs_vnops.c procfs_cmdline.c procfs_linux.c \ procfs_machdep.c procfs_map.c procfs_regs.c procfs_fpregs.c \ procfs_mem.c procfs_fd.c procfs_auxv.c Index: src/sys/sys/kauth.h diff -u src/sys/sys/kauth.h:1.73.10.1 src/sys/sys/kauth.h:1.73.10.2 --- src/sys/sys/kauth.h:1.73.10.1 Tue Aug 1 23:18:31 2017 +++ src/sys/sys/kauth.h Thu Apr 12 13:42:49 2018 @@ -1,4 +1,4 @@ -/* $NetBSD: kauth.h,v 1.73.10.1 2017/08/01 23:18:31 snj Exp $ */ +/* $NetBSD: kauth.h,v 1.73.10.2 2018/04/12 13:42:49 martin Exp $ */ /*- * Copyright (c) 2005, 2006 Elad Efrat <e...@netbsd.org> @@ -225,7 +225,6 @@ enum kauth_process_req { KAUTH_REQ_PROCESS_CORENAME_GET, KAUTH_REQ_PROCESS_CORENAME_SET, KAUTH_REQ_PROCESS_KTRACE_PERSISTENT, - KAUTH_REQ_PROCESS_PROCFS_CTL, KAUTH_REQ_PROCESS_PROCFS_READ, KAUTH_REQ_PROCESS_PROCFS_RW, KAUTH_REQ_PROCESS_PROCFS_WRITE, Index: src/sys/sys/proc.h diff -u src/sys/sys/proc.h:1.340 src/sys/sys/proc.h:1.340.6.1 --- src/sys/sys/proc.h:1.340 Thu Mar 30 20:17:11 2017 +++ src/sys/sys/proc.h Thu Apr 12 13:42:49 2018 @@ -1,4 +1,4 @@ -/* $NetBSD: proc.h,v 1.340 2017/03/30 20:17:11 christos Exp $ */ +/* $NetBSD: proc.h,v 1.340.6.1 2018/04/12 13:42:49 martin Exp $ */ /*- * Copyright (c) 2006, 2007, 2008 The NetBSD Foundation, Inc. @@ -411,7 +411,6 @@ struct proc { 0x00000010 /* traced process wants LWP exit events */ #define PSL_TRACED 0x00000800 /* Debugged process being traced */ -#define PSL_FSTRACE 0x00010000 /* Debugger process being traced by procfs */ #define PSL_CHTRACED 0x00400000 /* Child has been traced & reparented */ #define PSL_SYSCALL 0x04000000 /* process has PT_SYSCALL enabled */ #define PSL_SYSCALLEMU 0x08000000 /* cancel in-progress syscall */ @@ -436,7 +435,7 @@ struct proc { * Macro to compute the exit signal to be delivered. */ #define P_EXITSIG(p) \ - (((p)->p_slflag & (PSL_TRACED|PSL_FSTRACE)) ? SIGCHLD : p->p_exitsig) + (((p)->p_slflag & PSL_TRACED) ? SIGCHLD : p->p_exitsig) /* * Compute a wait(2) 16 bit exit status code */ Index: src/sys/sys/ptrace.h diff -u src/sys/sys/ptrace.h:1.60.6.1 src/sys/sys/ptrace.h:1.60.6.2 --- src/sys/sys/ptrace.h:1.60.6.1 Tue Mar 6 09:52:09 2018 +++ src/sys/sys/ptrace.h Thu Apr 12 13:42:49 2018 @@ -1,4 +1,4 @@ -/* $NetBSD: ptrace.h,v 1.60.6.1 2018/03/06 09:52:09 martin Exp $ */ +/* $NetBSD: ptrace.h,v 1.60.6.2 2018/04/12 13:42:49 martin Exp $ */ /*- * Copyright (c) 1984, 1993 @@ -182,8 +182,10 @@ struct fpreg; #endif struct ptrace_methods { - int (*ptm_copyinpiod)(struct ptrace_io_desc *, const void *); - void (*ptm_copyoutpiod)(const struct ptrace_io_desc *, void *); + int (*ptm_copyin_piod)(struct ptrace_io_desc *, const void *, size_t); + int (*ptm_copyout_piod)(const struct ptrace_io_desc *, void *, size_t); + int (*ptm_copyin_siginfo)(struct ptrace_siginfo *, const void *, size_t); + int (*ptm_copyout_siginfo)(const struct ptrace_siginfo *, void *, size_t); int (*ptm_doregs)(struct lwp *, struct lwp *, struct uio *); int (*ptm_dofpregs)(struct lwp *, struct lwp *, struct uio *); int (*ptm_dodbregs)(struct lwp *, struct lwp *, struct uio *); Index: src/sys/sys/sysctl.h diff -u src/sys/sys/sysctl.h:1.223 src/sys/sys/sysctl.h:1.223.6.1 --- src/sys/sys/sysctl.h:1.223 Sat Mar 25 05:55:36 2017 +++ src/sys/sys/sysctl.h Thu Apr 12 13:42:49 2018 @@ -1,4 +1,4 @@ -/* $NetBSD: sysctl.h,v 1.223 2017/03/25 05:55:36 pgoyette Exp $ */ +/* $NetBSD: sysctl.h,v 1.223.6.1 2018/04/12 13:42:49 martin Exp $ */ /* * Copyright (c) 1989, 1993 @@ -623,7 +623,6 @@ struct kinfo_proc2 { #define P_WEXIT 0x00002000 #define P_EXEC 0x00004000 #define P_OWEUPC 0x00008000 -#define P_FSTRACE 0x00010000 #define P_NOCLDWAIT 0x00020000 #define P_32 0x00040000 #define P_CLDSIGIGN 0x00080000