Commit 137d1a26c842a384c98dd2a6a605014fddf5c777
Committed by
Linus Torvalds
1 parent
9bd0a07712
Exists in
smarc-l5.0.0_1.0.0-ga
and in
5 other branches
um: fix possible race on task->mm
Checking for task->mm is dangerous as ->mm might disappear (exit_mm() assigns NULL under task_lock(), so tasklist lock is not enough). We can't use get_task_mm()/mmput() pair as mmput() might sleep, so let's take the task lock while we care about its mm. Note that we should also use find_lock_task_mm() to check all process' threads for a valid mm, but for uml we'll do it in a separate patch. Signed-off-by: Anton Vorontsov <anton.vorontsov@linaro.org> Cc: Richard Weinberger <richard@nod.at> Cc: Oleg Nesterov <oleg@redhat.com> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Showing 1 changed file with 5 additions and 2 deletions Inline Diff
arch/um/kernel/reboot.c
1 | /* | 1 | /* |
2 | * Copyright (C) 2000 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com) | 2 | * Copyright (C) 2000 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com) |
3 | * Licensed under the GPL | 3 | * Licensed under the GPL |
4 | */ | 4 | */ |
5 | 5 | ||
6 | #include "linux/sched.h" | 6 | #include "linux/sched.h" |
7 | #include "linux/spinlock.h" | 7 | #include "linux/spinlock.h" |
8 | #include "linux/slab.h" | 8 | #include "linux/slab.h" |
9 | #include "kern_util.h" | 9 | #include "kern_util.h" |
10 | #include "os.h" | 10 | #include "os.h" |
11 | #include "skas.h" | 11 | #include "skas.h" |
12 | 12 | ||
13 | void (*pm_power_off)(void); | 13 | void (*pm_power_off)(void); |
14 | 14 | ||
15 | static void kill_off_processes(void) | 15 | static void kill_off_processes(void) |
16 | { | 16 | { |
17 | if (proc_mm) | 17 | if (proc_mm) |
18 | /* | 18 | /* |
19 | * FIXME: need to loop over userspace_pids | 19 | * FIXME: need to loop over userspace_pids |
20 | */ | 20 | */ |
21 | os_kill_ptraced_process(userspace_pid[0], 1); | 21 | os_kill_ptraced_process(userspace_pid[0], 1); |
22 | else { | 22 | else { |
23 | struct task_struct *p; | 23 | struct task_struct *p; |
24 | int pid; | 24 | int pid; |
25 | 25 | ||
26 | read_lock(&tasklist_lock); | 26 | read_lock(&tasklist_lock); |
27 | for_each_process(p) { | 27 | for_each_process(p) { |
28 | if (p->mm == NULL) | 28 | task_lock(p); |
29 | if (!p->mm) { | ||
30 | task_unlock(p); | ||
29 | continue; | 31 | continue; |
30 | 32 | } | |
31 | pid = p->mm->context.id.u.pid; | 33 | pid = p->mm->context.id.u.pid; |
34 | task_unlock(p); | ||
32 | os_kill_ptraced_process(pid, 1); | 35 | os_kill_ptraced_process(pid, 1); |
33 | } | 36 | } |
34 | read_unlock(&tasklist_lock); | 37 | read_unlock(&tasklist_lock); |
35 | } | 38 | } |
36 | } | 39 | } |
37 | 40 | ||
38 | void uml_cleanup(void) | 41 | void uml_cleanup(void) |
39 | { | 42 | { |
40 | kmalloc_ok = 0; | 43 | kmalloc_ok = 0; |
41 | do_uml_exitcalls(); | 44 | do_uml_exitcalls(); |
42 | kill_off_processes(); | 45 | kill_off_processes(); |
43 | } | 46 | } |
44 | 47 | ||
45 | void machine_restart(char * __unused) | 48 | void machine_restart(char * __unused) |
46 | { | 49 | { |
47 | uml_cleanup(); | 50 | uml_cleanup(); |
48 | reboot_skas(); | 51 | reboot_skas(); |
49 | } | 52 | } |
50 | 53 | ||
51 | void machine_power_off(void) | 54 | void machine_power_off(void) |
52 | { | 55 | { |
53 | uml_cleanup(); | 56 | uml_cleanup(); |
54 | halt_skas(); | 57 | halt_skas(); |
55 | } | 58 | } |
56 | 59 | ||
57 | void machine_halt(void) | 60 | void machine_halt(void) |
58 | { | 61 | { |
59 | machine_power_off(); | 62 | machine_power_off(); |
60 | } | 63 | } |
61 | 64 |