io_uring can asynchronously add a task_work while the task is getting
freezed. TIF_NOTIFY_SIGNAL will prevent the task from sleeping in
do_freezer_trap(), and since the get_signal()'s relock loop doesn't
retry task_work, the task will spin there not being able to sleep
until the freezing is cancelled / the task is killed / etc.
Cc: stable@vger.kernel.org
Link: https://github.com/systemd/systemd/issues/33626
Fixes: 12db8b690010c ("entry: Add support for TIF_NOTIFY_SIGNAL")
Reported-by: Julian Orth <ju.orth@gmail.com>
Signed-off-by: Pavel Begunkov <asml.silence@gmail.com>
---
kernel/signal.c | 8 ++++++++
1 file changed, 8 insertions(+)
diff --git a/kernel/signal.c b/kernel/signal.c
index 1f9dd41c04be..60c737e423a1 100644
--- a/kernel/signal.c
+++ b/kernel/signal.c
@@ -2600,6 +2600,14 @@ static void do_freezer_trap(void)
spin_unlock_irq(¤t->sighand->siglock);
cgroup_enter_frozen();
schedule();
+
+ /*
+ * We could've been woken by task_work, run it to clear
+ * TIF_NOTIFY_SIGNAL. The caller will retry if necessary.
+ */
+ clear_notify_signal();
+ if (unlikely(task_work_pending(current)))
+ task_work_run();
}
static int ptrace_signal(int signr, kernel_siginfo_t *info, enum pid_type type)
--
2.44.0
On Tue, Jul 09, 2024 at 03:27:19PM +0100, Pavel Begunkov wrote:
> io_uring can asynchronously add a task_work while the task is getting
> freezed. TIF_NOTIFY_SIGNAL will prevent the task from sleeping in
> do_freezer_trap(), and since the get_signal()'s relock loop doesn't
> retry task_work, the task will spin there not being able to sleep
> until the freezing is cancelled / the task is killed / etc.
>
> Cc: stable@vger.kernel.org
> Link: https://github.com/systemd/systemd/issues/33626
> Fixes: 12db8b690010c ("entry: Add support for TIF_NOTIFY_SIGNAL")
> Reported-by: Julian Orth <ju.orth@gmail.com>
> Signed-off-by: Pavel Begunkov <asml.silence@gmail.com>
I haven't looked at the signal code for too long to be all that useful but
the problem described and the patch does make sense to me. FWIW,
Acked-by: Tejun Heo <tj@kernel.org>
Maybe note that this is structured specifically to ease backport and we need
further cleanups? It's not great that this is special cased in
do_freezer_trap() instead of being integrated into the outer loop.
Thanks.
--
tejun
On 7/10/24 01:57, Tejun Heo wrote:
> On Tue, Jul 09, 2024 at 03:27:19PM +0100, Pavel Begunkov wrote:
>> io_uring can asynchronously add a task_work while the task is getting
>> freezed. TIF_NOTIFY_SIGNAL will prevent the task from sleeping in
>> do_freezer_trap(), and since the get_signal()'s relock loop doesn't
>> retry task_work, the task will spin there not being able to sleep
>> until the freezing is cancelled / the task is killed / etc.
>>
>> Cc: stable@vger.kernel.org
>> Link: https://github.com/systemd/systemd/issues/33626
>> Fixes: 12db8b690010c ("entry: Add support for TIF_NOTIFY_SIGNAL")
>> Reported-by: Julian Orth <ju.orth@gmail.com>
>> Signed-off-by: Pavel Begunkov <asml.silence@gmail.com>
>
> I haven't looked at the signal code for too long to be all that useful but
> the problem described and the patch does make sense to me. FWIW,
>
> Acked-by: Tejun Heo <tj@kernel.org>
>
> Maybe note that this is structured specifically to ease backport and we need
> further cleanups? It's not great that this is special cased in
I'll add a couple of words
> do_freezer_trap() instead of being integrated into the outer loop.
v1 had it in the common loop, but might actually be good it's
limited to freezing, need more digging.
--
Pavel Begunkov
On 07/09, Pavel Begunkov wrote: > > --- a/kernel/signal.c > +++ b/kernel/signal.c > @@ -2600,6 +2600,14 @@ static void do_freezer_trap(void) > spin_unlock_irq(¤t->sighand->siglock); > cgroup_enter_frozen(); > schedule(); > + > + /* > + * We could've been woken by task_work, run it to clear > + * TIF_NOTIFY_SIGNAL. The caller will retry if necessary. > + */ > + clear_notify_signal(); > + if (unlikely(task_work_pending(current))) > + task_work_run(); > } Acked-by: Oleg Nesterov <oleg@redhat.com>
© 2016 - 2026 Red Hat, Inc.