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"
This commit is contained in:
commit
cfad81ce28
|
@ -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,
|
||||||
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,
|
||||||
/* 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(¤t->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,
|
||||||
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)
|
||||||
|
|
||||||
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)
|
||||||
|
|
||||||
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 @@ bad_wait:
|
||||||
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);
|
||||||
|
|
Loading…
Reference in a new issue