Skip site navigation (1)Skip section navigation (2)
Date:      Wed, 31 Mar 2021 10:50:47 GMT
From:      "Jonathan T. Looney" <jtl@FreeBSD.org>
To:        src-committers@FreeBSD.org, dev-commits-src-all@FreeBSD.org, dev-commits-src-branches@FreeBSD.org
Subject:   git: a25c17022e2d - stable/13 - Fetch the sigfastblock value in syscalls that wait for signals
Message-ID:  <202103311050.12VAolnu056374@gitrepo.freebsd.org>

next in thread | raw e-mail | index | archive | help
The branch stable/13 has been updated by jtl:

URL: https://cgit.FreeBSD.org/src/commit/?id=a25c17022e2d6344dcbc6192af276d2798d76d44

commit a25c17022e2d6344dcbc6192af276d2798d76d44
Author:     Jonathan T. Looney <jtl@FreeBSD.org>
AuthorDate: 2021-03-12 18:14:17 +0000
Commit:     Jonathan T. Looney <jtl@FreeBSD.org>
CommitDate: 2021-03-30 23:39:57 +0000

    Fetch the sigfastblock value in syscalls that wait for signals
    
    We have seen several cases of processes which have become "stuck" in
    kern_sigsuspend(). When this occurs, the kernel's td_sigblock_val
    is set to 0x10 (one block outstanding) and the userspace copy of the
    word is set to 0 (unblocked). Because the kernel's cached value
    shows that signals are blocked, kern_sigsuspend() blocks almost all
    signals, which means the process hangs indefinitely in sigsuspend().
    
    It is not entirely clear what is causing this condition to occur.
    However, it seems to make sense to add some protection against this
    case by fetching the latest sigfastblock value from userspace for
    syscalls which will sleep waiting for signals. Here, the change is
    applied to kern_sigsuspend() and kern_sigtimedwait().
    
    (cherry picked from commit dbec10e08808e375365fb2a2462f306e0cdfda32)
---
 sys/kern/kern_sig.c | 6 ++++++
 1 file changed, 6 insertions(+)

diff --git a/sys/kern/kern_sig.c b/sys/kern/kern_sig.c
index 7884b5be9f91..3d55405d3151 100644
--- a/sys/kern/kern_sig.c
+++ b/sys/kern/kern_sig.c
@@ -1268,6 +1268,9 @@ kern_sigtimedwait(struct thread *td, sigset_t waitset, ksiginfo_t *ksi,
 	ets.tv_nsec = 0;
 	traced = false;
 
+	/* Ensure the sigfastblock value is up to date. */
+	sigfastblock_fetch(td);
+
 	if (timeout != NULL) {
 		if (timeout->tv_nsec >= 0 && timeout->tv_nsec < 1000000000) {
 			timevalid = 1;
@@ -1527,6 +1530,9 @@ kern_sigsuspend(struct thread *td, sigset_t mask)
 	struct proc *p = td->td_proc;
 	int has_sig, sig;
 
+	/* Ensure the sigfastblock value is up to date. */
+	sigfastblock_fetch(td);
+
 	/*
 	 * When returning from sigsuspend, we want
 	 * the old mask to be restored after the



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?202103311050.12VAolnu056374>