public inbox for linux-kernel@vger.kernel.org
 help / color / mirror / Atom feed
* [PATCH] posix-timers: Target group sigqueue to current task only if not exiting
@ 2024-11-22 23:48 Frederic Weisbecker
  2024-11-23 10:13 ` Oleg Nesterov
  2024-11-29 12:26 ` [tip: timers/urgent] " tip-bot2 for Frederic Weisbecker
  0 siblings, 2 replies; 6+ messages in thread
From: Frederic Weisbecker @ 2024-11-22 23:48 UTC (permalink / raw)
  To: Thomas Gleixner
  Cc: LKML, Frederic Weisbecker, Dmitry Vyukov, Oleg Nesterov,
	Anna-Maria Behnsen, Anthony Mallet

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.

Reported-by: Anthony Mallet <anthony.mallet@laas.fr>
Fixes: bcb7ee79029d ("posix-timers: Prefer delivery of signals to the current thread")
Suggested-by: Oleg Nesterov <oleg@redhat.com>
Signed-off-by: Frederic Weisbecker <frederic@kernel.org>
---
 kernel/signal.c | 7 ++++---
 1 file changed, 4 insertions(+), 3 deletions(-)

diff --git a/kernel/signal.c b/kernel/signal.c
index 10b464b9d91f..7cdfb25d5078 100644
--- a/kernel/signal.c
+++ b/kernel/signal.c
@@ -1958,14 +1958,15 @@ static void posixtimer_queue_sigqueue(struct sigqueue *q, struct task_struct *t,
  *
  * 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.
+ * the same thread group as the target process and its sighand is
+ * stable, which avoids unnecessarily waking up a potentially idle task.
  */
 static inline struct task_struct *posixtimer_get_target(struct k_itimer *tmr)
 {
 	struct task_struct *t = pid_task(tmr->it_pid, tmr->it_pid_type);
 
-	if (t && tmr->it_pid_type != PIDTYPE_PID && same_thread_group(t, current))
+	if (t && tmr->it_pid_type != PIDTYPE_PID &&
+	    same_thread_group(t, current) && !current->exit_state)
 		t = current;
 	return t;
 }
-- 
2.46.0


^ permalink raw reply related	[flat|nested] 6+ messages in thread

* Re: [PATCH] posix-timers: Target group sigqueue to current task only if not exiting
  2024-11-22 23:48 [PATCH] posix-timers: Target group sigqueue to current task only if not exiting Frederic Weisbecker
@ 2024-11-23 10:13 ` Oleg Nesterov
  2024-11-25  9:46   ` Dmitry Vyukov
  2024-11-29 12:26 ` [tip: timers/urgent] " tip-bot2 for Frederic Weisbecker
  1 sibling, 1 reply; 6+ messages in thread
From: Oleg Nesterov @ 2024-11-23 10:13 UTC (permalink / raw)
  To: Frederic Weisbecker
  Cc: Thomas Gleixner, LKML, Dmitry Vyukov, Anna-Maria Behnsen,
	Anthony Mallet

On 11/23, Frederic Weisbecker wrote:
>
> - * the same thread group as the target process, which avoids
> - * unnecessarily waking up a potentially idle task.
> + * the same thread group as the target process and its sighand is
> + * stable, which avoids unnecessarily waking up a potentially idle task.
>   */
>  static inline struct task_struct *posixtimer_get_target(struct k_itimer *tmr)
>  {
>  	struct task_struct *t = pid_task(tmr->it_pid, tmr->it_pid_type);
>  
> -	if (t && tmr->it_pid_type != PIDTYPE_PID && same_thread_group(t, current))
> +	if (t && tmr->it_pid_type != PIDTYPE_PID &&
> +	    same_thread_group(t, current) && !current->exit_state)
>  		t = current;

Thanks!

Acked-by: Oleg Nesterov <oleg@redhat.com>


^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: [PATCH] posix-timers: Target group sigqueue to current task only if not exiting
  2024-11-23 10:13 ` Oleg Nesterov
@ 2024-11-25  9:46   ` Dmitry Vyukov
  2024-11-25 11:12     ` Oleg Nesterov
  0 siblings, 1 reply; 6+ messages in thread
From: Dmitry Vyukov @ 2024-11-25  9:46 UTC (permalink / raw)
  To: Oleg Nesterov
  Cc: Frederic Weisbecker, Thomas Gleixner, LKML, Anna-Maria Behnsen,
	Anthony Mallet

On Sat, 23 Nov 2024 at 11:13, Oleg Nesterov <oleg@redhat.com> wrote:
>
> On 11/23, Frederic Weisbecker wrote:
> >
> > - * the same thread group as the target process, which avoids
> > - * unnecessarily waking up a potentially idle task.
> > + * the same thread group as the target process and its sighand is
> > + * stable, which avoids unnecessarily waking up a potentially idle task.
> >   */
> >  static inline struct task_struct *posixtimer_get_target(struct k_itimer *tmr)
> >  {
> >       struct task_struct *t = pid_task(tmr->it_pid, tmr->it_pid_type);
> >
> > -     if (t && tmr->it_pid_type != PIDTYPE_PID && same_thread_group(t, current))
> > +     if (t && tmr->it_pid_type != PIDTYPE_PID &&
> > +         same_thread_group(t, current) && !current->exit_state)
> >               t = current;
>
> Thanks!
>
> Acked-by: Oleg Nesterov <oleg@redhat.com>

Can't the group leader be exiting as well? Though, that's still an
improvements. People usually don't do that (exiting from main w/o
killing the process). So thanks for the fix.

^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: [PATCH] posix-timers: Target group sigqueue to current task only if not exiting
  2024-11-25  9:46   ` Dmitry Vyukov
@ 2024-11-25 11:12     ` Oleg Nesterov
  2024-11-25 11:19       ` Dmitry Vyukov
  0 siblings, 1 reply; 6+ messages in thread
From: Oleg Nesterov @ 2024-11-25 11:12 UTC (permalink / raw)
  To: Dmitry Vyukov
  Cc: Frederic Weisbecker, Thomas Gleixner, LKML, Anna-Maria Behnsen,
	Anthony Mallet

On 11/25, Dmitry Vyukov wrote:
>
> On Sat, 23 Nov 2024 at 11:13, Oleg Nesterov <oleg@redhat.com> wrote:
> >
> > On 11/23, Frederic Weisbecker wrote:
> > >
> > > - * the same thread group as the target process, which avoids
> > > - * unnecessarily waking up a potentially idle task.
> > > + * the same thread group as the target process and its sighand is
> > > + * stable, which avoids unnecessarily waking up a potentially idle task.
> > >   */
> > >  static inline struct task_struct *posixtimer_get_target(struct k_itimer *tmr)
> > >  {
> > >       struct task_struct *t = pid_task(tmr->it_pid, tmr->it_pid_type);
> > >
> > > -     if (t && tmr->it_pid_type != PIDTYPE_PID && same_thread_group(t, current))
> > > +     if (t && tmr->it_pid_type != PIDTYPE_PID &&
> > > +         same_thread_group(t, current) && !current->exit_state)
> > >               t = current;
> >
> > Thanks!
> >
> > Acked-by: Oleg Nesterov <oleg@redhat.com>
>
> Can't the group leader be exiting as well?

It can. It is even possible that the group leader is already a zombie.

But this is fine. release_task(zombie-or-exiting-leader) (which does __exit_signal()
and clears ->sighand) won't be called until all the sub-threads have exited.

And. If all the sub-threads (and the group leader) have exited, then send_sigqueue()
makes no sense, the whole process is dead. so we do not care if lock_task_sighand()
fails in this case.

> Though, that's still an
> improvements. People usually don't do that (exiting from main w/o
> killing the process).

See above. Nothing to improve, AFAICS.

> So thanks for the fix.

Yes, thank you Anthony and Frederic!

Oleg.


^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: [PATCH] posix-timers: Target group sigqueue to current task only if not exiting
  2024-11-25 11:12     ` Oleg Nesterov
@ 2024-11-25 11:19       ` Dmitry Vyukov
  0 siblings, 0 replies; 6+ messages in thread
From: Dmitry Vyukov @ 2024-11-25 11:19 UTC (permalink / raw)
  To: Oleg Nesterov
  Cc: Frederic Weisbecker, Thomas Gleixner, LKML, Anna-Maria Behnsen,
	Anthony Mallet

On Mon, 25 Nov 2024 at 12:13, Oleg Nesterov <oleg@redhat.com> wrote:
>
> On 11/25, Dmitry Vyukov wrote:
> >
> > On Sat, 23 Nov 2024 at 11:13, Oleg Nesterov <oleg@redhat.com> wrote:
> > >
> > > On 11/23, Frederic Weisbecker wrote:
> > > >
> > > > - * the same thread group as the target process, which avoids
> > > > - * unnecessarily waking up a potentially idle task.
> > > > + * the same thread group as the target process and its sighand is
> > > > + * stable, which avoids unnecessarily waking up a potentially idle task.
> > > >   */
> > > >  static inline struct task_struct *posixtimer_get_target(struct k_itimer *tmr)
> > > >  {
> > > >       struct task_struct *t = pid_task(tmr->it_pid, tmr->it_pid_type);
> > > >
> > > > -     if (t && tmr->it_pid_type != PIDTYPE_PID && same_thread_group(t, current))
> > > > +     if (t && tmr->it_pid_type != PIDTYPE_PID &&
> > > > +         same_thread_group(t, current) && !current->exit_state)
> > > >               t = current;
> > >
> > > Thanks!
> > >
> > > Acked-by: Oleg Nesterov <oleg@redhat.com>
> >
> > Can't the group leader be exiting as well?
>
> It can. It is even possible that the group leader is already a zombie.
>
> But this is fine. release_task(zombie-or-exiting-leader) (which does __exit_signal()
> and clears ->sighand) won't be called until all the sub-threads have exited.
>
> And. If all the sub-threads (and the group leader) have exited, then send_sigqueue()
> makes no sense, the whole process is dead. so we do not care if lock_task_sighand()
> fails in this case.

Ah, I see. Thanks.

> > Though, that's still an
> > improvements. People usually don't do that (exiting from main w/o
> > killing the process).
>
> See above. Nothing to improve, AFAICS.
>
> > So thanks for the fix.
>
> Yes, thank you Anthony and Frederic!
>
> Oleg.
>

^ permalink raw reply	[flat|nested] 6+ messages in thread

* [tip: timers/urgent] posix-timers: Target group sigqueue to current task only if not exiting
  2024-11-22 23:48 [PATCH] posix-timers: Target group sigqueue to current task only if not exiting Frederic Weisbecker
  2024-11-23 10:13 ` Oleg Nesterov
@ 2024-11-29 12:26 ` tip-bot2 for Frederic Weisbecker
  1 sibling, 0 replies; 6+ messages in thread
From: tip-bot2 for Frederic Weisbecker @ 2024-11-29 12:26 UTC (permalink / raw)
  To: linux-tip-commits
  Cc: Anthony Mallet, Oleg Nesterov, Frederic Weisbecker,
	Thomas Gleixner, stable, x86, linux-kernel

The following commit has been merged into the timers/urgent branch of tip:

Commit-ID:     63dffecfba3eddcf67a8f76d80e0c141f93d44a5
Gitweb:        https://git.kernel.org/tip/63dffecfba3eddcf67a8f76d80e0c141f93d44a5
Author:        Frederic Weisbecker <frederic@kernel.org>
AuthorDate:    Sat, 23 Nov 2024 00:48:11 +01:00
Committer:     Thomas Gleixner <tglx@linutronix.de>
CommitterDate: Fri, 29 Nov 2024 13:19:09 +01:00

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

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: bcb7ee79029d ("posix-timers: Prefer delivery of signals to the current thread")
Reported-by: Anthony Mallet <anthony.mallet@laas.fr>
Suggested-by: Oleg Nesterov <oleg@redhat.com>
Signed-off-by: Frederic Weisbecker <frederic@kernel.org>
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Acked-by: Oleg 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
---
 kernel/signal.c | 7 ++++---
 1 file changed, 4 insertions(+), 3 deletions(-)

diff --git a/kernel/signal.c b/kernel/signal.c
index 98b65cb..989b1cc 100644
--- a/kernel/signal.c
+++ b/kernel/signal.c
@@ -1959,14 +1959,15 @@ static void posixtimer_queue_sigqueue(struct sigqueue *q, struct task_struct *t,
  *
  * 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.
+ * the same thread group as the target process and its sighand is
+ * stable, which avoids unnecessarily waking up a potentially idle task.
  */
 static inline struct task_struct *posixtimer_get_target(struct k_itimer *tmr)
 {
 	struct task_struct *t = pid_task(tmr->it_pid, tmr->it_pid_type);
 
-	if (t && tmr->it_pid_type != PIDTYPE_PID && same_thread_group(t, current))
+	if (t && tmr->it_pid_type != PIDTYPE_PID &&
+	    same_thread_group(t, current) && !current->exit_state)
 		t = current;
 	return t;
 }

^ permalink raw reply related	[flat|nested] 6+ messages in thread

end of thread, other threads:[~2024-11-29 12:26 UTC | newest]

Thread overview: 6+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2024-11-22 23:48 [PATCH] posix-timers: Target group sigqueue to current task only if not exiting Frederic Weisbecker
2024-11-23 10:13 ` Oleg Nesterov
2024-11-25  9:46   ` Dmitry Vyukov
2024-11-25 11:12     ` Oleg Nesterov
2024-11-25 11:19       ` Dmitry Vyukov
2024-11-29 12:26 ` [tip: timers/urgent] " tip-bot2 for Frederic Weisbecker

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox