VServer 1.9.2 (patch-2.6.8.1-vs1.9.2.diff)
[linux-2.6.git] / mm / mmap.c
index bc1c46c..0a89be9 100644 (file)
--- a/mm/mmap.c
+++ b/mm/mmap.c
@@ -25,7 +25,6 @@
 #include <linux/rmap.h>
 
 #include <asm/uaccess.h>
-#include <asm/pgalloc.h>
 #include <asm/cacheflush.h>
 #include <asm/tlb.h>
 
@@ -318,7 +317,6 @@ static void vma_link(struct mm_struct *mm, struct vm_area_struct *vma,
        if (mapping)
                spin_unlock(&mapping->i_mmap_lock);
 
-       mark_mm_hugetlb(mm, vma);
        mm->map_count++;
        validate_mm(mm);
 }
@@ -363,6 +361,7 @@ void vma_adjust(struct vm_area_struct *vma, unsigned long start,
 {
        struct mm_struct *mm = vma->vm_mm;
        struct vm_area_struct *next = vma->vm_next;
+       struct vm_area_struct *importer = NULL;
        struct address_space *mapping = NULL;
        struct prio_tree_root *root = NULL;
        struct file *file = vma->vm_file;
@@ -386,6 +385,7 @@ again:                      remove_next = 1 + (end > next->vm_end);
                         */
                        adjust_next = (end - next->vm_start) >> PAGE_SHIFT;
                        anon_vma = next->anon_vma;
+                       importer = vma;
                } else if (end < vma->vm_end) {
                        /*
                         * vma shrinks, and !insert tells it's not
@@ -394,6 +394,7 @@ again:                      remove_next = 1 + (end > next->vm_end);
                         */
                        adjust_next = - ((vma->vm_end - end) >> PAGE_SHIFT);
                        anon_vma = next->anon_vma;
+                       importer = next;
                }
        }
 
@@ -419,8 +420,18 @@ again:                     remove_next = 1 + (end > next->vm_end);
         */
        if (vma->anon_vma)
                anon_vma = vma->anon_vma;
-       if (anon_vma)
+       if (anon_vma) {
                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) {
                flush_dcache_mmap_lock(mapping);
@@ -739,6 +750,13 @@ unsigned long do_mmap_pgoff(struct file * file, unsigned long addr,
        int accountable = 1;
        unsigned long charged = 0;
 
+       /*
+        * Does the application expect PROT_READ to imply PROT_EXEC:
+        */
+       if (unlikely((prot & PROT_READ) &&
+                       (current->personality & READ_IMPLIES_EXEC)))
+               prot |= PROT_EXEC;
+
        if (file) {
                if (is_file_hugepages(file))
                        accountable = 0;