On Thu 13-10-16 01:20:18, Lorenzo Stoakes wrote:
> This patch removes the write parameter from __access_remote_vm() and replaces 
> it
> with a gup_flags parameter as use of this function previously _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 <lstoa...@gmail.com>

So I'm not convinced this (and the following two patches) is actually
helping much. By grepping for FOLL_FORCE we will easily see that any caller
of access_remote_vm() gets that semantics and can thus continue search
accordingly (it is much simpler than searching for all get_user_pages()
users and extracting from parameter lists what they actually pass as
'force' argument). Sure it makes somewhat more visible to callers of
access_remote_vm() that they get FOLL_FORCE semantics but OTOH it also
opens a space for issues where a caller of access_remote_vm() actually
wants FOLL_FORCE (and currently all of them want it) and just mistakenly
does not set it. All in all I'd prefer to keep access_remote_vm() and
friends as is...

                                                                Honza

> ---
>  mm/memory.c | 23 +++++++++++++++--------
>  mm/nommu.c  |  9 ++++++---
>  2 files changed, 21 insertions(+), 11 deletions(-)
> 
> diff --git a/mm/memory.c b/mm/memory.c
> index 20a9adb..79ebed3 100644
> --- a/mm/memory.c
> +++ b/mm/memory.c
> @@ -3869,14 +3869,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 */
> @@ -3886,7 +3883,7 @@ static int __access_remote_vm(struct task_struct *tsk, 
> struct mm_struct *mm,
>               struct page *page = NULL;
>  
>               ret = get_user_pages_remote(tsk, mm, addr, 1,
> -                             flags, &page, &vma);
> +                             gup_flags, &page, &vma);
>               if (ret <= 0) {
>  #ifndef CONFIG_HAVE_IOREMAP_PROT
>                       break;
> @@ -3945,7 +3942,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);
>  }
>  
>  /*
> @@ -3958,12 +3960,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;
> diff --git a/mm/nommu.c b/mm/nommu.c
> index 70cb844..bde7df3 100644
> --- a/mm/nommu.c
> +++ b/mm/nommu.c
> @@ -1809,9 +1809,10 @@ void filemap_map_pages(struct fault_env *fe,
>  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);
>  
> @@ -1853,7 +1854,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);
>  }
>  
>  /*
> @@ -1871,7 +1873,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;
> -- 
> 2.10.0
> 
-- 
Jan Kara <j...@suse.com>
SUSE Labs, CR

Reply via email to