Author: kevans
Date: Wed Sep 25 19:20:41 2019
New Revision: 352711
URL: https://svnweb.freebsd.org/changeset/base/352711

Log:
  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

Modified:
  head/lib/libc/sys/rfork.2
  head/sys/kern/kern_fork.c
  head/sys/kern/kern_sig.c
  head/sys/sys/proc.h
  head/sys/sys/signalvar.h
  head/sys/sys/unistd.h

Modified: head/lib/libc/sys/rfork.2
==============================================================================
--- head/lib/libc/sys/rfork.2   Wed Sep 25 18:50:57 2019        (r352710)
+++ head/lib/libc/sys/rfork.2   Wed Sep 25 19:20:41 2019        (r352711)
@@ -5,7 +5,7 @@
 .\"
 .\" $FreeBSD$
 .\"
-.Dd July 12, 2011
+.Dd September 25, 2019
 .Dt RFORK 2
 .Os
 .Sh NAME
@@ -34,7 +34,9 @@ and open files.
 The
 .Fa flags
 argument
-is the logical OR of some subset of:
+is either
+.Dv RFSPAWN
+or the logical OR of some subset of:
 .Bl -tag -width ".Dv RFLINUXTHPN"
 .It Dv RFPROC
 If set a new process is created; otherwise changes affect the
@@ -103,6 +105,14 @@ This is intended to mimic certain Linux clone behaviou
 File descriptors in a shared file descriptor table are kept
 open until either they are explicitly closed
 or all processes sharing the table exit.
+.Pp
+If
+.Dv RFSPAWN
+is passed,
+.Nm
+will use
+.Xr vfork 2
+semantics but reset all signal actions in the child to default.
 .Pp
 If
 .Dv RFPROC

Modified: head/sys/kern/kern_fork.c
==============================================================================
--- head/sys/kern/kern_fork.c   Wed Sep 25 18:50:57 2019        (r352710)
+++ head/sys/kern/kern_fork.c   Wed Sep 25 19:20:41 2019        (r352711)
@@ -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
        } 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)

Modified: head/sys/kern/kern_sig.c
==============================================================================
--- head/sys/kern/kern_sig.c    Wed Sep 25 18:50:57 2019        (r352710)
+++ head/sys/kern/kern_sig.c    Wed Sep 25 19:20:41 2019        (r352711)
@@ -986,12 +986,7 @@ execsigs(struct proc *p)
        PROC_LOCK_ASSERT(p, MA_OWNED);
        ps = p->p_sigacts;
        mtx_lock(&ps->ps_mtx);
-       while (SIGNOTEMPTY(ps->ps_sigcatch)) {
-               sig = sig_ffs(&ps->ps_sigcatch);
-               sigdflt(ps, sig);
-               if ((sigprop(sig) & SIGPROP_IGNORE) != 0)
-                       sigqueue_delete_proc(p, sig);
-       }
+       sig_drop_caught(p);
 
        /*
         * As CloudABI processes cannot modify signal handlers, fully
@@ -3856,4 +3851,21 @@ sigacts_shared(struct sigacts *ps)
 {
 
        return (ps->ps_refcnt > 1);
+}
+
+void
+sig_drop_caught(struct proc *p)
+{
+       int sig;
+       struct sigacts *ps;
+
+       ps = p->p_sigacts;
+       PROC_LOCK_ASSERT(p, MA_OWNED);
+       mtx_assert(&ps->ps_mtx, MA_OWNED);
+       while (SIGNOTEMPTY(ps->ps_sigcatch)) {
+               sig = sig_ffs(&ps->ps_sigcatch);
+               sigdflt(ps, sig);
+               if ((sigprop(sig) & SIGPROP_IGNORE) != 0)
+                       sigqueue_delete_proc(p, sig);
+       }
 }

Modified: head/sys/sys/proc.h
==============================================================================
--- head/sys/sys/proc.h Wed Sep 25 18:50:57 2019        (r352710)
+++ head/sys/sys/proc.h Wed Sep 25 19:20:41 2019        (r352711)
@@ -1006,6 +1006,8 @@ struct    fork_req {
        int             *fr_pd_fd;
        int             fr_pd_flags;
        struct filecaps *fr_pd_fcaps;
+       int             fr_flags2;
+#define        FR2_DROPSIG_CAUGHT      0x00001 /* Drop caught non-DFL signals 
*/
 };
 
 /*

Modified: head/sys/sys/signalvar.h
==============================================================================
--- head/sys/sys/signalvar.h    Wed Sep 25 18:50:57 2019        (r352710)
+++ head/sys/sys/signalvar.h    Wed Sep 25 19:20:41 2019        (r352711)
@@ -381,6 +381,7 @@ void        sigacts_copy(struct sigacts *dest, struct 
sigacts
 void   sigacts_free(struct sigacts *ps);
 struct sigacts *sigacts_hold(struct sigacts *ps);
 int    sigacts_shared(struct sigacts *ps);
+void   sig_drop_caught(struct proc *p);
 void   sigexit(struct thread *td, int sig) __dead2;
 int    sigev_findtd(struct proc *p, struct sigevent *sigev, struct thread **);
 int    sig_ffs(sigset_t *set);

Modified: head/sys/sys/unistd.h
==============================================================================
--- head/sys/sys/unistd.h       Wed Sep 25 18:50:57 2019        (r352710)
+++ head/sys/sys/unistd.h       Wed Sep 25 19:20:41 2019        (r352711)
@@ -188,11 +188,14 @@
 #define        RFTSIGNUM(flags)        (((flags) >> RFTSIGSHIFT) & RFTSIGMASK)
 #define        RFTSIGFLAGS(signum)     ((signum) << RFTSIGSHIFT)
 #define        RFPROCDESC      (1<<28) /* return a process descriptor */
-#define        RFPPWAIT        (1<<31) /* parent sleeps until child exits 
(vfork) */
+/* kernel: parent sleeps until child exits (vfork) */
+#define        RFPPWAIT        (1<<31)
+/* user: vfork(2) semantics, clear signals */
+#define        RFSPAWN         (1U<<31)
 #define        RFFLAGS         (RFFDG | RFPROC | RFMEM | RFNOWAIT | RFCFDG | \
     RFTHREAD | RFSIGSHARE | RFLINUXTHPN | RFSTOPPED | RFHIGHPID | RFTSIGZMB | \
-    RFPROCDESC | RFPPWAIT)
-#define        RFKERNELONLY    (RFSTOPPED | RFHIGHPID | RFPPWAIT | RFPROCDESC)
+    RFPROCDESC | RFSPAWN | RFPPWAIT)
+#define        RFKERNELONLY    (RFSTOPPED | RFHIGHPID | RFPROCDESC)
 
 #endif /* __BSD_VISIBLE */
 
_______________________________________________
svn-src-all@freebsd.org mailing list
https://lists.freebsd.org/mailman/listinfo/svn-src-all
To unsubscribe, send any mail to "svn-src-all-unsubscr...@freebsd.org"

Reply via email to