summaryrefslogtreecommitdiffstats
path: root/sys/kern/kern_fork.c
diff options
context:
space:
mode:
authorguenther <guenther@openbsd.org>2011-04-03 14:56:27 +0000
committerguenther <guenther@openbsd.org>2011-04-03 14:56:27 +0000
commitc0ce47d96f277436fbde5279039dad42b016a9b2 (patch)
treeba57ac46912617f1c7dd53acb3befb855db19709 /sys/kern/kern_fork.c
parentNo need to include uvm/uvm_extern.h and fix a typo. (diff)
downloadwireguard-openbsd-c0ce47d96f277436fbde5279039dad42b016a9b2.tar.xz
wireguard-openbsd-c0ce47d96f277436fbde5279039dad42b016a9b2.zip
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/kern_fork.c')
-rw-r--r--sys/kern/kern_fork.c16
1 files changed, 10 insertions, 6 deletions
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);
/*