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 6287851C05E; Thu, 17 Sep 2026 16:43:31 +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=1789663412; cv=none; b=NMQ00OK/7Qm/cK7E8+WIwVqB32ALCHoLsL1N8GRYK1BLImPPuL/ci8t9wM7rkGIYbj5VVgJ10kqzYeLncp4pv10zuV5sCxuInu2nbv0Kq9AO9kObBSn/76zl+XUoRxEB1dDguivGsN2t630fjqLSwTULCL6gyG14AHgaxHKLbhw= ARC-Message-Signature:i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1789663412; c=relaxed/simple; bh=FUHFpGdL5KZVRVlCuvz5idqKgH6ZuHhZHuvnhxOArGo=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=edfqrZaRfPT8ZYhizBokvOCCtcsYbWXVlk4V+I3wpgwuMJAvjc5kcsPfoWK31H9AyP9putb6cKGPoK4sKboxgsiaYYxYBDAGjyVoqzi4yv+InDwKl9UgkVT1hSBvRdACJ0uPQUqvCVg96M7DhKO1MN5IdQxPtfLQ1SuZHECTP9U= ARC-Authentication-Results:i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=U3VCmtam; 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="U3VCmtam" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 105461F000FF; Thu, 17 Sep 2026 16:43:00 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=kernel.org; s=k20260515; t=1789663411; bh=pbe5l45SH4yx4tHTzTY7+dgPoXtouc+iallQdj0tZTM=; h=From:Date:Subject:References:In-Reply-To:To:Cc; b=U3VCmtamsFZkAgO0QQp0B8Dds6bhn6Xl8VtQ3gAbfSk1DNVXLCJQTDAbPuGlRZSUh 7yqpqgv9jlRUltg2fRM/WuMoVC5li2aqV4W0sThfJFNHqKLA1UFjG8WjR5M82PpMC9 +nB6MzvYhPBSGwYvNXbh3ZbABwebZArPwvuGGJcg0/z/v+aWelMoyvQ7mEipMyya7f MCJU4d8pMhJWq1/5iiedVEnx2LZ8lG244dtSHttXpfGn/6yyJAzddzjz7f83DXHka4 tTzX/L9mPofs45bYAVH+C2P6GDU1LY21fbwKfxmnBaQ05UE2mA2PdjvAXvUgANHmgT qi3cjLkRQFK9g== From: "Lorenzo Stoakes (ARM)" Date: Thu, 17 Sep 2026 17:22:49 +0100 Subject: [PATCH v3 40/40] mm/vma: introduce and use vma[_flags]_can_gup() Precedence: bulk X-Mailing-List: linux-fbdev@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: <20260917-b4-mmap-prepare-vma-flag-sanify-v3-40-4583d8a23bca@kernel.org> References: <20260917-b4-mmap-prepare-vma-flag-sanify-v3-0-4583d8a23bca@kernel.org> In-Reply-To: <20260917-b4-mmap-prepare-vma-flag-sanify-v3-0-4583d8a23bca@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 , Chengming Zhou , Michal Hocko , Miklos Szeredi , Xu Xin 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=6501; i=ljs@kernel.org; h=from:subject:message-id; bh=FUHFpGdL5KZVRVlCuvz5idqKgH6ZuHhZHuvnhxOArGo=; b=owGbwMvMwCV2fu7ZrsZH9SKMp9WSGLLWCB8N6G3hqV537OvayJ1O+u1V977sddvVJvnh5ymNY 438WUo6HaUsDGJcDLJiiizPv4jvDxIJm9d5wd8NZg4rE8gQBi5OAZjIxDCGf+pJbLxPJRQLqx9k VRiK6Wznyd83Iavp9Cen9VXfUwXDLjMyTCz3M02xOsQ6/9lyJonHrud/Ol5PZfRjtf37uT/5lYE VIwA= 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(). A number of other places make the same check to decide whether a mapping can be populated or accessed as GUP would, so update those too. 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 5860a3b4dba9..1249e04d7b98 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 obtain pages from a PFN map (VMA_PFNMAP_BIT), which may have no + * struct pages behind it, and must not provide access to memory-mapped I/O + * (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 f166acf794e3..8e9ef5ee7498 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 6c011979401a..338fce99e711 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); @@ -7316,8 +7317,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 044ffb4f4128..2fd759e348ca 100644 --- a/mm/mempolicy.c +++ b/mm/mempolicy.c @@ -2013,7 +2013,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