From: Jan Kara <jack@suse.cz>
To: Lorenzo Stoakes <lstoakes@gmail.com>
Cc: linux-mips@linux-mips.org, linux-fbdev@vger.kernel.org,
Jan Kara <jack@suse.cz>,
kvm@vger.kernel.org, linux-sh@vger.kernel.org,
Dave Hansen <dave.hansen@linux.intel.com>,
dri-devel@lists.freedesktop.org, linux-mm@kvack.org,
netdev@vger.kernel.org, sparclinux@vger.kernel.org,
linux-ia64@vger.kernel.org, linux-s390@vger.kernel.org,
linux-samsung-soc@vger.kernel.org, linux-scsi@vger.kernel.org,
linux-rdma@vger.kernel.org, x86@kernel.org,
Hugh Dickins <hughd@google.com>,
linux-media@vger.kernel.org, Rik van Riel <riel@redhat.com>,
intel-gfx@lists.freedesktop.org,
adi-buildroot-devel@lists.sourceforge.net,
ceph-devel@vger.kernel.org, linux-arm-kernel@lists.infradead.org,
linux-cris-kernel@axis.com,
Linus Torvalds <torvalds@linux-foundation.org>,
linuxppc-dev@lists.ozlabs.org, linux-kernel@vger.kernel.org,
linux-security-module@vger.kernel.org,
linux-alpha@vger.kernel.orglin
Subject: Re: [PATCH 07/10] mm: replace get_user_pages_remote() write/force parameters with gup_flags
Date: Wed, 19 Oct 2016 07:47:07 +0000 [thread overview]
Message-ID: <20161019074707.GO29967@quack2.suse.cz> (raw)
In-Reply-To: <20161013002020.3062-8-lstoakes@gmail.com>
On Thu 13-10-16 01:20:17, Lorenzo Stoakes wrote:
> This patch removes the write and force parameters from get_user_pages_remote()
> and replaces them with a gup_flags parameter to make the use of FOLL_FORCE
> explicit in callers as use of this flag can result in surprising behaviour (and
> hence bugs) within the mm subsystem.
>
> Signed-off-by: Lorenzo Stoakes <lstoakes@gmail.com>
Looks good. You can add:
Reviewed-by: Jan Kara <jack@suse.cz>
Honza
> ---
> drivers/gpu/drm/etnaviv/etnaviv_gem.c | 7 +++++--
> drivers/gpu/drm/i915/i915_gem_userptr.c | 6 +++++-
> drivers/infiniband/core/umem_odp.c | 7 +++++--
> fs/exec.c | 9 +++++++--
> include/linux/mm.h | 2 +-
> kernel/events/uprobes.c | 6 ++++--
> mm/gup.c | 22 +++++++---------------
> mm/memory.c | 6 +++++-
> security/tomoyo/domain.c | 2 +-
> 9 files changed, 40 insertions(+), 27 deletions(-)
>
> diff --git a/drivers/gpu/drm/etnaviv/etnaviv_gem.c b/drivers/gpu/drm/etnaviv/etnaviv_gem.c
> index 5ce3603..0370b84 100644
> --- a/drivers/gpu/drm/etnaviv/etnaviv_gem.c
> +++ b/drivers/gpu/drm/etnaviv/etnaviv_gem.c
> @@ -748,19 +748,22 @@ static struct page **etnaviv_gem_userptr_do_get_pages(
> int ret = 0, pinned, npages = etnaviv_obj->base.size >> PAGE_SHIFT;
> struct page **pvec;
> uintptr_t ptr;
> + unsigned int flags = 0;
>
> pvec = drm_malloc_ab(npages, sizeof(struct page *));
> if (!pvec)
> return ERR_PTR(-ENOMEM);
>
> + if (!etnaviv_obj->userptr.ro)
> + flags |= FOLL_WRITE;
> +
> pinned = 0;
> ptr = etnaviv_obj->userptr.ptr;
>
> down_read(&mm->mmap_sem);
> while (pinned < npages) {
> ret = get_user_pages_remote(task, mm, ptr, npages - pinned,
> - !etnaviv_obj->userptr.ro, 0,
> - pvec + pinned, NULL);
> + flags, pvec + pinned, NULL);
> if (ret < 0)
> break;
>
> diff --git a/drivers/gpu/drm/i915/i915_gem_userptr.c b/drivers/gpu/drm/i915/i915_gem_userptr.c
> index e537930..c6f780f 100644
> --- a/drivers/gpu/drm/i915/i915_gem_userptr.c
> +++ b/drivers/gpu/drm/i915/i915_gem_userptr.c
> @@ -508,6 +508,10 @@ __i915_gem_userptr_get_pages_worker(struct work_struct *_work)
> pvec = drm_malloc_gfp(npages, sizeof(struct page *), GFP_TEMPORARY);
> if (pvec != NULL) {
> struct mm_struct *mm = obj->userptr.mm->mm;
> + unsigned int flags = 0;
> +
> + if (!obj->userptr.read_only)
> + flags |= FOLL_WRITE;
>
> ret = -EFAULT;
> if (atomic_inc_not_zero(&mm->mm_users)) {
> @@ -517,7 +521,7 @@ __i915_gem_userptr_get_pages_worker(struct work_struct *_work)
> (work->task, mm,
> obj->userptr.ptr + pinned * PAGE_SIZE,
> npages - pinned,
> - !obj->userptr.read_only, 0,
> + flags,
> pvec + pinned, NULL);
> if (ret < 0)
> break;
> diff --git a/drivers/infiniband/core/umem_odp.c b/drivers/infiniband/core/umem_odp.c
> index 75077a0..1f0fe32 100644
> --- a/drivers/infiniband/core/umem_odp.c
> +++ b/drivers/infiniband/core/umem_odp.c
> @@ -527,6 +527,7 @@ int ib_umem_odp_map_dma_pages(struct ib_umem *umem, u64 user_virt, u64 bcnt,
> u64 off;
> int j, k, ret = 0, start_idx, npages = 0;
> u64 base_virt_addr;
> + unsigned int flags = 0;
>
> if (access_mask = 0)
> return -EINVAL;
> @@ -556,6 +557,9 @@ int ib_umem_odp_map_dma_pages(struct ib_umem *umem, u64 user_virt, u64 bcnt,
> goto out_put_task;
> }
>
> + if (access_mask & ODP_WRITE_ALLOWED_BIT)
> + flags |= FOLL_WRITE;
> +
> start_idx = (user_virt - ib_umem_start(umem)) >> PAGE_SHIFT;
> k = start_idx;
>
> @@ -574,8 +578,7 @@ int ib_umem_odp_map_dma_pages(struct ib_umem *umem, u64 user_virt, u64 bcnt,
> */
> npages = get_user_pages_remote(owning_process, owning_mm,
> user_virt, gup_num_pages,
> - access_mask & ODP_WRITE_ALLOWED_BIT,
> - 0, local_page_list, NULL);
> + flags, local_page_list, NULL);
> up_read(&owning_mm->mmap_sem);
>
> if (npages < 0)
> diff --git a/fs/exec.c b/fs/exec.c
> index 6fcfb3f..4e497b9 100644
> --- a/fs/exec.c
> +++ b/fs/exec.c
> @@ -191,6 +191,7 @@ static struct page *get_arg_page(struct linux_binprm *bprm, unsigned long pos,
> {
> struct page *page;
> int ret;
> + unsigned int gup_flags = FOLL_FORCE;
>
> #ifdef CONFIG_STACK_GROWSUP
> if (write) {
> @@ -199,12 +200,16 @@ static struct page *get_arg_page(struct linux_binprm *bprm, unsigned long pos,
> return NULL;
> }
> #endif
> +
> + if (write)
> + gup_flags |= FOLL_WRITE;
> +
> /*
> * We are doing an exec(). 'current' is the process
> * doing the exec and bprm->mm is the new process's mm.
> */
> - ret = get_user_pages_remote(current, bprm->mm, pos, 1, write,
> - 1, &page, NULL);
> + ret = get_user_pages_remote(current, bprm->mm, pos, 1, gup_flags,
> + &page, NULL);
> if (ret <= 0)
> return NULL;
>
> diff --git a/include/linux/mm.h b/include/linux/mm.h
> index 686a477..2a481d3 100644
> --- a/include/linux/mm.h
> +++ b/include/linux/mm.h
> @@ -1276,7 +1276,7 @@ long __get_user_pages(struct task_struct *tsk, struct mm_struct *mm,
> struct vm_area_struct **vmas, int *nonblocking);
> long get_user_pages_remote(struct task_struct *tsk, struct mm_struct *mm,
> unsigned long start, unsigned long nr_pages,
> - int write, int force, struct page **pages,
> + unsigned int gup_flags, struct page **pages,
> struct vm_area_struct **vmas);
> long get_user_pages(unsigned long start, unsigned long nr_pages,
> unsigned int gup_flags, struct page **pages,
> diff --git a/kernel/events/uprobes.c b/kernel/events/uprobes.c
> index d4129bb..f9ec9ad 100644
> --- a/kernel/events/uprobes.c
> +++ b/kernel/events/uprobes.c
> @@ -300,7 +300,8 @@ int uprobe_write_opcode(struct mm_struct *mm, unsigned long vaddr,
>
> retry:
> /* Read the page with vaddr into memory */
> - ret = get_user_pages_remote(NULL, mm, vaddr, 1, 0, 1, &old_page, &vma);
> + ret = get_user_pages_remote(NULL, mm, vaddr, 1, FOLL_FORCE, &old_page,
> + &vma);
> if (ret <= 0)
> return ret;
>
> @@ -1710,7 +1711,8 @@ static int is_trap_at_addr(struct mm_struct *mm, unsigned long vaddr)
> * but we treat this as a 'remote' access since it is
> * essentially a kernel access to the memory.
> */
> - result = get_user_pages_remote(NULL, mm, vaddr, 1, 0, 1, &page, NULL);
> + result = get_user_pages_remote(NULL, mm, vaddr, 1, FOLL_FORCE, &page,
> + NULL);
> if (result < 0)
> return result;
>
> diff --git a/mm/gup.c b/mm/gup.c
> index dc91303..0deecf3 100644
> --- a/mm/gup.c
> +++ b/mm/gup.c
> @@ -905,9 +905,7 @@ EXPORT_SYMBOL(get_user_pages_unlocked);
> * @mm: mm_struct of target mm
> * @start: starting user address
> * @nr_pages: number of pages from start to pin
> - * @write: whether pages will be written to by the caller
> - * @force: whether to force access even when user mapping is currently
> - * protected (but never forces write access to shared mapping).
> + * @gup_flags: flags modifying lookup behaviour
> * @pages: array that receives pointers to the pages pinned.
> * Should be at least nr_pages long. Or NULL, if caller
> * only intends to ensure the pages are faulted in.
> @@ -936,9 +934,9 @@ EXPORT_SYMBOL(get_user_pages_unlocked);
> * or similar operation cannot guarantee anything stronger anyway because
> * locks can't be held over the syscall boundary.
> *
> - * If write=0, the page must not be written to. If the page is written to,
> - * set_page_dirty (or set_page_dirty_lock, as appropriate) must be called
> - * after the page is finished with, and before put_page is called.
> + * If gup_flags & FOLL_WRITE = 0, the page must not be written to. If the page
> + * is written to, set_page_dirty (or set_page_dirty_lock, as appropriate) must
> + * be called after the page is finished with, and before put_page is called.
> *
> * get_user_pages is typically used for fewer-copy IO operations, to get a
> * handle on the memory by some means other than accesses via the user virtual
> @@ -955,18 +953,12 @@ EXPORT_SYMBOL(get_user_pages_unlocked);
> */
> long get_user_pages_remote(struct task_struct *tsk, struct mm_struct *mm,
> unsigned long start, unsigned long nr_pages,
> - int write, int force, struct page **pages,
> + unsigned int gup_flags, struct page **pages,
> struct vm_area_struct **vmas)
> {
> - unsigned int flags = FOLL_TOUCH | FOLL_REMOTE;
> -
> - if (write)
> - flags |= FOLL_WRITE;
> - if (force)
> - flags |= FOLL_FORCE;
> -
> return __get_user_pages_locked(tsk, mm, start, nr_pages, pages, vmas,
> - NULL, false, flags);
> + NULL, false,
> + gup_flags | FOLL_TOUCH | FOLL_REMOTE);
> }
> EXPORT_SYMBOL(get_user_pages_remote);
>
> diff --git a/mm/memory.c b/mm/memory.c
> index fc1987d..20a9adb 100644
> --- a/mm/memory.c
> +++ b/mm/memory.c
> @@ -3873,6 +3873,10 @@ static int __access_remote_vm(struct task_struct *tsk, struct mm_struct *mm,
> {
> struct vm_area_struct *vma;
> void *old_buf = buf;
> + unsigned int flags = FOLL_FORCE;
> +
> + if (write)
> + flags |= FOLL_WRITE;
>
> down_read(&mm->mmap_sem);
> /* ignore errors, just check how much was successfully transferred */
> @@ -3882,7 +3886,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,
> - write, 1, &page, &vma);
> + flags, &page, &vma);
> if (ret <= 0) {
> #ifndef CONFIG_HAVE_IOREMAP_PROT
> break;
> diff --git a/security/tomoyo/domain.c b/security/tomoyo/domain.c
> index ade7c6c..682b73a 100644
> --- a/security/tomoyo/domain.c
> +++ b/security/tomoyo/domain.c
> @@ -881,7 +881,7 @@ bool tomoyo_dump_page(struct linux_binprm *bprm, unsigned long pos,
> * the execve().
> */
> if (get_user_pages_remote(current, bprm->mm, pos, 1,
> - 0, 1, &page, NULL) <= 0)
> + FOLL_FORCE, &page, NULL) <= 0)
> return false;
> #else
> page = bprm->page[pos / PAGE_SIZE];
> --
> 2.10.0
>
--
Jan Kara <jack@suse.com>
SUSE Labs, CR
next prev parent reply other threads:[~2016-10-19 7:47 UTC|newest]
Thread overview: 37+ messages / expand[flat|nested] mbox.gz Atom feed top
2016-10-13 0:20 [PATCH 00/10] mm: adjust get_user_pages* functions to explicitly pass FOLL_* flags Lorenzo Stoakes
2016-10-13 0:20 ` [PATCH 01/10] mm: remove write/force parameters from __get_user_pages_locked() Lorenzo Stoakes
2016-10-18 12:43 ` Jan Kara
2016-10-13 0:20 ` [PATCH 02/10] mm: remove write/force parameters from __get_user_pages_unlocked() Lorenzo Stoakes
2016-10-18 12:46 ` Jan Kara
2016-10-13 0:20 ` [PATCH 03/10] mm: replace get_user_pages_unlocked() write/force parameters with gup_flags Lorenzo Stoakes
2016-10-18 12:50 ` Jan Kara
2016-10-13 0:20 ` [PATCH 04/10] mm: replace get_user_pages_locked() " Lorenzo Stoakes
2016-10-18 12:54 ` Jan Kara
2016-10-18 13:56 ` Lorenzo Stoakes
2016-10-19 7:32 ` Jan Kara
2016-10-19 7:33 ` Jan Kara
2016-10-13 0:20 ` [PATCH 05/10] mm: replace get_vaddr_frames() " Lorenzo Stoakes
2016-10-19 7:34 ` Jan Kara
2016-10-13 0:20 ` [PATCH 06/10] mm: replace get_user_pages() " Lorenzo Stoakes
2016-10-17 9:22 ` Jesper Nilsson
2016-10-19 7:44 ` Jan Kara
2016-10-13 0:20 ` [PATCH 07/10] mm: replace get_user_pages_remote() " Lorenzo Stoakes
2016-10-19 7:47 ` Jan Kara [this message]
2016-10-13 0:20 ` [PATCH 08/10] mm: replace __access_remote_vm() write parameter " Lorenzo Stoakes
2016-10-19 7:59 ` Jan Kara
2016-10-19 8:13 ` Michal Hocko
2016-10-19 8:40 ` Lorenzo Stoakes
2016-10-19 8:52 ` Michal Hocko
2016-10-19 9:06 ` Lorenzo Stoakes
2016-10-19 9:23 ` Michal Hocko
2016-10-13 0:20 ` [PATCH 09/10] mm: replace access_remote_vm() " Lorenzo Stoakes
2016-10-13 0:20 ` [PATCH 10/10] mm: replace access_process_vm() " Lorenzo Stoakes
2016-10-17 9:23 ` Jesper Nilsson
2016-10-13 7:32 ` [PATCH 00/10] mm: adjust get_user_pages* functions to explicitly pass FOLL_* flags Christian König
2016-10-18 15:30 ` Michal Hocko
2016-10-19 8:58 ` Lorenzo Stoakes
2016-10-19 9:07 ` Michal Hocko
2016-10-19 16:49 ` Dave Hansen
2016-10-19 17:01 ` Michal Hocko
2016-10-19 17:23 ` Dave Hansen
2016-10-20 19:26 ` Michal Hocko
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20161019074707.GO29967@quack2.suse.cz \
--to=jack@suse.cz \
--cc=adi-buildroot-devel@lists.sourceforge.net \
--cc=ceph-devel@vger.kernel.org \
--cc=dave.hansen@linux.intel.com \
--cc=dri-devel@lists.freedesktop.org \
--cc=hughd@google.com \
--cc=intel-gfx@lists.freedesktop.org \
--cc=kvm@vger.kernel.org \
--cc=linux-alpha@vger.kernel.orglin \
--cc=linux-arm-kernel@lists.infradead.org \
--cc=linux-cris-kernel@axis.com \
--cc=linux-fbdev@vger.kernel.org \
--cc=linux-ia64@vger.kernel.org \
--cc=linux-kernel@vger.kernel.org \
--cc=linux-media@vger.kernel.org \
--cc=linux-mips@linux-mips.org \
--cc=linux-mm@kvack.org \
--cc=linux-rdma@vger.kernel.org \
--cc=linux-s390@vger.kernel.org \
--cc=linux-samsung-soc@vger.kernel.org \
--cc=linux-scsi@vger.kernel.org \
--cc=linux-security-module@vger.kernel.org \
--cc=linux-sh@vger.kernel.org \
--cc=linuxppc-dev@lists.ozlabs.org \
--cc=lstoakes@gmail.com \
--cc=netdev@vger.kernel.org \
--cc=riel@redhat.com \
--cc=sparclinux@vger.kernel.org \
--cc=torvalds@linux-foundation.org \
--cc=x86@kernel.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).