mm/gup: adapt get_user_page_vma_remote() to never return NULL
authorLorenzo Stoakes <lstoakes@gmail.com>
Mon, 2 Oct 2023 23:14:54 +0000 (00:14 +0100)
committerAndrew Morton <akpm@linux-foundation.org>
Wed, 18 Oct 2023 21:34:15 +0000 (14:34 -0700)
get_user_pages_remote() will never return 0 except in the case of
FOLL_NOWAIT being specified, which we explicitly disallow.

This simplifies error handling for the caller and avoids the awkwardness
of dealing with both errors and failing to pin.  Failing to pin here is an
error.

Link: https://lkml.kernel.org/r/00319ce292d27b3aae76a0eb220ce3f528187508.1696288092.git.lstoakes@gmail.com
Signed-off-by: Lorenzo Stoakes <lstoakes@gmail.com>
Suggested-by: Arnd Bergmann <arnd@arndb.de>
Reviewed-by: Arnd Bergmann <arnd@arndb.de>
Acked-by: Catalin Marinas <catalin.marinas@arm.com>
Reviewed-by: David Hildenbrand <david@redhat.com>
Reviewed-by: Jason Gunthorpe <jgg@nvidia.com>
Cc: Adrian Hunter <adrian.hunter@intel.com>
Cc: Alexander Shishkin <alexander.shishkin@linux.intel.com>
Cc: Arnaldo Carvalho de Melo <acme@kernel.org>
Cc: Ian Rogers <irogers@google.com>
Cc: Ingo Molnar <mingo@redhat.com>
Cc: Jiri Olsa <jolsa@kernel.org>
Cc: John Hubbard <jhubbard@nvidia.com>
Cc: Mark Rutland <mark.rutland@arm.com>
Cc: Namhyung Kim <namhyung@kernel.org>
Cc: Oleg Nesterov <oleg@redhat.com>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Richard Cochran <richardcochran@gmail.com>
Cc: Will Deacon <will@kernel.org>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
arch/arm64/kernel/mte.c
include/linux/mm.h
kernel/events/uprobes.c
mm/memory.c

index 4edecaac8f919a232528806fb0daa79dc11b3e9b..8878b392df58b074dc49cba4d098388f3c80269f 100644 (file)
@@ -411,8 +411,8 @@ static int __access_remote_tags(struct mm_struct *mm, unsigned long addr,
                struct page *page = get_user_page_vma_remote(mm, addr,
                                                             gup_flags, &vma);
 
-               if (IS_ERR_OR_NULL(page)) {
-                       err = page == NULL ? -EIO : PTR_ERR(page);
+               if (IS_ERR(page)) {
+                       err = PTR_ERR(page);
                        break;
                }
 
index 7b89f7bd420d6d6eb3209a8b30d6f37b4f0a9b03..fa608cba041f065607faa592b622870ebebe0a46 100644 (file)
@@ -2425,6 +2425,9 @@ long pin_user_pages_remote(struct mm_struct *mm,
                           unsigned int gup_flags, struct page **pages,
                           int *locked);
 
+/*
+ * Retrieves a single page alongside its VMA. Does not support FOLL_NOWAIT.
+ */
 static inline struct page *get_user_page_vma_remote(struct mm_struct *mm,
                                                    unsigned long addr,
                                                    int gup_flags,
@@ -2432,12 +2435,15 @@ static inline struct page *get_user_page_vma_remote(struct mm_struct *mm,
 {
        struct page *page;
        struct vm_area_struct *vma;
-       int got = get_user_pages_remote(mm, addr, 1, gup_flags, &page, NULL);
+       int got;
+
+       if (WARN_ON_ONCE(unlikely(gup_flags & FOLL_NOWAIT)))
+               return ERR_PTR(-EINVAL);
+
+       got = get_user_pages_remote(mm, addr, 1, gup_flags, &page, NULL);
 
        if (got < 0)
                return ERR_PTR(got);
-       if (got == 0)
-               return NULL;
 
        vma = vma_lookup(mm, addr);
        if (WARN_ON_ONCE(!vma)) {
index 3048589e2e8516e12a817875988bdc5986c6ad09..435aac1d8c2721624e1712895eda1bc982db4e83 100644 (file)
@@ -474,8 +474,8 @@ retry:
                gup_flags |= FOLL_SPLIT_PMD;
        /* Read the page with vaddr into memory */
        old_page = get_user_page_vma_remote(mm, vaddr, gup_flags, &vma);
-       if (IS_ERR_OR_NULL(old_page))
-               return old_page ? PTR_ERR(old_page) : 0;
+       if (IS_ERR(old_page))
+               return PTR_ERR(old_page);
 
        ret = verify_opcode(old_page, vaddr, &opcode);
        if (ret <= 0)
index e47c36c0aef0e720f85cb28593f519169fc13b84..1f88e4f6fbf21e348fadf994b0c6cf69dacfeb23 100644 (file)
@@ -5815,7 +5815,7 @@ static int __access_remote_vm(struct mm_struct *mm, unsigned long addr,
                struct page *page = get_user_page_vma_remote(mm, addr,
                                                             gup_flags, &vma);
 
-               if (IS_ERR_OR_NULL(page)) {
+               if (IS_ERR(page)) {
                        /* We might need to expand the stack to access it */
                        vma = vma_lookup(mm, addr);
                        if (!vma) {
@@ -5829,7 +5829,6 @@ static int __access_remote_vm(struct mm_struct *mm, unsigned long addr,
                                continue;
                        }
 
-
                        /*
                         * Check if this is a VM_IO | VM_PFNMAP VMA, which
                         * we can access using slightly different code.