summaryrefslogtreecommitdiff
path: root/sys/kern/kern_sig.c
diff options
context:
space:
mode:
authorClaudio Jeker <claudio@cvs.openbsd.org>2023-09-29 12:47:35 +0000
committerClaudio Jeker <claudio@cvs.openbsd.org>2023-09-29 12:47:35 +0000
commitc16ee4429eea649a45a7b9417e039bfe8e12a40e (patch)
tree7c4ceb62bfa91754108a2236450cc9d92137af4d /sys/kern/kern_sig.c
parent4c5ef00d9d44f0099d34f965c9e52148a76b8643 (diff)
Extend single_thread_set() mode with additional flag attributes.
The mode can now be or-ed with SINGLE_DEEP or SINGLE_NOWAIT to alter the behaviour of single_thread_set(). This allows explicit control of the SINGLE_DEEP behaviour. If SINGLE_DEEP is set the deep flag is passed to the initial check call and by that the check will error out instead of suspending (SINGLE_UNWIND) or exiting (SINGLE_EXIT). The SINGLE_DEEP flag is required in calls to single_thread_set() outside of userret. E.g. at the start of sys_execve because the proc is not allowed to call exit1() in that location. SINGLE_NOWAIT skips the wait at the end of single_thread_set() and therefor returns BEFORE all threads have been parked. Currently this is only used by the ptrace code and should not be used anywhere else. Not waiting for all threads to settle is asking for trouble. This solves an issue by using SINGLE_UNWIND in the coredump case where the code should actually exit in case another thread crashed moments earlier. Also the SINGLE_UNWIND in pledge_fail() is now marked SINGLE_DEEP since the call to pledge_fail() is for sure not at the kernel boundary. OK mpi@
Diffstat (limited to 'sys/kern/kern_sig.c')
-rw-r--r--sys/kern/kern_sig.c16
1 files changed, 8 insertions, 8 deletions
diff --git a/sys/kern/kern_sig.c b/sys/kern/kern_sig.c
index 2bffc053225..89a703af7b2 100644
--- a/sys/kern/kern_sig.c
+++ b/sys/kern/kern_sig.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: kern_sig.c,v 1.318 2023/09/19 10:43:33 claudio Exp $ */
+/* $OpenBSD: kern_sig.c,v 1.319 2023/09/29 12:47:34 claudio Exp $ */
/* $NetBSD: kern_sig.c,v 1.54 1996/04/22 01:38:32 christos Exp $ */
/*
@@ -840,7 +840,7 @@ trapsignal(struct proc *p, int signum, u_long trapno, int code,
signum != SIGKILL && (p->p_sigmask & mask) != 0) {
int s;
- single_thread_set(p, SINGLE_SUSPEND, 0);
+ single_thread_set(p, SINGLE_SUSPEND | SINGLE_NOWAIT);
pr->ps_xsig = signum;
SCHED_LOCK(s);
@@ -1290,7 +1290,7 @@ cursig(struct proc *p, struct sigctx *sctx)
*/
if (((pr->ps_flags & (PS_TRACED | PS_PPWAIT)) == PS_TRACED) &&
signum != SIGKILL) {
- single_thread_set(p, SINGLE_SUSPEND, 0);
+ single_thread_set(p, SINGLE_SUSPEND | SINGLE_NOWAIT);
pr->ps_xsig = signum;
SCHED_LOCK(s);
@@ -1559,7 +1559,7 @@ sigexit(struct proc *p, int signum)
/* if there are other threads, pause them */
if (P_HASSIBLING(p))
- single_thread_set(p, SINGLE_UNWIND, 1);
+ single_thread_set(p, SINGLE_UNWIND);
if (coredump(p) == 0)
signum |= WCOREFLAG;
@@ -2066,16 +2066,16 @@ single_thread_check(struct proc *p, int deep)
* - SINGLE_EXIT: unwind to kernel boundary and exit
*/
int
-single_thread_set(struct proc *p, enum single_thread_mode mode, int wait)
+single_thread_set(struct proc *p, int flags)
{
struct process *pr = p->p_p;
struct proc *q;
- int error, s;
+ int error, s, mode = flags & SINGLE_MASK;
KASSERT(curproc == p);
SCHED_LOCK(s);
- error = single_thread_check_locked(p, (mode == SINGLE_UNWIND), s);
+ error = single_thread_check_locked(p, flags & SINGLE_DEEP, s);
if (error) {
SCHED_UNLOCK(s);
return error;
@@ -2146,7 +2146,7 @@ single_thread_set(struct proc *p, enum single_thread_mode mode, int wait)
}
SCHED_UNLOCK(s);
- if (wait)
+ if ((flags & SINGLE_NOWAIT) == 0)
single_thread_wait(pr, 1);
return 0;