diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2014-07-20 23:28:04 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2014-07-20 23:28:04 -0400 |
commit | cfad81ce28b6d47fbc7c8afabd3ab16d9a8499e9 (patch) | |
tree | 2637aa130e58b10480245c3000989c258b8257c5 | |
parent | da83fc6e0f379bf80d68d34cca38788a046a71f4 (diff) | |
parent | bb6a1b2e189f797c0e4a116aec7ce77c344f11e0 (diff) |
Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/rw/uml
Pull UML fixes from Richard Weinberger:
"Four fixes, all discovered by Trinity"
* 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/rw/uml:
um: segv: Save regs only in case of a kernel mode fault
um: Fix hung task in fix_range_common()
um: Ensure that a stub page cannot get unmapped
Revert "um: Fix wait_stub_done() error handling"
-rw-r--r-- | arch/um/kernel/tlb.c | 9 | ||||
-rw-r--r-- | arch/um/kernel/trap.c | 2 | ||||
-rw-r--r-- | arch/um/os-Linux/skas/process.c | 9 |
3 files changed, 11 insertions, 9 deletions
diff --git a/arch/um/kernel/tlb.c b/arch/um/kernel/tlb.c index 9472079471bb..f1b3eb14b855 100644 --- a/arch/um/kernel/tlb.c +++ b/arch/um/kernel/tlb.c | |||
@@ -12,6 +12,7 @@ | |||
12 | #include <mem_user.h> | 12 | #include <mem_user.h> |
13 | #include <os.h> | 13 | #include <os.h> |
14 | #include <skas.h> | 14 | #include <skas.h> |
15 | #include <kern_util.h> | ||
15 | 16 | ||
16 | struct host_vm_change { | 17 | struct host_vm_change { |
17 | struct host_vm_op { | 18 | struct host_vm_op { |
@@ -124,6 +125,9 @@ static int add_munmap(unsigned long addr, unsigned long len, | |||
124 | struct host_vm_op *last; | 125 | struct host_vm_op *last; |
125 | int ret = 0; | 126 | int ret = 0; |
126 | 127 | ||
128 | if ((addr >= STUB_START) && (addr < STUB_END)) | ||
129 | return -EINVAL; | ||
130 | |||
127 | if (hvc->index != 0) { | 131 | if (hvc->index != 0) { |
128 | last = &hvc->ops[hvc->index - 1]; | 132 | last = &hvc->ops[hvc->index - 1]; |
129 | if ((last->type == MUNMAP) && | 133 | if ((last->type == MUNMAP) && |
@@ -283,8 +287,11 @@ void fix_range_common(struct mm_struct *mm, unsigned long start_addr, | |||
283 | /* This is not an else because ret is modified above */ | 287 | /* This is not an else because ret is modified above */ |
284 | if (ret) { | 288 | if (ret) { |
285 | printk(KERN_ERR "fix_range_common: failed, killing current " | 289 | printk(KERN_ERR "fix_range_common: failed, killing current " |
286 | "process\n"); | 290 | "process: %d\n", task_tgid_vnr(current)); |
291 | /* We are under mmap_sem, release it such that current can terminate */ | ||
292 | up_write(¤t->mm->mmap_sem); | ||
287 | force_sig(SIGKILL, current); | 293 | force_sig(SIGKILL, current); |
294 | do_signal(); | ||
288 | } | 295 | } |
289 | } | 296 | } |
290 | 297 | ||
diff --git a/arch/um/kernel/trap.c b/arch/um/kernel/trap.c index 974b87474a99..5678c3571e7c 100644 --- a/arch/um/kernel/trap.c +++ b/arch/um/kernel/trap.c | |||
@@ -206,7 +206,7 @@ unsigned long segv(struct faultinfo fi, unsigned long ip, int is_user, | |||
206 | int is_write = FAULT_WRITE(fi); | 206 | int is_write = FAULT_WRITE(fi); |
207 | unsigned long address = FAULT_ADDRESS(fi); | 207 | unsigned long address = FAULT_ADDRESS(fi); |
208 | 208 | ||
209 | if (regs) | 209 | if (!is_user && regs) |
210 | current->thread.segv_regs = container_of(regs, struct pt_regs, regs); | 210 | current->thread.segv_regs = container_of(regs, struct pt_regs, regs); |
211 | 211 | ||
212 | if (!is_user && (address >= start_vm) && (address < end_vm)) { | 212 | if (!is_user && (address >= start_vm) && (address < end_vm)) { |
diff --git a/arch/um/os-Linux/skas/process.c b/arch/um/os-Linux/skas/process.c index d531879a4617..908579f2b0ab 100644 --- a/arch/um/os-Linux/skas/process.c +++ b/arch/um/os-Linux/skas/process.c | |||
@@ -54,7 +54,7 @@ static int ptrace_dump_regs(int pid) | |||
54 | 54 | ||
55 | void wait_stub_done(int pid) | 55 | void wait_stub_done(int pid) |
56 | { | 56 | { |
57 | int n, status, err, bad_stop = 0; | 57 | int n, status, err; |
58 | 58 | ||
59 | while (1) { | 59 | while (1) { |
60 | CATCH_EINTR(n = waitpid(pid, &status, WUNTRACED | __WALL)); | 60 | CATCH_EINTR(n = waitpid(pid, &status, WUNTRACED | __WALL)); |
@@ -74,8 +74,6 @@ void wait_stub_done(int pid) | |||
74 | 74 | ||
75 | if (((1 << WSTOPSIG(status)) & STUB_DONE_MASK) != 0) | 75 | if (((1 << WSTOPSIG(status)) & STUB_DONE_MASK) != 0) |
76 | return; | 76 | return; |
77 | else | ||
78 | bad_stop = 1; | ||
79 | 77 | ||
80 | bad_wait: | 78 | bad_wait: |
81 | err = ptrace_dump_regs(pid); | 79 | err = ptrace_dump_regs(pid); |
@@ -85,10 +83,7 @@ bad_wait: | |||
85 | printk(UM_KERN_ERR "wait_stub_done : failed to wait for SIGTRAP, " | 83 | printk(UM_KERN_ERR "wait_stub_done : failed to wait for SIGTRAP, " |
86 | "pid = %d, n = %d, errno = %d, status = 0x%x\n", pid, n, errno, | 84 | "pid = %d, n = %d, errno = %d, status = 0x%x\n", pid, n, errno, |
87 | status); | 85 | status); |
88 | if (bad_stop) | 86 | fatal_sigsegv(); |
89 | kill(pid, SIGKILL); | ||
90 | else | ||
91 | fatal_sigsegv(); | ||
92 | } | 87 | } |
93 | 88 | ||
94 | extern unsigned long current_stub_stack(void); | 89 | extern unsigned long current_stub_stack(void); |