aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKonstantin Belousov <kib@FreeBSD.org>2021-01-11 01:22:44 +0000
committerKonstantin Belousov <kib@FreeBSD.org>2021-01-12 10:45:26 +0000
commit57f22c828ec01e0d92bc8858f61df06b4d81ea5c (patch)
treea338d0366a4baca4d1bfc8ffca4069387fffae5b
parent513320c0f1122f096468c0b01623ba7c7e77cbe2 (diff)
downloadsrc-57f22c828ec01e0d92bc8858f61df06b4d81ea5c.tar.gz
src-57f22c828ec01e0d92bc8858f61df06b4d81ea5c.zip
sigfastblock: do not skip cursig/postsig loop in ast()
Even if sigfastblock block is non-zero, non-blockable signals must be checked on ast and delivered now. This also affects debugger ability to attach, because issignal() also calls ptracestop() if there is a pending stop for debugee. Instead of checking for sigfastblock, and either setting PENDING flag for usermode or doing signal delivery loop, always do the loop after checking, and then handle PENDING bit. issignal() already does the right thing for fast-blocked case, allowing only STOPs and SIGKILL delivery to happen. Reported by: Vasily Postnicov <shamaz.mazum@gmail.com>, markj Reviewed by: markj Sponsored by: The FreeBSD Foundation Differential Revision: https://reviews.freebsd.org/D28089
-rw-r--r--sys/kern/subr_trap.c26
1 files changed, 12 insertions, 14 deletions
diff --git a/sys/kern/subr_trap.c b/sys/kern/subr_trap.c
index 0c7e43c40ea2..8981091b50ed 100644
--- a/sys/kern/subr_trap.c
+++ b/sys/kern/subr_trap.c
@@ -204,6 +204,7 @@ ast(struct trapframe *framep)
struct thread *td;
struct proc *p;
int flags, sig;
+ bool resched_sigs;
td = curthread;
p = td->td_proc;
@@ -316,27 +317,24 @@ ast(struct trapframe *framep)
if (flags & TDF_NEEDSIGCHK || p->p_pendingcnt > 0 ||
!SIGISEMPTY(p->p_siglist)) {
sigfastblock_fetch(td);
- if ((td->td_pflags & TDP_SIGFASTBLOCK) != 0 &&
- td->td_sigblock_val != 0) {
- sigfastblock_setpend(td, true);
- } else {
- PROC_LOCK(p);
- mtx_lock(&p->p_sigacts->ps_mtx);
- while ((sig = cursig(td)) != 0) {
- KASSERT(sig >= 0, ("sig %d", sig));
- postsig(sig);
- }
- mtx_unlock(&p->p_sigacts->ps_mtx);
- PROC_UNLOCK(p);
+ PROC_LOCK(p);
+ mtx_lock(&p->p_sigacts->ps_mtx);
+ while ((sig = cursig(td)) != 0) {
+ KASSERT(sig >= 0, ("sig %d", sig));
+ postsig(sig);
}
+ mtx_unlock(&p->p_sigacts->ps_mtx);
+ PROC_UNLOCK(p);
+ resched_sigs = true;
+ } else {
+ resched_sigs = false;
}
/*
* Handle deferred update of the fast sigblock value, after
* the postsig() loop was performed.
*/
- if (td->td_pflags & TDP_SIGFASTPENDING)
- sigfastblock_setpend(td, false);
+ sigfastblock_setpend(td, resched_sigs);
#ifdef KTRACE
KTRUSERRET(td);