Commit 3090bbe0 authored by Frederic Weisbecker's avatar Frederic Weisbecker Committed by Wen Zhiwei
Browse files

posix-timers: Target group sigqueue to current task only if not exiting

stable inclusion
from stable-v6.6.64
commit f3b82bb26f5beeae830a9eff1538e89a4bbca0e7
category: bugfix
bugzilla: https://gitee.com/openeuler/kernel/issues/IBL4B6

Reference: https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git/commit/?id=f3b82bb26f5beeae830a9eff1538e89a4bbca0e7



--------------------------------

commit 63dffecfba3eddcf67a8f76d80e0c141f93d44a5 upstream.

A sigqueue belonging to a posix timer, which target is not a specific
thread but a whole thread group, is preferrably targeted to the current
task if it is part of that thread group.

However nothing prevents a posix timer event from queueing such a
sigqueue from a reaped yet running task. The interruptible code space
between exit_notify() and the final call to schedule() is enough for
posix_timer_fn() hrtimer to fire.

If that happens while the current task is part of the thread group
target, it is proposed to handle it but since its sighand pointer may
have been cleared already, the sigqueue is dropped even if there are
other tasks running within the group that could handle it.

As a result posix timers with thread group wide target may miss signals
when some of their threads are exiting.

Fix this with verifying that the current task hasn't been through
exit_notify() before proposing it as a preferred target so as to ensure
that its sighand is still here and stable.

complete_signal() might still reconsider the choice and find a better
target within the group if current has passed retarget_shared_pending()
already.

Fixes: bcb7ee79 ("posix-timers: Prefer delivery of signals to the current thread")
Reported-by: default avatarAnthony Mallet <anthony.mallet@laas.fr>
Suggested-by: default avatarOleg Nesterov <oleg@redhat.com>
Signed-off-by: default avatarFrederic Weisbecker <frederic@kernel.org>
Signed-off-by: default avatarThomas Gleixner <tglx@linutronix.de>
Acked-by: default avatarOleg Nesterov <oleg@redhat.com>
Cc: stable@vger.kernel.org
Link: https://lore.kernel.org/all/20241122234811.60455-1-frederic@kernel.org
Closes: https://lore.kernel.org/all/26411.57288.238690.681680@gargle.gargle.HOWL


Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Signed-off-by: default avatarWen Zhiwei <wenzhiwei@kylinos.cn>
parent 8167ecf7
Loading
Loading
Loading
Loading
+5 −4
Original line number Diff line number Diff line
@@ -1999,14 +1999,15 @@ int send_sigqueue(struct sigqueue *q, struct pid *pid, enum pid_type type)
	 * into t->pending).
	 *
	 * Where type is not PIDTYPE_PID, signals must be delivered to the
	 * process. In this case, prefer to deliver to current if it is in
	 * the same thread group as the target process, which avoids
	 * unnecessarily waking up a potentially idle task.
	 * process. In this case, prefer to deliver to current if it is in the
	 * same thread group as the target process and its sighand is stable,
	 * which avoids unnecessarily waking up a potentially idle task.
	 */
	t = pid_task(pid, type);
	if (!t)
		goto ret;
	if (type != PIDTYPE_PID && same_thread_group(t, current))
	if (type != PIDTYPE_PID &&
	    same_thread_group(t, current) && !current->exit_state)
		t = current;
	if (!likely(lock_task_sighand(t, &flags)))
		goto ret;