Merge branch 'perf/core' into perf/uprobes
[linux-2.6-block.git] / mm / mmap.c
index a7bf6a31c9f62be11cb8e5819322565b7cf2c266..b17a39f31a5efd66fecda38d1f3804a4eb41c234 100644 (file)
--- a/mm/mmap.c
+++ b/mm/mmap.c
@@ -30,6 +30,7 @@
 #include <linux/perf_event.h>
 #include <linux/audit.h>
 #include <linux/khugepaged.h>
+#include <linux/uprobes.h>
 
 #include <asm/uaccess.h>
 #include <asm/cacheflush.h>
@@ -217,6 +218,7 @@ void unlink_file_vma(struct vm_area_struct *vma)
                mutex_lock(&mapping->i_mmap_mutex);
                __remove_shared_vm_struct(vma, file, mapping);
                mutex_unlock(&mapping->i_mmap_mutex);
+               uprobe_munmap(vma);
        }
 }
 
@@ -544,8 +546,14 @@ again:                     remove_next = 1 + (end > next->vm_end);
 
        if (file) {
                mapping = file->f_mapping;
-               if (!(vma->vm_flags & VM_NONLINEAR))
+               if (!(vma->vm_flags & VM_NONLINEAR)) {
                        root = &mapping->i_mmap;
+                       uprobe_munmap(vma);
+
+                       if (adjust_next)
+                               uprobe_munmap(next);
+               }
+
                mutex_lock(&mapping->i_mmap_mutex);
                if (insert) {
                        /*
@@ -615,8 +623,16 @@ again:                     remove_next = 1 + (end > next->vm_end);
        if (mapping)
                mutex_unlock(&mapping->i_mmap_mutex);
 
+       if (root) {
+               uprobe_mmap(vma);
+
+               if (adjust_next)
+                       uprobe_mmap(next);
+       }
+
        if (remove_next) {
                if (file) {
+                       uprobe_munmap(next);
                        fput(file);
                        if (next->vm_flags & VM_EXECUTABLE)
                                removed_exe_file_vma(mm);
@@ -636,6 +652,8 @@ again:                      remove_next = 1 + (end > next->vm_end);
                        goto again;
                }
        }
+       if (insert && file)
+               uprobe_mmap(insert);
 
        validate_mm(mm);
 
@@ -1344,6 +1362,11 @@ out:
                        mm->locked_vm += (len >> PAGE_SHIFT);
        } else if ((flags & MAP_POPULATE) && !(flags & MAP_NONBLOCK))
                make_pages_present(addr, addr + len);
+
+       if (file && uprobe_mmap(vma))
+               /* matching probes but cannot insert */
+               goto unmap_and_free_vma;
+
        return addr;
 
 unmap_and_free_vma:
@@ -2311,6 +2334,10 @@ int insert_vm_struct(struct mm_struct * mm, struct vm_area_struct * vma)
        if ((vma->vm_flags & VM_ACCOUNT) &&
             security_vm_enough_memory_mm(mm, vma_pages(vma)))
                return -ENOMEM;
+
+       if (vma->vm_file && uprobe_mmap(vma))
+               return -EINVAL;
+
        vma_link(mm, vma, prev, rb_link, rb_parent);
        return 0;
 }
@@ -2380,6 +2407,10 @@ struct vm_area_struct *copy_vma(struct vm_area_struct **vmap,
                        new_vma->vm_pgoff = pgoff;
                        if (new_vma->vm_file) {
                                get_file(new_vma->vm_file);
+
+                               if (uprobe_mmap(new_vma))
+                                       goto out_free_mempol;
+
                                if (vma->vm_flags & VM_EXECUTABLE)
                                        added_exe_file_vma(mm);
                        }