diff options
Diffstat (limited to 'mm')
-rw-r--r-- | mm/mmap.c | 17 | ||||
-rw-r--r-- | mm/truncate.c | 11 |
2 files changed, 22 insertions, 6 deletions
diff --git a/mm/mmap.c b/mm/mmap.c index c7ed061f4507..d799d896d74a 100644 --- a/mm/mmap.c +++ b/mm/mmap.c @@ -30,6 +30,10 @@ #include <asm/cacheflush.h> #include <asm/tlb.h> +#ifndef arch_mmap_check +#define arch_mmap_check(addr, len, flags) (0) +#endif + static void unmap_region(struct mm_struct *mm, struct vm_area_struct *vma, struct vm_area_struct *prev, unsigned long start, unsigned long end); @@ -920,6 +924,10 @@ unsigned long do_mmap_pgoff(struct file * file, unsigned long addr, if (!len) return -EINVAL; + error = arch_mmap_check(addr, len, flags); + if (error) + return error; + /* Careful about overflows.. */ len = PAGE_ALIGN(len); if (!len || len > TASK_SIZE) @@ -1866,6 +1874,7 @@ unsigned long do_brk(unsigned long addr, unsigned long len) unsigned long flags; struct rb_node ** rb_link, * rb_parent; pgoff_t pgoff = addr >> PAGE_SHIFT; + int error; len = PAGE_ALIGN(len); if (!len) @@ -1874,6 +1883,12 @@ unsigned long do_brk(unsigned long addr, unsigned long len) if ((addr + len) > TASK_SIZE || (addr + len) < addr) return -EINVAL; + flags = VM_DATA_DEFAULT_FLAGS | VM_ACCOUNT | mm->def_flags; + + error = arch_mmap_check(addr, len, flags); + if (error) + return error; + /* * mlock MCL_FUTURE? */ @@ -1914,8 +1929,6 @@ unsigned long do_brk(unsigned long addr, unsigned long len) if (security_vm_enough_memory(len >> PAGE_SHIFT)) return -ENOMEM; - flags = VM_DATA_DEFAULT_FLAGS | VM_ACCOUNT | mm->def_flags; - /* Can we just expand an old private anonymous mapping? */ if (vma_merge(mm, prev, addr, addr + len, flags, NULL, NULL, pgoff, NULL)) diff --git a/mm/truncate.c b/mm/truncate.c index cf1b015df4a7..c6ab55ec6883 100644 --- a/mm/truncate.c +++ b/mm/truncate.c @@ -68,10 +68,10 @@ invalidate_complete_page(struct address_space *mapping, struct page *page) return 0; write_lock_irq(&mapping->tree_lock); - if (PageDirty(page)) { - write_unlock_irq(&mapping->tree_lock); - return 0; - } + if (PageDirty(page)) + goto failed; + if (page_count(page) != 2) /* caller's ref + pagecache ref */ + goto failed; BUG_ON(PagePrivate(page)); __remove_from_page_cache(page); @@ -79,6 +79,9 @@ invalidate_complete_page(struct address_space *mapping, struct page *page) ClearPageUptodate(page); page_cache_release(page); /* pagecache ref */ return 1; +failed: + write_unlock_irq(&mapping->tree_lock); + return 0; } /** |