|
@@ -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,7 @@ 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)))
|
|
|
+ if (!arch_vma_access_permitted(vma, write, foreign))
|
|
|
return -EFAULT;
|
|
|
return 0;
|
|
|
}
|
|
@@ -615,7 +619,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 +628,9 @@ 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.
|
|
|
*/
|
|
|
- if (!arch_vma_access_permitted(vma, write))
|
|
|
+ if (!arch_vma_access_permitted(vma, write, foreign))
|
|
|
return false;
|
|
|
|
|
|
return true;
|