From 49e9d6d1f8185d923d4aff9724369e39339492ce Mon Sep 17 00:00:00 2001 From: claudio Date: Mon, 14 Feb 2022 11:26:05 +0000 Subject: [PATCH] Introduce a signal context that is used to pass signal related information 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 | 8 +--- sys/kern/kern_sig.c | 86 ++++++++++++++++++++++------------------ sys/kern/kern_synch.c | 7 ++-- sys/sys/signalvar.h | 20 +++++++--- sys/ufs/mfs/mfs_vfsops.c | 5 ++- 5 files changed, 72 insertions(+), 54 deletions(-) diff --git a/sys/kern/kern_exit.c b/sys/kern/kern_exit.c index 632792c0240..4886a55c4a0 100644 --- a/sys/kern/kern_exit.c +++ b/sys/kern/kern_exit.c @@ -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); diff --git a/sys/kern/kern_sig.c b/sys/kern/kern_sig.c index c738f056a9d..9109b65847b 100644 --- a/sys/kern/kern_sig.c +++ b/sys/kern/kern_sig.c @@ -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 #include +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(); } diff --git a/sys/kern/kern_synch.c b/sys/kern/kern_synch.c index f0190261fe6..e993131cd9b 100644 --- a/sys/kern/kern_synch.c +++ b/sys/kern/kern_synch.c @@ -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; diff --git a/sys/sys/signalvar.h b/sys/sys/signalvar.h index 4990cf6d0e9..3374a103749 100644 --- a/sys/sys/signalvar.h +++ b/sys/sys/signalvar.h @@ -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: diff --git a/sys/ufs/mfs/mfs_vfsops.c b/sys/ufs/mfs/mfs_vfsops.c index 5d1bd458565..ff6d46997f6 100644 --- a/sys/ufs/mfs/mfs_vfsops.c +++ b/sys/ufs/mfs/mfs_vfsops.c @@ -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, -- 2.20.1