From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-alma10-1.taild15c8.ts.net [100.103.45.18]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 97A9A3B2FD0; Tue, 8 Sep 2026 20:21:02 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=100.103.45.18 ARC-Seal:i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1788898864; cv=none; b=g5u0oFwBGS3gJhucL1FTycsaBSTyYi09M4rWy4D9JH6c8R9LJSaMYwCodrrY+ZywSpDZVwdFjqtx5y+dVtNGraFNh12+ngYVhUgTfd+DrnGs/bJpCqpuzlJB/08+IJumn3WrweXjBKyGaCzu0ubK+DTZ9+6ha0g1kK+wz4ysIJU= ARC-Message-Signature:i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1788898864; c=relaxed/simple; bh=kPVMWaJCwo1lhrTWXad/wqA8hcD1f6brZZ1kpIuur1c=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=lcIRzwwOx48RTwkHoU58T3dO9AsJBufp5Nt4Iivx8DcPEkSSAINpFJcQD0QZp7ohW0P8UlZ1Zo9ecP62O3HvlDp8crc0n5w7W/EBmwsyHsFp1u6l1n9UeiEnKbKQ7jATOSsJCk+WzmT2xK3iELz2/u0A2m7lZgWD4oujt7kBkBM= ARC-Authentication-Results:i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=AEp1REBG; arc=none smtp.client-ip=100.103.45.18 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="AEp1REBG" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 81F2A1F00A3D; Tue, 8 Sep 2026 20:20:34 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=kernel.org; s=k20260515; t=1788898862; bh=MOMisn73rdVVhY8+AjzvTNNmNUkAEb20IWBzE7CPZUU=; h=From:Date:Subject:References:In-Reply-To:To:Cc; b=AEp1REBGH+pakt3xHUNX2JKqVONYzgzvgZGlCes8VpWTcWPNIU+TMTKT2sVwlEKVf 3d3HkthAX1FMsxxuYzx8BEFXz0VIq1fV7vOp89w+HJFBkSkxQzPGw8pf6KjunCOEha aAStY4j8dulgMJGDKYfg6byPl0UaLo7QmScwkKnJQEb6SoGID7WBqLjmi9Q6nJiQDi mFJrZqwN9amg72vbTmq5g4P0vaGZ3NaK3J55pnKuUo/GxMyGPJDy7MEpcYr2/8hWSF tX/1SpYavP4hBrQt3jwlo8PTcuszTSW3joN1et5kS8WFYzcq8/vxvnduS3NkwS0fQ2 k0/tNEa3pZ2VQ== From: "Lorenzo Stoakes (ARM)" Date: Tue, 08 Sep 2026 21:01:43 +0100 Subject: [PATCH 39/39] mm/vma: introduce and use vma[_flags]_can_gup() Precedence: bulk X-Mailing-List: linux-trace-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: 7bit Message-Id: <20260908-b4-mmap-prepare-vma-flag-sanify-v1-39-dacf19cce22b@kernel.org> References: <20260908-b4-mmap-prepare-vma-flag-sanify-v1-0-dacf19cce22b@kernel.org> In-Reply-To: <20260908-b4-mmap-prepare-vma-flag-sanify-v1-0-dacf19cce22b@kernel.org> To: Andrew Morton , "Liam R. Howlett" , Vlastimil Babka , Jann Horn , Pedro Falcato , David Hildenbrand , Mike Rapoport , Suren Baghdasaryan , Michal Hocko , Jonathan Corbet , Greg Kroah-Hartman , Dennis Dalessandro , Jason Gunthorpe , Leon Romanovsky , Paul Moore , Stephen Smalley , Jaroslav Kysela , Takashi Iwai , Alexei Starovoitov , Daniel Borkmann , Andrii Nakryiko , Eduard Zingerman , Kumar Kartikeya Dwivedi , Zi Yan , Baolin Wang , Nico Pache , Ryan Roberts , Dev Jain , Barry Song , Lance Yang , Usama Arif , Kiryl Shutsemau , Doug Gilbert , "James E.J. Bottomley" , "Martin K. Petersen" , Jaya Kumar , Simona Vetter , Helge Deller , Sebastian Reichel , John Hubbard , Peter Xu , Masami Hiramatsu , Oleg Nesterov , Peter Zijlstra , Thomas Gleixner , Ingo Molnar , Borislav Petkov , Dave Hansen , x86@kernel.org, Arnaldo Carvalho de Melo , Namhyung Kim , Mark Rutland , Rik van Riel , Harry Yoo , Juri Lelli , Vincent Guittot , Maarten Lankhorst , Maxime Ripard , Thomas Zimmermann , David Airlie , Will Deacon , "Aneesh Kumar K.V" , Nick Piggin , Arnd Bergmann , Muchun Song , Oscar Salvador , "Matthew Wilcox (Oracle)" , Jan Kara , Marc Zyngier , Oliver Upton , Catalin Marinas , Madhavan Srinivasan , Anup Patel , Paul Walmsley , Palmer Dabbelt , Albert Ou , Christian Borntraeger , Janosch Frank , Claudio Imbrenda , Alexander Gordeev , Gerald Schaefer , Heiko Carstens , Vasily Gorbik , "David S. Miller" , Andreas Larsson , Alexander Viro , Christian Brauner , Matthew Brost , Joshua Hahn , Rakie Kim , Byungchul Park , Gregory Price , Ying Huang , Alistair Popple , Chris Li , Kairui Song , Kemeng Shi , Nhat Pham , Baoquan He , Youngjun Park , Johannes Weiner , Qi Zheng , Shakeel Butt , Axel Rasmussen , Yuanchu Xie , Wei Xu , Xu Xin , Chengming Zhou , Michal Hocko , Miklos Szeredi Cc: linux-mm@kvack.org, linux-kernel@vger.kernel.org, linux-doc@vger.kernel.org, linux-usb@vger.kernel.org, linux-rdma@vger.kernel.org, selinux@vger.kernel.org, linux-sound@vger.kernel.org, bpf@vger.kernel.org, linux-scsi@vger.kernel.org, linux-fbdev@vger.kernel.org, dri-devel@lists.freedesktop.org, linux-trace-kernel@vger.kernel.org, linux-perf-users@vger.kernel.org, linux-arch@vger.kernel.org, linux-fsdevel@vger.kernel.org, linux-arm-kernel@lists.infradead.org, kvmarm@lists.linux.dev, linuxppc-dev@lists.ozlabs.org, kvm@vger.kernel.org, kvm-riscv@lists.infradead.org, linux-riscv@lists.infradead.org, linux-s390@vger.kernel.org, sparclinux@vger.kernel.org, fuse-devel@lists.linux.dev, "Lorenzo Stoakes (ARM)" X-Mailer: b4 0.14.3 X-Developer-Signature: v=1; a=openpgp-sha256; l=6584; i=ljs@kernel.org; h=from:subject:message-id; bh=kPVMWaJCwo1lhrTWXad/wqA8hcD1f6brZZ1kpIuur1c=; b=owGbwMvMwCV2fu7ZrsZH9SKMp9WSGLIWZG6vmyVSwLU385PLJLOsm8wrPI48vnjnyrRcyfpXr QZ5rW9tO0pZGMS4GGTFFFmefxHfHyQSNq/zgr8bzBxWJpAhDFycAjCR5KWMDE9+ar3kPPvQ5u7F 6lzR+P7LZzmWGP6c93zVo4ye57oHDxox/BU80L30947zd/l2STndnSQ2b77G82v3+VnlD9utDXp utJEDAA== X-Developer-Key: i=ljs@kernel.org; a=openpgp; fpr=E7F417BF5214569E89D04F46CF9DCD8A81E27F14 GUP cannot be used for VMAs which set VMA_IO_BIT - because memory-mapped I/O must not be accessed on the user's behalf - or VMA_PFNMAP_BIT - because PFN maps have no folios which the kernel is permitted to access. Rather than keeping these checks open-coded, abstract them to vma_flags_can_gup() and its VMA wrapper vma_can_gup(). This is useful as there are a number of additional places within the kernel that need to check whether a mapping can be accessed via GUP. Therefore, update all such occurrences. While here, drop a reference to 'special' and replace a use of the deprecated VMA flags API in vma_dump_size(). No functional change intended. Signed-off-by: Lorenzo Stoakes (ARM) --- fs/coredump.c | 4 ++-- include/linux/mm.h | 29 +++++++++++++++++++++++++++++ mm/gup.c | 7 +++---- mm/hmm.c | 3 +-- mm/memory.c | 14 ++++++++------ mm/mempolicy.c | 3 ++- 6 files changed, 45 insertions(+), 15 deletions(-) diff --git a/fs/coredump.c b/fs/coredump.c index fb21fb6703dd..9f729c594c47 100644 --- a/fs/coredump.c +++ b/fs/coredump.c @@ -1616,8 +1616,8 @@ static unsigned long vma_dump_size(struct vm_area_struct *vma, return 0; } - /* Do not dump I/O mapped devices or special mappings */ - if (vma->vm_flags & VM_IO) + /* Do not dump memory-mapped I/O, which may have side effects on read. */ + if (vma_test(vma, VMA_IO_BIT)) return 0; /* By default, dump shared memory if mapped from an anonymous file. */ diff --git a/include/linux/mm.h b/include/linux/mm.h index b5784685272a..1902d4c77481 100644 --- a/include/linux/mm.h +++ b/include/linux/mm.h @@ -1777,6 +1777,35 @@ static inline bool vma_is_persistent(const struct vm_area_struct *vma) return vma_flags_is_persistent(&vma->flags); } +/** + * vma_flags_can_gup() - Do the specified VMA flags permit GUP to access the + * mapping's pages? + * @flags: The VMA flags to test. + * + * GUP cannot access pages belonging to mappings whose pages are not permitted + * to be accessed (VMA_PFNMAP_BIT) and must not manipulate or provide access to + * memory-mapped I/O ranges to users (VMA_IO_BIT). + * + * Returns: true if GUP may access pages from the mapping, otherwise false. + */ +static inline bool vma_flags_can_gup(const vma_flags_t *flags) +{ + return !vma_flags_test_any(flags, VMA_IO_BIT, VMA_PFNMAP_BIT); +} + +/** + * vma_can_gup() - May GUP obtain pages from @vma? + * @vma: The VMA to test. + * + * See vma_flags_can_gup() for details. + * + * Returns: true if GUP may access pages from the mapping, otherwise false. + */ +static inline bool vma_can_gup(const struct vm_area_struct *vma) +{ + return vma_flags_can_gup(&vma->flags); +} + /** * vma_kernel_pagesize - Default page size granularity for this VMA. * @vma: The user mapping. diff --git a/mm/gup.c b/mm/gup.c index 66b306911703..f4d0cfcb602b 100644 --- a/mm/gup.c +++ b/mm/gup.c @@ -1204,7 +1204,7 @@ static int check_vma_flags(struct vm_area_struct *vma, unsigned long gup_flags) int foreign = (gup_flags & FOLL_REMOTE); bool vma_anon = vma_is_anonymous(vma); - if (vm_flags & (VM_IO | VM_PFNMAP)) + if (!vma_can_gup(vma)) return -EFAULT; if ((gup_flags & FOLL_ANON) && !vma_anon) @@ -1955,7 +1955,7 @@ int __mm_populate(unsigned long start, unsigned long len, int ignore_errors) * range with the first VMA. Also, skip undesirable VMA types. */ nend = min(end, vma->vm_end); - if (vma->vm_flags & (VM_IO | VM_PFNMAP)) + if (!vma_can_gup(vma)) continue; if (nstart < vma->vm_start) nstart = vma->vm_start; @@ -2017,8 +2017,7 @@ static long __get_user_pages_locked(struct mm_struct *mm, unsigned long start, break; /* protect what we can, including chardevs */ - if ((vma->vm_flags & (VM_IO | VM_PFNMAP)) || - !(vm_flags & vma->vm_flags)) + if (!vma_can_gup(vma) || !(vm_flags & vma->vm_flags)) break; if (pages) { diff --git a/mm/hmm.c b/mm/hmm.c index 2f1e98c6b644..e9569b82a1f0 100644 --- a/mm/hmm.c +++ b/mm/hmm.c @@ -595,8 +595,7 @@ static int hmm_vma_walk_test(unsigned long start, unsigned long end, struct hmm_range *range = hmm_vma_walk->range; struct vm_area_struct *vma = walk->vma; - if (!(vma->vm_flags & (VM_IO | VM_PFNMAP)) && - vma->vm_flags & VM_READ) + if (vma_can_gup(vma) && vma_test(vma, VMA_READ_BIT)) return 0; /* diff --git a/mm/memory.c b/mm/memory.c index 9a38c7d4cc40..cb56d67b17ca 100644 --- a/mm/memory.c +++ b/mm/memory.c @@ -2417,11 +2417,11 @@ static bool vm_mixed_zeropage_allowed(struct vm_area_struct *vma) * be problematic as soon as the zeropage gets replaced by a different * page due to vma->vm_ops->pfn_mkwrite, because what's mapped would * now differ to what GUP looked up. FSDAX is incompatible to - * FOLL_LONGTERM and VM_IO is incompatible to GUP completely (see - * check_vma_flags). + * FOLL_LONGTERM and memory-mapped I/O is incompatible to GUP completely + * (see vma_can_gup()). */ return vma->vm_ops && vma->vm_ops->pfn_mkwrite && - (vma_is_fsdax(vma) || vma->vm_flags & VM_IO); + (vma_is_fsdax(vma) || vma_test(vma, VMA_IO_BIT)); } static int validate_page_before_insert(struct vm_area_struct *vma, @@ -7116,7 +7116,8 @@ int follow_pfnmap_start(struct follow_pfnmap_args *args) if (unlikely(address < vma->vm_start || address >= vma->vm_end)) goto out; - if (!(vma->vm_flags & (VM_IO | VM_PFNMAP))) + /* Only mappings GUP cannot handle are followed here. */ + if (vma_can_gup(vma)) goto out; retry: pgdp = pgd_offset(mm, address); @@ -7310,8 +7311,9 @@ static int __access_remote_vm(struct mm_struct *mm, unsigned long addr, } /* - * Check if this is a VM_IO | VM_PFNMAP VMA, which - * we can access using slightly different code. + * GUP failed, perhaps because this is a mapping it + * cannot handle (see vma_can_gup()) - such mappings may + * provide access via vm_ops->access() instead. */ bytes = 0; #ifdef CONFIG_HAVE_IOREMAP_PROT diff --git a/mm/mempolicy.c b/mm/mempolicy.c index aeb99c5933cb..ed444061631c 100644 --- a/mm/mempolicy.c +++ b/mm/mempolicy.c @@ -2011,7 +2011,8 @@ SYSCALL_DEFINE5(get_mempolicy, int __user *, policy, bool vma_migratable(struct vm_area_struct *vma) { - if (vma->vm_flags & (VM_IO | VM_PFNMAP)) + /* Pages which GUP cannot obtain cannot be migrated either. */ + if (!vma_can_gup(vma)) return false; /* -- 2.55.0