Commit 137d1a26c842a384c98dd2a6a605014fddf5c777

Authored by Anton Vorontsov
Committed by Linus Torvalds
1 parent 9bd0a07712

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