]> git.ipfire.org Git - thirdparty/kernel/stable.git/commitdiff
mm: replace __access_remote_vm() write parameter with gup_flags
authorLorenzo Stoakes <lstoakes@gmail.com>
Thu, 13 Oct 2016 00:20:18 +0000 (01:20 +0100)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Mon, 17 Dec 2018 20:55:17 +0000 (21:55 +0100)
commit 442486ec1096781c50227b73f721a63974b0fdda upstream.

This removes the 'write' argument from __access_remote_vm() and replaces
it with 'gup_flags' as use of this function previously silently implied
FOLL_FORCE, whereas after this patch callers explicitly pass this flag.

We make this explicit as use of FOLL_FORCE can result in surprising
behaviour (and hence bugs) within the mm subsystem.

Signed-off-by: Lorenzo Stoakes <lstoakes@gmail.com>
Acked-by: Michal Hocko <mhocko@suse.com>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
[bwh: Backported to 4.4: adjust context]
Signed-off-by: Ben Hutchings <ben.hutchings@codethink.co.uk>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
mm/memory.c
mm/nommu.c

index 13142accda4f726811b17a297f6aa3bcbf14e71f..1a0d727687d0a176ff199c7c9adff27d64e6aa2f 100644 (file)
@@ -3711,14 +3711,11 @@ EXPORT_SYMBOL_GPL(generic_access_phys);
  * given task for page fault accounting.
  */
 static int __access_remote_vm(struct task_struct *tsk, struct mm_struct *mm,
-               unsigned long addr, void *buf, int len, int write)
+               unsigned long addr, void *buf, int len, unsigned int gup_flags)
 {
        struct vm_area_struct *vma;
        void *old_buf = buf;
-       unsigned int flags = FOLL_FORCE;
-
-       if (write)
-               flags |= FOLL_WRITE;
+       int write = gup_flags & FOLL_WRITE;
 
        down_read(&mm->mmap_sem);
        /* ignore errors, just check how much was successfully transferred */
@@ -3728,7 +3725,7 @@ static int __access_remote_vm(struct task_struct *tsk, struct mm_struct *mm,
                struct page *page = NULL;
 
                ret = get_user_pages(tsk, mm, addr, 1,
-                               flags, &page, &vma);
+                               gup_flags, &page, &vma);
                if (ret <= 0) {
 #ifndef CONFIG_HAVE_IOREMAP_PROT
                        break;
@@ -3787,7 +3784,12 @@ static int __access_remote_vm(struct task_struct *tsk, struct mm_struct *mm,
 int access_remote_vm(struct mm_struct *mm, unsigned long addr,
                void *buf, int len, int write)
 {
-       return __access_remote_vm(NULL, mm, addr, buf, len, write);
+       unsigned int flags = FOLL_FORCE;
+
+       if (write)
+               flags |= FOLL_WRITE;
+
+       return __access_remote_vm(NULL, mm, addr, buf, len, flags);
 }
 
 /*
@@ -3800,12 +3802,17 @@ int access_process_vm(struct task_struct *tsk, unsigned long addr,
 {
        struct mm_struct *mm;
        int ret;
+       unsigned int flags = FOLL_FORCE;
 
        mm = get_task_mm(tsk);
        if (!mm)
                return 0;
 
-       ret = __access_remote_vm(tsk, mm, addr, buf, len, write);
+       if (write)
+               flags |= FOLL_WRITE;
+
+       ret = __access_remote_vm(tsk, mm, addr, buf, len, flags);
+
        mmput(mm);
 
        return ret;
index 073ea36abc21c9ffa05464232c0e891bddbe4e66..6ffc6be4344f8c6787a2271ac119463f6241383a 100644 (file)
@@ -1929,9 +1929,10 @@ void filemap_map_pages(struct vm_area_struct *vma, struct vm_fault *vmf)
 EXPORT_SYMBOL(filemap_map_pages);
 
 static int __access_remote_vm(struct task_struct *tsk, struct mm_struct *mm,
-               unsigned long addr, void *buf, int len, int write)
+               unsigned long addr, void *buf, int len, unsigned int gup_flags)
 {
        struct vm_area_struct *vma;
+       int write = gup_flags & FOLL_WRITE;
 
        down_read(&mm->mmap_sem);
 
@@ -1973,7 +1974,8 @@ static int __access_remote_vm(struct task_struct *tsk, struct mm_struct *mm,
 int access_remote_vm(struct mm_struct *mm, unsigned long addr,
                void *buf, int len, int write)
 {
-       return __access_remote_vm(NULL, mm, addr, buf, len, write);
+       return __access_remote_vm(NULL, mm, addr, buf, len,
+                       write ? FOLL_WRITE : 0);
 }
 
 /*
@@ -1991,7 +1993,8 @@ int access_process_vm(struct task_struct *tsk, unsigned long addr, void *buf, in
        if (!mm)
                return 0;
 
-       len = __access_remote_vm(tsk, mm, addr, buf, len, write);
+       len = __access_remote_vm(tsk, mm, addr, buf, len,
+                       write ? FOLL_WRITE : 0);
 
        mmput(mm);
        return len;