summaryrefslogtreecommitdiff
path: root/sys
diff options
context:
space:
mode:
authorClaudio Jeker <claudio@cvs.openbsd.org>2022-02-14 11:26:06 +0000
committerClaudio Jeker <claudio@cvs.openbsd.org>2022-02-14 11:26:06 +0000
commitb29ff111cb6b76be86d1a5d30570ccff73d1c031 (patch)
treeea508a9ea62a28c07fce855259385144d48faada /sys
parent55737b855cd9bf4179e9ed6e633cce2069bdb94b (diff)
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@
Diffstat (limited to 'sys')
-rw-r--r--sys/kern/kern_exit.c8
-rw-r--r--sys/kern/kern_sig.c86
-rw-r--r--sys/kern/kern_synch.c7
-rw-r--r--sys/sys/signalvar.h20
-rw-r--r--sys/ufs/mfs/mfs_vfsops.c5
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 <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();
}
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,