All of lore.kernel.org
 help / color / mirror / Atom feed
From: "Eric W. Biederman" <ebiederm@xmission.com>
To: Oleg Nesterov <oleg@redhat.com>
Cc: Andrew Morton <akpm@linux-foundation.org>,
	 Andy Lutomirski <luto@kernel.org>,  Kees Cook <kees@kernel.org>,
	 Kusaram Devineni <kusaram@devineni.in>,
	 Peter Zijlstra <peterz@infradead.org>,
	 Thomas Gleixner <tglx@kernel.org>,
	 Will Drewry <wad@chromium.org>,
	linux-kernel@vger.kernel.org,
	 Linus Torvalds <torvalds@linux-foundation.org>,
	 Christian Brauner <brauner@kernel.org>
Subject: [PATCH 03/14] signal: More accurate ignoring of signals based on sig_can_short_circuit
Date: Fri, 03 Jul 2026 16:37:50 -0500	[thread overview]
Message-ID: <87pl133gb5.fsf_-_@email.froward.int.ebiederm.org> (raw)
In-Reply-To: <877bnb4uyw.fsf_-_@email.froward.int.ebiederm.org> (Eric W. Biederman's message of "Fri, 03 Jul 2026 16:35:51 -0500")


For a signal to be ignored two things need to happen:
- The conditions need to be present to ignore calling the signal handler.
- The signal needs to be deliverable to at least one thread of the process

In rare cases the like unblocked signals on a dead thread the current
code will ignore signals that are blocked by all living threads.

Opportunities to ignore signals are missed when another thread has the
signal unblocked.

Implement sig_can_short_circuit to properly detect that short
circuiting is possible.

Rename sig_task_ignored to sig_ingored.

Signed-off-by: "Eric W. Biederman" <ebiederm@xmission.com>
---
 kernel/signal.c | 59 ++++++++++++++++++++++++++++++++++++-------------
 1 file changed, 44 insertions(+), 15 deletions(-)

diff --git a/kernel/signal.c b/kernel/signal.c
index 1a8183606dc0..4429d3ec6776 100644
--- a/kernel/signal.c
+++ b/kernel/signal.c
@@ -81,7 +81,7 @@ static inline bool sig_handler_ignored(void __user *handler, int sig)
 	       (handler == SIG_DFL && sig_kernel_ignore(sig));
 }
 
-static bool sig_task_ignored(struct task_struct *t, int sig, bool force)
+static bool sig_ignored(struct task_struct *t, int sig, bool force)
 {
 	void __user *handler;
 
@@ -122,25 +122,49 @@ static bool sig_blocked(struct task_struct *t, int sig)
 		sigismember(&t->real_blocked, sig);
 }
 
-static bool sig_ignored(struct task_struct *t, int sig, bool force)
+static bool sig_can_short_circuit_to_thread(struct task_struct *thread, int sig)
 {
+	/* Only a living thread can receive a short circuit signal */
+	if (__fatal_signal_pending(thread) || (thread->flags & PF_EXITING))
+		return false;
+
 	/*
-	 * Blocked signals are never ignored, since the
-	 * signal handler may change by the time it is
-	 * unblocked.
+	 * If the signal handler is blocked then short circuit
+	 * delivery may not happen because the signal handler may
+	 * change by the time it is unblocked.
 	 */
-	if (sig_blocked(t, sig))
+	if (sig_blocked(thread, sig))
 		return false;
 
 	/*
-	 * Tracers may want to know about even ignored signal unless it
-	 * is SIGKILL which can't be reported anyway but can be ignored
-	 * by SIGNAL_UNKILLABLE task.
+	 * Tracers are allowed to see and modify all signals.
+	 * SIGKILL and the SA_IMMUTABLE signals are an exception.
 	 */
-	if (t->ptrace && sig != SIGKILL)
+	if (thread->ptrace &&
+	    (sig != SIGKILL) &&
+	    !(thread->sighand->action[sig - 1].sa.sa_flags & SA_IMMUTABLE))
 		return false;
 
-	return sig_task_ignored(t, sig, force);
+	return true;
+}
+
+static bool sig_can_short_circuit(struct task_struct *p, enum pid_type type, int sig)
+{
+	/*
+	 * Is there at least one thread where the short circuit
+	 * delivery is valid?
+	 */
+	struct task_struct *thread;
+
+	if (type == PIDTYPE_PID)
+		return sig_can_short_circuit_to_thread(p, sig);
+
+	for_each_thread(p, thread) {
+		if (sig_can_short_circuit_to_thread(thread, sig))
+			return true;
+	}
+
+	return false;
 }
 
 /*
@@ -887,7 +911,8 @@ static void ptrace_trap_notify(struct task_struct *t)
  * Returns true if the signal should be actually delivered, otherwise
  * it should be dropped.
  */
-static bool prepare_signal(int sig, struct task_struct *p, bool force)
+static bool prepare_signal(int sig, struct task_struct *p,
+			   enum pid_type type, bool force)
 {
 	struct signal_struct *signal = p->signal;
 	struct task_struct *t;
@@ -951,7 +976,11 @@ static bool prepare_signal(int sig, struct task_struct *p, bool force)
 		}
 	}
 
-	return !sig_ignored(p, sig, force);
+	/* Stop process the signal if nothing more needs to be done */
+	if (sig_ignored(p, sig, force) && sig_can_short_circuit(p, type, sig))
+		return false;
+
+	return true;
 }
 
 /*
@@ -1082,7 +1111,7 @@ static int __send_signal_locked(int sig, struct kernel_siginfo *info,
 	lockdep_assert_held(&t->sighand->siglock);
 
 	result = TRACE_SIGNAL_IGNORED;
-	if (!prepare_signal(sig, t, force))
+	if (!prepare_signal(sig, t, type, force))
 		goto ret;
 
 	pending = (type != PIDTYPE_PID) ? &t->signal->shared_pending : &t->pending;
@@ -2020,7 +2049,7 @@ void posixtimer_send_sigqueue(struct k_itimer *tmr)
 	 */
 	tmr->it_sig_periodic = tmr->it_status == POSIX_TIMER_REQUEUE_PENDING;
 
-	if (!prepare_signal(sig, t, false)) {
+	if (!prepare_signal(sig, t, tmr->it_pid_type, false)) {
 		result = TRACE_SIGNAL_IGNORED;
 
 		if (!list_empty(&q->list)) {
-- 
2.41.0


  parent reply	other threads:[~2026-07-03 21:38 UTC|newest]

Thread overview: 58+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-06-19 13:27 [PATCH v2 1/3] signal: change force_sig_info_to_task() to call __send_signal_locked() Oleg Nesterov
2026-06-19 13:27 ` [PATCH v2 2/3] signal: turn the "bool force" arg of __send_signal_locked() into "int flags" Oleg Nesterov
2026-07-06 13:23   ` Bradley Morgan
2026-06-19 13:28 ` [PATCH v2 3/3] signal: fix evasion of SA_IMMUTABLE signals Oleg Nesterov
2026-07-06 13:23   ` Bradley Morgan
2026-06-26 16:52 ` [PATCH 0/11] Short circuit delivery for coredump signals Eric W. Biederman
2026-06-26 16:54   ` [PATCH 01/11] signal: Compute the exit_code in get_signal Eric W. Biederman
2026-06-26 16:54   ` [PATCH 02/11] signal: In get_signal call do_exit when it is unnecessary to shoot down threads Eric W. Biederman
2026-06-26 16:55   ` [PATCH 03/11] signal: Bring down all threads when handling a non-coredump fatal signal Eric W. Biederman
2026-06-26 16:55   ` [PATCH 04/11] signal: Move stopping for the coredump from do_exit into get_signal Eric W. Biederman
2026-06-26 16:56   ` [PATCH 05/11] signal: Move audit_core_dumps from do_coredump " Eric W. Biederman
2026-06-26 16:57   ` [PATCH 06/11] coredump: In zap_threads complete startup if there is no need to wait Eric W. Biederman
2026-06-26 16:57   ` [PATCH 07/11] signal: Use the thread killing in get_signal for coredumps Eric W. Biederman
2026-06-26 16:58   ` [PATCH 08/11] exit: Make do_group_exit static Eric W. Biederman
2026-06-26 16:59   ` [PATCH 09/11] signal: Dequeue fatal signals Eric W. Biederman
2026-06-26 16:59   ` [PATCH 10/11] signal: Short circuit deliver coredump signals Eric W. Biederman
2026-06-26 17:00   ` [PATCH 11/11] signal: Remove SA_IMMUTABLE Eric W. Biederman
2026-06-28 14:29   ` [PATCH 0/11] Short circuit delivery for coredump signals Oleg Nesterov
2026-06-29  6:22     ` Eric W. Biederman
2026-06-29 17:45       ` Eric W. Biederman
2026-07-02 10:36         ` Oleg Nesterov
2026-07-03 20:16           ` Eric W. Biederman
2026-07-05 15:54             ` Oleg Nesterov
2026-07-06  9:21               ` Christian Brauner
2026-07-06 12:30                 ` Eric W. Biederman
2026-07-06 15:58                   ` Christian Brauner
2026-07-03 21:35       ` [PATCH v2 00/14] " Eric W. Biederman
2026-07-03 21:36         ` [PATCH 01/14] signal: Generalize posixtimer_queue_sigqueue into enqueue_signal Eric W. Biederman
2026-07-06 12:54           ` Bradley Morgan
2026-07-03 21:37         ` [PATCH 02/14] signal: Factor out sig_blocked from sig_ignored Eric W. Biederman
2026-07-06 13:01           ` Bradley Morgan
2026-07-03 21:37         ` Eric W. Biederman [this message]
2026-07-06 13:02           ` [PATCH 03/14] signal: More accurate ignoring of signals based on sig_can_short_circuit Bradley Morgan
2026-07-03 21:38         ` [PATCH 04/14] signal: Use sig_can_short_circuit to improve fatal signal delivery Eric W. Biederman
2026-07-06 13:03           ` Bradley Morgan
2026-07-03 21:39         ` [PATCH 05/14] signal: Compute the exit_code in get_signal Eric W. Biederman
2026-07-06 13:03           ` Bradley Morgan
2026-07-03 21:39         ` Eric W. Biederman
2026-07-03 21:40         ` [PATCH 06/14] signal: In get_signal call do_exit when it is unnecessary to shoot down threads Eric W. Biederman
2026-07-06 13:04           ` Bradley Morgan
2026-07-03 21:40         ` [PATCH 07/14] signal: Bring down all threads when handling a non-coredump fatal signal Eric W. Biederman
2026-07-06 13:05           ` Bradley Morgan
2026-07-03 21:41         ` [PATCH 08/14] signal: Move stopping for the coredump from do_exit into get_signal Eric W. Biederman
2026-07-06 13:08           ` Bradley Morgan
2026-07-03 21:41         ` [PATCH 09/14] signal: Move audit_core_dumps from do_coredump " Eric W. Biederman
2026-07-06 13:08           ` Bradley Morgan
2026-07-03 21:42         ` [PATCH 10/14] coredump: In zap_threads complete startup if there is no need to wait Eric W. Biederman
2026-07-06 13:09           ` Bradley Morgan
2026-07-03 21:43         ` [PATCH 11/14] signal: Use the thread killing in get_signal for coredumps Eric W. Biederman
2026-07-06 13:13           ` Bradley Morgan
2026-07-03 21:43         ` [PATCH 12/14] exit: Make do_group_exit static Eric W. Biederman
2026-07-06 13:14           ` Bradley Morgan
2026-07-03 21:44         ` [PATCH 13/14] signal: Dequeue fatal signals Eric W. Biederman
2026-07-06 13:16           ` Bradley Morgan
2026-07-03 21:44         ` [PATCH 14/14] signal: Short circuit deliver coredump signals Eric W. Biederman
2026-07-06 13:17           ` Bradley Morgan
2026-07-06 13:18     ` [PATCH 0/11] Short circuit delivery for " Bradley Morgan
2026-07-06 13:23 ` [PATCH v2 1/3] signal: change force_sig_info_to_task() to call __send_signal_locked() Bradley Morgan

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=87pl133gb5.fsf_-_@email.froward.int.ebiederm.org \
    --to=ebiederm@xmission.com \
    --cc=akpm@linux-foundation.org \
    --cc=brauner@kernel.org \
    --cc=kees@kernel.org \
    --cc=kusaram@devineni.in \
    --cc=linux-kernel@vger.kernel.org \
    --cc=luto@kernel.org \
    --cc=oleg@redhat.com \
    --cc=peterz@infradead.org \
    --cc=tglx@kernel.org \
    --cc=torvalds@linux-foundation.org \
    --cc=wad@chromium.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.