Introduce a signal context that is used to pass signal related information
authorclaudio <claudio@openbsd.org>
Mon, 14 Feb 2022 11:26:05 +0000 (11:26 +0000)
committerclaudio <claudio@openbsd.org>
Mon, 14 Feb 2022 11:26:05 +0000 (11:26 +0000)
from cursig() to postsig() or the caller itself. This will simplify locking.
Also alter sigactsfree() a bit and move it into process_zap() so ps_sigacts
is always a valid pointer.
OK semarie@

sys/kern/kern_exit.c
sys/kern/kern_sig.c
sys/kern/kern_synch.c
sys/sys/signalvar.h
sys/ufs/mfs/mfs_vfsops.c

index 632792c..4886a55 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: kern_exit.c,v 1.201 2022/01/28 07:11:15 guenther Exp $        */
+/*     $OpenBSD: kern_exit.c,v 1.202 2022/02/14 11:26:05 claudio Exp $ */
 /*     $NetBSD: kern_exit.c,v 1.39 1996/04/22 01:38:25 christos Exp $  */
 
 /*
@@ -332,11 +332,6 @@ exit1(struct proc *p, int xexit, int xsig, int flags)
                        process_reparent(pr, initprocess);
                        wakeup(ppr);
                }
-
-               /*
-                * Release the process's signal state.
-                */
-               sigactsfree(pr);
        }
 
        /* just a thread? detach it from its process */
@@ -731,6 +726,7 @@ process_zap(struct process *pr)
                free(pr->ps_ptstat, M_SUBPROC, sizeof(*pr->ps_ptstat));
        pool_put(&rusage_pool, pr->ps_ru);
        KASSERT(TAILQ_EMPTY(&pr->ps_threads));
+       sigactsfree(pr->ps_sigacts);
        lim_free(pr->ps_limit);
        crfree(pr->ps_ucred);
        pool_put(&process_pool, pr);
index c738f05..9109b65 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: kern_sig.c,v 1.293 2022/02/06 09:57:59 claudio Exp $  */
+/*     $OpenBSD: kern_sig.c,v 1.294 2022/02/14 11:26:05 claudio Exp $  */
 /*     $NetBSD: kern_sig.c,v 1.54 1996/04/22 01:38:32 christos Exp $   */
 
 /*
@@ -72,6 +72,8 @@
 #include <uvm/uvm_extern.h>
 #include <machine/tcb.h>
 
+int nosuidcoredump = 1;
+
 int    filt_sigattach(struct knote *kn);
 void   filt_sigdetach(struct knote *kn);
 int    filt_signal(struct knote *kn, long hint);
@@ -132,8 +134,9 @@ void proc_stop(struct proc *p, int);
 void proc_stop_sweep(void *);
 void *proc_stop_si;
 
+void setsigctx(struct proc *, int, struct sigctx *);
 void postsig_done(struct proc *, int, sigset_t, int);
-void postsig(struct proc *, int);
+void postsig(struct proc *, int, struct sigctx *);
 int cansignal(struct proc *, struct process *, int);
 
 struct pool sigacts_pool;      /* memory pool for sigacts structures */
@@ -242,12 +245,8 @@ sigactsinit(struct process *pr)
  * Release a sigacts structure.
  */
 void
-sigactsfree(struct process *pr)
+sigactsfree(struct sigacts *ps)
 {
-       struct sigacts *ps = pr->ps_sigacts;
-
-       pr->ps_sigacts = NULL;
-
        pool_put(&sigacts_pool, ps);
 }
 
@@ -494,7 +493,6 @@ sys_sigprocmask(struct proc *p, void *v, register_t *retval)
 int
 sys_sigpending(struct proc *p, void *v, register_t *retval)
 {
-
        *retval = p->p_siglist | p->p_p->ps_siglist;
        return (0);
 }
@@ -1174,6 +1172,23 @@ out:
                wakeup(pr->ps_pptr);
 }
 
+/* fill the signal context which should be used by postsig() and issignal() */
+void
+setsigctx(struct proc *p, int signum, struct sigctx *sctx)
+{
+       struct sigacts *ps = p->p_p->ps_sigacts;
+       sigset_t mask;
+
+       mask = sigmask(signum);
+       sctx->sig_action = ps->ps_sigact[signum];
+       sctx->sig_catchmask = ps->ps_catchmask[signum];
+       sctx->sig_reset = (ps->ps_sigreset & mask) != 0;
+       sctx->sig_info = (ps->ps_siginfo & mask) != 0;
+       sctx->sig_intr = (ps->ps_sigintr & mask) != 0;
+       sctx->sig_onstack = (ps->ps_sigonstack & mask) != 0;
+       sctx->sig_ignore = (ps->ps_sigignore & mask) != 0;
+}
+
 /*
  * Determine signal that should be delivered to process p, the current
  * process, 0 if none.
@@ -1184,14 +1199,14 @@ out:
  * they aren't returned.  This is checked after each entry to the system for
  * a syscall or trap. The normal call sequence is
  *
- *     while (signum = cursig(curproc))
- *             postsig(signum);
+ *     while (signum = cursig(curproc, &ctx))
+ *             postsig(signum, &ctx);
  *
  * Assumes that if the P_SINTR flag is set, we're holding both the
  * kernel and scheduler locks.
  */
 int
-cursig(struct proc *p)
+cursig(struct proc *p, struct sigctx *sctx)
 {
        struct process *pr = p->p_p;
        int signum, mask, prop;
@@ -1199,6 +1214,7 @@ cursig(struct proc *p)
        int s;
 
        KERNEL_ASSERT_LOCKED();
+       KASSERT(p == curproc);
 
        for (;;) {
                mask = (p->p_siglist | pr->ps_siglist);
@@ -1210,15 +1226,17 @@ cursig(struct proc *p)
                        return (0);
                signum = ffs((long)mask);
                mask = sigmask(signum);
+
+               /* take the signal! */
                atomic_clearbits_int(&p->p_siglist, mask);
                atomic_clearbits_int(&pr->ps_siglist, mask);
+               setsigctx(p, signum, sctx);
 
                /*
                 * We should see pending but ignored signals
                 * only if PS_TRACED was on when they were posted.
                 */
-               if (mask & pr->ps_sigacts->ps_sigignore &&
-                   (pr->ps_flags & PS_TRACED) == 0)
+               if (sctx->sig_ignore && (pr->ps_flags & PS_TRACED) == 0)
                        continue;
 
                /*
@@ -1260,6 +1278,7 @@ cursig(struct proc *p)
                        /* take the signal! */
                        atomic_clearbits_int(&p->p_siglist, mask);
                        atomic_clearbits_int(&pr->ps_siglist, mask);
+                       setsigctx(p, signum, sctx);
                }
 
                prop = sigprop[signum];
@@ -1269,7 +1288,7 @@ cursig(struct proc *p)
                 * Return the signal's number, or fall through
                 * to clear it from the pending mask.
                 */
-               switch ((long)pr->ps_sigacts->ps_sigact[signum]) {
+               switch ((long)sctx->sig_action) {
                case (long)SIG_DFL:
                        /*
                         * Don't take default actions on system processes.
@@ -1392,28 +1411,19 @@ proc_stop_sweep(void *v)
  * from the current set of pending signals.
  */
 void
-postsig(struct proc *p, int signum)
+postsig(struct proc *p, int signum, struct sigctx *sctx)
 {
-       struct process *pr = p->p_p;
-       struct sigacts *ps = pr->ps_sigacts;
-       sig_t action;
        u_long trapno;
        int mask, returnmask;
-       sigset_t catchmask;
        siginfo_t si;
        union sigval sigval;
-       int s, code, info, onstack, reset;
+       int s, code;
 
        KASSERT(signum != 0);
        KERNEL_ASSERT_LOCKED();
 
        mask = sigmask(signum);
        atomic_clearbits_int(&p->p_siglist, mask);
-       action = ps->ps_sigact[signum];
-       catchmask = ps->ps_catchmask[signum];
-       info = (ps->ps_siginfo & mask) != 0;
-       onstack = (ps->ps_sigonstack & mask) != 0;
-       reset = (ps->ps_sigreset & mask) != 0;
        sigval.sival_ptr = NULL;
 
        if (p->p_sisig != signum) {
@@ -1429,11 +1439,11 @@ postsig(struct proc *p, int signum)
 
 #ifdef KTRACE
        if (KTRPOINT(p, KTR_PSIG)) {
-               ktrpsig(p, signum, action, p->p_flag & P_SIGSUSPEND ?
+               ktrpsig(p, signum, sctx->sig_action, p->p_flag & P_SIGSUSPEND ?
                    p->p_oldmask : p->p_sigmask, code, &si);
        }
 #endif
-       if (action == SIG_DFL) {
+       if (sctx->sig_action == SIG_DFL) {
                /*
                 * Default action, where the default is to kill
                 * the process.  (Other cases were ignored above.)
@@ -1445,7 +1455,7 @@ postsig(struct proc *p, int signum)
                 * If we get here, the signal must be caught.
                 */
 #ifdef DIAGNOSTIC
-               if (action == SIG_IGN || (p->p_sigmask & mask))
+               if (sctx->sig_action == SIG_IGN || (p->p_sigmask & mask))
                        panic("postsig action");
 #endif
                /*
@@ -1475,11 +1485,12 @@ postsig(struct proc *p, int signum)
                        p->p_sigval.sival_ptr = NULL;
                }
 
-               if (sendsig(action, signum, returnmask, &si, info, onstack)) {
+               if (sendsig(sctx->sig_action, signum, returnmask, &si,
+                   sctx->sig_info, sctx->sig_onstack)) {
                        sigexit(p, SIGILL);
                        /* NOTREACHED */
                }
-               postsig_done(p, signum, catchmask, reset);
+               postsig_done(p, signum, sctx->sig_catchmask, sctx->sig_reset);
                splx(s);
        }
 }
@@ -1544,8 +1555,6 @@ sigismasked(struct proc *p, int sig)
        return 0;
 }
 
-int nosuidcoredump = 1;
-
 struct coredump_iostate {
        struct proc *io_proc;
        struct vnode *io_vp;
@@ -1745,7 +1754,6 @@ coredump_unmap(void *cookie, vaddr_t start, vaddr_t end)
 int
 sys_nosys(struct proc *p, void *v, register_t *retval)
 {
-
        ptsignal(p, SIGSYS, STHREAD);
        return (ENOSYS);
 }
@@ -1759,6 +1767,7 @@ sys___thrsigdivert(struct proc *p, void *v, register_t *retval)
                syscallarg(siginfo_t *) info;
                syscallarg(const struct timespec *) timeout;
        } */ *uap = v;
+       struct sigctx ctx;
        sigset_t mask = SCARG(uap, sigmask) &~ sigcantmask;
        siginfo_t si;
        uint64_t nsecs = INFSLP;
@@ -1783,7 +1792,7 @@ sys___thrsigdivert(struct proc *p, void *v, register_t *retval)
 
        dosigsuspend(p, p->p_sigmask &~ mask);
        for (;;) {
-               si.si_signo = cursig(p);
+               si.si_signo = cursig(p, &ctx);
                if (si.si_signo != 0) {
                        sigset_t smask = sigmask(si.si_signo);
                        if (smask & mask) {
@@ -1898,6 +1907,7 @@ filt_signal(struct knote *kn, long hint)
 void
 userret(struct proc *p)
 {
+       struct sigctx ctx;
        int signum;
 
        /* send SIGPROF or SIGVTALRM if their timers interrupted this thread */
@@ -1916,8 +1926,8 @@ userret(struct proc *p)
 
        if (SIGPENDING(p) != 0 || ISSET(p->p_p->ps_flags, PS_TRACED)) {
                KERNEL_LOCK();
-               while ((signum = cursig(p)) != 0)
-                       postsig(p, signum);
+               while ((signum = cursig(p, &ctx)) != 0)
+                       postsig(p, signum, &ctx);
                KERNEL_UNLOCK();
        }
 
@@ -1932,8 +1942,8 @@ userret(struct proc *p)
                p->p_sigmask = p->p_oldmask;
 
                KERNEL_LOCK();
-               while ((signum = cursig(p)) != 0)
-                       postsig(p, signum);
+               while ((signum = cursig(p, &ctx)) != 0)
+                       postsig(p, signum, &ctx);
                KERNEL_UNLOCK();
        }
 
index f019026..e993131 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: kern_synch.c,v 1.180 2021/10/07 08:51:00 mpi Exp $    */
+/*     $OpenBSD: kern_synch.c,v 1.181 2022/02/14 11:26:05 claudio Exp $        */
 /*     $NetBSD: kern_synch.c,v 1.37 1996/04/22 01:38:37 christos Exp $ */
 
 /*
@@ -475,12 +475,13 @@ int
 sleep_signal_check(void)
 {
        struct proc *p = curproc;
+       struct sigctx ctx;
        int err, sig;
 
        if ((err = single_thread_check(p, 1)) != 0)
                return err;
-       if ((sig = cursig(p)) != 0) {
-               if (p->p_p->ps_sigacts->ps_sigintr & sigmask(sig))
+       if ((sig = cursig(p, &ctx)) != 0) {
+               if (ctx.sig_intr)
                        return EINTR;
                else
                        return ERESTART;
index 4990cf6..3374a10 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: signalvar.h,v 1.52 2021/11/26 04:42:13 visa Exp $     */
+/*     $OpenBSD: signalvar.h,v 1.53 2022/02/14 11:26:05 claudio Exp $  */
 /*     $NetBSD: signalvar.h,v 1.17 1996/04/22 01:23:31 christos Exp $  */
 
 /*
@@ -89,18 +89,27 @@ enum signal_type { SPROCESS, STHREAD, SPROPAGATED };
 
 struct sigio_ref;
 
+struct sigctx {
+       sig_t           sig_action;
+       sigset_t        sig_catchmask;
+       int             sig_onstack;
+       int             sig_intr;
+       int             sig_reset;
+       int             sig_info;
+       int             sig_ignore;
+};
+
 /*
  * Machine-independent functions:
  */
 int    coredump(struct proc *p);
 void   execsigs(struct proc *p);
-int    cursig(struct proc *p);
+int    cursig(struct proc *p, struct sigctx *);
 void   pgsigio(struct sigio_ref *sir, int sig, int checkctty);
 void   pgsignal(struct pgrp *pgrp, int sig, int checkctty);
 void   psignal(struct proc *p, int sig);
 void   ptsignal(struct proc *p, int sig, enum signal_type type);
 #define prsignal(pr,sig)       ptsignal((pr)->ps_mainproc, (sig), SPROCESS)
-void   siginit(struct sigacts *);
 void   trapsignal(struct proc *p, int sig, u_long code, int type,
            union sigval val);
 __dead void sigexit(struct proc *, int);
@@ -111,9 +120,10 @@ int        killpg1(struct proc *, int, int, int);
 
 void   signal_init(void);
 
-struct sigacts *sigactsinit(struct process *);
 void   sigstkinit(struct sigaltstack *);
-void   sigactsfree(struct process *);
+struct sigacts *sigactsinit(struct process *);
+void   sigactsfree(struct sigacts *);
+void   siginit(struct sigacts *);
 
 /*
  * Machine-dependent functions:
index 5d1bd45..ff6d469 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: mfs_vfsops.c,v 1.61 2021/10/05 08:38:19 claudio Exp $ */
+/*     $OpenBSD: mfs_vfsops.c,v 1.62 2022/02/14 11:26:05 claudio Exp $ */
 /*     $NetBSD: mfs_vfsops.c,v 1.10 1996/02/09 22:31:28 christos Exp $ */
 
 /*
@@ -167,6 +167,7 @@ mfs_start(struct mount *mp, int flags, struct proc *p)
        struct mfsnode *mfsp = VTOMFS(vp);
        struct buf *bp;
        int sleepreturn = 0, sig;
+       struct sigctx ctx;
 
        while (1) {
                while (1) {
@@ -188,7 +189,7 @@ mfs_start(struct mount *mp, int flags, struct proc *p)
                 * EINTR/ERESTART.
                 */
                if (sleepreturn != 0) {
-                       sig = cursig(p);
+                       sig = cursig(p, &ctx);
                        if (vfs_busy(mp, VB_WRITE|VB_NOWAIT) ||
                            dounmount(mp, (sig == SIGKILL) ? MNT_FORCE : 0, p))
                                atomic_clearbits_int(&p->p_siglist,