Commit 622c72b6 authored by Linus Torvalds's avatar Linus Torvalds

Merge tag 'timers-urgent-2021-11-14' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip

Pull timer fix from Thomas Gleixner:
 "A single fix for POSIX CPU timers to address a problem where POSIX CPU
  timer delivery stops working for a new child task because
  copy_process() copies state information which is only valid for the
  parent task"

* tag 'timers-urgent-2021-11-14' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip:
  posix-cpu-timers: Clear task::posix_cputimers_work in copy_process()
parents c36e33e2 ca7752ca
...@@ -184,8 +184,10 @@ static inline void posix_cputimers_group_init(struct posix_cputimers *pct, ...@@ -184,8 +184,10 @@ static inline void posix_cputimers_group_init(struct posix_cputimers *pct,
#endif #endif
#ifdef CONFIG_POSIX_CPU_TIMERS_TASK_WORK #ifdef CONFIG_POSIX_CPU_TIMERS_TASK_WORK
void clear_posix_cputimers_work(struct task_struct *p);
void posix_cputimers_init_work(void); void posix_cputimers_init_work(void);
#else #else
static inline void clear_posix_cputimers_work(struct task_struct *p) { }
static inline void posix_cputimers_init_work(void) { } static inline void posix_cputimers_init_work(void) { }
#endif #endif
......
...@@ -2277,6 +2277,7 @@ static __latent_entropy struct task_struct *copy_process( ...@@ -2277,6 +2277,7 @@ static __latent_entropy struct task_struct *copy_process(
p->pdeath_signal = 0; p->pdeath_signal = 0;
INIT_LIST_HEAD(&p->thread_group); INIT_LIST_HEAD(&p->thread_group);
p->task_works = NULL; p->task_works = NULL;
clear_posix_cputimers_work(p);
#ifdef CONFIG_KRETPROBES #ifdef CONFIG_KRETPROBES
p->kretprobe_instances.first = NULL; p->kretprobe_instances.first = NULL;
......
...@@ -1158,14 +1158,29 @@ static void posix_cpu_timers_work(struct callback_head *work) ...@@ -1158,14 +1158,29 @@ static void posix_cpu_timers_work(struct callback_head *work)
handle_posix_cpu_timers(current); handle_posix_cpu_timers(current);
} }
/*
* Clear existing posix CPU timers task work.
*/
void clear_posix_cputimers_work(struct task_struct *p)
{
/*
* A copied work entry from the old task is not meaningful, clear it.
* N.B. init_task_work will not do this.
*/
memset(&p->posix_cputimers_work.work, 0,
sizeof(p->posix_cputimers_work.work));
init_task_work(&p->posix_cputimers_work.work,
posix_cpu_timers_work);
p->posix_cputimers_work.scheduled = false;
}
/* /*
* Initialize posix CPU timers task work in init task. Out of line to * Initialize posix CPU timers task work in init task. Out of line to
* keep the callback static and to avoid header recursion hell. * keep the callback static and to avoid header recursion hell.
*/ */
void __init posix_cputimers_init_work(void) void __init posix_cputimers_init_work(void)
{ {
init_task_work(&current->posix_cputimers_work.work, clear_posix_cputimers_work(current);
posix_cpu_timers_work);
} }
/* /*
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment