Commit cfad81ce authored by Linus Torvalds's avatar Linus Torvalds

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"
parents da83fc6e bb6a1b2e
...@@ -12,6 +12,7 @@ ...@@ -12,6 +12,7 @@
#include <mem_user.h> #include <mem_user.h>
#include <os.h> #include <os.h>
#include <skas.h> #include <skas.h>
#include <kern_util.h>
struct host_vm_change { struct host_vm_change {
struct host_vm_op { struct host_vm_op {
...@@ -124,6 +125,9 @@ static int add_munmap(unsigned long addr, unsigned long len, ...@@ -124,6 +125,9 @@ static int add_munmap(unsigned long addr, unsigned long len,
struct host_vm_op *last; struct host_vm_op *last;
int ret = 0; int ret = 0;
if ((addr >= STUB_START) && (addr < STUB_END))
return -EINVAL;
if (hvc->index != 0) { if (hvc->index != 0) {
last = &hvc->ops[hvc->index - 1]; last = &hvc->ops[hvc->index - 1];
if ((last->type == MUNMAP) && if ((last->type == MUNMAP) &&
...@@ -283,8 +287,11 @@ void fix_range_common(struct mm_struct *mm, unsigned long start_addr, ...@@ -283,8 +287,11 @@ void fix_range_common(struct mm_struct *mm, unsigned long start_addr,
/* This is not an else because ret is modified above */ /* This is not an else because ret is modified above */
if (ret) { if (ret) {
printk(KERN_ERR "fix_range_common: failed, killing current " printk(KERN_ERR "fix_range_common: failed, killing current "
"process\n"); "process: %d\n", task_tgid_vnr(current));
/* We are under mmap_sem, release it such that current can terminate */
up_write(&current->mm->mmap_sem);
force_sig(SIGKILL, current); force_sig(SIGKILL, current);
do_signal();
} }
} }
......
...@@ -206,7 +206,7 @@ unsigned long segv(struct faultinfo fi, unsigned long ip, int is_user, ...@@ -206,7 +206,7 @@ unsigned long segv(struct faultinfo fi, unsigned long ip, int is_user,
int is_write = FAULT_WRITE(fi); int is_write = FAULT_WRITE(fi);
unsigned long address = FAULT_ADDRESS(fi); unsigned long address = FAULT_ADDRESS(fi);
if (regs) if (!is_user && regs)
current->thread.segv_regs = container_of(regs, struct pt_regs, regs); current->thread.segv_regs = container_of(regs, struct pt_regs, regs);
if (!is_user && (address >= start_vm) && (address < end_vm)) { if (!is_user && (address >= start_vm) && (address < end_vm)) {
......
...@@ -54,7 +54,7 @@ static int ptrace_dump_regs(int pid) ...@@ -54,7 +54,7 @@ static int ptrace_dump_regs(int pid)
void wait_stub_done(int pid) void wait_stub_done(int pid)
{ {
int n, status, err, bad_stop = 0; int n, status, err;
while (1) { while (1) {
CATCH_EINTR(n = waitpid(pid, &status, WUNTRACED | __WALL)); CATCH_EINTR(n = waitpid(pid, &status, WUNTRACED | __WALL));
...@@ -74,8 +74,6 @@ void wait_stub_done(int pid) ...@@ -74,8 +74,6 @@ void wait_stub_done(int pid)
if (((1 << WSTOPSIG(status)) & STUB_DONE_MASK) != 0) if (((1 << WSTOPSIG(status)) & STUB_DONE_MASK) != 0)
return; return;
else
bad_stop = 1;
bad_wait: bad_wait:
err = ptrace_dump_regs(pid); err = ptrace_dump_regs(pid);
...@@ -85,10 +83,7 @@ void wait_stub_done(int pid) ...@@ -85,10 +83,7 @@ void wait_stub_done(int pid)
printk(UM_KERN_ERR "wait_stub_done : failed to wait for SIGTRAP, " printk(UM_KERN_ERR "wait_stub_done : failed to wait for SIGTRAP, "
"pid = %d, n = %d, errno = %d, status = 0x%x\n", pid, n, errno, "pid = %d, n = %d, errno = %d, status = 0x%x\n", pid, n, errno,
status); status);
if (bad_stop) fatal_sigsegv();
kill(pid, SIGKILL);
else
fatal_sigsegv();
} }
extern unsigned long current_stub_stack(void); extern unsigned long current_stub_stack(void);
......
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