aboutsummaryrefslogtreecommitdiff
path: root/sys/kern/kern_fork.c
diff options
context:
space:
mode:
authorKyle Evans <kevans@FreeBSD.org>2019-09-25 19:20:41 +0000
committerKyle Evans <kevans@FreeBSD.org>2019-09-25 19:20:41 +0000
commit079c5b9ed809af6dec664accc70119a4ef989420 (patch)
tree5efcf1bdba3006d2614d5720c66190a3fecb9576 /sys/kern/kern_fork.c
parent5763a8cf06a297c067aa7af13973f50ab44c2a4d (diff)
downloadsrc-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.c15
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)