Commit 6eb47fb7 authored by Hugh Dickins's avatar Hugh Dickins Committed by Linus Torvalds

[PATCH] mprotect propagate anon_vma

When mprotect shifts the boundary between vmas (merging the reprotected
area into the vma before or the vma after), make sure that the expanding
vma has anon_vma if the shrinking vma had, to cover anon pages imported.
Thanks to Andrea for alerting us to this oversight.

Cc: <andrea@suse.de>
Signed-off-by: default avatarHugh Dickins <hugh@veritas.com>
Signed-off-by: default avatarAndrew Morton <akpm@osdl.org>
Signed-off-by: default avatarLinus Torvalds <torvalds@osdl.org>
parent 46bb3931
...@@ -362,6 +362,7 @@ void vma_adjust(struct vm_area_struct *vma, unsigned long start, ...@@ -362,6 +362,7 @@ void vma_adjust(struct vm_area_struct *vma, unsigned long start,
{ {
struct mm_struct *mm = vma->vm_mm; struct mm_struct *mm = vma->vm_mm;
struct vm_area_struct *next = vma->vm_next; struct vm_area_struct *next = vma->vm_next;
struct vm_area_struct *importer = NULL;
struct address_space *mapping = NULL; struct address_space *mapping = NULL;
struct prio_tree_root *root = NULL; struct prio_tree_root *root = NULL;
struct file *file = vma->vm_file; struct file *file = vma->vm_file;
...@@ -385,6 +386,7 @@ again: remove_next = 1 + (end > next->vm_end); ...@@ -385,6 +386,7 @@ again: remove_next = 1 + (end > next->vm_end);
*/ */
adjust_next = (end - next->vm_start) >> PAGE_SHIFT; adjust_next = (end - next->vm_start) >> PAGE_SHIFT;
anon_vma = next->anon_vma; anon_vma = next->anon_vma;
importer = vma;
} else if (end < vma->vm_end) { } else if (end < vma->vm_end) {
/* /*
* vma shrinks, and !insert tells it's not * vma shrinks, and !insert tells it's not
...@@ -393,6 +395,7 @@ again: remove_next = 1 + (end > next->vm_end); ...@@ -393,6 +395,7 @@ again: remove_next = 1 + (end > next->vm_end);
*/ */
adjust_next = - ((vma->vm_end - end) >> PAGE_SHIFT); adjust_next = - ((vma->vm_end - end) >> PAGE_SHIFT);
anon_vma = next->anon_vma; anon_vma = next->anon_vma;
importer = next;
} }
} }
...@@ -418,8 +421,18 @@ again: remove_next = 1 + (end > next->vm_end); ...@@ -418,8 +421,18 @@ again: remove_next = 1 + (end > next->vm_end);
*/ */
if (vma->anon_vma) if (vma->anon_vma)
anon_vma = vma->anon_vma; anon_vma = vma->anon_vma;
if (anon_vma) if (anon_vma) {
spin_lock(&anon_vma->lock); spin_lock(&anon_vma->lock);
/*
* Easily overlooked: when mprotect shifts the boundary,
* make sure the expanding vma has anon_vma set if the
* shrinking vma had, to cover any anon pages imported.
*/
if (importer && !importer->anon_vma) {
importer->anon_vma = anon_vma;
__anon_vma_link(importer);
}
}
if (root) { if (root) {
flush_dcache_mmap_lock(mapping); flush_dcache_mmap_lock(mapping);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment