[PATCH v2 2/2] kernel: rerun task_work while freezing in get_signal()

Pavel Begunkov posted 2 patches 1 year, 7 months ago
There is a newer version of this series
[PATCH v2 2/2] kernel: rerun task_work while freezing in get_signal()
Posted by Pavel Begunkov 1 year, 7 months ago
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(&current->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
Re: [PATCH v2 2/2] kernel: rerun task_work while freezing in get_signal()
Posted by Tejun Heo 1 year, 7 months ago
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
Re: [PATCH v2 2/2] kernel: rerun task_work while freezing in get_signal()
Posted by Pavel Begunkov 1 year, 7 months ago
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
Re: [PATCH v2 2/2] kernel: rerun task_work while freezing in get_signal()
Posted by Oleg Nesterov 1 year, 7 months ago
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(&current->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>