Skip to content

Commit 622c72b

Browse files
committed
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()
2 parents c36e33e + ca7752c commit 622c72b

File tree

3 files changed

+20
-2
lines changed

3 files changed

+20
-2
lines changed

include/linux/posix-timers.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -184,8 +184,10 @@ static inline void posix_cputimers_group_init(struct posix_cputimers *pct,
184184
#endif
185185

186186
#ifdef CONFIG_POSIX_CPU_TIMERS_TASK_WORK
187+
void clear_posix_cputimers_work(struct task_struct *p);
187188
void posix_cputimers_init_work(void);
188189
#else
190+
static inline void clear_posix_cputimers_work(struct task_struct *p) { }
189191
static inline void posix_cputimers_init_work(void) { }
190192
#endif
191193

kernel/fork.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2277,6 +2277,7 @@ static __latent_entropy struct task_struct *copy_process(
22772277
p->pdeath_signal = 0;
22782278
INIT_LIST_HEAD(&p->thread_group);
22792279
p->task_works = NULL;
2280+
clear_posix_cputimers_work(p);
22802281

22812282
#ifdef CONFIG_KRETPROBES
22822283
p->kretprobe_instances.first = NULL;

kernel/time/posix-cpu-timers.c

Lines changed: 17 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1158,14 +1158,29 @@ static void posix_cpu_timers_work(struct callback_head *work)
11581158
handle_posix_cpu_timers(current);
11591159
}
11601160

1161+
/*
1162+
* Clear existing posix CPU timers task work.
1163+
*/
1164+
void clear_posix_cputimers_work(struct task_struct *p)
1165+
{
1166+
/*
1167+
* A copied work entry from the old task is not meaningful, clear it.
1168+
* N.B. init_task_work will not do this.
1169+
*/
1170+
memset(&p->posix_cputimers_work.work, 0,
1171+
sizeof(p->posix_cputimers_work.work));
1172+
init_task_work(&p->posix_cputimers_work.work,
1173+
posix_cpu_timers_work);
1174+
p->posix_cputimers_work.scheduled = false;
1175+
}
1176+
11611177
/*
11621178
* Initialize posix CPU timers task work in init task. Out of line to
11631179
* keep the callback static and to avoid header recursion hell.
11641180
*/
11651181
void __init posix_cputimers_init_work(void)
11661182
{
1167-
init_task_work(&current->posix_cputimers_work.work,
1168-
posix_cpu_timers_work);
1183+
clear_posix_cputimers_work(current);
11691184
}
11701185

11711186
/*

0 commit comments

Comments
 (0)