summaryrefslogtreecommitdiff
path: root/sys
diff options
context:
space:
mode:
authorPhilip Guenthe <guenther@cvs.openbsd.org>2012-02-20 22:23:40 +0000
committerPhilip Guenthe <guenther@cvs.openbsd.org>2012-02-20 22:23:40 +0000
commit23d4c835c870fad1811850ff7a698a2f77d42891 (patch)
tree5a131e9e444f40e7cd66618e1c99d06b4bafa989 /sys
parentb73a150e06f421a7575e708802b38aa3d837f2b7 (diff)
First steps for making ptrace work with rthreads:
- move the P_TRACED and P_INEXEC flags, and p_oppid, p_ptmask, and p_ptstat member from struct proc to struct process - sort the PT_* requests into those that take a PID vs those that can also take a TID - stub in PT_GET_THREAD_FIRST and PT_GET_THREAD_NEXT ok kettenis@
Diffstat (limited to 'sys')
-rw-r--r--sys/dev/systrace.c8
-rw-r--r--sys/kern/kern_exec.c12
-rw-r--r--sys/kern/kern_exit.c26
-rw-r--r--sys/kern/kern_fork.c45
-rw-r--r--sys/kern/kern_prot.c4
-rw-r--r--sys/kern/kern_sig.c32
-rw-r--r--sys/kern/kern_sysctl.c4
-rw-r--r--sys/kern/sched_bsd.c4
-rw-r--r--sys/kern/sys_process.c182
-rw-r--r--sys/miscfs/procfs/procfs_vnops.c4
-rw-r--r--sys/sys/proc.h20
-rw-r--r--sys/sys/ptrace.h11
-rw-r--r--sys/sys/signalvar.h4
13 files changed, 223 insertions, 133 deletions
diff --git a/sys/dev/systrace.c b/sys/dev/systrace.c
index f48ffdec652..16d01c7d53d 100644
--- a/sys/dev/systrace.c
+++ b/sys/dev/systrace.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: systrace.c,v 1.61 2012/02/15 04:26:27 guenther Exp $ */
+/* $OpenBSD: systrace.c,v 1.62 2012/02/20 22:23:39 guenther Exp $ */
/*
* Copyright 2002 Niels Provos <provos@citi.umich.edu>
* All rights reserved.
@@ -1203,12 +1203,12 @@ systrace_attach(struct fsystrace *fst, pid_t pid)
struct proc *proc, *p = curproc;
struct str_process *newstrp;
- if ((proc = pfind(pid)) == NULL) {
+ if ((proc = pfind(pid)) == NULL || (proc->p_flag & P_THREAD)) {
error = ESRCH;
goto out;
}
- if (ISSET(proc->p_flag, P_INEXEC)) {
+ if (ISSET(proc->p_p->ps_flags, PS_INEXEC)) {
error = EAGAIN;
goto out;
}
@@ -1217,7 +1217,7 @@ systrace_attach(struct fsystrace *fst, pid_t pid)
* You can't attach to a process if:
* (1) it's the process that's doing the attaching,
*/
- if (proc->p_pid == p->p_pid) {
+ if (proc->p_p == p->p_p) {
error = EINVAL;
goto out;
}
diff --git a/sys/kern/kern_exec.c b/sys/kern/kern_exec.c
index 1b1ac0d84d2..c8c2f1c1378 100644
--- a/sys/kern/kern_exec.c
+++ b/sys/kern/kern_exec.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: kern_exec.c,v 1.123 2012/02/15 04:26:27 guenther Exp $ */
+/* $OpenBSD: kern_exec.c,v 1.124 2012/02/20 22:23:39 guenther Exp $ */
/* $NetBSD: kern_exec.c,v 1.75 1996/02/09 18:59:28 christos Exp $ */
/*-
@@ -275,7 +275,7 @@ sys_execve(struct proc *p, void *v, register_t *retval)
* Cheap solution to complicated problems.
* Mark this process as "leave me alone, I'm execing".
*/
- atomic_setbits_int(&p->p_flag, P_INEXEC);
+ atomic_setbits_int(&pr->ps_flags, PS_INEXEC);
#if NSYSTRACE > 0
if (ISSET(p->p_flag, P_SYSTRACE)) {
@@ -642,7 +642,7 @@ sys_execve(struct proc *p, void *v, register_t *retval)
goto free_pack_abort;
#endif
- if (p->p_flag & P_TRACED)
+ if (pr->ps_flags & PS_TRACED)
psignal(p, SIGTRAP);
free(pack.ep_hdr, M_EXEC);
@@ -680,7 +680,7 @@ sys_execve(struct proc *p, void *v, register_t *retval)
ktremul(p, p->p_emul->e_name);
#endif
- atomic_clearbits_int(&p->p_flag, P_INEXEC);
+ atomic_clearbits_int(&pr->ps_flags, PS_INEXEC);
single_thread_clear(p);
#if NSYSTRACE > 0
@@ -718,7 +718,7 @@ bad:
#if NSYSTRACE > 0
clrflag:
#endif
- atomic_clearbits_int(&p->p_flag, P_INEXEC);
+ atomic_clearbits_int(&pr->ps_flags, PS_INEXEC);
single_thread_clear(p);
if (pathbuf != NULL)
@@ -747,7 +747,7 @@ free_pack_abort:
exit1(p, W_EXITCODE(0, SIGABRT), EXIT_NORMAL);
/* NOTREACHED */
- atomic_clearbits_int(&p->p_flag, P_INEXEC);
+ atomic_clearbits_int(&pr->ps_flags, PS_INEXEC);
if (pathbuf != NULL)
pool_put(&namei_pool, pathbuf);
diff --git a/sys/kern/kern_exit.c b/sys/kern/kern_exit.c
index 50e9e0e3cf9..89f4fa423fc 100644
--- a/sys/kern/kern_exit.c
+++ b/sys/kern/kern_exit.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: kern_exit.c,v 1.106 2012/01/17 02:34:18 guenther Exp $ */
+/* $OpenBSD: kern_exit.c,v 1.107 2012/02/20 22:23:39 guenther Exp $ */
/* $NetBSD: kern_exit.c,v 1.39 1996/04/22 01:38:25 christos Exp $ */
/*
@@ -262,9 +262,8 @@ exit1(struct proc *p, int rv, int flags)
* Traced processes are killed
* since their existence means someone is screwing up.
*/
- if (qr->ps_mainproc->p_flag & P_TRACED) {
- atomic_clearbits_int(&qr->ps_mainproc->p_flag,
- P_TRACED);
+ if (qr->ps_flags & PS_TRACED) {
+ atomic_clearbits_int(&qr->ps_flags, PS_TRACED);
prsignal(qr, SIGKILL);
}
}
@@ -476,7 +475,8 @@ loop:
}
if (p->p_stat == SSTOP &&
(p->p_flag & (P_WAITED|P_SUSPSINGLE)) == 0 &&
- (p->p_flag & P_TRACED || SCARG(uap, options) & WUNTRACED)) {
+ (pr->ps_flags & PS_TRACED ||
+ SCARG(uap, options) & WUNTRACED)) {
atomic_setbits_int(&p->p_flag, P_WAITED);
retval[0] = p->p_pid;
@@ -515,16 +515,18 @@ loop:
void
proc_finish_wait(struct proc *waiter, struct proc *p)
{
- struct process *tr;
+ struct process *pr, *tr;
/*
* If we got the child via a ptrace 'attach',
* we need to give it back to the old parent.
*/
- if (p->p_oppid && (tr = prfind(p->p_oppid))) {
- atomic_clearbits_int(&p->p_flag, P_TRACED);
- p->p_oppid = 0;
- proc_reparent(p->p_p, tr);
+ pr = p->p_p;
+ if ((p->p_flag & P_THREAD) == 0 && pr->ps_oppid &&
+ (tr = prfind(pr->ps_oppid))) {
+ atomic_clearbits_int(&pr->ps_flags, PS_TRACED);
+ pr->ps_oppid = 0;
+ proc_reparent(pr, tr);
if (p->p_exitsig != 0)
prsignal(tr, p->p_exitsig);
wakeup(tr);
@@ -560,8 +562,8 @@ proc_zap(struct proc *p)
struct process *pr = p->p_p;
pool_put(&rusage_pool, p->p_ru);
- if (p->p_ptstat)
- free(p->p_ptstat, M_SUBPROC);
+ if ((p->p_flag & P_THREAD) == 0 && pr->ps_ptstat)
+ free(pr->ps_ptstat, M_SUBPROC);
/*
* Finally finished with old proc entry.
diff --git a/sys/kern/kern_fork.c b/sys/kern/kern_fork.c
index 0c3745ba139..bf667d3b901 100644
--- a/sys/kern/kern_fork.c
+++ b/sys/kern/kern_fork.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: kern_fork.c,v 1.133 2011/12/14 07:32:16 guenther Exp $ */
+/* $OpenBSD: kern_fork.c,v 1.134 2012/02/20 22:23:39 guenther Exp $ */
/* $NetBSD: kern_fork.c,v 1.29 1996/02/09 18:59:34 christos Exp $ */
/*
@@ -85,7 +85,7 @@ fork_return(void *arg)
{
struct proc *p = (struct proc *)arg;
- if (p->p_flag & P_TRACED)
+ if (p->p_p->ps_flags & PS_TRACED)
psignal(p, SIGTRAP);
child_return(p);
@@ -98,7 +98,7 @@ sys_fork(struct proc *p, void *v, register_t *retval)
int flags;
flags = FORK_FORK;
- if (p->p_ptmask & PTRACE_FORK)
+ if (p->p_p->ps_ptmask & PTRACE_FORK)
flags |= FORK_PTRACE;
return (fork1(p, SIGCHLD, flags, NULL, 0,
fork_return, NULL, retval, NULL));
@@ -341,7 +341,7 @@ fork1(struct proc *curp, int exitsig, int flags, void *stack, pid_t *tidptr,
if (curp->p_flag & P_PROFIL)
startprofclock(p);
if (flags & FORK_PTRACE)
- atomic_setbits_int(&p->p_flag, curp->p_flag & P_TRACED);
+ atomic_setbits_int(&pr->ps_flags, curpr->ps_flags & PS_TRACED);
/* bump references to the text vnode (for procfs) */
p->p_textvp = curp->p_textvp;
@@ -427,7 +427,7 @@ fork1(struct proc *curp, int exitsig, int flags, void *stack, pid_t *tidptr,
forkstat.sizkthread += vm->vm_dsize + vm->vm_ssize;
}
- if (p->p_flag & P_TRACED && flags & FORK_FORK)
+ if (pr->ps_flags & PS_TRACED && flags & FORK_FORK)
newptstat = malloc(sizeof(*newptstat), M_SUBPROC, M_WAITOK);
#if NSYSTRACE > 0
if (ISSET(curp->p_flag, P_SYSTRACE))
@@ -445,24 +445,23 @@ fork1(struct proc *curp, int exitsig, int flags, void *stack, pid_t *tidptr,
if ((flags & FORK_THREAD) == 0) {
LIST_INSERT_AFTER(curpr, pr, ps_pglist);
LIST_INSERT_HEAD(&curpr->ps_children, pr, ps_sibling);
- }
- if (p->p_flag & P_TRACED) {
- p->p_oppid = curp->p_pid;
- if ((flags & FORK_THREAD) == 0 &&
- pr->ps_pptr != curpr->ps_pptr)
- proc_reparent(pr, curpr->ps_pptr);
-
- /*
- * Set ptrace status.
- */
- if (flags & FORK_FORK) {
- p->p_ptstat = newptstat;
- newptstat = NULL;
- curp->p_ptstat->pe_report_event = PTRACE_FORK;
- p->p_ptstat->pe_report_event = PTRACE_FORK;
- curp->p_ptstat->pe_other_pid = p->p_pid;
- p->p_ptstat->pe_other_pid = curp->p_pid;
+ if (pr->ps_flags & PS_TRACED) {
+ pr->ps_oppid = curpr->ps_pid;
+ if (pr->ps_pptr != curpr->ps_pptr)
+ proc_reparent(pr, curpr->ps_pptr);
+
+ /*
+ * Set ptrace status.
+ */
+ if (flags & FORK_FORK) {
+ pr->ps_ptstat = newptstat;
+ newptstat = NULL;
+ curpr->ps_ptstat->pe_report_event = PTRACE_FORK;
+ pr->ps_ptstat->pe_report_event = PTRACE_FORK;
+ curpr->ps_ptstat->pe_other_pid = pr->ps_pid;
+ pr->ps_ptstat->pe_other_pid = curpr->ps_pid;
+ }
}
}
@@ -527,7 +526,7 @@ fork1(struct proc *curp, int exitsig, int flags, void *stack, pid_t *tidptr,
/*
* If we're tracing the child, alert the parent too.
*/
- if ((flags & FORK_PTRACE) && (curp->p_flag & P_TRACED))
+ if ((flags & FORK_PTRACE) && (curpr->ps_flags & PS_TRACED))
psignal(curp, SIGTRAP);
/*
diff --git a/sys/kern/kern_prot.c b/sys/kern/kern_prot.c
index e936e44970e..95a7c0a2401 100644
--- a/sys/kern/kern_prot.c
+++ b/sys/kern/kern_prot.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: kern_prot.c,v 1.51 2011/10/15 23:35:29 guenther Exp $ */
+/* $OpenBSD: kern_prot.c,v 1.52 2012/02/20 22:23:39 guenther Exp $ */
/* $NetBSD: kern_prot.c,v 1.33 1996/02/09 18:59:42 christos Exp $ */
/*
@@ -884,7 +884,7 @@ int
proc_cansugid(struct proc *p)
{
/* ptrace(2)d processes shouldn't. */
- if ((p->p_flag & P_TRACED) != 0)
+ if ((p->p_p->ps_flags & PS_TRACED) != 0)
return (0);
/* processes with shared filedescriptors shouldn't. */
diff --git a/sys/kern/kern_sig.c b/sys/kern/kern_sig.c
index de6f59f7188..e3ec6386bc0 100644
--- a/sys/kern/kern_sig.c
+++ b/sys/kern/kern_sig.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: kern_sig.c,v 1.133 2012/01/25 06:12:13 guenther Exp $ */
+/* $OpenBSD: kern_sig.c,v 1.134 2012/02/20 22:23:39 guenther Exp $ */
/* $NetBSD: kern_sig.c,v 1.54 1996/04/22 01:38:32 christos Exp $ */
/*
@@ -694,7 +694,8 @@ trapsignal(struct proc *p, int signum, u_long trapno, int code,
int mask;
mask = sigmask(signum);
- if ((p->p_flag & P_TRACED) == 0 && (ps->ps_sigcatch & mask) != 0 &&
+ if ((p->p_p->ps_flags & PS_TRACED) == 0 &&
+ (ps->ps_sigcatch & mask) != 0 &&
(p->p_sigmask & mask) == 0) {
#ifdef KTRACE
if (KTRPOINT(p, KTR_PSIG)) {
@@ -805,7 +806,7 @@ ptsignal(struct proc *p, int signum, enum signal_type type)
/*
* If proc is traced, always give parent a chance.
*/
- if (p->p_flag & P_TRACED) {
+ if (pr->ps_flags & PS_TRACED) {
action = SIG_DFL;
atomic_setbits_int(&p->p_siglist, mask);
} else if (p->p_sigdivert & mask) {
@@ -890,7 +891,7 @@ ptsignal(struct proc *p, int signum, enum signal_type type)
* so it can discover the signal in issignal() and stop
* for the parent.
*/
- if (p->p_flag & P_TRACED)
+ if (pr->ps_flags & PS_TRACED)
goto run;
/*
* If SIGCONT is default (or ignored) and process is
@@ -929,14 +930,16 @@ ptsignal(struct proc *p, int signum, enum signal_type type)
* If traced process is already stopped,
* then no further action is necessary.
*/
- if (p->p_flag & P_TRACED)
+ if (pr->ps_flags & PS_TRACED)
goto out;
/*
* Kill signal always sets processes running.
*/
- if (signum == SIGKILL)
+ if (signum == SIGKILL) {
+ atomic_clearbits_int(&p->p_flag, P_SUSPSIG);
goto runfast;
+ }
if (prop & SA_CONT) {
/*
@@ -950,6 +953,7 @@ ptsignal(struct proc *p, int signum, enum signal_type type)
* Otherwise, process goes back to sleep state.
*/
atomic_setbits_int(&p->p_flag, P_CONTINUED);
+ atomic_clearbits_int(&p->p_flag, P_SUSPSIG);
wakeparent = 1;
if (action == SIG_DFL)
atomic_clearbits_int(&p->p_siglist, mask);
@@ -1022,13 +1026,14 @@ out:
int
issignal(struct proc *p)
{
+ struct process *pr = p->p_p;
int signum, mask, prop;
int dolock = (p->p_flag & P_SINTR) == 0;
int s;
for (;;) {
mask = p->p_siglist & ~p->p_sigmask;
- if (p->p_p->ps_flags & PS_PPWAIT)
+ if (pr->ps_flags & PS_PPWAIT)
mask &= ~stopsigmask;
if (mask == 0) /* no signal to send */
return (0);
@@ -1041,11 +1046,10 @@ issignal(struct proc *p)
* only if P_TRACED was on when they were posted.
*/
if (mask & p->p_sigacts->ps_sigignore &&
- (p->p_flag & P_TRACED) == 0)
+ (pr->ps_flags & PS_TRACED) == 0)
continue;
- if (p->p_flag & P_TRACED &&
- (p->p_p->ps_flags & PS_PPWAIT) == 0) {
+ if ((pr->ps_flags & (PS_TRACED | PS_PPWAIT)) == PS_TRACED) {
/*
* If traced, always stop, and stay
* stopped until released by the debugger.
@@ -1062,7 +1066,7 @@ issignal(struct proc *p)
* If we are no longer being traced, or the parent
* didn't give us a signal, look for more signals.
*/
- if ((p->p_flag & P_TRACED) == 0 || p->p_xstat == 0)
+ if ((pr->ps_flags & PS_TRACED) == 0 || p->p_xstat == 0)
continue;
/*
@@ -1110,8 +1114,8 @@ issignal(struct proc *p)
* process group, ignore tty stop signals.
*/
if (prop & SA_STOP) {
- if (p->p_flag & P_TRACED ||
- (p->p_p->ps_pgrp->pg_jobc == 0 &&
+ if (pr->ps_flags & PS_TRACED ||
+ (pr->ps_pgrp->pg_jobc == 0 &&
prop & SA_TTYSTOP))
break; /* == ignore */
p->p_xstat = signum;
@@ -1138,7 +1142,7 @@ issignal(struct proc *p)
* than SIGCONT, unless process is traced.
*/
if ((prop & SA_CONT) == 0 &&
- (p->p_flag & P_TRACED) == 0)
+ (pr->ps_flags & PS_TRACED) == 0)
printf("issignal\n");
break; /* == ignore */
diff --git a/sys/kern/kern_sysctl.c b/sys/kern/kern_sysctl.c
index 408cbf793a0..9fc8513424f 100644
--- a/sys/kern/kern_sysctl.c
+++ b/sys/kern/kern_sysctl.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: kern_sysctl.c,v 1.213 2012/02/15 04:29:09 guenther Exp $ */
+/* $OpenBSD: kern_sysctl.c,v 1.214 2012/02/20 22:23:39 guenther Exp $ */
/* $NetBSD: kern_sysctl.c,v 1.17 1996/05/20 17:49:05 mrg Exp $ */
/*-
@@ -1584,7 +1584,7 @@ sysctl_proc_args(int *name, u_int namelen, void *oldp, size_t *oldlenp,
return (ESRCH);
/* Execing - danger. */
- if ((vp->p_flag & P_INEXEC))
+ if ((vp->p_p->ps_flags & PS_INEXEC))
return (EBUSY);
vm = vp->p_vmspace;
diff --git a/sys/kern/sched_bsd.c b/sys/kern/sched_bsd.c
index 2a79afb234e..6fb2772e5ce 100644
--- a/sys/kern/sched_bsd.c
+++ b/sys/kern/sched_bsd.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: sched_bsd.c,v 1.27 2011/07/07 18:00:33 guenther Exp $ */
+/* $OpenBSD: sched_bsd.c,v 1.28 2012/02/20 22:23:39 guenther Exp $ */
/* $NetBSD: kern_synch.c,v 1.37 1996/04/22 01:38:37 christos Exp $ */
/*-
@@ -507,7 +507,7 @@ setrunnable(struct proc *p)
* If we're being traced (possibly because someone attached us
* while we were stopped), check for a signal from the debugger.
*/
- if ((p->p_flag & P_TRACED) != 0 && p->p_xstat != 0)
+ if ((p->p_p->ps_flags & PS_TRACED) != 0 && p->p_xstat != 0)
atomic_setbits_int(&p->p_siglist, sigmask(p->p_xstat));
case SSLEEP:
unsleep(p); /* e.g. when sending signals */
diff --git a/sys/kern/sys_process.c b/sys/kern/sys_process.c
index cfc19e44305..7ab663c1c65 100644
--- a/sys/kern/sys_process.c
+++ b/sys/kern/sys_process.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: sys_process.c,v 1.48 2011/04/02 17:04:35 guenther Exp $ */
+/* $OpenBSD: sys_process.c,v 1.49 2012/02/20 22:23:39 guenther Exp $ */
/* $NetBSD: sys_process.c,v 1.55 1996/05/15 06:17:47 tls Exp $ */
/*-
@@ -82,7 +82,9 @@ sys_ptrace(struct proc *p, void *v, register_t *retval)
syscallarg(caddr_t) addr;
syscallarg(int) data;
} */ *uap = v;
- struct proc *t; /* target process */
+ struct proc *t; /* target thread */
+ struct process *tr; /* target process */
+ struct proc *q;
struct uio uio;
struct iovec iov;
struct ptrace_io_desc piod;
@@ -99,24 +101,65 @@ sys_ptrace(struct proc *p, void *v, register_t *retval)
#endif
int error, write;
int temp;
- int req;
+ int req = SCARG(uap, req);
int s;
/* "A foolish consistency..." XXX */
- if (SCARG(uap, req) == PT_TRACE_ME)
+ switch (req) {
+ case PT_TRACE_ME:
t = p;
- else {
+ break;
+ /* calls that only operate on the PID */
+ case PT_READ_I:
+ case PT_READ_D:
+ case PT_WRITE_I:
+ case PT_WRITE_D:
+ case PT_KILL:
+ case PT_ATTACH:
+ case PT_IO:
+ case PT_SET_EVENT_MASK:
+ case PT_GET_EVENT_MASK:
+ case PT_GET_PROCESS_STATE:
+ case PT_GET_THREAD_FIRST:
+ case PT_GET_THREAD_NEXT:
+ default:
/* Find the process we're supposed to be operating on. */
if ((t = pfind(SCARG(uap, pid))) == NULL)
return (ESRCH);
+ if (t->p_flag & P_THREAD)
+ return (ESRCH);
+ break;
+
+ /* calls that accept a PID or a thread ID */
+ case PT_CONTINUE:
+ case PT_DETACH:
+#ifdef PT_STEP
+ case PT_STEP:
+#endif
+ case PT_GETREGS:
+ case PT_SETREGS:
+ case PT_GETFPREGS:
+ case PT_SETFPREGS:
+ if (SCARG(uap, pid) > THREAD_PID_OFFSET) {
+ t = pfind(SCARG(uap, pid) - THREAD_PID_OFFSET);
+ if (t == NULL)
+ return (ESRCH);
+ } else {
+ if ((t = pfind(SCARG(uap, pid))) == NULL)
+ return (ESRCH);
+ if (t->p_flag & P_THREAD)
+ return (ESRCH);
+ }
+ break;
}
+ tr = t->p_p;
- if ((t->p_flag & P_INEXEC) != 0)
+ if ((tr->ps_flags & PS_INEXEC) != 0)
return (EAGAIN);
/* Make sure we can operate on it. */
- switch (SCARG(uap, req)) {
+ switch (req) {
case PT_TRACE_ME:
/* Saying that you're being traced is always legal. */
break;
@@ -126,7 +169,7 @@ sys_ptrace(struct proc *p, void *v, register_t *retval)
* 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)
+ if (tr == p->p_p)
return (EINVAL);
/*
@@ -138,7 +181,7 @@ sys_ptrace(struct proc *p, void *v, register_t *retval)
/*
* (3) it's already being traced, or
*/
- if (ISSET(t->p_flag, P_TRACED))
+ if (ISSET(tr->ps_flags, PS_TRACED))
return (EBUSY);
/*
@@ -152,8 +195,8 @@ sys_ptrace(struct proc *p, void *v, register_t *retval)
* process which revokes its special privileges using
* setuid() from being traced. This is good security.]
*/
- if ((t->p_cred->p_ruid != p->p_cred->p_ruid ||
- ISSET(t->p_p->ps_flags, PS_SUGIDEXEC | PS_SUGID)) &&
+ if ((tr->ps_cred->p_ruid != p->p_cred->p_ruid ||
+ ISSET(tr->ps_flags, PS_SUGIDEXEC | PS_SUGID)) &&
(error = suser(p, 0)) != 0)
return (error);
@@ -163,7 +206,7 @@ sys_ptrace(struct proc *p, void *v, register_t *retval)
* compiled with permanently insecure mode turned
* on.
*/
- if ((t->p_pid == 1) && (securelevel > -1))
+ if ((tr->ps_pid == 1) && (securelevel > -1))
return (EPERM);
/*
@@ -171,7 +214,7 @@ sys_ptrace(struct proc *p, void *v, register_t *retval)
* not init (because that would create a loop in
* the process graph).
*/
- if (t->p_pid != 1 && inferior(p->p_p, t->p_p))
+ if (tr->ps_pid != 1 && inferior(p->p_p, tr))
return (EINVAL);
break;
@@ -210,13 +253,13 @@ sys_ptrace(struct proc *p, void *v, register_t *retval)
* You can't do what you want to the process if:
* (1) It's not being traced at all,
*/
- if (!ISSET(t->p_flag, P_TRACED))
+ if (!ISSET(tr->ps_flags, PS_TRACED))
return (EPERM);
/*
* (2) it's not being traced by _you_, or
*/
- if (t->p_p->ps_pptr != p->p_p)
+ if (tr->ps_pptr != p->p_p)
return (EBUSY);
/*
@@ -226,6 +269,31 @@ sys_ptrace(struct proc *p, void *v, register_t *retval)
return (EBUSY);
break;
+ case PT_GET_THREAD_FIRST:
+ case PT_GET_THREAD_NEXT:
+ /*
+ * You can't do what you want to the process if:
+ * (1) It's not being traced at all,
+ */
+ if (!ISSET(tr->ps_flags, PS_TRACED))
+ return (EPERM);
+
+ /*
+ * (2) it's not being traced by _you_, or
+ */
+ if (tr->ps_pptr != p->p_p)
+ return (EBUSY);
+
+ /*
+ * Do the work here because the request isn't actually
+ * associated with 't'
+ * XXX
+ */
+
+ return (ENOTSUP); /* XXX */
+
+ break;
+
default: /* It was not a legal request. */
return (EINVAL);
}
@@ -237,15 +305,15 @@ sys_ptrace(struct proc *p, void *v, register_t *retval)
write = 0;
*retval = 0;
- switch (SCARG(uap, req)) {
+ switch (req) {
case PT_TRACE_ME:
/* Just set the trace flag. */
- atomic_setbits_int(&t->p_flag, P_TRACED);
- t->p_oppid = t->p_p->ps_pptr->ps_pid;
- if (t->p_ptstat == NULL)
- t->p_ptstat = malloc(sizeof(*t->p_ptstat),
+ atomic_setbits_int(&tr->ps_flags, PS_TRACED);
+ tr->ps_oppid = tr->ps_pptr->ps_pid;
+ if (tr->ps_ptstat == NULL)
+ tr->ps_ptstat = malloc(sizeof(*tr->ps_ptstat),
M_SUBPROC, M_WAITOK);
- bzero(t->p_ptstat, sizeof(*t->p_ptstat));
+ bzero(tr->ps_ptstat, sizeof(*tr->ps_ptstat));
return (0);
case PT_WRITE_I: /* XXX no separate I and D spaces */
@@ -353,7 +421,7 @@ sys_ptrace(struct proc *p, void *v, register_t *retval)
/*
* Arrange for a single-step, if that's requested and possible.
*/
- error = process_sstep(t, SCARG(uap, req) == PT_STEP);
+ error = process_sstep(t, req == PT_STEP);
if (error)
goto relebad;
#endif
@@ -380,25 +448,26 @@ sys_ptrace(struct proc *p, void *v, register_t *retval)
/*
* Arrange for a single-step, if that's requested and possible.
*/
- error = process_sstep(t, SCARG(uap, req) == PT_STEP);
+ error = process_sstep(t, req == PT_STEP);
if (error)
goto relebad;
#endif
/* give process back to original parent or init */
- if (t->p_oppid != t->p_p->ps_pptr->ps_pid) {
+ if (tr->ps_oppid != tr->ps_pptr->ps_pid) {
struct process *ppr;
- ppr = prfind(t->p_oppid);
- proc_reparent(t->p_p, ppr ? ppr : initproc->p_p);
+ ppr = prfind(tr->ps_oppid);
+ proc_reparent(tr, ppr ? ppr : initproc->p_p);
}
/* not being traced any more */
- t->p_oppid = 0;
- atomic_clearbits_int(&t->p_flag, P_TRACED|P_WAITED);
+ tr->ps_oppid = 0;
+ atomic_clearbits_int(&tr->ps_flags, PS_TRACED);
+ atomic_clearbits_int(&t->p_flag, P_WAITED);
sendsig:
- bzero(t->p_ptstat, sizeof(*t->p_ptstat));
+ bzero(tr->ps_ptstat, sizeof(*tr->ps_ptstat));
/* Finally, deliver the requested signal (or none). */
if (t->p_stat == SSTOP) {
@@ -410,6 +479,13 @@ sys_ptrace(struct proc *p, void *v, register_t *retval)
if (SCARG(uap, data) != 0)
psignal(t, SCARG(uap, data));
}
+ SCHED_LOCK(s);
+ TAILQ_FOREACH(q, &tr->ps_threads, p_thr_link) {
+ if (q != t && q->p_stat == SSTOP) {
+ setrunnable(q);
+ }
+ }
+ SCHED_UNLOCK(s);
return (0);
relebad:
@@ -430,12 +506,12 @@ sys_ptrace(struct proc *p, void *v, register_t *retval)
* proc gets to see all the action.
* Stop the target.
*/
- atomic_setbits_int(&t->p_flag, P_TRACED);
- t->p_oppid = t->p_p->ps_pptr->ps_pid;
- if (t->p_p->ps_pptr != p->p_p)
- proc_reparent(t->p_p, p->p_p);
- if (t->p_ptstat == NULL)
- t->p_ptstat = malloc(sizeof(*t->p_ptstat),
+ atomic_setbits_int(&tr->ps_flags, PS_TRACED);
+ tr->ps_oppid = tr->ps_pptr->ps_pid;
+ if (tr->ps_pptr != p->p_p)
+ proc_reparent(tr, p->p_p);
+ if (tr->ps_ptstat == NULL)
+ tr->ps_ptstat = malloc(sizeof(*tr->ps_ptstat),
M_SUBPROC, M_WAITOK);
SCARG(uap, data) = SIGSTOP;
goto sendsig;
@@ -444,25 +520,25 @@ sys_ptrace(struct proc *p, void *v, register_t *retval)
if (SCARG(uap, data) != sizeof(pe))
return (EINVAL);
bzero(&pe, sizeof(pe));
- pe.pe_set_event = t->p_ptmask;
+ pe.pe_set_event = tr->ps_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;
+ tr->ps_ptmask = pe.pe_set_event;
return (0);
case PT_GET_PROCESS_STATE:
- if (SCARG(uap, data) != sizeof(*t->p_ptstat))
+ if (SCARG(uap, data) != sizeof(*tr->ps_ptstat))
return (EINVAL);
- return (copyout(t->p_ptstat, SCARG(uap, addr),
- sizeof(*t->p_ptstat)));
+ return (copyout(tr->ps_ptstat, SCARG(uap, addr),
+ sizeof(*tr->ps_ptstat)));
case PT_SETREGS:
KASSERT((p->p_flag & P_SYSTEM) == 0);
- if ((error = process_checkioperm(p, t)) != 0)
+ if ((error = process_checkioperm(p, tr)) != 0)
return (error);
regs = malloc(sizeof(*regs), M_TEMP, M_WAITOK);
@@ -474,7 +550,7 @@ sys_ptrace(struct proc *p, void *v, register_t *retval)
return (error);
case PT_GETREGS:
KASSERT((p->p_flag & P_SYSTEM) == 0);
- if ((error = process_checkioperm(p, t)) != 0)
+ if ((error = process_checkioperm(p, tr)) != 0)
return (error);
regs = malloc(sizeof(*regs), M_TEMP, M_WAITOK);
@@ -487,7 +563,7 @@ sys_ptrace(struct proc *p, void *v, register_t *retval)
#ifdef PT_SETFPREGS
case PT_SETFPREGS:
KASSERT((p->p_flag & P_SYSTEM) == 0);
- if ((error = process_checkioperm(p, t)) != 0)
+ if ((error = process_checkioperm(p, tr)) != 0)
return (error);
fpregs = malloc(sizeof(*fpregs), M_TEMP, M_WAITOK);
@@ -501,7 +577,7 @@ sys_ptrace(struct proc *p, void *v, register_t *retval)
#ifdef PT_GETFPREGS
case PT_GETFPREGS:
KASSERT((p->p_flag & P_SYSTEM) == 0);
- if ((error = process_checkioperm(p, t)) != 0)
+ if ((error = process_checkioperm(p, tr)) != 0)
return (error);
fpregs = malloc(sizeof(*fpregs), M_TEMP, M_WAITOK);
@@ -515,7 +591,7 @@ sys_ptrace(struct proc *p, void *v, register_t *retval)
#ifdef PT_SETXMMREGS
case PT_SETXMMREGS:
KASSERT((p->p_flag & P_SYSTEM) == 0);
- if ((error = process_checkioperm(p, t)) != 0)
+ if ((error = process_checkioperm(p, tr)) != 0)
return (error);
xmmregs = malloc(sizeof(*xmmregs), M_TEMP, M_WAITOK);
@@ -529,7 +605,7 @@ sys_ptrace(struct proc *p, void *v, register_t *retval)
#ifdef PT_GETXMMREGS
case PT_GETXMMREGS:
KASSERT((p->p_flag & P_SYSTEM) == 0);
- if ((error = process_checkioperm(p, t)) != 0)
+ if ((error = process_checkioperm(p, tr)) != 0)
return (error);
xmmregs = malloc(sizeof(*xmmregs), M_TEMP, M_WAITOK);
@@ -559,7 +635,7 @@ sys_ptrace(struct proc *p, void *v, register_t *retval)
* Check if a process is allowed to fiddle with the memory of another.
*
* p = tracer
- * t = tracee
+ * tr = tracee
*
* 1. You can't attach to a process not owned by you or one that has raised
* its privileges.
@@ -573,19 +649,19 @@ sys_ptrace(struct proc *p, void *v, register_t *retval)
* second.
*/
int
-process_checkioperm(struct proc *p, struct proc *t)
+process_checkioperm(struct proc *p, struct process *tr)
{
int error;
- if ((t->p_cred->p_ruid != p->p_cred->p_ruid ||
- ISSET(t->p_p->ps_flags, PS_SUGIDEXEC | PS_SUGID)) &&
+ if ((tr->ps_cred->p_ruid != p->p_cred->p_ruid ||
+ ISSET(tr->ps_flags, PS_SUGIDEXEC | PS_SUGID)) &&
(error = suser(p, 0)) != 0)
return (error);
- if ((t->p_pid == 1) && (securelevel > -1))
+ if ((tr->ps_pid == 1) && (securelevel > -1))
return (EPERM);
- if (t->p_flag & P_INEXEC)
+ if (tr->ps_flags & PS_INEXEC)
return (EAGAIN);
return (0);
@@ -603,7 +679,7 @@ process_domem(struct proc *curp, struct proc *p, struct uio *uio, int req)
if (len == 0)
return (0);
- if ((error = process_checkioperm(curp, p)) != 0)
+ if ((error = process_checkioperm(curp, p->p_p)) != 0)
return (error);
/* XXXCDC: how should locking work here? */
diff --git a/sys/miscfs/procfs/procfs_vnops.c b/sys/miscfs/procfs/procfs_vnops.c
index 25ac75ee0bb..be897b61490 100644
--- a/sys/miscfs/procfs/procfs_vnops.c
+++ b/sys/miscfs/procfs/procfs_vnops.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: procfs_vnops.c,v 1.53 2011/12/24 04:34:20 guenther Exp $ */
+/* $OpenBSD: procfs_vnops.c,v 1.54 2012/02/20 22:23:39 guenther Exp $ */
/* $NetBSD: procfs_vnops.c,v 1.40 1996/03/16 23:52:55 christos Exp $ */
/*
@@ -198,7 +198,7 @@ procfs_open(void *v)
((pfs->pfs_flags & O_EXCL) && (ap->a_mode & FWRITE)))
return (EBUSY);
- if ((error = process_checkioperm(p1, p2)) != 0)
+ if ((error = process_checkioperm(p1, p2->p_p)) != 0)
return (error);
if (ap->a_mode & FWRITE)
diff --git a/sys/sys/proc.h b/sys/sys/proc.h
index 5a5215a312a..e6a584101b0 100644
--- a/sys/sys/proc.h
+++ b/sys/sys/proc.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: proc.h,v 1.149 2012/01/07 05:38:12 guenther Exp $ */
+/* $OpenBSD: proc.h,v 1.150 2012/02/20 22:23:39 guenther Exp $ */
/* $NetBSD: proc.h,v 1.44 1996/04/22 01:23:21 christos Exp $ */
/*-
@@ -162,6 +162,10 @@ struct process {
struct vnode *ps_tracevp; /* Trace to vnode. */
struct ucred *ps_tracecred; /* Creds for writing trace */
+ pid_t ps_oppid; /* Save parent pid during ptrace. */
+ int ps_ptmask; /* Ptrace event mask */
+ struct ptrace_state *ps_ptstat;/* Ptrace state */
+
/* End area that is zeroed on creation. */
#define ps_endzero ps_startcopy
@@ -236,9 +240,8 @@ struct proc {
LIST_ENTRY(proc) p_hash; /* Hash chain. */
/* The following fields are all zeroed upon creation in fork. */
-#define p_startzero p_oppid
+#define p_startzero p_dupfd
- pid_t p_oppid; /* Save parent pid during ptrace. XXX */
int p_dupfd; /* Sideways return value from filedescopen. XXX */
long p_thrslpid; /* for thrsleep syscall */
@@ -270,9 +273,6 @@ 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. */
@@ -341,7 +341,7 @@ struct proc {
#define _P_SUGID 0x000100 /* Had set id privs since last exec. */
#define P_SYSTEM 0x000200 /* No sigs, stats or swapping. */
#define P_TIMEOUT 0x000400 /* Timing out during sleep. */
-#define P_TRACED 0x000800 /* Debugged process being traced. */
+#define _P_TRACED 0x000800 /* Debugged process being traced. */
#define P_WAITED 0x001000 /* Debugging proc has waited for child. */
/* XXX - Should be merged with INEXEC */
#define P_WEXIT 0x002000 /* Working on exiting. */
@@ -357,7 +357,7 @@ struct proc {
#define P_SUSPSINGLE 0x080000 /* Need to stop for single threading. */
#define P_NOZOMBIE 0x100000 /* Pid 1 waits for me instead of dad */
-#define P_INEXEC 0x200000 /* Process is doing an exec right now */
+#define _P_INEXEC 0x200000 /* Process is doing an exec right now */
#define P_SYSTRACE 0x400000 /* Process system call tracing active*/
#define P_CONTINUED 0x800000 /* Proc has continued from a stopped state. */
#define _P_SINGLEEXIT 0x1000000 /* Other threads must die. */
@@ -372,8 +372,10 @@ struct proc {
#define P_CONTROLT _P_CONTROLT
#define P_PPWAIT _P_PPWAIT
#define P_SUGID _P_SUGID
+#define P_TRACED _P_TRACED
#define P_EXEC _P_EXEC
#define P_SUGIDEXEC _P_SUGIDEXEC
+#define P_INEXEC _P_INEXEC
#endif
#define P_BITS \
@@ -386,7 +388,7 @@ struct proc {
/* Macro to compute the exit signal to be delivered. */
#define P_EXITSIG(p) \
- (((p)->p_flag & P_TRACED) ? SIGCHLD : (p)->p_exitsig)
+ (((p)->p_p->ps_flags & PS_TRACED) ? SIGCHLD : (p)->p_exitsig)
#define THREAD_PID_OFFSET 1000000
diff --git a/sys/sys/ptrace.h b/sys/sys/ptrace.h
index 4baebcd3aca..d29b03bcb22 100644
--- a/sys/sys/ptrace.h
+++ b/sys/sys/ptrace.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: ptrace.h,v 1.12 2010/07/26 01:56:27 guenther Exp $ */
+/* $OpenBSD: ptrace.h,v 1.13 2012/02/20 22:23:39 guenther Exp $ */
/* $NetBSD: ptrace.h,v 1.21 1996/02/09 18:25:26 christos Exp $ */
/*-
@@ -78,6 +78,13 @@ typedef struct ptrace_state {
pid_t pe_other_pid;
} ptrace_state_t;
+#define PT_GET_THREAD_FIRST 15
+#define PT_GET_THREAD_NEXT 16
+
+struct ptrace_thread_state {
+ pid_t pts_tid;
+};
+
#define PT_FIRSTMACH 32 /* for machine-specific requests */
#include <machine/ptrace.h> /* machine-specific requests, if any */
@@ -107,7 +114,7 @@ int process_sstep(struct proc *p, int sstep);
int process_write_fpregs(struct proc *p, struct fpreg *regs);
#endif
int process_write_regs(struct proc *p, struct reg *regs);
-int process_checkioperm(struct proc *, struct proc *);
+int process_checkioperm(struct proc *, struct process *);
int process_domem(struct proc *, struct proc *, struct uio *, int);
#ifndef FIX_SSTEP
diff --git a/sys/sys/signalvar.h b/sys/sys/signalvar.h
index 692d2c730f6..38c92cfa9c3 100644
--- a/sys/sys/signalvar.h
+++ b/sys/sys/signalvar.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: signalvar.h,v 1.24 2011/11/22 23:20:19 joshe Exp $ */
+/* $OpenBSD: signalvar.h,v 1.25 2012/02/20 22:23:39 guenther Exp $ */
/* $NetBSD: signalvar.h,v 1.17 1996/04/22 01:23:31 christos Exp $ */
/*
@@ -77,7 +77,7 @@ struct sigacts {
*/
#define CURSIG(p) \
(((p)->p_siglist == 0 || \
- (((p)->p_flag & P_TRACED) == 0 && \
+ (((p)->p_p->ps_flags & PS_TRACED) == 0 && \
((p)->p_siglist & ~(p)->p_sigmask) == 0)) ? \
0 : issignal(p))