Re: [PATCH] signal: Use list_del_init_careful() in flush_sigqueue()

Thomas Gleixner <[email protected]>
Newsgroups org.kernel.vger.linux-kernel
Message-ID <8733w3j1i1.ffs@fw13>
On Mon, Aug 24 2026 at 10:04, Thomas Gleixner wrote:

> On Sat, Aug 22 2026 at 14:37, Hyunwoo Kim wrote:
>> diff --git a/kernel/signal.c b/kernel/signal.c
>> index bbc0fd4cc4d7c1..ec9a0a0490d19f 100644
>> --- a/kernel/signal.c
>> +++ b/kernel/signal.c
>> @@ -482,7 +482,11 @@ void flush_sigqueue(struct sigpending *queue)
>>  	sigemptyset(&queue->signal);
>>  	while (!list_empty(&queue->list)) {
>>  		q = list_entry(queue->list.next, struct sigqueue , list);
>> -		list_del_init(&q->list);
>> +		/*
>> +		 * Pairs with the list_empty() in posixtimer_send_sigqueue().
>
> No. That list_empty() would need to be changed to list_empty_careful()
> to be correct on weakly ordered architectures.
>
> Aside of that I'm not convinced that this is the right way to handle
> this as it cures the symptom and not the underlying problem. Let me
> stare at this some more.

Something like the untested below.

Thanks,

        tglx
---
--- a/fs/exec.c
+++ b/fs/exec.c
@@ -983,6 +983,18 @@ static int de_thread(struct task_struct
 		}
 
 		/*
+		 * Ensure that POSIX timer SIGEV_THREAD_ID signals pending for
+		 * the former leader are removed under sighand::siglock _before_
+		 * taking over the leader's TID. Otherwise the lockless cleanup
+		 * in release_task() can race against a concurrent signal
+		 * delivery to the new leader. The former leader has PF_EXITING
+		 * set which prevents queueing of SIGEV_THREAD_ID signals up to
+		 * the point where it's sighand gets cleared.
+		 */
+		scoped_guard(spinlock_irq, lock)
+			flush_sigqueue(&leader->pending);
+
+		/*
 		 * The only record we have of the real-time age of a
 		 * process, regardless of execs it's done, is start_time.
 		 * All the past CPU time is accumulated in signal_struct
--- a/kernel/signal.c
+++ b/kernel/signal.c
@@ -1998,6 +1998,13 @@ void posixtimer_send_sigqueue(struct k_i
 		return;
 
 	/*
+	 * If the signal is targeted at a specific thread, validate with sighand
+	 * lock held that the thread is not exiting.
+	 */
+	if (unlikely(tmr->it_pid_type == PIDTYPE_PID  && t->flags & PF_EXITING))
+		goto unlock;
+
+	/*
 	 * Update @tmr::sigqueue_seq for posix timer signals with sighand
 	 * locked to prevent a race against dequeue_signal().
 	 */
@@ -2088,6 +2095,7 @@ void posixtimer_send_sigqueue(struct k_i
 	result = TRACE_SIGNAL_DELIVERED;
 out:
 	trace_signal_generate(sig, &q->info, t, tmr->it_pid_type != PIDTYPE_PID, result);
+unlock:
 	unlock_task_sighand(t, &flags);
 }
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.