[PATCH 2/2] um: Ensure that nobody remaps the stub vma
From: Richard Weinberger
Date: Sat May 03 2014 - 15:23:15 EST
This fixes a long standing problem that UML crashes
or locks up if a task messes with it' stub vma.
Reported-by: toralf.foerster@xxxxxx
Signed-off-by: Richard Weinberger <richard@xxxxxx>
---
arch/um/kernel/tlb.c | 18 +++++++++++++++---
1 file changed, 15 insertions(+), 3 deletions(-)
diff --git a/arch/um/kernel/tlb.c b/arch/um/kernel/tlb.c
index 9472079..b33d1d1 100644
--- a/arch/um/kernel/tlb.c
+++ b/arch/um/kernel/tlb.c
@@ -12,6 +12,7 @@
#include <mem_user.h>
#include <os.h>
#include <skas.h>
+#include <kern_util.h>
struct host_vm_change {
struct host_vm_op {
@@ -90,6 +91,9 @@ static int add_mmap(unsigned long virt, unsigned long phys, unsigned long len,
struct host_vm_op *last;
int fd, ret = 0;
+ if ((virt >= STUB_START) && (virt < STUB_END))
+ return -EINVAL;
+
fd = phys_mapping(phys, &offset);
if (hvc->index != 0) {
last = &hvc->ops[hvc->index - 1];
@@ -124,6 +128,9 @@ static int add_munmap(unsigned long addr, unsigned long len,
struct host_vm_op *last;
int ret = 0;
+ if ((addr >= STUB_START) && (addr < STUB_END))
+ return -EINVAL;
+
if (hvc->index != 0) {
last = &hvc->ops[hvc->index - 1];
if ((last->type == MUNMAP) &&
@@ -283,8 +290,10 @@ void fix_range_common(struct mm_struct *mm, unsigned long start_addr,
/* This is not an else because ret is modified above */
if (ret) {
printk(KERN_ERR "fix_range_common: failed, killing current "
- "process\n");
- force_sig(SIGKILL, current);
+ "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);
+ fatal_sigsegv();
}
}
@@ -409,6 +418,9 @@ void flush_tlb_page(struct vm_area_struct *vma, unsigned long address)
w = 0;
}
+ if ((address >= STUB_START) && (address < STUB_END))
+ goto kill;
+
mm_id = &mm->context.id;
prot = ((r ? UM_PROT_READ : 0) | (w ? UM_PROT_WRITE : 0) |
(x ? UM_PROT_EXEC : 0));
@@ -435,7 +447,7 @@ void flush_tlb_page(struct vm_area_struct *vma, unsigned long address)
kill:
printk(KERN_ERR "Failed to flush page for address 0x%lx\n", address);
- force_sig(SIGKILL, current);
+ fatal_sigsegv();
}
pgd_t *pgd_offset_proc(struct mm_struct *mm, unsigned long address)
--
1.8.1.4
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/