diff options
author | Ingo Molnar <mingo@kernel.org> | 2016-03-07 11:27:30 +0300 |
---|---|---|
committer | Ingo Molnar <mingo@kernel.org> | 2016-03-07 11:27:30 +0300 |
commit | ec87e1cf7d8399d81d8965c6d852f8057a8dd687 (patch) | |
tree | 472a168fa4861090edf110c8a9712a5c15ea259f /mm/mmap.c | |
parent | 869ae76147ffdf21ad24f0e599303cd58a2bb39f (diff) | |
parent | f6cede5b49e822ebc41a099fe41ab4989f64e2cb (diff) | |
download | linux-ec87e1cf7d8399d81d8965c6d852f8057a8dd687.tar.xz |
Merge tag 'v4.5-rc7' into x86/asm, to pick up SMAP fix
Signed-off-by: Ingo Molnar <mingo@kernel.org>
Diffstat (limited to 'mm/mmap.c')
-rw-r--r-- | mm/mmap.c | 34 |
1 files changed, 29 insertions, 5 deletions
diff --git a/mm/mmap.c b/mm/mmap.c index e2e9f48b06c2..90e3b869a8b9 100644 --- a/mm/mmap.c +++ b/mm/mmap.c @@ -2664,12 +2664,29 @@ SYSCALL_DEFINE5(remap_file_pages, unsigned long, start, unsigned long, size, if (!vma || !(vma->vm_flags & VM_SHARED)) goto out; - if (start < vma->vm_start || start + size > vma->vm_end) + if (start < vma->vm_start) goto out; - if (pgoff == linear_page_index(vma, start)) { - ret = 0; - goto out; + if (start + size > vma->vm_end) { + struct vm_area_struct *next; + + for (next = vma->vm_next; next; next = next->vm_next) { + /* hole between vmas ? */ + if (next->vm_start != next->vm_prev->vm_end) + goto out; + + if (next->vm_file != vma->vm_file) + goto out; + + if (next->vm_flags != vma->vm_flags) + goto out; + + if (start + size <= next->vm_end) + break; + } + + if (!next) + goto out; } prot |= vma->vm_flags & VM_READ ? PROT_READ : 0; @@ -2679,9 +2696,16 @@ SYSCALL_DEFINE5(remap_file_pages, unsigned long, start, unsigned long, size, flags &= MAP_NONBLOCK; flags |= MAP_SHARED | MAP_FIXED | MAP_POPULATE; if (vma->vm_flags & VM_LOCKED) { + struct vm_area_struct *tmp; flags |= MAP_LOCKED; + /* drop PG_Mlocked flag for over-mapped range */ - munlock_vma_pages_range(vma, start, start + size); + for (tmp = vma; tmp->vm_start >= start + size; + tmp = tmp->vm_next) { + munlock_vma_pages_range(tmp, + max(tmp->vm_start, start), + min(tmp->vm_end, start + size)); + } } file = get_file(vma->vm_file); |