diff options
author | 2005-09-14 20:55:59 +0000 | |
---|---|---|
committer | 2005-09-14 20:55:59 +0000 | |
commit | f38bed7f869bd3503530c554b4860228ea4e8641 (patch) | |
tree | 78ea133c0d1af019f0fb9951cb0ade43e4df70e7 | |
parent | knf (diff) | |
download | wireguard-openbsd-f38bed7f869bd3503530c554b4860228ea4e8641.tar.xz wireguard-openbsd-f38bed7f869bd3503530c554b4860228ea4e8641.zip |
ptrace(2) following fork(2)
ok miod@
-rw-r--r-- | lib/libc/sys/ptrace.2 | 65 | ||||
-rw-r--r-- | sys/kern/kern_exit.c | 4 | ||||
-rw-r--r-- | sys/kern/kern_fork.c | 49 | ||||
-rw-r--r-- | sys/kern/sys_process.c | 35 | ||||
-rw-r--r-- | sys/sys/proc.h | 6 | ||||
-rw-r--r-- | sys/sys/ptrace.h | 18 |
6 files changed, 169 insertions, 8 deletions
diff --git a/lib/libc/sys/ptrace.2 b/lib/libc/sys/ptrace.2 index a5d9f0b2fad..70c53dd316a 100644 --- a/lib/libc/sys/ptrace.2 +++ b/lib/libc/sys/ptrace.2 @@ -1,4 +1,4 @@ -.\" $OpenBSD: ptrace.2,v 1.19 2005/07/20 21:51:36 miod Exp $ +.\" $OpenBSD: ptrace.2,v 1.20 2005/09/14 20:55:59 kettenis Exp $ .\" $NetBSD: ptrace.2,v 1.3 1996/02/23 01:39:41 jtc Exp $ .\" .\" This file is in the public domain. @@ -232,6 +232,69 @@ will return .Li -1 and set .Va errno . +.It Dv PT_SET_EVENT_MASK +This request can be used to specify which events in the traced process +should be reported to the tracing process. +These events are specified in a +.Dq Li "struct ptrace_event" +defined as: +.Bd -literal -offset indent +typedef struct ptrace_event { + int pe_set_event; +} ptrace_event_t; +.Ed +Where +.Fa pe_set_event +is the set of events to be reported. +This set is formed by OR'ing together the following values: +.Bl -tag -width 18n +.It PTRACE_FORK +Report +.Xr fork 2 . +.El +.Pp +A pointer to this structure is passed in +.Fa addr . +The +.Fa data +argument should be set to +.Li sizeof(struct ptrace_event) . +.It Dv PT_GET_EVENT_MASK +This request can be used to determine which events in the traced +process will be reported. +The information is read into the +.Dq Li struct ptrace_event +pointed to by +.Fa addr . +The +.Fa data +argument should be set to +.Li sizeof(struct ptrace_event) . +.It Dv PT_GET_PROCESS_STATE +This request reads the state information associated with the event +that stopped the traced process. +The information is reported in a +.Dq Li "struct ptrace_state" +defined as: +.Bd -literal -offset indent +typedef struct ptrace_state { + int pe_report_event; + pid_t pe_other_pid; +} ptrace_state_t; +.Ed +Where +.Fa pe_report_event +is the event being reported. +If the event being reported is +.Dv PTRACE_FORK , +.Fa pe_other_pid +will be set to the process ID of the other end of the fork. +A pointer to this structure is passed in +.Fa addr . +The +.Fa data +argument should be set to +.Li sizeof(struct ptrace_state) . .El .Pp Additionally, machine-specific requests can exist. diff --git a/sys/kern/kern_exit.c b/sys/kern/kern_exit.c index 8664f92be3e..ed642342fee 100644 --- a/sys/kern/kern_exit.c +++ b/sys/kern/kern_exit.c @@ -1,4 +1,4 @@ -/* $OpenBSD: kern_exit.c,v 1.54 2004/12/26 21:22:13 miod Exp $ */ +/* $OpenBSD: kern_exit.c,v 1.55 2005/09/14 20:55:59 kettenis Exp $ */ /* $NetBSD: kern_exit.c,v 1.39 1996/04/22 01:38:25 christos Exp $ */ /* @@ -540,6 +540,8 @@ void proc_zap(struct proc *p) { pool_put(&rusage_pool, p->p_ru); + if (p->p_ptstat) + free(p->p_ptstat, M_SUBPROC); /* * Finally finished with old proc entry. diff --git a/sys/kern/kern_fork.c b/sys/kern/kern_fork.c index 5e0d1273538..45d51df536d 100644 --- a/sys/kern/kern_fork.c +++ b/sys/kern/kern_fork.c @@ -1,4 +1,4 @@ -/* $OpenBSD: kern_fork.c,v 1.76 2005/05/29 03:20:41 deraadt Exp $ */ +/* $OpenBSD: kern_fork.c,v 1.77 2005/09/14 20:55:59 kettenis Exp $ */ /* $NetBSD: kern_fork.c,v 1.29 1996/02/09 18:59:34 christos Exp $ */ /* @@ -55,6 +55,7 @@ #include <dev/rndvar.h> #include <sys/pool.h> #include <sys/mman.h> +#include <sys/ptrace.h> #include <sys/syscallargs.h> @@ -69,14 +70,31 @@ int randompid; /* when set to 1, pid's go random */ pid_t lastpid; struct forkstat forkstat; +void fork_return(void *); int pidtaken(pid_t); +void +fork_return(void *arg) +{ + struct proc *p = (struct proc *)arg; + + if (p->p_flag & P_TRACED) + psignal(p, SIGTRAP); + + child_return(p); +} + /*ARGSUSED*/ int sys_fork(struct proc *p, void *v, register_t *retval) { - return (fork1(p, SIGCHLD, FORK_FORK, NULL, 0, NULL, - NULL, retval, NULL)); + int flags; + + flags = FORK_FORK; + if (p->p_ptmask & PTRACE_FORK) + flags |= FORK_PTRACE; + return (fork1(p, SIGCHLD, flags, NULL, 0, + fork_return, NULL, retval, NULL)); } /*ARGSUSED*/ @@ -220,6 +238,8 @@ fork1(struct proc *p1, int exitsig, int flags, void *stack, size_t stacksize, if (p1->p_flag & P_PROFIL) startprofclock(p2); p2->p_flag |= (p1->p_flag & (P_SUGID | P_SUGIDEXEC)); + if (flags & FORK_PTRACE) + p2->p_flag |= (p1->p_flag & P_TRACED); p2->p_cred = pool_get(&pcred_pool, PR_WAITOK); bcopy(p1->p_cred, p2->p_cred, sizeof(*p2->p_cred)); p2->p_cred->p_refcnt = 1; @@ -329,6 +349,23 @@ fork1(struct proc *p1, int exitsig, int flags, void *stack, size_t stacksize, lastpid = 1 + (randompid ? arc4random() : lastpid) % PID_MAX; } while (pidtaken(lastpid)); p2->p_pid = lastpid; + if (p2->p_flag & P_TRACED) { + p2->p_oppid = p1->p_pid; + if (p2->p_pptr != p1->p_pptr) + proc_reparent(p2, p1->p_pptr); + + /* + * Set ptrace status. + */ + if (flags & FORK_FORK) { + p2->p_ptstat = malloc(sizeof(*p2->p_ptstat), + M_SUBPROC, M_WAITOK); + p1->p_ptstat->pe_report_event = PTRACE_FORK; + p2->p_ptstat->pe_report_event = PTRACE_FORK; + p1->p_ptstat->pe_other_pid = p2->p_pid; + p2->p_ptstat->pe_other_pid = p1->p_pid; + } + } LIST_INSERT_HEAD(&allproc, p2, p_list); LIST_INSERT_HEAD(PIDHASH(p2->p_pid), p2, p_hash); @@ -386,6 +423,12 @@ fork1(struct proc *p1, int exitsig, int flags, void *stack, size_t stacksize, tsleep(p1, PWAIT, "ppwait", 0); /* + * If we're tracing the child, alert the parent too. + */ + if ((flags & FORK_PTRACE) && (p1->p_flag & P_TRACED)) + psignal(p1, SIGTRAP); + + /* * Return child pid to parent process, * marking us as parent via retval[1]. */ diff --git a/sys/kern/sys_process.c b/sys/kern/sys_process.c index 98647d1226c..f6bd38083f7 100644 --- a/sys/kern/sys_process.c +++ b/sys/kern/sys_process.c @@ -1,4 +1,4 @@ -/* $OpenBSD: sys_process.c,v 1.31 2005/08/02 18:04:07 kettenis Exp $ */ +/* $OpenBSD: sys_process.c,v 1.32 2005/09/14 20:55:59 kettenis Exp $ */ /* $NetBSD: sys_process.c,v 1.55 1996/05/15 06:17:47 tls Exp $ */ /*- @@ -88,6 +88,7 @@ sys_ptrace(p, v, retval) struct uio uio; struct iovec iov; struct ptrace_io_desc piod; + struct ptrace_event pe; struct reg *regs; #if defined (PT_SETFPREGS) || defined (PT_GETFPREGS) struct fpreg *fpregs; @@ -179,6 +180,9 @@ sys_ptrace(p, v, retval) #ifdef PT_STEP case PT_STEP: #endif + case PT_SET_EVENT_MASK: + case PT_GET_EVENT_MASK: + case PT_GET_PROCESS_STATE: case PT_GETREGS: case PT_SETREGS: #ifdef PT_GETFPREGS @@ -232,6 +236,10 @@ sys_ptrace(p, v, retval) /* Just set the trace flag. */ SET(t->p_flag, P_TRACED); t->p_oppid = t->p_pptr->p_pid; + if (t->p_ptstat == NULL) + t->p_ptstat = malloc(sizeof(*t->p_ptstat), + M_SUBPROC, M_WAITOK); + bzero(t->p_ptstat, sizeof(*t->p_ptstat)); return (0); case PT_WRITE_I: /* XXX no separate I and D spaces */ @@ -366,6 +374,8 @@ sys_ptrace(p, v, retval) CLR(t->p_flag, P_TRACED|P_WAITED); sendsig: + bzero(t->p_ptstat, sizeof(*t->p_ptstat)); + /* Finally, deliver the requested signal (or none). */ if (t->p_stat == SSTOP) { t->p_xstat = SCARG(uap, data); @@ -401,9 +411,32 @@ sys_ptrace(p, v, retval) t->p_oppid = t->p_pptr->p_pid; if (t->p_pptr != p) proc_reparent(t, p); + if (t->p_ptstat == NULL) + t->p_ptstat = malloc(sizeof(*t->p_ptstat), + M_SUBPROC, M_WAITOK); SCARG(uap, data) = SIGSTOP; goto sendsig; + case PT_GET_EVENT_MASK: + if (SCARG(uap, data) != sizeof(pe)) + return (EINVAL); + bzero(&pe, sizeof(pe)); + pe.pe_set_event = t->p_ptmask; + return (copyout(&pe, SCARG(uap, addr), sizeof(pe))); + case PT_SET_EVENT_MASK: + if (SCARG(uap, data) != sizeof(pe)) + return (EINVAL); + if ((error = copyin(SCARG(uap, addr), &pe, sizeof(pe)))) + return (error); + t->p_ptmask = pe.pe_set_event; + return (0); + + case PT_GET_PROCESS_STATE: + if (SCARG(uap, data) != sizeof(*t->p_ptstat)) + return (EINVAL); + return (copyout(t->p_ptstat, SCARG(uap, addr), + sizeof(*t->p_ptstat))); + case PT_SETREGS: KASSERT((p->p_flag & P_SYSTEM) == 0); if ((error = procfs_checkioperm(p, t)) != 0) diff --git a/sys/sys/proc.h b/sys/sys/proc.h index 2d804b9c84f..642633e87e2 100644 --- a/sys/sys/proc.h +++ b/sys/sys/proc.h @@ -1,4 +1,4 @@ -/* $OpenBSD: proc.h,v 1.79 2005/05/29 03:20:42 deraadt Exp $ */ +/* $OpenBSD: proc.h,v 1.80 2005/09/14 20:55:59 kettenis Exp $ */ /* $NetBSD: proc.h,v 1.44 1996/04/22 01:23:21 christos Exp $ */ /*- @@ -186,6 +186,9 @@ struct proc { void *p_systrace; /* Back pointer to systrace */ + int p_ptmask; /* Ptrace event mask */ + struct ptrace_state *p_ptstat; /* Ptrace state */ + int p_siglist; /* Signals arrived but not delivered. */ struct vnode *p_textvp; /* Vnode of executable. */ @@ -357,6 +360,7 @@ struct uidinfo *uid_find(uid_t); #define FORK_NOZOMBIE 0x00000040 #define FORK_SHAREVM 0x00000080 #define FORK_SIGHAND 0x00000200 +#define FORK_PTRACE 0x00000400 #define PIDHASH(pid) (&pidhashtbl[(pid) & pidhash]) extern LIST_HEAD(pidhashhead, proc) *pidhashtbl; diff --git a/sys/sys/ptrace.h b/sys/sys/ptrace.h index e66a65a3c24..e20a7490fee 100644 --- a/sys/sys/ptrace.h +++ b/sys/sys/ptrace.h @@ -1,4 +1,4 @@ -/* $OpenBSD: ptrace.h,v 1.8 2003/06/02 23:28:21 millert Exp $ */ +/* $OpenBSD: ptrace.h,v 1.9 2005/09/14 20:55:59 kettenis Exp $ */ /* $NetBSD: ptrace.h,v 1.21 1996/02/09 18:25:26 christos Exp $ */ /*- @@ -61,6 +61,22 @@ struct ptrace_io_desc { #define PIOD_READ_I 3 /* Read from I space */ #define PIOD_WRITE_I 4 /* Write to I space */ +#define PT_SET_EVENT_MASK 12 +#define PT_GET_EVENT_MASK 13 + +typedef struct ptrace_event { + int pe_set_event; +} ptrace_event_t; + +#define PTRACE_FORK 0x0002 /* Report forks */ + +#define PT_GET_PROCESS_STATE 14 + +typedef struct ptrace_state { + int pe_report_event; + pid_t pe_other_pid; +} ptrace_state_t; + #define PT_FIRSTMACH 32 /* for machine-specific requests */ #include <machine/ptrace.h> /* machine-specific requests, if any */ |