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); |
@@ -920,6 +924,10 @@ unsigned long do_mmap_pgoff(struct file * file, unsigned long addr, | |||
920 | if (!len) | 924 | if (!len) |
921 | return -EINVAL; | 925 | return -EINVAL; |
922 | 926 | ||
927 | error = arch_mmap_check(addr, len, flags); | ||
928 | if (error) | ||
929 | return error; | ||
930 | |||
923 | /* Careful about overflows.. */ | 931 | /* Careful about overflows.. */ |
924 | len = PAGE_ALIGN(len); | 932 | len = PAGE_ALIGN(len); |
925 | if (!len || len > TASK_SIZE) | 933 | if (!len || len > TASK_SIZE) |
@@ -1866,6 +1874,7 @@ unsigned long do_brk(unsigned long addr, unsigned long len) | |||
1866 | unsigned long flags; | 1874 | unsigned long flags; |
1867 | struct rb_node ** rb_link, * rb_parent; | 1875 | struct rb_node ** rb_link, * rb_parent; |
1868 | pgoff_t pgoff = addr >> PAGE_SHIFT; | 1876 | pgoff_t pgoff = addr >> PAGE_SHIFT; |
1877 | int error; | ||
1869 | 1878 | ||
1870 | len = PAGE_ALIGN(len); | 1879 | len = PAGE_ALIGN(len); |
1871 | if (!len) | 1880 | if (!len) |
@@ -1874,6 +1883,12 @@ unsigned long do_brk(unsigned long addr, unsigned long len) | |||
1874 | if ((addr + len) > TASK_SIZE || (addr + len) < addr) | 1883 | if ((addr + len) > TASK_SIZE || (addr + len) < addr) |
1875 | return -EINVAL; | 1884 | return -EINVAL; |
1876 | 1885 | ||
1886 | flags = VM_DATA_DEFAULT_FLAGS | VM_ACCOUNT | mm->def_flags; | ||
1887 | |||
1888 | error = arch_mmap_check(addr, len, flags); | ||
1889 | if (error) | ||
1890 | return error; | ||
1891 | |||
1877 | /* | 1892 | /* |
1878 | * mlock MCL_FUTURE? | 1893 | * mlock MCL_FUTURE? |
1879 | */ | 1894 | */ |
@@ -1914,8 +1929,6 @@ unsigned long do_brk(unsigned long addr, unsigned long len) | |||
1914 | if (security_vm_enough_memory(len >> PAGE_SHIFT)) | 1929 | if (security_vm_enough_memory(len >> PAGE_SHIFT)) |
1915 | return -ENOMEM; | 1930 | return -ENOMEM; |
1916 | 1931 | ||
1917 | flags = VM_DATA_DEFAULT_FLAGS | VM_ACCOUNT | mm->def_flags; | ||
1918 | |||
1919 | /* Can we just expand an old private anonymous mapping? */ | 1932 | /* Can we just expand an old private anonymous mapping? */ |
1920 | if (vma_merge(mm, prev, addr, addr + len, flags, | 1933 | if (vma_merge(mm, prev, addr, addr + len, flags, |
1921 | NULL, NULL, pgoff, NULL)) | 1934 | 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 | /** |