diff options
author | Kyle Evans <kevans@FreeBSD.org> | 2019-09-25 19:20:41 +0000 |
---|---|---|
committer | Kyle Evans <kevans@FreeBSD.org> | 2019-09-25 19:20:41 +0000 |
commit | 079c5b9ed809af6dec664accc70119a4ef989420 (patch) | |
tree | 5efcf1bdba3006d2614d5720c66190a3fecb9576 /sys/kern/kern_fork.c | |
parent | 5763a8cf06a297c067aa7af13973f50ab44c2a4d (diff) | |
download | src-079c5b9ed809af6dec664accc70119a4ef989420.tar.gz src-079c5b9ed809af6dec664accc70119a4ef989420.zip |
rfork(2): add RFSPAWN flag
When RFSPAWN is passed, rfork exhibits vfork(2) semantics but also resets
signal handlers in the child during creation to avoid a point of corruption
of parent state from the child.
This flag will be used by posix_spawn(3) to handle potential signal issues.
Reviewed by: jilles, kib
Differential Revision: https://reviews.freebsd.org/D19058
Notes
Notes:
svn path=/head/; revision=352711
Diffstat (limited to 'sys/kern/kern_fork.c')
-rw-r--r-- | sys/kern/kern_fork.c | 15 |
1 files changed, 14 insertions, 1 deletions
diff --git a/sys/kern/kern_fork.c b/sys/kern/kern_fork.c index 7fc5750a1f07..b397dee1aaa4 100644 --- a/sys/kern/kern_fork.c +++ b/sys/kern/kern_fork.c @@ -170,10 +170,18 @@ sys_rfork(struct thread *td, struct rfork_args *uap) /* Don't allow kernel-only flags. */ if ((uap->flags & RFKERNELONLY) != 0) return (EINVAL); + /* RFSPAWN must not appear with others */ + if ((uap->flags & RFSPAWN) != 0 && uap->flags != RFSPAWN) + return (EINVAL); AUDIT_ARG_FFLAGS(uap->flags); bzero(&fr, sizeof(fr)); - fr.fr_flags = uap->flags; + if ((uap->flags & RFSPAWN) != 0) { + fr.fr_flags = RFFDG | RFPROC | RFPPWAIT | RFMEM; + fr.fr_flags2 = FR2_DROPSIG_CAUGHT; + } else { + fr.fr_flags = uap->flags; + } fr.fr_pidp = &pid; error = fork1(td, &fr); if (error == 0) { @@ -471,6 +479,11 @@ do_fork(struct thread *td, struct fork_req *fr, struct proc *p2, struct thread * } else { sigacts_copy(newsigacts, p1->p_sigacts); p2->p_sigacts = newsigacts; + if ((fr->fr_flags2 & FR2_DROPSIG_CAUGHT) != 0) { + mtx_lock(&p2->p_sigacts->ps_mtx); + sig_drop_caught(p2); + mtx_unlock(&p2->p_sigacts->ps_mtx); + } } if (fr->fr_flags & RFTSIGZMB) |