mm/core, x86/mm/pkeys: Differentiate instruction fetches
[linux-2.6-block.git] / mm / gup.c
index e0f5f3574d16a9749efff3fc53d502e5f1614453..7f1c4fb77cfa5e9c6ca4fd4c04c83e01a9b273b1 100644 (file)
--- a/mm/gup.c
+++ b/mm/gup.c
@@ -365,6 +365,8 @@ static int faultin_page(struct task_struct *tsk, struct vm_area_struct *vma,
                return -ENOENT;
        if (*flags & FOLL_WRITE)
                fault_flags |= FAULT_FLAG_WRITE;
+       if (*flags & FOLL_REMOTE)
+               fault_flags |= FAULT_FLAG_REMOTE;
        if (nonblocking)
                fault_flags |= FAULT_FLAG_ALLOW_RETRY;
        if (*flags & FOLL_NOWAIT)
@@ -415,11 +417,13 @@ static int faultin_page(struct task_struct *tsk, struct vm_area_struct *vma,
 static int check_vma_flags(struct vm_area_struct *vma, unsigned long gup_flags)
 {
        vm_flags_t vm_flags = vma->vm_flags;
+       int write = (gup_flags & FOLL_WRITE);
+       int foreign = (gup_flags & FOLL_REMOTE);
 
        if (vm_flags & (VM_IO | VM_PFNMAP))
                return -EFAULT;
 
-       if (gup_flags & FOLL_WRITE) {
+       if (write) {
                if (!(vm_flags & VM_WRITE)) {
                        if (!(gup_flags & FOLL_FORCE))
                                return -EFAULT;
@@ -445,7 +449,11 @@ static int check_vma_flags(struct vm_area_struct *vma, unsigned long gup_flags)
                if (!(vm_flags & VM_MAYREAD))
                        return -EFAULT;
        }
-       if (!arch_vma_access_permitted(vma, (gup_flags & FOLL_WRITE)))
+       /*
+        * gups are always data accesses, not instruction
+        * fetches, so execute=false here
+        */
+       if (!arch_vma_access_permitted(vma, write, false, foreign))
                return -EFAULT;
        return 0;
 }
@@ -615,7 +623,8 @@ EXPORT_SYMBOL(__get_user_pages);
 
 bool vma_permits_fault(struct vm_area_struct *vma, unsigned int fault_flags)
 {
-       bool write = !!(fault_flags & FAULT_FLAG_WRITE);
+       bool write   = !!(fault_flags & FAULT_FLAG_WRITE);
+       bool foreign = !!(fault_flags & FAULT_FLAG_REMOTE);
        vm_flags_t vm_flags = write ? VM_WRITE : VM_READ;
 
        if (!(vm_flags & vma->vm_flags))
@@ -623,9 +632,12 @@ bool vma_permits_fault(struct vm_area_struct *vma, unsigned int fault_flags)
 
        /*
         * The architecture might have a hardware protection
-        * mechanism other than read/write that can deny access
+        * mechanism other than read/write that can deny access.
+        *
+        * gup always represents data access, not instruction
+        * fetches, so execute=false here:
         */
-       if (!arch_vma_access_permitted(vma, write))
+       if (!arch_vma_access_permitted(vma, write, false, foreign))
                return false;
 
        return true;