FAILED: patch "[PATCH] fix race between exit_itimers() and /proc/pid/timers" failed to apply to 5.4-stable tree
Subsystems (4)
[email protected]
maintainerThe patch below does not apply to the 5.4-stable tree.
If someone wants it applied there, or to any other stable or longterm tree, then please email the backport, including the original git commit id to <[email protected]>.
thanks,
greg k-h
------------------ original commit in Linus's tree ------------------
From d5b36a4dbd06c5e8e36ca8ccc552f679069e2946 Mon Sep 17 00:00:00 2001
From: Oleg Nesterov <[email protected]>
Date: Mon, 11 Jul 2022 18:16:25 +0200
Subject: [PATCH] fix race between exit_itimers() and /proc/pid/timers
As Chris explains, the comment above exit_itimers() is not correct, we can race with proc_timers_seq_ops. Change exit_itimers() to clear signal->posix_timers with ->siglock held.
Cc <[email protected]>
Reported-by [email protected]
Signed-off-by Oleg Nesterov <[email protected]>
Signed-off-by Linus Torvalds <[email protected]>
fs/exec.c +1 -1
@@ -1301,7 +1301,7 @@ int begin_new_exec(struct linux_binprm * bprm) bprm->mm =NULL ;#ifdef CONFIG_POSIX_TIMERS -exit_itimers (me->signal); +exit_itimers (me);flush_itimer_signals ();#endif
include/linux/sched/task.h +1 -1
@@ -85,7 +85,7 @@ static inline void exit_thread(struct task_struct *tsk)extern __noreturn void do_group_exit (int );extern void exit_files (struct task_struct *); -extern void exit_itimers (struct signal_struct *); +extern void exit_itimers (struct task_struct *);extern pid_t kernel_clone (struct kernel_clone_args *kargs);struct task_struct *create_io_thread (int (*fn)(void *),void *arg,int node);
kernel/exit.c +1 -1
@@ -766,7 +766,7 @@ void __noreturn do_exit(long code)#ifdef CONFIG_POSIX_TIMERS hrtimer_cancel (&tsk->signal->real_timer); -exit_itimers (tsk->signal); +exit_itimers (tsk);#endif if (tsk->mm)setmax_mm_hiwater_rss (&tsk->signal->maxrss, tsk->mm);
kernel/time/posix-timers.c +14 -5
@@ -1051,15 +1051,24 @@ static void itimer_delete(struct k_itimer *timer) }/* -* This is called by do_exit or de_thread, only when there are no more -* references to the shared signal_struct. +* This is called by do_exit or de_thread, only when nobody else can +* modify the signal->posix_timers list. Yet we need sighand->siglock +* to prevent the race with /proc/pid/timers. */ -void exit_itimers (struct signal_struct *sig) +void exit_itimers (struct task_struct *tsk) { +struct list_head timers;struct k_itimer *tmr; -while (!list_empty (&sig->posix_timers)) { - tmr = list_entry(sig->posix_timers.next, struct k_itimer, list); +if (list_empty (&tsk->signal->posix_timers)) +return ; + +spin_lock_irq (&tsk->sighand->siglock); +list_replace_init (&tsk->signal->posix_timers, &timers); +spin_unlock_irq (&tsk->sighand->siglock); + +while (!list_empty (&timers)) { + tmr = list_first_entry(&timers, struct k_itimer, list);itimer_delete (tmr); } }