From: Sean Christopherson <[email protected]>

Add vm_ops()->may_mprotect() to check additional constrains set by a
subsystem for a mprotect() call.

Signed-off-by: Sean Christopherson <[email protected]>
---
 include/linux/mm.h |  2 ++
 mm/mprotect.c      | 13 ++++++++++---
 2 files changed, 12 insertions(+), 3 deletions(-)

diff --git a/include/linux/mm.h b/include/linux/mm.h
index 0334ca97c584..405cea65057a 100644
--- a/include/linux/mm.h
+++ b/include/linux/mm.h
@@ -469,6 +469,8 @@ struct vm_operations_struct {
        void (*close)(struct vm_area_struct * area);
        int (*split)(struct vm_area_struct * area, unsigned long addr);
        int (*mremap)(struct vm_area_struct * area);
+       int (*may_mprotect)(struct vm_area_struct *vma, unsigned long start,
+                           unsigned long end, unsigned long prot);
        vm_fault_t (*fault)(struct vm_fault *vmf);
        vm_fault_t (*huge_fault)(struct vm_fault *vmf,
                        enum page_entry_size pe_size);
diff --git a/mm/mprotect.c b/mm/mprotect.c
index bf38dfbbb4b4..18732543b295 100644
--- a/mm/mprotect.c
+++ b/mm/mprotect.c
@@ -547,13 +547,20 @@ static int do_mprotect_pkey(unsigned long start, size_t 
len,
                        goto out;
                }
 
+               tmp = vma->vm_end;
+               if (tmp > end)
+                       tmp = end;
+
+               if (vma->vm_ops && vma->vm_ops->may_mprotect) {
+                       error = vma->vm_ops->may_mprotect(vma, nstart, tmp, 
prot);
+                       if (error)
+                               goto out;
+               }
+
                error = security_file_mprotect(vma, reqprot, prot);
                if (error)
                        goto out;
 
-               tmp = vma->vm_end;
-               if (tmp > end)
-                       tmp = end;
                error = mprotect_fixup(vma, &prev, nstart, tmp, newflags);
                if (error)
                        goto out;
-- 
2.20.1

Reply via email to