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
| @@ -30,6 +30,10 @@ | |||
| 30 | #include <asm/cacheflush.h> | 30 | #include <asm/cacheflush.h> |
| 31 | #include <asm/tlb.h> | 31 | #include <asm/tlb.h> |
| 32 | 32 | ||
| 33 | #ifndef arch_mmap_check | ||
| 34 | #define arch_mmap_check(addr, len, flags) (0) | ||
| 35 | #endif | ||
| 36 | |||
| 33 | static void unmap_region(struct mm_struct *mm, | 37 | static void unmap_region(struct mm_struct *mm, |
| 34 | struct vm_area_struct *vma, struct vm_area_struct *prev, | 38 | struct vm_area_struct *vma, struct vm_area_struct *prev, |
| 35 | unsigned long start, unsigned long end); | 39 | unsigned long start, unsigned long end); |
| @@ -913,6 +917,10 @@ unsigned long do_mmap_pgoff(struct file * file, unsigned long addr, | |||
| 913 | if (!len) | 917 | if (!len) |
| 914 | return -EINVAL; | 918 | return -EINVAL; |
| 915 | 919 | ||
| 920 | error = arch_mmap_check(addr, len, flags); | ||
| 921 | if (error) | ||
| 922 | return error; | ||
| 923 | |||
| 916 | /* Careful about overflows.. */ | 924 | /* Careful about overflows.. */ |
| 917 | len = PAGE_ALIGN(len); | 925 | len = PAGE_ALIGN(len); |
| 918 | if (!len || len > TASK_SIZE) | 926 | if (!len || len > TASK_SIZE) |
| @@ -1859,6 +1867,7 @@ unsigned long do_brk(unsigned long addr, unsigned long len) | |||
| 1859 | unsigned long flags; | 1867 | unsigned long flags; |
| 1860 | struct rb_node ** rb_link, * rb_parent; | 1868 | struct rb_node ** rb_link, * rb_parent; |
| 1861 | pgoff_t pgoff = addr >> PAGE_SHIFT; | 1869 | pgoff_t pgoff = addr >> PAGE_SHIFT; |
| 1870 | int error; | ||
| 1862 | 1871 | ||
| 1863 | len = PAGE_ALIGN(len); | 1872 | len = PAGE_ALIGN(len); |
| 1864 | if (!len) | 1873 | if (!len) |
| @@ -1867,6 +1876,12 @@ unsigned long do_brk(unsigned long addr, unsigned long len) | |||
| 1867 | if ((addr + len) > TASK_SIZE || (addr + len) < addr) | 1876 | if ((addr + len) > TASK_SIZE || (addr + len) < addr) |
| 1868 | return -EINVAL; | 1877 | return -EINVAL; |
| 1869 | 1878 | ||
| 1879 | flags = VM_DATA_DEFAULT_FLAGS | VM_ACCOUNT | mm->def_flags; | ||
| 1880 | |||
| 1881 | error = arch_mmap_check(addr, len, flags); | ||
| 1882 | if (error) | ||
| 1883 | return error; | ||
| 1884 | |||
| 1870 | /* | 1885 | /* |
| 1871 | * mlock MCL_FUTURE? | 1886 | * mlock MCL_FUTURE? |
| 1872 | */ | 1887 | */ |
| @@ -1907,8 +1922,6 @@ unsigned long do_brk(unsigned long addr, unsigned long len) | |||
| 1907 | if (security_vm_enough_memory(len >> PAGE_SHIFT)) | 1922 | if (security_vm_enough_memory(len >> PAGE_SHIFT)) |
| 1908 | return -ENOMEM; | 1923 | return -ENOMEM; |
| 1909 | 1924 | ||
| 1910 | flags = VM_DATA_DEFAULT_FLAGS | VM_ACCOUNT | mm->def_flags; | ||
| 1911 | |||
| 1912 | /* Can we just expand an old private anonymous mapping? */ | 1925 | /* Can we just expand an old private anonymous mapping? */ |
| 1913 | if (vma_merge(mm, prev, addr, addr + len, flags, | 1926 | if (vma_merge(mm, prev, addr, addr + len, flags, |
| 1914 | NULL, NULL, pgoff, NULL)) | 1927 | 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) | |||
| 68 | return 0; | 68 | return 0; |
| 69 | 69 | ||
| 70 | write_lock_irq(&mapping->tree_lock); | 70 | write_lock_irq(&mapping->tree_lock); |
| 71 | if (PageDirty(page)) { | 71 | if (PageDirty(page)) |
| 72 | write_unlock_irq(&mapping->tree_lock); | 72 | goto failed; |
| 73 | return 0; | 73 | if (page_count(page) != 2) /* caller's ref + pagecache ref */ |
| 74 | } | 74 | goto failed; |
| 75 | 75 | ||
| 76 | BUG_ON(PagePrivate(page)); | 76 | BUG_ON(PagePrivate(page)); |
| 77 | __remove_from_page_cache(page); | 77 | __remove_from_page_cache(page); |
| @@ -79,6 +79,9 @@ invalidate_complete_page(struct address_space *mapping, struct page *page) | |||
| 79 | ClearPageUptodate(page); | 79 | ClearPageUptodate(page); |
| 80 | page_cache_release(page); /* pagecache ref */ | 80 | page_cache_release(page); /* pagecache ref */ |
| 81 | return 1; | 81 | return 1; |
| 82 | failed: | ||
| 83 | write_unlock_irq(&mapping->tree_lock); | ||
| 84 | return 0; | ||
| 82 | } | 85 | } |
| 83 | 86 | ||
| 84 | /** | 87 | /** |
