From b40723891dca1d623c82ba1be8c4afa5c42da12d Mon Sep 17 00:00:00 2001 From: Yongli He Date: Mon, 25 Aug 2008 10:59:44 +0800 Subject: [PATCH 01/12] revoke special mmap handling V7 From: Pekka Enberg This adds special handling for revoked shared memory mappings. We want to raise SIGBUS if someone accesses a revoked mapping and return ENODEV if somebody tries to remap one with mmap(2). Cc: Alan Cox Cc: Al Viro Cc: Christoph Hellwig Cc: Peter Zijlstra Signed-off-by: Pekka Enberg Integrated-by: Yongli he --- include/linux/mm.h | 3 +++ mm/memory.c | 3 +++ mm/mmap.c | 12 ++++++++---- 3 files changed, 14 insertions(+), 4 deletions(-) diff --git a/include/linux/mm.h b/include/linux/mm.h index 461baba..3d2019c 100644 --- a/include/linux/mm.h +++ b/include/linux/mm.h @@ -111,6 +111,9 @@ extern unsigned int kobjsize(const void *objp); #define VM_PAGEEXEC 0x80000000 /* vma->vm_page_prot needs special handling */ #endif +#define VM_REVOKED 0x20000000 /* Mapping has been revoked */ + + #ifndef VM_STACK_DEFAULT_FLAGS /* arch can override this */ #define VM_STACK_DEFAULT_FLAGS VM_DATA_DEFAULT_FLAGS #endif diff --git a/mm/memory.c b/mm/memory.c index 2bf4fcd..b1e56ef 100644 --- a/mm/memory.c +++ b/mm/memory.c @@ -3458,6 +3458,9 @@ int handle_mm_fault(struct mm_struct *mm, struct vm_area_struct *vma, } #endif + if (unlikely(vma->vm_flags & VM_REVOKED)) + return VM_FAULT_SIGBUS; + pgd = pgd_offset(mm, address); pud = pud_alloc(mm, pgd, address); if (!pud) diff --git a/mm/mmap.c b/mm/mmap.c index 0ab80ae..1f8c0ac 100644 --- a/mm/mmap.c +++ b/mm/mmap.c @@ -1315,11 +1315,15 @@ unsigned long mmap_region(struct file *file, unsigned long addr, /* Clear old maps */ error = -ENOMEM; vma = find_vma_prepare(mm, addr, &prev, &rb_link, &rb_parent); - if (vma && vma->vm_start < addr + len) { - if (do_munmap(mm, addr, len)) - return -ENOMEM; - vma = find_vma_prepare(mm, addr, &prev, &rb_link, &rb_parent); + if (vma) { + if (unlikely(vma->vm_flags & VM_REVOKED)) + return -ENODEV; + if (vma->vm_start < addr + len) { + if (do_munmap(mm, addr, len)) + return -ENOMEM; + vma = find_vma_prepare(mm, addr, &prev, &rb_link, &rb_parent); BUG_ON(vma && vma->vm_start < addr + len); + } } /* Check against address space limit. */ -- 1.6.5.2