diff options
author | Philip Guenthe <guenther@cvs.openbsd.org> | 2011-04-03 14:56:29 +0000 |
---|---|---|
committer | Philip Guenthe <guenther@cvs.openbsd.org> | 2011-04-03 14:56:29 +0000 |
commit | 445a93dfa951cfdb8d9253fd13836d6a25a4ac4b (patch) | |
tree | 9248ed7a9eb63023a13f069c04bd049ee460f416 /sys/kern | |
parent | e3f9e42db6dd7e48f8bd5a3da7d5b2bb44f3752f (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.c | 7 | ||||
-rw-r--r-- | sys/kern/kern_exit.c | 10 | ||||
-rw-r--r-- | sys/kern/kern_fork.c | 16 | ||||
-rw-r--r-- | sys/kern/kern_sig.c | 9 | ||||
-rw-r--r-- | sys/kern/tty.c | 8 | ||||
-rw-r--r-- | sys/kern/tty_pty.c | 4 |
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, |