summaryrefslogtreecommitdiff
path: root/sys/kern
diff options
context:
space:
mode:
authorPhilip Guenthe <guenther@cvs.openbsd.org>2011-04-03 14:56:29 +0000
committerPhilip Guenthe <guenther@cvs.openbsd.org>2011-04-03 14:56:29 +0000
commit445a93dfa951cfdb8d9253fd13836d6a25a4ac4b (patch)
tree9248ed7a9eb63023a13f069c04bd049ee460f416 /sys/kern
parente3f9e42db6dd7e48f8bd5a3da7d5b2bb44f3752f (diff)
Move PPWAIT flag from struct proc to process, so that rthreads in
a vforked child behave correctly. Have the parent in a vfork() wait on a (different) flag in *its* process instead of the child to prevent a possible use-after-free. When ktracing the child return from a fork, call it rfork if an rthread was created. ok blambert@
Diffstat (limited to 'sys/kern')
-rw-r--r--sys/kern/kern_exec.c7
-rw-r--r--sys/kern/kern_exit.c10
-rw-r--r--sys/kern/kern_fork.c16
-rw-r--r--sys/kern/kern_sig.c9
-rw-r--r--sys/kern/tty.c8
-rw-r--r--sys/kern/tty_pty.c4
6 files changed, 31 insertions, 23 deletions
diff --git a/sys/kern/kern_exec.c b/sys/kern/kern_exec.c
index 74b5647c3c3..65fe753077b 100644
--- a/sys/kern/kern_exec.c
+++ b/sys/kern/kern_exec.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: kern_exec.c,v 1.115 2011/04/02 17:04:35 guenther Exp $ */
+/* $OpenBSD: kern_exec.c,v 1.116 2011/04/03 14:56:28 guenther Exp $ */
/* $NetBSD: kern_exec.c,v 1.75 1996/02/09 18:59:28 christos Exp $ */
/*-
@@ -468,8 +468,9 @@ sys_execve(struct proc *p, void *v, register_t *retval)
p->p_textvp = pack.ep_vp;
atomic_setbits_int(&p->p_flag, P_EXEC);
- if (pr->ps_mainproc->p_flag & P_PPWAIT) {
- atomic_clearbits_int(&pr->ps_mainproc->p_flag, P_PPWAIT);
+ if (pr->ps_flags & PS_PPWAIT) {
+ atomic_clearbits_int(&pr->ps_flags, PS_PPWAIT);
+ atomic_clearbits_int(&pr->ps_pptr->ps_flags, PS_ISPWAIT);
wakeup(pr->ps_pptr);
}
diff --git a/sys/kern/kern_exit.c b/sys/kern/kern_exit.c
index 792f8391340..40c73d9a7ab 100644
--- a/sys/kern/kern_exit.c
+++ b/sys/kern/kern_exit.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: kern_exit.c,v 1.97 2010/08/02 19:54:07 guenther Exp $ */
+/* $OpenBSD: kern_exit.c,v 1.98 2011/04/03 14:56:28 guenther Exp $ */
/* $NetBSD: kern_exit.c,v 1.39 1996/04/22 01:38:25 christos Exp $ */
/*
@@ -162,11 +162,13 @@ exit1(struct proc *p, int rv, int flags)
while (!TAILQ_EMPTY(&pr->ps_threads))
tsleep(&pr->ps_threads, PUSER, "thrdeath", 0);
/*
- * If parent is waiting for us to exit or exec, P_PPWAIT
+ * If parent is waiting for us to exit or exec, PS_PPWAIT
* is set; we wake up the parent early to avoid deadlock.
*/
- if (p->p_flag & P_PPWAIT) {
- atomic_clearbits_int(&p->p_flag, P_PPWAIT);
+ if (pr->ps_flags & PS_PPWAIT) {
+ atomic_clearbits_int(&pr->ps_flags, PS_PPWAIT);
+ atomic_clearbits_int(&pr->ps_pptr->ps_flags,
+ PS_ISPWAIT);
wakeup(pr->ps_pptr);
}
}
diff --git a/sys/kern/kern_fork.c b/sys/kern/kern_fork.c
index 8707f472ac1..1753df4bbf3 100644
--- a/sys/kern/kern_fork.c
+++ b/sys/kern/kern_fork.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: kern_fork.c,v 1.124 2011/04/02 17:04:35 guenther Exp $ */
+/* $OpenBSD: kern_fork.c,v 1.125 2011/04/03 14:56:28 guenther Exp $ */
/* $NetBSD: kern_fork.c,v 1.29 1996/02/09 18:59:34 christos Exp $ */
/*
@@ -319,8 +319,10 @@ fork1(struct proc *p1, int exitsig, int flags, void *stack, size_t stacksize,
else
p2->p_fd = fdcopy(p1);
- if (flags & FORK_PPWAIT)
- atomic_setbits_int(&p2->p_flag, P_PPWAIT);
+ if (flags & FORK_PPWAIT) {
+ atomic_setbits_int(&p2->p_p->ps_flags, PS_PPWAIT);
+ atomic_setbits_int(&p1->p_p->ps_flags, PS_ISPWAIT);
+ }
if (flags & FORK_NOZOMBIE)
atomic_setbits_int(&p2->p_flag, P_NOZOMBIE);
@@ -462,11 +464,13 @@ fork1(struct proc *p1, int exitsig, int flags, void *stack, size_t stacksize,
/*
* Preserve synchronization semantics of vfork. If waiting for
- * child to exec or exit, set P_PPWAIT on child, and sleep on our
- * process (in case of exit).
+ * child to exec or exit, set PS_PPWAIT on child and PS_ISPWAIT
+ * on ourselves, and sleep on our process for the latter flag
+ * to go away.
+ * XXX Need to stop other rthreads in the parent
*/
if (flags & FORK_PPWAIT)
- while (p2->p_flag & P_PPWAIT)
+ while (p1->p_p->ps_flags & PS_ISPWAIT)
tsleep(p1->p_p, PWAIT, "ppwait", 0);
/*
diff --git a/sys/kern/kern_sig.c b/sys/kern/kern_sig.c
index 39bf31572e7..6e1c1ead1e9 100644
--- a/sys/kern/kern_sig.c
+++ b/sys/kern/kern_sig.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: kern_sig.c,v 1.118 2011/04/02 17:04:35 guenther Exp $ */
+/* $OpenBSD: kern_sig.c,v 1.119 2011/04/03 14:56:28 guenther Exp $ */
/* $NetBSD: kern_sig.c,v 1.54 1996/04/22 01:38:32 christos Exp $ */
/*
@@ -938,7 +938,7 @@ ptsignal(struct proc *p, int signum, enum signal_type type)
* If a child holding parent blocked,
* stopping could cause deadlock.
*/
- if (p->p_flag & P_PPWAIT)
+ if (p->p_p->ps_flags & PS_PPWAIT)
goto out;
atomic_clearbits_int(&p->p_siglist, mask);
p->p_xstat = signum;
@@ -1056,7 +1056,7 @@ issignal(struct proc *p)
for (;;) {
mask = p->p_siglist & ~p->p_sigmask;
- if (p->p_flag & P_PPWAIT)
+ if (p->p_p->ps_flags & PS_PPWAIT)
mask &= ~stopsigmask;
if (mask == 0) /* no signal to send */
return (0);
@@ -1071,7 +1071,8 @@ issignal(struct proc *p)
if (mask & p->p_sigignore && (p->p_flag & P_TRACED) == 0)
continue;
- if (p->p_flag & P_TRACED && (p->p_flag & P_PPWAIT) == 0) {
+ if (p->p_flag & P_TRACED &&
+ (p->p_p->ps_flags & PS_PPWAIT) == 0) {
/*
* If traced, always stop, and stay
* stopped until released by the debugger.
diff --git a/sys/kern/tty.c b/sys/kern/tty.c
index c8120bf02c6..5b3769ae34a 100644
--- a/sys/kern/tty.c
+++ b/sys/kern/tty.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: tty.c,v 1.88 2010/07/26 01:56:27 guenther Exp $ */
+/* $OpenBSD: tty.c,v 1.89 2011/04/03 14:56:28 guenther Exp $ */
/* $NetBSD: tty.c,v 1.68.4.2 1996/06/06 16:04:52 thorpej Exp $ */
/*-
@@ -749,7 +749,7 @@ ttioctl(struct tty *tp, u_long cmd, caddr_t data, int flag, struct proc *p)
case TIOCSLTC:
#endif
while (isbackground(pr, tp) &&
- (p->p_flag & P_PPWAIT) == 0 &&
+ (pr->ps_flags & PS_PPWAIT) == 0 &&
(p->p_sigignore & sigmask(SIGTTOU)) == 0 &&
(p->p_sigmask & sigmask(SIGTTOU)) == 0) {
if (pr->ps_pgrp->pg_jobc == 0)
@@ -1464,7 +1464,7 @@ loop: lflag = tp->t_lflag;
if (isbackground(pr, tp)) {
if ((p->p_sigignore & sigmask(SIGTTIN)) ||
(p->p_sigmask & sigmask(SIGTTIN)) ||
- p->p_flag & P_PPWAIT || pr->ps_pgrp->pg_jobc == 0) {
+ pr->ps_flags & PS_PPWAIT || pr->ps_pgrp->pg_jobc == 0) {
error = EIO;
goto out;
}
@@ -1718,7 +1718,7 @@ loop:
p = curproc;
pr = p->p_p;
if (isbackground(pr, tp) &&
- ISSET(tp->t_lflag, TOSTOP) && (p->p_flag & P_PPWAIT) == 0 &&
+ ISSET(tp->t_lflag, TOSTOP) && (pr->ps_flags & PS_PPWAIT) == 0 &&
(p->p_sigignore & sigmask(SIGTTOU)) == 0 &&
(p->p_sigmask & sigmask(SIGTTOU)) == 0) {
if (pr->ps_pgrp->pg_jobc == 0) {
diff --git a/sys/kern/tty_pty.c b/sys/kern/tty_pty.c
index 9ad6757f7b1..dde88c46a50 100644
--- a/sys/kern/tty_pty.c
+++ b/sys/kern/tty_pty.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: tty_pty.c,v 1.52 2010/09/24 02:59:39 deraadt Exp $ */
+/* $OpenBSD: tty_pty.c,v 1.53 2011/04/03 14:56:28 guenther Exp $ */
/* $NetBSD: tty_pty.c,v 1.33.4.1 1996/06/02 09:08:11 mrg Exp $ */
/*
@@ -294,7 +294,7 @@ again:
if ((p->p_sigignore & sigmask(SIGTTIN)) ||
(p->p_sigmask & sigmask(SIGTTIN)) ||
pr->ps_pgrp->pg_jobc == 0 ||
- p->p_flag & P_PPWAIT)
+ pr->ps_flags & PS_PPWAIT)
return (EIO);
pgsignal(pr->ps_pgrp, SIGTTIN, 1);
error = ttysleep(tp, &lbolt,