Kernel KVM virtualization development
 help / color / mirror / Atom feed
* [PATCH 00/39] mm: make VMA flag semantics explicit, eliminate VM_SPECIAL
@ 2026-09-08 20:01 Lorenzo Stoakes (ARM)
  2026-09-08 20:01 ` [PATCH 01/39] mm/vma: predicate setting mmap_prepare VMA fields on new vma alloc Lorenzo Stoakes (ARM)
                   ` (38 more replies)
  0 siblings, 39 replies; 89+ messages in thread
From: Lorenzo Stoakes (ARM) @ 2026-09-08 20:01 UTC (permalink / raw)
  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,
	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, linux-kernel, linux-doc, linux-usb, linux-rdma, selinux,
	linux-sound, bpf, linux-scsi, linux-fbdev, dri-devel,
	linux-trace-kernel, linux-perf-users, linux-arch, linux-fsdevel,
	linux-arm-kernel, kvmarm, linuxppc-dev, kvm, kvm-riscv,
	linux-riscv, linux-s390, sparclinux, fuse-devel,
	Lorenzo Stoakes (ARM)

The VM_SPECIAL / VMA_SPECIAL_FLAGS mask conflates several unrelated
properties:

* Is this kernel-owned, whether MMIO, kernel-allocated pages, or ordinary
  pages a driver maps itself?
* Can it be expanded or merged?
* Is this a 'weird' case like mlock where migration might race and we
  'have' to set invalid flags to notify?
* Is it another 'weird' case where we just want to stop GUP from touching
  it?

Driver writers have often been confused about this, and who can blame them?

It also interacts badly with the eternal edgecase known as hugetlb - which
sets VMA_DONTEXPAND_BIT but doesn't also want to be treated like a
'special' flag.

Another issue is that we cannot make sensible assumptions about flag
use. It's not possible to assume VMA_IO_BIT means iommu because drivers
abuse it and mlock abuses it.

Special is also an overloaded term in mm. VDSO and VVAR mappings are also
called 'special' but they're special in a... special way.

Sometimes things are called special that are a subset of
VMA_SPECIAL_FLAGS (VMA_PFNMAP_BIT and VMA_MIXEDMAP_BIT for instance when it
comes to zapping or vm_normal_folio()).

There's a specific kind of special for THP too, which considers
PFN map, mixed map 'special' but DAX not.

It's all rather a mess.

This series brings some order to things by both limiting what drivers can
do with VMA flags and switching to using predicates that describe
behaviour, not arbitrary flags.

It establishes the invariant that only kernel-owned mappings may set
VMA_IO_BIT or clear VMA_MAYWRITE_BIT in an mmap hook, enforcing this by
validating VMA state after every mmap and mmap_prepare hook.

It updates usbmon and sg to mmap_prepare in order to do so, adding a new
mmap action for mapping discontiguous kernel pages, and has hfi1 and the
ALSA PCM status page map their pages eagerly instead.

It also establishes the invariant that VMA_MIXEDMAP_BIT be set when mapping
kernel memory, something that is usually the case but happens not to be for
some users - specifically defio, cmt_speech, uprobes and the bpf arena, all
of which are updated to do the right thing.

It replaces VM_SPECIAL and arbitrary flag tests with predicates that say
what is actually being tested:

   vma_is_kernel_owned()   Does a driver or kernel code manage a VMA's
                           life cycle?

  vma_is_fixed_mapping()   Is the VMA not permitted to be expanded or
                           merged?

     vma_is_persistent()   Do bytes written to the VMA stay written, and
                           bytes read stay the same unless userland changes
                           them?

         vma_can_merge()   Can the VMA be merged with a compatible
                           neighbour?

           vma_can_gup()   Can GUP obtain pages from the VMA, i.e. is it
                           neither a PFN map nor memory-mapped I/O?

Remaining raw VMA_IO_BIT, VMA_PFNMAP_BIT and VMA_MIXEDMAP_BIT tests
scattered across mm are also converted to predicates where it makes sense
to do so.

And also the opportunity is taken to eliminate THP's vma_is_special_huge()
which was an existing source of confusion.

Signed-off-by: Lorenzo Stoakes (ARM) <ljs@kernel.org>
---
Lorenzo Stoakes (ARM) (39):
      mm/vma: predicate setting mmap_prepare VMA fields on new vma alloc
      mm/vma: introduce and use vma_[flags_]can_merge()
      mm: consistently validate VMA state after mmap[_prepare] hooks
      mm/vma: ensure mmap_prepare doesn't set actions on a mergeable vma
      mm: make map_kernel_pages_[prepare,complete] internal and unexported
      mm/vma: tidy up map kernel pages enum values
      mm: add mmap action for discontiguous kernel page mapping
      docs: filesystems: update mmap_prepare docs for discontig kernel pgs
      drivers/usb/mon: update to use mmap_prepare + map kernel pages
      infiniband: update hfi1 to use remap_vmalloc_range()
      selinux: reject writable opens of policy file, drop mmap shared/write check
      ALSA: pcm: use vm_insert_page() to map PCM status page
      bpf: arena: mark arena_map_mmap() mappings VM_MIXEDMAP
      mm/vma: add vma[_flags]_is_kernel_owned() predicates
      mm/vma: only allow mmap to clear VMA_MAYWRITE_BIT if kernel-owned
      mm/vma: add and use vma_[flags]_is_fixed_mapping
      scsi: sg: convert mmap hook to mmap_prepare and rework
      fbdev: defio: assert FBINFO_VIRTFB, drop VM_IO, add VM_MIXEDMAP
      HSI: cmt_speech: convert mmap hook to mmap_prepare, refactor
      mm/gup: error out early on !VMA_MAYREAD_BIT VMAs
      uprobes: remove VM_IO, set VM_MIXEDMAP for mapped kernel pages
      mm/mlock: clear VMA_LOCKED_MASK over mmap callback
      mm/mlock: eliminate weird VMA_IO_BIT abuse and simplify
      mm/vma: enforce that only kernel-owned mappings may set VMA_IO_BIT
      mm: remove VMA_IO_BIT check in vma[_flags]_is_kernel_owned()
      mm: remove hugetlb_inline.h
      mm: rename is_vm_hugetlb_page() to vma_is_hugetlb()
      mm: drop some redundant checks around hugetlb VMAs
      mm/madvise: update is_valid_guard_vma() to use vma_can_merge()
      mm/vma: introduce vma[_flags]_is_persistent()
      mm/uffd: use predicates for userfaultfd checks
      mm/madvise: use predicates for madvise(..., MADV_DOFORK)
      mm: eliminate VMA_SPECIAL_FLAGS usage when hugetlb explicitly tested
      mm: eliminate VMA_SPECIAL_FLAGS check in lru_gen_look_around()
      mm: avoid use of VMA_SPECIAL_FLAGS in migrate_vma_setup()
      mm: eliminate VM_SPECIAL, VMA_SPECIAL_FLAGS
      fuse: dax: do not set VM_MIXEDMAP
      mm/huge_memory: remove vma_is_special_huge()
      mm/vma: introduce and use vma[_flags]_can_gup()

 Documentation/filesystems/mmap_prepare.rst |  81 +++++++++
 arch/arm64/kvm/mmu.c                       |   4 +-
 arch/powerpc/mm/book3s64/radix_tlb.c       |   6 +-
 arch/powerpc/mm/nohash/e500_hugetlbpage.c  |   2 +-
 arch/powerpc/mm/nohash/tlb.c               |   2 +-
 arch/riscv/kvm/mmu.c                       |   2 +-
 arch/riscv/mm/tlbflush.c                   |   2 +-
 arch/s390/mm/gmap_helpers.c                |   6 +-
 arch/sparc/mm/init_64.c                    |   2 +-
 arch/x86/kernel/uprobes.c                  |   2 +-
 drivers/gpu/drm/drm_gpusvm.c               |   5 +-
 drivers/hsi/clients/cmt_speech.c           |  33 +---
 drivers/infiniband/hw/hfi1/file_ops.c      |  79 +++------
 drivers/scsi/sg.c                          | 115 ++++++-------
 drivers/usb/mon/mon_bin.c                  |  82 +++++----
 drivers/video/fbdev/core/fb_defio.c        |   6 +-
 drivers/video/fbdev/ssd1307fb.c            |   2 +
 fs/coredump.c                              |   6 +-
 fs/fuse/dax.c                              |   2 +-
 fs/hugetlbfs/inode.c                       |   2 +-
 fs/proc/task_mmu.c                         |   8 +-
 include/asm-generic/tlb.h                  |   4 +-
 include/linux/hugetlb.h                    |   5 +-
 include/linux/hugetlb_inline.h             |  28 ---
 include/linux/mm.h                         | 266 +++++++++++++++++++++++++++--
 include/linux/mm_types.h                   |  50 +++++-
 include/linux/pagemap.h                    |   1 -
 include/linux/rmap.h                       |   2 +-
 include/linux/userfaultfd_k.h              |   1 -
 kernel/bpf/arena.c                         |   3 +-
 kernel/events/core.c                       |   2 +-
 kernel/events/uprobes.c                    |   4 +-
 kernel/sched/fair.c                        |   3 +-
 mm/folio.c                                 |   2 +-
 mm/gup.c                                   |  15 +-
 mm/hmm.c                                   |   3 +-
 mm/huge_memory.c                           |  31 ++--
 mm/hugetlb.c                               |  14 +-
 mm/internal.h                              |  71 ++++----
 mm/ksm.c                                   |   4 +-
 mm/madvise.c                               |  28 +--
 mm/memory.c                                | 142 ++++++++++++---
 mm/mempolicy.c                             |   5 +-
 mm/migrate_device.c                        |  12 +-
 mm/mlock.c                                 |  51 +++---
 mm/mmap.c                                  |   2 +-
 mm/mmu_gather.c                            |   2 +-
 mm/mprotect.c                              |   5 +-
 mm/mremap.c                                |  11 +-
 mm/page_vma_mapped.c                       |   4 +-
 mm/pagewalk.c                              |   2 +-
 mm/rmap.c                                  |   4 +-
 mm/swapfile.c                              |   2 +-
 mm/userfaultfd.c                           |  45 +++--
 mm/util.c                                  |  22 ++-
 mm/vma.c                                   | 161 +++++++++++++----
 mm/vma.h                                   |  24 ++-
 mm/vma_internal.h                          |   1 -
 mm/vmscan.c                                |   9 +-
 security/selinux/selinuxfs.c               |  11 +-
 sound/core/pcm_native.c                    |  37 ++--
 tools/testing/vma/include/dup.h            |  60 +++++--
 tools/testing/vma/include/stubs.h          |   2 +-
 tools/testing/vma/tests/merge.c            |  10 +-
 64 files changed, 1071 insertions(+), 539 deletions(-)
---
base-commit: d118502628f8b673be9023db8bdf878f64a7ed45
change-id: 20260721-b4-mmap-prepare-vma-flag-sanify-2100425df5aa

Best regards,
-- 
Lorenzo Stoakes (ARM) <ljs@kernel.org>


^ permalink raw reply	[flat|nested] 89+ messages in thread

* [PATCH 01/39] mm/vma: predicate setting mmap_prepare VMA fields on new vma alloc
  2026-09-08 20:01 [PATCH 00/39] mm: make VMA flag semantics explicit, eliminate VM_SPECIAL Lorenzo Stoakes (ARM)
@ 2026-09-08 20:01 ` Lorenzo Stoakes (ARM)
  2026-09-08 20:42   ` sashiko-bot
  2026-09-08 20:01 ` [PATCH 02/39] mm/vma: introduce and use vma_[flags_]can_merge() Lorenzo Stoakes (ARM)
                   ` (37 subsequent siblings)
  38 siblings, 1 reply; 89+ messages in thread
From: Lorenzo Stoakes (ARM) @ 2026-09-08 20:01 UTC (permalink / raw)
  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,
	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, linux-kernel, linux-doc, linux-usb, linux-rdma, selinux,
	linux-sound, bpf, linux-scsi, linux-fbdev, dri-devel,
	linux-trace-kernel, linux-perf-users, linux-arch, linux-fsdevel,
	linux-arm-kernel, kvmarm, linuxppc-dev, kvm, kvm-riscv,
	linux-riscv, linux-s390, sparclinux, fuse-devel,
	Lorenzo Stoakes (ARM)

It only makes sense to manipulate VMA fields if we allocated a new VMA,
rather than merged it.

VMA merging does not compare vm_ops or vm_private_data, so a merged VMA
keeps its own, which is also what the legacy f_op->mmap path does since it
never touches an existing VMA. Previously set_vma_user_defined_fields()
overwrote the merged VMA's fields with those set for the new mapping. In
practice these are the same values, with rare exceptions such as shmem
selecting vm_ops based on whether the file has been unlinked, so no
user-visible change is expected.

Make this dependency explicit, and additionally constify have_mmap_prepare
while we're here.

Signed-off-by: Lorenzo Stoakes (ARM) <ljs@kernel.org>
---
 mm/vma.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/mm/vma.c b/mm/vma.c
index 97567fb7ef33..2a90c509bb31 100644
--- a/mm/vma.c
+++ b/mm/vma.c
@@ -2866,7 +2866,7 @@ static unsigned long __mmap_region(struct file *file, unsigned long addr,
 {
 	struct mm_struct *mm = current->mm;
 	struct vm_area_struct *vma = NULL;
-	bool have_mmap_prepare = file && file->f_op->mmap_prepare;
+	const bool have_mmap_prepare = file && file->f_op->mmap_prepare;
 	VMA_ITERATOR(vmi, mm, addr);
 	const pgoff_t anon_pgoff = addr >> PAGE_SHIFT;
 	MMAP_STATE(map, mm, &vmi, addr, len, pgoff, anon_pgoff, vma_flags, file);
@@ -2909,7 +2909,7 @@ static unsigned long __mmap_region(struct file *file, unsigned long addr,
 		allocated_new = true;
 	}
 
-	if (have_mmap_prepare && !map_is_anon(&map))
+	if (have_mmap_prepare && allocated_new && !map_is_anon(&map))
 		set_vma_user_defined_fields(vma, &map);
 
 	__mmap_complete(&map, vma);

-- 
2.55.0


^ permalink raw reply related	[flat|nested] 89+ messages in thread

* [PATCH 02/39] mm/vma: introduce and use vma_[flags_]can_merge()
  2026-09-08 20:01 [PATCH 00/39] mm: make VMA flag semantics explicit, eliminate VM_SPECIAL Lorenzo Stoakes (ARM)
  2026-09-08 20:01 ` [PATCH 01/39] mm/vma: predicate setting mmap_prepare VMA fields on new vma alloc Lorenzo Stoakes (ARM)
@ 2026-09-08 20:01 ` Lorenzo Stoakes (ARM)
  2026-09-08 20:27   ` sashiko-bot
  2026-09-08 20:01 ` [PATCH 03/39] mm: consistently validate VMA state after mmap[_prepare] hooks Lorenzo Stoakes (ARM)
                   ` (36 subsequent siblings)
  38 siblings, 1 reply; 89+ messages in thread
From: Lorenzo Stoakes (ARM) @ 2026-09-08 20:01 UTC (permalink / raw)
  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,
	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, linux-kernel, linux-doc, linux-usb, linux-rdma, selinux,
	linux-sound, bpf, linux-scsi, linux-fbdev, dri-devel,
	linux-trace-kernel, linux-perf-users, linux-arch, linux-fsdevel,
	linux-arm-kernel, kvmarm, linuxppc-dev, kvm, kvm-riscv,
	linux-riscv, linux-s390, sparclinux, fuse-devel,
	Lorenzo Stoakes (ARM)

Replace the open-coded VMA_SPECIAL_FLAGS check in the VMA merge logic with
two new functions vma_flags_can_merge() and vma_can_merge() and update the
merge logic to use the former.

This abstracts the check and expresses it in terms of the desired behaviour
rather than an arbitrary and confusing VMA flag.

This also lays the groundwork for making further improvements in VMA flag
usage.

Also update the userland VMA tests to reflect the change.

No functional change intended.

Signed-off-by: Lorenzo Stoakes (ARM) <ljs@kernel.org>
---
 include/linux/mm.h              | 21 +++++++++++++++++++++
 mm/vma.c                        | 19 +++++++++++--------
 tools/testing/vma/include/dup.h |  5 +++++
 3 files changed, 37 insertions(+), 8 deletions(-)

diff --git a/include/linux/mm.h b/include/linux/mm.h
index c49ef99b4413..83979ec28f5c 100644
--- a/include/linux/mm.h
+++ b/include/linux/mm.h
@@ -1612,6 +1612,27 @@ static inline bool vma_is_shared_maywrite(const struct vm_area_struct *vma)
 	return is_shared_maywrite(&vma->flags);
 }
 
+/**
+ * vma_flags_can_merge() - Do the specified VMA flags permit the VMA to be
+ * merged with another?
+ * @flags: The VMA flags to test.
+ * Returns: true if the flags permit merging, false otherwise.
+ */
+static inline bool vma_flags_can_merge(const vma_flags_t *flags)
+{
+	return !vma_flags_test_any_mask(flags, VMA_SPECIAL_FLAGS);
+}
+
+/**
+ * vma_can_merge() - Do @vma's flags permit it to be merged with another VMA?
+ * @vma: The VMA to test.
+ * Returns: true if the flags permit merging, otherwise false.
+ */
+static inline bool vma_can_merge(const struct vm_area_struct *vma)
+{
+	return vma_flags_can_merge(&vma->flags);
+}
+
 /**
  * vma_kernel_pagesize - Default page size granularity for this VMA.
  * @vma: The user mapping.
diff --git a/mm/vma.c b/mm/vma.c
index 2a90c509bb31..0db2fc306993 100644
--- a/mm/vma.c
+++ b/mm/vma.c
@@ -924,13 +924,14 @@ static __must_check struct vm_area_struct *vma_merge_existing_range(
 
 	vmg->state = VMA_MERGE_NOMERGE;
 
+	if (!vma_flags_can_merge(&vmg->vma_flags))
+		return NULL;
 	/*
-	 * If a special mapping or if the range being modified is neither at the
-	 * furthermost left or right side of the VMA, then we have no chance of
-	 * merging and should abort.
+	 * If the range being modified is neither at the furthermost left or
+	 * right side of the VMA, then we have no chance of merging and should
+	 * abort.
 	 */
-	if (vma_flags_test_any_mask(&vmg->vma_flags, VMA_SPECIAL_FLAGS) ||
-	    (!left_side && !right_side))
+	if (!left_side && !right_side)
 		return NULL;
 
 	if (left_side)
@@ -1152,9 +1153,11 @@ struct vm_area_struct *vma_merge_new_range(struct vma_merge_struct *vmg)
 
 	vmg->state = VMA_MERGE_NOMERGE;
 
-	/* Special VMAs are unmergeable, also if no prev/next. */
-	if (vma_flags_test_any_mask(&vmg->vma_flags, VMA_SPECIAL_FLAGS) ||
-	    (!prev && !next))
+	if (!vma_flags_can_merge(&vmg->vma_flags))
+		return NULL;
+
+	/* VMAs with no prev/next are unmergeable. */
+	if (!prev && !next)
 		return NULL;
 
 	can_merge_left = can_vma_merge_left(vmg);
diff --git a/tools/testing/vma/include/dup.h b/tools/testing/vma/include/dup.h
index 16c09dac59d9..2fd422789717 100644
--- a/tools/testing/vma/include/dup.h
+++ b/tools/testing/vma/include/dup.h
@@ -1647,3 +1647,8 @@ static inline bool file_is_dev_zero(const struct file *file)
 {
 	return file && file->f_op == &zero_fops;
 }
+
+static inline bool vma_flags_can_merge(const vma_flags_t *flags)
+{
+	return !vma_flags_test_any_mask(flags, VMA_SPECIAL_FLAGS);
+}

-- 
2.55.0


^ permalink raw reply related	[flat|nested] 89+ messages in thread

* [PATCH 03/39] mm: consistently validate VMA state after mmap[_prepare] hooks
  2026-09-08 20:01 [PATCH 00/39] mm: make VMA flag semantics explicit, eliminate VM_SPECIAL Lorenzo Stoakes (ARM)
  2026-09-08 20:01 ` [PATCH 01/39] mm/vma: predicate setting mmap_prepare VMA fields on new vma alloc Lorenzo Stoakes (ARM)
  2026-09-08 20:01 ` [PATCH 02/39] mm/vma: introduce and use vma_[flags_]can_merge() Lorenzo Stoakes (ARM)
@ 2026-09-08 20:01 ` Lorenzo Stoakes (ARM)
  2026-09-08 20:40   ` sashiko-bot
  2026-09-08 20:01 ` [PATCH 04/39] mm/vma: ensure mmap_prepare doesn't set actions on a mergeable vma Lorenzo Stoakes (ARM)
                   ` (35 subsequent siblings)
  38 siblings, 1 reply; 89+ messages in thread
From: Lorenzo Stoakes (ARM) @ 2026-09-08 20:01 UTC (permalink / raw)
  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,
	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, linux-kernel, linux-doc, linux-usb, linux-rdma, selinux,
	linux-sound, bpf, linux-scsi, linux-fbdev, dri-devel,
	linux-trace-kernel, linux-perf-users, linux-arch, linux-fsdevel,
	linux-arm-kernel, kvmarm, linuxppc-dev, kvm, kvm-riscv,
	linux-riscv, linux-s390, sparclinux, fuse-devel,
	Lorenzo Stoakes (ARM)

When the f_op->mmap_prepare or deprecated f_op->mmap hooks are invoked, the
driver might have done something crazy that is not permitted by the kernel.

Currently we check for three such cases in __mmap_new_file_vma(), but only
if the legacy f_op->mmap hook is used:

* Did sparc ADI result in invalid flags?

* Did the driver alter vma->vm_start?

* Did the driver make a file-backed mapping on a read-only file writable?

Generalise these checks for both mmap_prepare and mmap and apply to all
invocations of mmap_file(), the f_op->mmap and f_op->mmap_prepare handling
in the core VMA code and the mmap_prepare compatibility layer.

We also WARN_ON_ONCE() on these conditions as they are things that should
simply not occur in the kernel and it's important to call it out when it
does.

We invoke mmap_prepare_validate() after mmap_action_prepare(), as mmap
actions often manipulate state in the descriptor thus providing the final
state the VMA will be derived from.

Also call mmap_validate_vma_flags() in insert_vm_struct() to ensure that
special regions which are inserted (such as a VDSO or VVAR) also satisfy
the sanity checks.

This way every VMA established through an mmap hook, whether via mmap() or
the compatibility layer, or inserted via insert_vm_struct(), has been
validated. brk() VMAs never pass through a driver hook and so need no such
check.

While we're here, also fixup a couple disjoint blocks of #ifdef CONFIG_MMU.

Finally, update the VMA userland tests to reflect the change.

Signed-off-by: Lorenzo Stoakes (ARM) <ljs@kernel.org>
---
 mm/internal.h                   | 47 ++++++++++++--------
 mm/util.c                       |  7 +++
 mm/vma.c                        | 98 ++++++++++++++++++++++++++++++++++-------
 mm/vma.h                        | 24 ++++++++--
 tools/testing/vma/include/dup.h | 10 +++++
 5 files changed, 148 insertions(+), 38 deletions(-)

diff --git a/mm/internal.h b/mm/internal.h
index da14c56fb24e..abb0fae8c637 100644
--- a/mm/internal.h
+++ b/mm/internal.h
@@ -212,6 +212,24 @@ static inline void *folio_raw_mapping(const struct folio *folio)
 	return (void *)(mapping & ~FOLIO_MAPPING_FLAGS);
 }
 
+/*
+ * If the VMA has a close hook then close it, and since closing it might leave
+ * it in an inconsistent state which makes the use of any hooks suspect, clear
+ * them down by installing dummy empty hooks.
+ */
+static inline void vma_close(struct vm_area_struct *vma)
+{
+	if (vma->vm_ops && vma->vm_ops->close) {
+		vma->vm_ops->close(vma);
+
+		/*
+		 * The mapping is in an inconsistent state, and no further hooks
+		 * may be invoked upon it.
+		 */
+		vma->vm_ops = &vma_dummy_vm_ops;
+	}
+}
+
 /*
  * This is a file-backed mapping, and is about to be memory mapped - invoke its
  * mmap hook and safely handle error conditions. On error, VMA hooks will be
@@ -224,8 +242,11 @@ static inline void *folio_raw_mapping(const struct folio *folio)
  */
 static inline int mmap_file(struct file *file, struct vm_area_struct *vma)
 {
-	int err = vfs_mmap(file, vma);
+	const unsigned long prev_start = vma->vm_start;
+	const vma_flags_t prev_flags = vma->flags;
+	int err;
 
+	err = vfs_mmap(file, vma);
 	/*
 	 * Either we tried to call the file hook for mmap() and an error arose
 	 * or a driver set vma->vm_ops = NULL intending there to be no VMA
@@ -238,26 +259,14 @@ static inline int mmap_file(struct file *file, struct vm_area_struct *vma)
 	 */
 	if (unlikely(err || !vma->vm_ops))
 		vma->vm_ops = &vma_dummy_vm_ops;
+	if (unlikely(err))
+		return err;
 
-	return err;
-}
-
-/*
- * If the VMA has a close hook then close it, and since closing it might leave
- * it in an inconsistent state which makes the use of any hooks suspect, clear
- * them down by installing dummy empty hooks.
- */
-static inline void vma_close(struct vm_area_struct *vma)
-{
-	if (vma->vm_ops && vma->vm_ops->close) {
-		vma->vm_ops->close(vma);
+	err = mmap_hook_validate(prev_start, &prev_flags, vma);
+	if (unlikely(err))
+		vma_close(vma);
 
-		/*
-		 * The mapping is in an inconsistent state, and no further hooks
-		 * may be invoked upon it.
-		 */
-		vma->vm_ops = &vma_dummy_vm_ops;
-	}
+	return err;
 }
 
 /* unmap_vmas is in mm/memory.c */
diff --git a/mm/util.c b/mm/util.c
index bf0513d1d3d0..a3cef493ed70 100644
--- a/mm/util.c
+++ b/mm/util.c
@@ -1224,10 +1224,17 @@ EXPORT_SYMBOL(compat_set_desc_from_vma);
 int __compat_vma_mmap(struct vm_area_desc *desc,
 		      struct vm_area_struct *vma)
 {
+	struct vm_area_desc prev_desc;
 	int err;
 
+	/* Derive state prior to mmap_prepare hook. */
+	compat_set_desc_from_vma(&prev_desc, desc->file, vma);
 	/* Perform any preparatory tasks for mmap action. */
 	err = mmap_action_prepare(desc);
+	if (err)
+		return err;
+	/* Check the caller did nothing crazy. */
+	err = mmap_prepare_validate(&prev_desc, desc);
 	if (err)
 		return err;
 	/* Update the VMA from the descriptor. */
diff --git a/mm/vma.c b/mm/vma.c
index 0db2fc306993..a24f04428580 100644
--- a/mm/vma.c
+++ b/mm/vma.c
@@ -2581,7 +2581,6 @@ static int __mmap_setup(struct mmap_state *map, struct vm_area_desc *desc,
 	return 0;
 }
 
-
 static int __mmap_new_file_vma(struct mmap_state *map,
 			       struct vm_area_struct *vma)
 {
@@ -2608,16 +2607,6 @@ static int __mmap_new_file_vma(struct mmap_state *map,
 		return error;
 	}
 
-	/* Drivers cannot alter the address of the VMA. */
-	WARN_ON_ONCE(map->addr != vma->vm_start);
-	/*
-	 * Drivers should not permit writability when previously it was
-	 * disallowed.
-	 */
-	VM_WARN_ON_ONCE(!vma_flags_same_pair(&map->vma_flags, &vma->flags) &&
-			!vma_flags_test(&map->vma_flags, VMA_MAYWRITE_BIT) &&
-			vma_test(vma, VMA_MAYWRITE_BIT));
-
 	map->file = vma->vm_file;
 	map->vma_flags = vma->flags;
 
@@ -2696,11 +2685,6 @@ static int __mmap_new_vma(struct mmap_state *map, struct vm_area_struct **vmap,
 		vma->flags = map->vma_flags;
 	}
 
-#ifdef CONFIG_SPARC64
-	/* TODO: Fix SPARC ADI! */
-	WARN_ON_ONCE(!arch_validate_flags(map->vm_flags));
-#endif
-
 	/* Lock the VMA since it is modified after insertion into VMA tree */
 	vma_start_write(vma);
 	vma_iter_store_new(vmi, vma);
@@ -2763,6 +2747,76 @@ static void __mmap_complete(struct mmap_state *map, struct vm_area_struct *vma)
 	vma_set_page_prot(vma);
 }
 
+/* Check to ensure that the VMA flags of a newly mapped VMA are sane. */
+static int mmap_validate_vma_flags(const vma_flags_t *flags)
+{
+#ifdef CONFIG_SPARC64
+	const vm_flags_t legacy_flags = vma_flags_to_legacy(*flags);
+
+	/* TODO: Fix SPARC ADI! */
+	if (WARN_ON_ONCE(!arch_validate_flags(legacy_flags)))
+		return -EINVAL;
+#endif
+
+	return 0;
+}
+
+/* Check to ensure a driver hasn't done something crazy. */
+static int mmap_validate(unsigned long prev_start,
+			 unsigned long curr_start,
+			 const vma_flags_t *prev_flags,
+			 const vma_flags_t *curr_flags)
+{
+	bool was_maywrite, is_maywrite;
+
+	/* Drivers cannot alter the address of the VMA. */
+	if (WARN_ON_ONCE(prev_start != curr_start))
+		return -EINVAL;
+
+	was_maywrite = vma_flags_test(prev_flags, VMA_MAYWRITE_BIT);
+	is_maywrite = vma_flags_test(curr_flags, VMA_MAYWRITE_BIT);
+
+	/* A driver may not make a previously unwritable mapping writable. */
+	if (WARN_ON_ONCE(!was_maywrite && is_maywrite))
+		return -EINVAL;
+
+	return mmap_validate_vma_flags(curr_flags);
+}
+
+/**
+ * mmap_prepare_validate() - Ensure the driver hasn't violated invariants in its
+ * f_op->mmap_prepare hook.
+ * @prev_desc: The VMA descriptor prior to the mmap_prepare hook being called.
+ * @desc: The VMA descriptor after the mmap_prepare hook has been called.
+ *
+ * Returns: 0 on success, otherwise an error.
+ */
+int mmap_prepare_validate(const struct vm_area_desc *prev_desc,
+			  const struct vm_area_desc *desc)
+{
+	return mmap_validate(prev_desc->start, desc->start,
+			     &prev_desc->vma_flags, &desc->vma_flags);
+}
+
+/**
+ * mmap_hook_validate() - Ensure the driver hasn't violated invariants in
+ * its f_op->mmap hook.
+ * @prev_start: The start of the mapping prior to the mmap hook.
+ * @prev_flags: The VMA flags set for the VMA prior to the mmap hook.
+ * @vma: The VMA after the hook has been applied.
+ *
+ * Returns: 0 on success, otherwise an error.
+ */
+int mmap_hook_validate(unsigned long prev_start,
+		       const vma_flags_t *prev_flags,
+		       const struct vm_area_struct *vma)
+{
+	const unsigned long start = vma->vm_start;
+	const vma_flags_t *flags = &vma->flags;
+
+	return mmap_validate(prev_start, start, prev_flags, flags);
+}
+
 static int call_action_prepare(struct mmap_state *map,
 			       struct vm_area_desc *desc)
 {
@@ -2789,6 +2843,7 @@ static int call_action_prepare(struct mmap_state *map,
 static int call_mmap_prepare(struct mmap_state *map,
 		struct vm_area_desc *desc)
 {
+	const struct vm_area_desc prev_desc = *desc;
 	int err;
 
 	/* Invoke the hook. */
@@ -2800,10 +2855,16 @@ static int call_mmap_prepare(struct mmap_state *map,
 	if (!desc->vm_ops)
 		return -EINVAL;
 
+	/* Perform any preparatory tasks for mmap action. */
 	err = call_action_prepare(map, desc);
 	if (err)
 		return err;
 
+	/* Check the caller did nothing crazy. */
+	err = mmap_prepare_validate(&prev_desc, desc);
+	if (err)
+		return err;
+
 	/* Update fields permitted to be changed. */
 	map->pgoff = desc->pgoff;
 	if (desc->vm_file != map->file) {
@@ -3432,10 +3493,15 @@ int __vm_munmap(unsigned long start, size_t len, bool unlock)
 int insert_vm_struct(struct mm_struct *mm, struct vm_area_struct *vma)
 {
 	unsigned long charged = vma_pages(vma);
+	int err;
 
 	if (find_vma_intersection(mm, vma->vm_start, vma->vm_end))
 		return -ENOMEM;
 
+	err = mmap_validate_vma_flags(&vma->flags);
+	if (err)
+		return err;
+
 	if (vma_test(vma, VMA_ACCOUNT_BIT) &&
 	     security_vm_enough_memory_mm(mm, charged))
 		return -ENOMEM;
diff --git a/mm/vma.h b/mm/vma.h
index e97bd2dfa786..af14ed7265ce 100644
--- a/mm/vma.h
+++ b/mm/vma.h
@@ -780,14 +780,19 @@ struct vm_area_struct *vm_area_alloc(struct mm_struct *mm);
 struct vm_area_struct *vm_area_dup(struct vm_area_struct *orig);
 void vm_area_free(struct vm_area_struct *vma);
 
-/* vma_exec.c */
 #ifdef CONFIG_MMU
+int mmap_prepare_validate(const struct vm_area_desc *prev_desc,
+			  const struct vm_area_desc *desc);
+
+int mmap_hook_validate(unsigned long prev_start,
+		       const vma_flags_t *prev_flags,
+		       const struct vm_area_struct *vma);
+
+/* vma_exec.c */
 int create_init_stack_vma(struct mm_struct *mm, struct vm_area_struct **vmap,
 			  unsigned long *top_mem_p);
 int relocate_vma_down(struct vm_area_struct *vma, unsigned long shift);
-#endif
 
-#ifdef CONFIG_MMU
 /*
  * Denies creating a writable executable mapping or gaining executable permissions.
  *
@@ -836,6 +841,19 @@ static inline bool map_deny_write_exec(const vma_flags_t *old,
 
 	return false;
 }
+#else
+static inline int mmap_prepare_validate(const struct vm_area_desc *prev_desc,
+					const struct vm_area_desc *desc)
+{
+	return 0;
+}
+
+static inline int mmap_hook_validate(unsigned long prev_start,
+				     const vma_flags_t *prev_flags,
+				     const struct vm_area_struct *vma)
+{
+	return 0;
+}
 #endif
 
 struct vm_area_struct *__install_special_mapping(struct mm_struct *mm,
diff --git a/tools/testing/vma/include/dup.h b/tools/testing/vma/include/dup.h
index 2fd422789717..2986ae6ca1e5 100644
--- a/tools/testing/vma/include/dup.h
+++ b/tools/testing/vma/include/dup.h
@@ -1359,13 +1359,23 @@ static inline int vfs_mmap_prepare(struct file *file, struct vm_area_desc *desc)
 	return file->f_op->mmap_prepare(desc);
 }
 
+int mmap_prepare_validate(const struct vm_area_desc *prev_desc,
+			  const struct vm_area_desc *desc);
+
 static inline int __compat_vma_mmap(struct vm_area_desc *desc,
 		struct vm_area_struct *vma)
 {
+	struct vm_area_desc prev_desc;
 	int err;
 
+	/* Derive state prior to mmap_prepare hook. */
+	compat_set_desc_from_vma(&prev_desc, desc->file, vma);
 	/* Perform any preparatory tasks for mmap action. */
 	err = mmap_action_prepare(desc);
+	if (err)
+		return err;
+	/* Check the caller did nothing crazy. */
+	err = mmap_prepare_validate(&prev_desc, desc);
 	if (err)
 		return err;
 	/* Update the VMA from the descriptor. */

-- 
2.55.0


^ permalink raw reply related	[flat|nested] 89+ messages in thread

* [PATCH 04/39] mm/vma: ensure mmap_prepare doesn't set actions on a mergeable vma
  2026-09-08 20:01 [PATCH 00/39] mm: make VMA flag semantics explicit, eliminate VM_SPECIAL Lorenzo Stoakes (ARM)
                   ` (2 preceding siblings ...)
  2026-09-08 20:01 ` [PATCH 03/39] mm: consistently validate VMA state after mmap[_prepare] hooks Lorenzo Stoakes (ARM)
@ 2026-09-08 20:01 ` Lorenzo Stoakes (ARM)
  2026-09-08 20:36   ` sashiko-bot
  2026-09-08 20:01 ` [PATCH 05/39] mm: make map_kernel_pages_[prepare,complete] internal and unexported Lorenzo Stoakes (ARM)
                   ` (34 subsequent siblings)
  38 siblings, 1 reply; 89+ messages in thread
From: Lorenzo Stoakes (ARM) @ 2026-09-08 20:01 UTC (permalink / raw)
  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,
	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, linux-kernel, linux-doc, linux-usb, linux-rdma, selinux,
	linux-sound, bpf, linux-scsi, linux-fbdev, dri-devel,
	linux-trace-kernel, linux-perf-users, linux-arch, linux-fsdevel,
	linux-arm-kernel, kvmarm, linuxppc-dev, kvm, kvm-riscv,
	linux-riscv, linux-s390, sparclinux, fuse-devel,
	Lorenzo Stoakes (ARM)

When a user requests an mmap_action be performed in mmap_prepare, this
involves populating the VMA range with data.

However, if the VMA is mergeable, it might then mistakenly be merged with
another VMA without having populated the range.

Every mmap action currently available sets VMA flags such that the VMA
cannot be merged.

However, to ensure that no future mmap action falls foul of this, assert
that this is the case upon mmap_prepare validation.

Signed-off-by: Lorenzo Stoakes (ARM) <ljs@kernel.org>
---
 mm/vma.c | 9 +++++++++
 1 file changed, 9 insertions(+)

diff --git a/mm/vma.c b/mm/vma.c
index a24f04428580..9e45fc83f74c 100644
--- a/mm/vma.c
+++ b/mm/vma.c
@@ -2794,6 +2794,15 @@ static int mmap_validate(unsigned long prev_start,
 int mmap_prepare_validate(const struct vm_area_desc *prev_desc,
 			  const struct vm_area_desc *desc)
 {
+	/*
+	 * It is not valid to execute mmap actions for VMAs which can be merged,
+	 * as any such merge would leave portions of the mapping incorrectly
+	 * unmapped.
+	 */
+	if (vma_flags_can_merge(&desc->vma_flags) &&
+	    WARN_ON_ONCE(desc->action.type != MMAP_NOTHING))
+		return -EINVAL;
+
 	return mmap_validate(prev_desc->start, desc->start,
 			     &prev_desc->vma_flags, &desc->vma_flags);
 }

-- 
2.55.0


^ permalink raw reply related	[flat|nested] 89+ messages in thread

* [PATCH 05/39] mm: make map_kernel_pages_[prepare,complete] internal and unexported
  2026-09-08 20:01 [PATCH 00/39] mm: make VMA flag semantics explicit, eliminate VM_SPECIAL Lorenzo Stoakes (ARM)
                   ` (3 preceding siblings ...)
  2026-09-08 20:01 ` [PATCH 04/39] mm/vma: ensure mmap_prepare doesn't set actions on a mergeable vma Lorenzo Stoakes (ARM)
@ 2026-09-08 20:01 ` Lorenzo Stoakes (ARM)
  2026-09-08 20:24   ` sashiko-bot
  2026-09-08 20:01 ` [PATCH 06/39] mm/vma: tidy up map kernel pages enum values Lorenzo Stoakes (ARM)
                   ` (33 subsequent siblings)
  38 siblings, 1 reply; 89+ messages in thread
From: Lorenzo Stoakes (ARM) @ 2026-09-08 20:01 UTC (permalink / raw)
  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,
	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, linux-kernel, linux-doc, linux-usb, linux-rdma, selinux,
	linux-sound, bpf, linux-scsi, linux-fbdev, dri-devel,
	linux-trace-kernel, linux-perf-users, linux-arch, linux-fsdevel,
	linux-arm-kernel, kvmarm, linuxppc-dev, kvm, kvm-riscv,
	linux-riscv, linux-s390, sparclinux, fuse-devel,
	Lorenzo Stoakes (ARM)

There's no reason to export the symbols for these functions which are only
called from internal mm logic, additionally there's no reason for them to
be declared in mm.h.

This patch therefore removes the exports and moves the declarations to
mm/internal.h.

No functional change intended.

Signed-off-by: Lorenzo Stoakes (ARM) <ljs@kernel.org>
---
 include/linux/mm.h | 3 ---
 mm/internal.h      | 3 +++
 mm/memory.c        | 2 --
 3 files changed, 3 insertions(+), 5 deletions(-)

diff --git a/include/linux/mm.h b/include/linux/mm.h
index 83979ec28f5c..5709b03b6ed3 100644
--- a/include/linux/mm.h
+++ b/include/linux/mm.h
@@ -4768,9 +4768,6 @@ int remap_pfn_range(struct vm_area_struct *vma, unsigned long addr,
 int vm_insert_page(struct vm_area_struct *, unsigned long addr, struct page *);
 int vm_insert_pages(struct vm_area_struct *vma, unsigned long addr,
 			struct page **pages, unsigned long *num);
-int map_kernel_pages_prepare(struct vm_area_desc *desc);
-int map_kernel_pages_complete(struct vm_area_struct *vma,
-			      struct mmap_action *action);
 int vm_map_pages(struct vm_area_struct *vma, struct page **pages,
 				unsigned long num);
 int vm_map_pages_zero(struct vm_area_struct *vma, struct page **pages,
diff --git a/mm/internal.h b/mm/internal.h
index abb0fae8c637..fe93be1cea32 100644
--- a/mm/internal.h
+++ b/mm/internal.h
@@ -1517,6 +1517,9 @@ int remap_pfn_range_prepare(struct vm_area_desc *desc);
 int remap_pfn_range_complete(struct vm_area_struct *vma,
 			     struct mmap_action *action);
 int simple_ioremap_prepare(struct vm_area_desc *desc);
+int map_kernel_pages_prepare(struct vm_area_desc *desc);
+int map_kernel_pages_complete(struct vm_area_struct *vma,
+			      struct mmap_action *action);
 
 static inline int io_remap_pfn_range_prepare(struct vm_area_desc *desc)
 {
diff --git a/mm/memory.c b/mm/memory.c
index ec63dd6212ac..dc38cad1dcb7 100644
--- a/mm/memory.c
+++ b/mm/memory.c
@@ -2628,7 +2628,6 @@ int map_kernel_pages_prepare(struct vm_area_desc *desc)
 
 	return 0;
 }
-EXPORT_SYMBOL(map_kernel_pages_prepare);
 
 int map_kernel_pages_complete(struct vm_area_struct *vma,
 			      struct mmap_action *action)
@@ -2640,7 +2639,6 @@ int map_kernel_pages_complete(struct vm_area_struct *vma,
 			    action->map_kernel.pages,
 			    &nr_pages, vma->vm_page_prot);
 }
-EXPORT_SYMBOL(map_kernel_pages_complete);
 
 /**
  * vm_insert_page - insert single page into user vma

-- 
2.55.0


^ permalink raw reply related	[flat|nested] 89+ messages in thread

* [PATCH 06/39] mm/vma: tidy up map kernel pages enum values
  2026-09-08 20:01 [PATCH 00/39] mm: make VMA flag semantics explicit, eliminate VM_SPECIAL Lorenzo Stoakes (ARM)
                   ` (4 preceding siblings ...)
  2026-09-08 20:01 ` [PATCH 05/39] mm: make map_kernel_pages_[prepare,complete] internal and unexported Lorenzo Stoakes (ARM)
@ 2026-09-08 20:01 ` Lorenzo Stoakes (ARM)
  2026-09-08 20:27   ` sashiko-bot
  2026-09-08 20:01 ` [PATCH 07/39] mm: add mmap action for discontiguous kernel page mapping Lorenzo Stoakes (ARM)
                   ` (32 subsequent siblings)
  38 siblings, 1 reply; 89+ messages in thread
From: Lorenzo Stoakes (ARM) @ 2026-09-08 20:01 UTC (permalink / raw)
  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,
	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, linux-kernel, linux-doc, linux-usb, linux-rdma, selinux,
	linux-sound, bpf, linux-scsi, linux-fbdev, dri-devel,
	linux-trace-kernel, linux-perf-users, linux-arch, linux-fsdevel,
	linux-arm-kernel, kvmarm, linuxppc-dev, kvm, kvm-riscv,
	linux-riscv, linux-s390, sparclinux, fuse-devel,
	Lorenzo Stoakes (ARM)

MMAP_MAP_KERNEL_PAGES is a mouthful, discard the MAP_ as that's implied by
MMAP.

Also while we're here delete useless comments for mmap actions whose names
clearly indicate what they are for.

Also update the userland VMA tests to reflect this change.

No functional change intended.

Signed-off-by: Lorenzo Stoakes (ARM) <ljs@kernel.org>
---
 include/linux/mm.h              | 2 +-
 include/linux/mm_types.h        | 8 ++++----
 mm/util.c                       | 8 ++++----
 tools/testing/vma/include/dup.h | 8 ++++----
 4 files changed, 13 insertions(+), 13 deletions(-)

diff --git a/include/linux/mm.h b/include/linux/mm.h
index 5709b03b6ed3..94b860b8c50a 100644
--- a/include/linux/mm.h
+++ b/include/linux/mm.h
@@ -4623,7 +4623,7 @@ static inline void mmap_action_map_kernel_pages(struct vm_area_desc *desc,
 {
 	struct mmap_action *action = &desc->action;
 
-	action->type = MMAP_MAP_KERNEL_PAGES;
+	action->type = MMAP_KERNEL_PAGES;
 	action->map_kernel.start = start;
 	action->map_kernel.pages = pages;
 	action->map_kernel.nr_pages = nr_pages;
diff --git a/include/linux/mm_types.h b/include/linux/mm_types.h
index 5413bd10fff2..9ca2ea3664bc 100644
--- a/include/linux/mm_types.h
+++ b/include/linux/mm_types.h
@@ -815,11 +815,11 @@ struct pfnmap_track_ctx {
 
 /* What action should be taken after an .mmap_prepare call is complete? */
 enum mmap_action_type {
-	MMAP_NOTHING,		/* Mapping is complete, no further action. */
-	MMAP_REMAP_PFN,		/* Remap PFN range. */
-	MMAP_IO_REMAP_PFN,	/* I/O remap PFN range. */
+	MMAP_NOTHING,
+	MMAP_REMAP_PFN,
+	MMAP_IO_REMAP_PFN,
 	MMAP_SIMPLE_IO_REMAP,	/* I/O remap with guardrails. */
-	MMAP_MAP_KERNEL_PAGES,	/* Map kernel page range from array. */
+	MMAP_KERNEL_PAGES,	/* Map kernel page range from array. */
 };
 
 /*
diff --git a/mm/util.c b/mm/util.c
index a3cef493ed70..b6f1bec9da15 100644
--- a/mm/util.c
+++ b/mm/util.c
@@ -1462,7 +1462,7 @@ int mmap_action_prepare(struct vm_area_desc *desc)
 		return io_remap_pfn_range_prepare(desc);
 	case MMAP_SIMPLE_IO_REMAP:
 		return simple_ioremap_prepare(desc);
-	case MMAP_MAP_KERNEL_PAGES:
+	case MMAP_KERNEL_PAGES:
 		return map_kernel_pages_prepare(desc);
 	}
 
@@ -1493,7 +1493,7 @@ int mmap_action_complete(struct vm_area_struct *vma,
 	case MMAP_REMAP_PFN:
 		err = remap_pfn_range_complete(vma, action);
 		break;
-	case MMAP_MAP_KERNEL_PAGES:
+	case MMAP_KERNEL_PAGES:
 		err = map_kernel_pages_complete(vma, action);
 		break;
 	case MMAP_IO_REMAP_PFN:
@@ -1516,7 +1516,7 @@ int mmap_action_prepare(struct vm_area_desc *desc)
 	case MMAP_REMAP_PFN:
 	case MMAP_IO_REMAP_PFN:
 	case MMAP_SIMPLE_IO_REMAP:
-	case MMAP_MAP_KERNEL_PAGES:
+	case MMAP_KERNEL_PAGES:
 		WARN_ON_ONCE(1); /* nommu cannot handle these. */
 		break;
 	}
@@ -1537,7 +1537,7 @@ int mmap_action_complete(struct vm_area_struct *vma,
 	case MMAP_REMAP_PFN:
 	case MMAP_IO_REMAP_PFN:
 	case MMAP_SIMPLE_IO_REMAP:
-	case MMAP_MAP_KERNEL_PAGES:
+	case MMAP_KERNEL_PAGES:
 		WARN_ON_ONCE(1); /* nommu cannot handle this. */
 
 		err = -EINVAL;
diff --git a/tools/testing/vma/include/dup.h b/tools/testing/vma/include/dup.h
index 2986ae6ca1e5..1098655a5f4a 100644
--- a/tools/testing/vma/include/dup.h
+++ b/tools/testing/vma/include/dup.h
@@ -454,11 +454,11 @@ static __always_inline bool vma_flags_empty(const vma_flags_t *flags)
 
 /* What action should be taken after an .mmap_prepare call is complete? */
 enum mmap_action_type {
-	MMAP_NOTHING,		/* Mapping is complete, no further action. */
-	MMAP_REMAP_PFN,		/* Remap PFN range. */
-	MMAP_IO_REMAP_PFN,	/* I/O remap PFN range. */
+	MMAP_NOTHING,
+	MMAP_REMAP_PFN,
+	MMAP_IO_REMAP_PFN,
 	MMAP_SIMPLE_IO_REMAP,	/* I/O remap with guardrails. */
-	MMAP_MAP_KERNEL_PAGES,	/* Map kernel page range from an array. */
+	MMAP_KERNEL_PAGES,	/* Map kernel page range from array. */
 };
 
 /*

-- 
2.55.0


^ permalink raw reply related	[flat|nested] 89+ messages in thread

* [PATCH 07/39] mm: add mmap action for discontiguous kernel page mapping
  2026-09-08 20:01 [PATCH 00/39] mm: make VMA flag semantics explicit, eliminate VM_SPECIAL Lorenzo Stoakes (ARM)
                   ` (5 preceding siblings ...)
  2026-09-08 20:01 ` [PATCH 06/39] mm/vma: tidy up map kernel pages enum values Lorenzo Stoakes (ARM)
@ 2026-09-08 20:01 ` Lorenzo Stoakes (ARM)
  2026-09-08 20:34   ` sashiko-bot
  2026-09-08 20:01 ` [PATCH 08/39] docs: filesystems: update mmap_prepare docs for discontig kernel pgs Lorenzo Stoakes (ARM)
                   ` (31 subsequent siblings)
  38 siblings, 1 reply; 89+ messages in thread
From: Lorenzo Stoakes (ARM) @ 2026-09-08 20:01 UTC (permalink / raw)
  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,
	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, linux-kernel, linux-doc, linux-usb, linux-rdma, selinux,
	linux-sound, bpf, linux-scsi, linux-fbdev, dri-devel,
	linux-trace-kernel, linux-perf-users, linux-arch, linux-fsdevel,
	linux-arm-kernel, kvmarm, linuxppc-dev, kvm, kvm-riscv,
	linux-riscv, linux-s390, sparclinux, fuse-devel,
	Lorenzo Stoakes (ARM)

The existing kernel page mapping mmap actions allow for partial and full
mapping of an array of struct page pointers.

However some drivers require the mapping of discontiguous ranges. Permit
this by providing discontig_kernel_page_ops which allows a driver to
specify how the operation should begin and how batches of pages should be
retrieved.

It uses the minimum exposed interface to do so, providing address, page
offset and both vm_private_data state and a local private state object.

ops->init can establish state for the operation, and ops->get outputs the
pages to map and their count. Should an error arise the core unmaps the
VMA, invoking vm_ops->close, which is therefore where any state established
by ops->init is released.

The code carefully checks to ensure the user doesn't exceed VMA bounds. It
intentionally allows mapping of less than the VMA range in case the driver
wishes to allow the user to map an area larger than available data.

To use it, users invoke mmap_action_map_discontig_kernel_pages() with
initial local private state and a set of operations.

Users can then use one of the provided helper functions to perform an
action:

* discontig_kernel_map_abort() - Abort and leave the mapping as it has
  been accumulated so far.
* discontig_kernel_map_page() - Map a single page, or a compound page given
  its head page.
* discontig_kernel_map_page_range() - Maps a struct page ** array of a
  specified count.

The enum copy in the userland VMA tests is updated accordingly.

Signed-off-by: Lorenzo Stoakes (ARM) <ljs@kernel.org>
---
 include/linux/mm.h              |  45 +++++++++++++++++
 include/linux/mm_types.h        |  44 +++++++++++++++-
 mm/internal.h                   |   3 ++
 mm/memory.c                     | 108 ++++++++++++++++++++++++++++++++++++++--
 mm/util.c                       |   7 +++
 tools/testing/vma/include/dup.h |   5 +-
 6 files changed, 203 insertions(+), 9 deletions(-)

diff --git a/include/linux/mm.h b/include/linux/mm.h
index 94b860b8c50a..4604cd011ca4 100644
--- a/include/linux/mm.h
+++ b/include/linux/mm.h
@@ -4647,10 +4647,55 @@ static inline void mmap_action_map_kernel_pages_full(struct vm_area_desc *desc,
 				     vma_desc_pages(desc));
 }
 
+static inline
+void mmap_action_map_discontig_kernel_pages(struct vm_area_desc *desc,
+		void *init_private, const struct discontig_kernel_page_ops *ops)
+{
+	struct mmap_action *action = &desc->action;
+
+	action->type = MMAP_DISCONTIG_KERNEL_PAGES;
+	action->map_kernel_discontig.init_private = init_private;
+	action->map_kernel_discontig.ops = ops;
+}
+
 int mmap_action_prepare(struct vm_area_desc *desc);
 int mmap_action_complete(struct vm_area_struct *vma,
 			 struct mmap_action *action, bool is_compat);
 
+static inline void
+discontig_kernel_map_abort(struct discontig_kernel_page_state *state)
+{
+	state->action = DISCONTIG_KERNEL_PAGE_ABORT;
+}
+
+static inline void
+discontig_kernel_map_page(struct discontig_kernel_page_state *state,
+			  struct page *page)
+{
+	struct folio *folio = page_folio(page);
+
+	if (folio_test_large(folio)) {
+		VM_WARN_ON_ONCE(page != folio_page(folio, 0));
+		state->action = DISCONTIG_KERNEL_PAGE_MAP_COMPOUND_PAGE;
+		state->__folio = folio;
+		state->__nr_pages = min(state->nr_pages_remain,
+					folio_nr_pages(folio));
+	} else {
+		state->action = DISCONTIG_KERNEL_PAGE_MAP_PAGE;
+		state->__page = page;
+		state->__nr_pages = 1;
+	}
+}
+
+static inline void
+discontig_kernel_map_page_range(struct discontig_kernel_page_state *state,
+				struct page **page_arr, unsigned long nr_pages)
+{
+	state->action = DISCONTIG_KERNEL_PAGE_MAP_PAGE_RANGE;
+	state->__page_arr = page_arr;
+	state->__nr_pages = nr_pages;
+}
+
 /* Look up the first VMA which exactly match the interval vm_start ... vm_end */
 static inline struct vm_area_struct *find_exact_vma(struct mm_struct *mm,
 				unsigned long vm_start, unsigned long vm_end)
diff --git a/include/linux/mm_types.h b/include/linux/mm_types.h
index 9ca2ea3664bc..0cb4f9603956 100644
--- a/include/linux/mm_types.h
+++ b/include/linux/mm_types.h
@@ -818,8 +818,44 @@ enum mmap_action_type {
 	MMAP_NOTHING,
 	MMAP_REMAP_PFN,
 	MMAP_IO_REMAP_PFN,
-	MMAP_SIMPLE_IO_REMAP,	/* I/O remap with guardrails. */
-	MMAP_KERNEL_PAGES,	/* Map kernel page range from array. */
+	MMAP_SIMPLE_IO_REMAP,		/* I/O remap with guardrails. */
+	MMAP_KERNEL_PAGES,		/* Map kernel page range from array. */
+	MMAP_DISCONTIG_KERNEL_PAGES,	/* Map kernel discontig page range. */
+};
+
+enum discontig_kernel_page_action {
+	DISCONTIG_KERNEL_PAGE_ABORT,
+	DISCONTIG_KERNEL_PAGE_MAP_PAGE,
+	DISCONTIG_KERNEL_PAGE_MAP_COMPOUND_PAGE,
+	DISCONTIG_KERNEL_PAGE_MAP_PAGE_RANGE,
+};
+
+struct discontig_kernel_page_state {
+	/* Map state. */
+	const unsigned long start;	/* Start address of VMA. */
+	const unsigned long end;	/* End address of VMA. */
+	unsigned long addr;		/* The current address to be mapped. */
+	pgoff_t pgoff;			/* The current pgoff to be mapped. */
+	unsigned long nr_pages_mapped;	/* The number of pages mapped. */
+	unsigned long nr_pages_remain;	/* The number of pages remaining. */
+
+	/* User-defined state. */
+	void *vm_private_data;		/* VMA private data. */
+	void *private;			/* Mapping private data. */
+
+	/* Users should not touch these, use discontig_kernel_map_*() helpers. */
+	enum discontig_kernel_page_action action;
+	union {
+		struct page *__page;
+		struct folio *__folio;
+		struct page **__page_arr;
+	};
+	unsigned long __nr_pages;
+};
+
+struct discontig_kernel_page_ops {
+	int (*init)(void *vm_private_data, void **private);
+	int (*get)(struct discontig_kernel_page_state *state);
 };
 
 /*
@@ -844,6 +880,10 @@ struct mmap_action {
 			unsigned long nr_pages;
 			pgoff_t pgoff;
 		} map_kernel;
+		struct {
+			void *init_private;
+			const struct discontig_kernel_page_ops *ops;
+		} map_kernel_discontig;
 	};
 	enum mmap_action_type type;
 
diff --git a/mm/internal.h b/mm/internal.h
index fe93be1cea32..a86b9803a4c3 100644
--- a/mm/internal.h
+++ b/mm/internal.h
@@ -1520,6 +1520,9 @@ int simple_ioremap_prepare(struct vm_area_desc *desc);
 int map_kernel_pages_prepare(struct vm_area_desc *desc);
 int map_kernel_pages_complete(struct vm_area_struct *vma,
 			      struct mmap_action *action);
+int map_discontig_kernel_pages_prepare(struct vm_area_desc *desc);
+int map_discontig_kernel_pages_complete(struct vm_area_struct *vma,
+					struct mmap_action *action);
 
 static inline int io_remap_pfn_range_prepare(struct vm_area_desc *desc)
 {
diff --git a/mm/memory.c b/mm/memory.c
index dc38cad1dcb7..8c9675451d4b 100644
--- a/mm/memory.c
+++ b/mm/memory.c
@@ -2609,17 +2609,23 @@ int vm_insert_pages(struct vm_area_struct *vma, unsigned long addr,
 }
 EXPORT_SYMBOL(vm_insert_pages);
 
+static void __map_kernel_pages_prepare(struct vm_area_desc *desc)
+{
+	if (vma_desc_test(desc, VMA_MIXEDMAP_BIT))
+		return;
+
+	VM_WARN_ON_ONCE(mmap_read_trylock(desc->mm));
+	VM_WARN_ON_ONCE(vma_desc_test(desc, VMA_PFNMAP_BIT));
+	vma_desc_set_flags(desc, VMA_MIXEDMAP_BIT);
+}
+
 int map_kernel_pages_prepare(struct vm_area_desc *desc)
 {
 	const struct mmap_action *action = &desc->action;
 	const unsigned long addr = action->map_kernel.start;
 	unsigned long nr_pages, end;
 
-	if (!vma_desc_test(desc, VMA_MIXEDMAP_BIT)) {
-		VM_WARN_ON_ONCE(mmap_read_trylock(desc->mm));
-		VM_WARN_ON_ONCE(vma_desc_test(desc, VMA_PFNMAP_BIT));
-		vma_desc_set_flags(desc, VMA_MIXEDMAP_BIT);
-	}
+	__map_kernel_pages_prepare(desc);
 
 	nr_pages = action->map_kernel.nr_pages;
 	end = addr + PAGE_SIZE * nr_pages;
@@ -2640,6 +2646,98 @@ int map_kernel_pages_complete(struct vm_area_struct *vma,
 			    &nr_pages, vma->vm_page_prot);
 }
 
+int map_discontig_kernel_pages_prepare(struct vm_area_desc *desc)
+{
+	const struct mmap_action *action = &desc->action;
+	const struct discontig_kernel_page_ops *ops =
+		action->map_kernel_discontig.ops;
+
+	/* At minimum need to be able to get pages. */
+	if (WARN_ON_ONCE(!ops->get))
+		return -EINVAL;
+
+	__map_kernel_pages_prepare(desc);
+	return 0;
+}
+
+static int apply_discontig_action(struct vm_area_struct *vma,
+				  struct discontig_kernel_page_state *state)
+{
+	unsigned long nr_pages = state->__nr_pages;
+	unsigned long addr = state->addr;
+	unsigned long i;
+
+	if (state->action == DISCONTIG_KERNEL_PAGE_MAP_PAGE)
+		return insert_page(vma, addr, state->__page,
+				   vma->vm_page_prot, /*mkwrite=*/false);
+	if (state->action == DISCONTIG_KERNEL_PAGE_MAP_PAGE_RANGE)
+		return insert_pages(vma, addr, state->__page_arr,
+				    &nr_pages, vma->vm_page_prot);
+
+	/* Compound folio - have to iterate through each page. */
+	for (i = 0; i < nr_pages; i++, addr += PAGE_SIZE) {
+		struct page *page = folio_page(state->__folio, i);
+		int err;
+
+		err = insert_page(vma, addr, page, vma->vm_page_prot,
+				  /*mkwrite=*/false);
+		if (err)
+			return err;
+	}
+	return 0;
+}
+
+int map_discontig_kernel_pages_complete(struct vm_area_struct *vma,
+					struct mmap_action *action)
+{
+	const struct discontig_kernel_page_ops *ops =
+		action->map_kernel_discontig.ops;
+	struct discontig_kernel_page_state state = {
+		.start = vma->vm_start,
+		.end = vma->vm_end,
+		.addr = vma->vm_start,
+		.pgoff = vma->vm_pgoff,
+		.nr_pages_mapped = 0,
+		.nr_pages_remain = vma_pages(vma),
+		.vm_private_data = vma->vm_private_data,
+		.private = action->map_kernel_discontig.init_private,
+	};
+	int err = 0;
+
+	if (ops->init)
+		err = ops->init(vma->vm_private_data, &state.private);
+	if (err)
+		return err;
+
+	do {
+		unsigned long end, pgoff_end;
+		unsigned long nr_pages;
+
+		/* Default to abort. */
+		state.action = DISCONTIG_KERNEL_PAGE_ABORT;
+		err = ops->get(&state);
+		if (err || state.action == DISCONTIG_KERNEL_PAGE_ABORT)
+			return err;
+		nr_pages = state.__nr_pages;
+
+		end = state.addr + PAGE_SIZE * nr_pages;
+		if (end > vma->vm_end)
+			return -EINVAL;
+		pgoff_end = state.pgoff + nr_pages;
+
+		err = apply_discontig_action(vma, &state);
+		if (err)
+			return err;
+
+		state.addr = end;
+		state.pgoff = pgoff_end;
+		state.nr_pages_mapped += nr_pages;
+		state.nr_pages_remain -= nr_pages;
+	} while (state.addr < vma->vm_end);
+
+	return 0;
+}
+
 /**
  * vm_insert_page - insert single page into user vma
  * @vma: user vma to map to
diff --git a/mm/util.c b/mm/util.c
index b6f1bec9da15..5a1916d8fdc1 100644
--- a/mm/util.c
+++ b/mm/util.c
@@ -1464,6 +1464,8 @@ int mmap_action_prepare(struct vm_area_desc *desc)
 		return simple_ioremap_prepare(desc);
 	case MMAP_KERNEL_PAGES:
 		return map_kernel_pages_prepare(desc);
+	case MMAP_DISCONTIG_KERNEL_PAGES:
+		return map_discontig_kernel_pages_prepare(desc);
 	}
 
 	WARN_ON_ONCE(1);
@@ -1496,6 +1498,9 @@ int mmap_action_complete(struct vm_area_struct *vma,
 	case MMAP_KERNEL_PAGES:
 		err = map_kernel_pages_complete(vma, action);
 		break;
+	case MMAP_DISCONTIG_KERNEL_PAGES:
+		err = map_discontig_kernel_pages_complete(vma, action);
+		break;
 	case MMAP_IO_REMAP_PFN:
 	case MMAP_SIMPLE_IO_REMAP:
 		/* Should have been delegated. */
@@ -1517,6 +1522,7 @@ int mmap_action_prepare(struct vm_area_desc *desc)
 	case MMAP_IO_REMAP_PFN:
 	case MMAP_SIMPLE_IO_REMAP:
 	case MMAP_KERNEL_PAGES:
+	case MMAP_DISCONTIG_KERNEL_PAGES:
 		WARN_ON_ONCE(1); /* nommu cannot handle these. */
 		break;
 	}
@@ -1538,6 +1544,7 @@ int mmap_action_complete(struct vm_area_struct *vma,
 	case MMAP_IO_REMAP_PFN:
 	case MMAP_SIMPLE_IO_REMAP:
 	case MMAP_KERNEL_PAGES:
+	case MMAP_DISCONTIG_KERNEL_PAGES:
 		WARN_ON_ONCE(1); /* nommu cannot handle this. */
 
 		err = -EINVAL;
diff --git a/tools/testing/vma/include/dup.h b/tools/testing/vma/include/dup.h
index 1098655a5f4a..52eee05e6c32 100644
--- a/tools/testing/vma/include/dup.h
+++ b/tools/testing/vma/include/dup.h
@@ -457,8 +457,9 @@ enum mmap_action_type {
 	MMAP_NOTHING,
 	MMAP_REMAP_PFN,
 	MMAP_IO_REMAP_PFN,
-	MMAP_SIMPLE_IO_REMAP,	/* I/O remap with guardrails. */
-	MMAP_KERNEL_PAGES,	/* Map kernel page range from array. */
+	MMAP_SIMPLE_IO_REMAP,		/* I/O remap with guardrails. */
+	MMAP_KERNEL_PAGES,		/* Map kernel page range from array. */
+	MMAP_DISCONTIG_KERNEL_PAGES,	/* Map kernel discontig page range. */
 };
 
 /*

-- 
2.55.0


^ permalink raw reply related	[flat|nested] 89+ messages in thread

* [PATCH 08/39] docs: filesystems: update mmap_prepare docs for discontig kernel pgs
  2026-09-08 20:01 [PATCH 00/39] mm: make VMA flag semantics explicit, eliminate VM_SPECIAL Lorenzo Stoakes (ARM)
                   ` (6 preceding siblings ...)
  2026-09-08 20:01 ` [PATCH 07/39] mm: add mmap action for discontiguous kernel page mapping Lorenzo Stoakes (ARM)
@ 2026-09-08 20:01 ` Lorenzo Stoakes (ARM)
  2026-09-08 20:38   ` sashiko-bot
  2026-09-08 20:01 ` [PATCH 09/39] drivers/usb/mon: update to use mmap_prepare + map kernel pages Lorenzo Stoakes (ARM)
                   ` (30 subsequent siblings)
  38 siblings, 1 reply; 89+ messages in thread
From: Lorenzo Stoakes (ARM) @ 2026-09-08 20:01 UTC (permalink / raw)
  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,
	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, linux-kernel, linux-doc, linux-usb, linux-rdma, selinux,
	linux-sound, bpf, linux-scsi, linux-fbdev, dri-devel,
	linux-trace-kernel, linux-perf-users, linux-arch, linux-fsdevel,
	linux-arm-kernel, kvmarm, linuxppc-dev, kvm, kvm-riscv,
	linux-riscv, linux-s390, sparclinux, fuse-devel,
	Lorenzo Stoakes (ARM)

Describe the newly introduced discontiguous kernel page mapping mechanism,
detailing how to use it sensibly and how the API looks.

Explicitly detail the various discontiguous actions available and how to
use them.

Signed-off-by: Lorenzo Stoakes (ARM) <ljs@kernel.org>
---
 Documentation/filesystems/mmap_prepare.rst | 81 ++++++++++++++++++++++++++++++
 1 file changed, 81 insertions(+)

diff --git a/Documentation/filesystems/mmap_prepare.rst b/Documentation/filesystems/mmap_prepare.rst
index 82c99c95ad85..a476e1006bf1 100644
--- a/Documentation/filesystems/mmap_prepare.rst
+++ b/Documentation/filesystems/mmap_prepare.rst
@@ -164,5 +164,86 @@ pointer. These are:
   sufficient entries in the page array to cover the entire range of the
   described VMA.
 
+* mmap_action_map_discontig_kernel_pages() - Maps a discontiguous range of
+  `struct page` pointers over the VMA. They must span from the start of the VMA,
+  but may terminate prior to the end (leaving the remainder unmapped).
+
 **NOTE:** The ``action`` field should never normally be manipulated directly,
 rather you ought to use one of these helpers.
+
+Discontiguous Actions
+=====================
+
+Some actions can be performed across discontiguous ranges.
+
+Map kernel pages
+----------------
+
+To map kernel pages discontiguously, you must provide hooks using ``struct
+discontig_kernel_page_ops``:
+
+.. code-block:: C
+
+    struct discontig_kernel_page_ops {
+        int (*init)(void *vm_private_data, void **private);
+        int (*get)(struct discontig_kernel_page_state *state);
+    };
+
+The ``init`` hook is optional and allows state to be established before the
+operation starts, for instance taking a reference count. Nothing is invoked
+after the operation, so ``init`` must not leave locks held, and state that must
+be released once the mapping goes away should be released in
+``vm_ops->close``.
+
+The ``init`` hook, if provided, is invoked prior to the operation starting. It
+may update what is pointed to by ``vm_private_data`` and/or ``private``. If an
+error is returned, then the operation is aborted. The ``private`` field can be
+reassigned.
+
+**NOTE:** The operation may sleep between invocations of ``get``, so locks
+needed to stabilise state must be taken and released within each hook.
+
+The ``get`` handler is the key means through which the operation is
+executed. The current state of the operation is provided through ``struct
+discontig_kernel_page_state``:
+
+.. code-block:: C
+
+    struct discontig_kernel_page_state {
+        /* Map state. */
+        unsigned long start;            /* Start address of VMA. */
+        unsigned long end;              /* End address of VMA. */
+        unsigned long addr;             /* The current address to be mapped. */
+        pgoff_t pgoff;                  /* The current pgoff to be mapped. */
+        unsigned long nr_pages_mapped;  /* The number of pages mapped. */
+        unsigned long nr_pages_remain;  /* The number of pages remaining. */
+
+        /* User-defined state. */
+        void *vm_private_data;          /* VMA private data. */
+        void *private;                  /* Mapping private data. */
+
+        /* Users should not touch these, use discontig_kernel_map_*() helpers. */
+        ... internal fields ...
+    };
+
+With ``private`` being an additional user-controllable state variable,
+initialised via ``mmap_action_map_discontig_kernel_pages()``, and
+``vm_private_data`` being equal to the ``desc->private_data`` field set in
+the ``mmap_prepare()`` hook.
+
+In the ``get`` hook, the user must choose how to map kernel pages:
+
+* ``discontig_kernel_map_abort()`` - Call this to abort the operation, whatever
+  has been mapped so far will be retained, the rest of the mapping will SIGBUS
+  if accessed.
+* ``discontig_kernel_map_page()`` - Maps a single page, correctly handling
+  compound pages (if the compound page is bigger than the remaining pages in the
+  VMA, then only those pages that fit will be mapped). For a compound page, the
+  head page must be passed.
+* ``discontig_kernel_map_page_range()`` - Map an array of pages of a specified
+  size. Note that if the number of pages specified exceeds the VMA size then an
+  error will arise.
+
+If an error arises after ``init`` succeeded, the core unmaps the VMA, invoking
+``vm_ops->close`` if set, which is therefore the place to release any state
+that ``init`` established.

-- 
2.55.0


^ permalink raw reply related	[flat|nested] 89+ messages in thread

* [PATCH 09/39] drivers/usb/mon: update to use mmap_prepare + map kernel pages
  2026-09-08 20:01 [PATCH 00/39] mm: make VMA flag semantics explicit, eliminate VM_SPECIAL Lorenzo Stoakes (ARM)
                   ` (7 preceding siblings ...)
  2026-09-08 20:01 ` [PATCH 08/39] docs: filesystems: update mmap_prepare docs for discontig kernel pgs Lorenzo Stoakes (ARM)
@ 2026-09-08 20:01 ` Lorenzo Stoakes (ARM)
  2026-09-08 20:35   ` sashiko-bot
  2026-09-09  7:37   ` Greg Kroah-Hartman
  2026-09-08 20:01 ` [PATCH 10/39] infiniband: update hfi1 to use remap_vmalloc_range() Lorenzo Stoakes (ARM)
                   ` (29 subsequent siblings)
  38 siblings, 2 replies; 89+ messages in thread
From: Lorenzo Stoakes (ARM) @ 2026-09-08 20:01 UTC (permalink / raw)
  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,
	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, linux-kernel, linux-doc, linux-usb, linux-rdma, selinux,
	linux-sound, bpf, linux-scsi, linux-fbdev, dri-devel,
	linux-trace-kernel, linux-perf-users, linux-arch, linux-fsdevel,
	linux-arm-kernel, kvmarm, linuxppc-dev, kvm, kvm-riscv,
	linux-riscv, linux-s390, sparclinux, fuse-devel,
	Lorenzo Stoakes (ARM)

Replace the deprecated .mmap hook with its replacement .mmap_prepare. As
part of this change, additionally take the approach of mapping pages upon
mmap rather than providing a fault handler.

The page span cannot be mutated when an mmap mapping is in place, so this
is safe to do in advance (the MON_IOCT_RING_SIZE ioctl operation exits
-EBUSY if it's attempted, gated by the rp->mmap_active reference count).

Utilise the newly introduced mmap_action_map_discontig_kernel_pages() to do
this, which allows for iteration over pages in mon_bin_discontig_get().

mon_bin_discontig_init() increments the rp->mmap_active reference count to
stabilise page spans. Should an error arise the core unmaps the VMA and
mon_bin_vma_close() drops the reference again.

The vm_ops->close hook implemented in mon_bin_vma_close() will ensure
correct reference count arithmetic upon unmap (with mon_bin_vma_open()
accounting for splitting).

The existing semantics are all retained, including not mapping past the
range of available pages, with a SIGBUS being raised in a userland process
that attempts to access past this point.

Ultimately insert_page() is invoked to insert each page, which increments
the reference count on each mapped page. This mimics what was being done
previously, only we pre-map the entire range rather than doing so on
demand.

The existing fault handler did nothing that required demand paging, and was
presumably implemented this way due for historic reasons.

One behavioural difference: pages are no longer faulted in on demand, so a
page discarded with MADV_DONTNEED is not repopulated and a subsequent
access raises SIGBUS, as with other pre-populated kernel mappings.

Signed-off-by: Lorenzo Stoakes (ARM) <ljs@kernel.org>
---
 drivers/usb/mon/mon_bin.c | 82 ++++++++++++++++++++++++++++++-----------------
 1 file changed, 53 insertions(+), 29 deletions(-)

diff --git a/drivers/usb/mon/mon_bin.c b/drivers/usb/mon/mon_bin.c
index 687f6a8981f3..9d00b21a8153 100644
--- a/drivers/usb/mon/mon_bin.c
+++ b/drivers/usb/mon/mon_bin.c
@@ -1219,6 +1219,15 @@ mon_bin_poll(struct file *file, struct poll_table_struct *wait)
 	return mask;
 }
 
+static void __mon_bin_vma_open(struct mon_reader_bin *rp)
+{
+	unsigned long flags;
+
+	spin_lock_irqsave(&rp->b_lock, flags);
+	rp->mmap_active++;
+	spin_unlock_irqrestore(&rp->b_lock, flags);
+}
+
 /*
  * open and close: just keep track of how many times the device is
  * mapped, to use the proper memory allocation function.
@@ -1226,64 +1235,79 @@ mon_bin_poll(struct file *file, struct poll_table_struct *wait)
 static void mon_bin_vma_open(struct vm_area_struct *vma)
 {
 	struct mon_reader_bin *rp = vma->vm_private_data;
-	unsigned long flags;
 
-	spin_lock_irqsave(&rp->b_lock, flags);
-	rp->mmap_active++;
-	spin_unlock_irqrestore(&rp->b_lock, flags);
+	__mon_bin_vma_open(rp);
 }
 
-static void mon_bin_vma_close(struct vm_area_struct *vma)
+static void __mon_bin_vma_close(struct mon_reader_bin *rp)
 {
 	unsigned long flags;
 
-	struct mon_reader_bin *rp = vma->vm_private_data;
 	spin_lock_irqsave(&rp->b_lock, flags);
 	rp->mmap_active--;
 	spin_unlock_irqrestore(&rp->b_lock, flags);
 }
 
-/*
- * Map ring pages to user space.
- */
-static vm_fault_t mon_bin_vma_fault(struct vm_fault *vmf)
+static void mon_bin_vma_close(struct vm_area_struct *vma)
 {
-	struct mon_reader_bin *rp = vmf->vma->vm_private_data;
+	struct mon_reader_bin *rp = vma->vm_private_data;
+
+	__mon_bin_vma_close(rp);
+}
+
+static const struct vm_operations_struct mon_bin_vm_ops = {
+	.open =     mon_bin_vma_open,
+	.close =    mon_bin_vma_close,
+};
+
+static int mon_bin_discontig_init(void *vm_private_data, void **private)
+{
+	struct mon_reader_bin *rp = vm_private_data;
+
+	/* Dropped by mon_bin_vma_close() on unmap, including on error. */
+	__mon_bin_vma_open(rp);
+	return 0;
+}
+
+static int mon_bin_discontig_get(struct discontig_kernel_page_state *state)
+{
+	struct mon_reader_bin *rp = state->vm_private_data;
 	unsigned long offset, chunk_idx;
-	struct page *pageptr;
 	unsigned long flags;
 
 	spin_lock_irqsave(&rp->b_lock, flags);
-	offset = vmf->pgoff << PAGE_SHIFT;
+
+	offset = state->pgoff << PAGE_SHIFT;
 	if (offset >= rp->b_size) {
 		spin_unlock_irqrestore(&rp->b_lock, flags);
-		return VM_FAULT_SIGBUS;
+		discontig_kernel_map_abort(state);
+		return 0;
 	}
 	chunk_idx = offset / CHUNK_SIZE;
-	pageptr = rp->b_vec[chunk_idx].pg;
-	get_page(pageptr);
-	vmf->page = pageptr;
+	discontig_kernel_map_page(state, rp->b_vec[chunk_idx].pg);
+
 	spin_unlock_irqrestore(&rp->b_lock, flags);
 	return 0;
 }
 
-static const struct vm_operations_struct mon_bin_vm_ops = {
-	.open =     mon_bin_vma_open,
-	.close =    mon_bin_vma_close,
-	.fault =    mon_bin_vma_fault,
+static const struct discontig_kernel_page_ops mon_discontig_ops = {
+	.init = mon_bin_discontig_init,
+	.get = mon_bin_discontig_get,
 };
 
-static int mon_bin_mmap(struct file *filp, struct vm_area_struct *vma)
+static int mon_bin_mmap_prepare(struct vm_area_desc *desc)
 {
-	/* don't do anything here: "fault" will set up page table entries */
-	vma->vm_ops = &mon_bin_vm_ops;
+	const struct file *filp = desc->file;
 
-	if (vma->vm_flags & VM_WRITE)
+	if (vma_desc_test(desc, VMA_WRITE_BIT))
 		return -EPERM;
 
-	vm_flags_mod(vma, VM_DONTEXPAND | VM_DONTDUMP, VM_MAYWRITE);
-	vma->vm_private_data = filp->private_data;
-	mon_bin_vma_open(vma);
+	desc->vm_ops = &mon_bin_vm_ops;
+	vma_desc_clear_flags(desc, VMA_MAYWRITE_BIT);
+	vma_desc_set_flags(desc, VMA_DONTEXPAND_BIT, VMA_DONTDUMP_BIT);
+	desc->private_data = filp->private_data;
+
+	mmap_action_map_discontig_kernel_pages(desc, NULL, &mon_discontig_ops);
 	return 0;
 }
 
@@ -1298,7 +1322,7 @@ static const struct file_operations mon_fops_binary = {
 	.compat_ioctl =	mon_bin_compat_ioctl,
 #endif
 	.release =	mon_bin_release,
-	.mmap =		mon_bin_mmap,
+	.mmap_prepare = mon_bin_mmap_prepare,
 };
 
 static int mon_bin_wait_event(struct file *file, struct mon_reader_bin *rp)

-- 
2.55.0


^ permalink raw reply related	[flat|nested] 89+ messages in thread

* [PATCH 10/39] infiniband: update hfi1 to use remap_vmalloc_range()
  2026-09-08 20:01 [PATCH 00/39] mm: make VMA flag semantics explicit, eliminate VM_SPECIAL Lorenzo Stoakes (ARM)
                   ` (8 preceding siblings ...)
  2026-09-08 20:01 ` [PATCH 09/39] drivers/usb/mon: update to use mmap_prepare + map kernel pages Lorenzo Stoakes (ARM)
@ 2026-09-08 20:01 ` Lorenzo Stoakes (ARM)
  2026-09-08 20:42   ` sashiko-bot
  2026-09-08 20:01 ` [PATCH 11/39] selinux: reject writable opens of policy file, drop mmap shared/write check Lorenzo Stoakes (ARM)
                   ` (28 subsequent siblings)
  38 siblings, 1 reply; 89+ messages in thread
From: Lorenzo Stoakes (ARM) @ 2026-09-08 20:01 UTC (permalink / raw)
  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,
	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, linux-kernel, linux-doc, linux-usb, linux-rdma, selinux,
	linux-sound, bpf, linux-scsi, linux-fbdev, dri-devel,
	linux-trace-kernel, linux-perf-users, linux-arch, linux-fsdevel,
	linux-arm-kernel, kvmarm, linuxppc-dev, kvm, kvm-riscv,
	linux-riscv, linux-s390, sparclinux, fuse-devel,
	Lorenzo Stoakes (ARM)

In cases which map chip memory from vmalloc()'d ranges, the hfi1 infiniband
drivers currently installs a fault handler, and then smuggles the kernel
virtual address of this range in vma->vm_pgoff.

This is exposing KASLR-sensitive internal kernel state in the VMA, and is
entirely unnecessary.

Instead, use remap_vmalloc_range() to remap the VMA to the span, and
eliminate the fault handler altogether.

remap_vmalloc_range() checks that the VMA does not extend beyond the
vmalloc area, and the driver already requires the VMA to exactly match the
span of the memory being mapped, so this has no impact.

The memory is all preallocated so not having a fault handler has no impact
either, other than pre-mapping the ranges which is beneficial.

We also remove the VM_IO flag as it's not appropriate here, and the
VM_DONTEXPAND flag as remap_vmalloc_range() will set it (and also mark the
range correctly as a mixed map).

We also update the vmalloc paths to place the virtual kernel address in
memvirt, rather than overloading the physical address memaddr. We predicate
the vmalloc handling on the vmalloc flag before we check memvirt for the
virtual address-derived PFN remap path, so this works fine.

remap_vmalloc_range() requires that the vmalloc()'d areas were all
allocated using vmalloc_user() - each of cq->comps,
uctxt->subctxt_rcvegrbuf, uctxt->subctxt_rcvhdr_base,
uctxt->subctxt_uregbase and dd->events were allocated this way, so that
requirement is satisfied.

We also remove VM_IO and VM_DONTEXPAND from the STATUS command, as these
are both set on remap.

Finally, we remove VM_DONTEXPAND from the PIO_BUFS, PIO_BUFS_SOP and UREGS
commands, as these are also all set on remap. PIO_CRED retains it, as
dma_mmap_coherent() may map via vm_insert_page() on the IOMMU-DMA path,
which sets only VM_MIXEDMAP.

Note that we retain expected behaviour throughout - the vmalloc remapped
ranges set VM_MIXEDMAP | VM_DONTDUMP | VM_DONTEXPAND for each range.

VM_IO was never appropriate as the ranges are explicitly not MMIO, and the
reference to the v3.7 VM_RESERVED semantics map on to VM_MIXEDMAP |
VM_DONTDUMP | VM_DONTEXPAND correctly - no core dump, unmergeable, no
normal vm page for purposes of reclaim/migration/etc.

There is a change in behaviour in that pages mapped using
remap_vmalloc_range() will now have normal GUP-able pages, however this
should have no impact as there is no reason not to allow this.

Signed-off-by: Lorenzo Stoakes (ARM) <ljs@kernel.org>
---
 drivers/infiniband/hw/hfi1/file_ops.c | 79 ++++++++++-------------------------
 1 file changed, 22 insertions(+), 57 deletions(-)

diff --git a/drivers/infiniband/hw/hfi1/file_ops.c b/drivers/infiniband/hw/hfi1/file_ops.c
index dc548e6802e2..7119d734edc7 100644
--- a/drivers/infiniband/hw/hfi1/file_ops.c
+++ b/drivers/infiniband/hw/hfi1/file_ops.c
@@ -70,7 +70,6 @@ static int set_ctxt_pkey(struct hfi1_ctxtdata *uctxt, unsigned long arg);
 static int ctxt_reset(struct hfi1_ctxtdata *uctxt);
 static int manage_rcvq(struct hfi1_ctxtdata *uctxt, u16 subctxt,
 		       unsigned long arg);
-static vm_fault_t vma_fault(struct vm_fault *vmf);
 static long hfi1_file_ioctl(struct file *fp, unsigned int cmd,
 			    unsigned long arg);
 
@@ -85,10 +84,6 @@ static const struct file_operations hfi1_file_ops = {
 	.llseek = noop_llseek,
 };
 
-static const struct vm_operations_struct vm_ops = {
-	.fault = vma_fault,
-};
-
 /*
  * Types of memories mapped into user processes' space
  */
@@ -304,13 +299,13 @@ static ssize_t hfi1_write_iter(struct kiocb *kiocb, struct iov_iter *from)
 	return reqs;
 }
 
-static inline void mmap_cdbg(u16 ctxt, u8 subctxt, u8 type, u8 mapio, u8 vmf,
+static inline void mmap_cdbg(u16 ctxt, u8 subctxt, u8 type, u8 mapio, u8 is_vmalloc,
 			     u64 memaddr, void *memvirt, dma_addr_t memdma,
 			     ssize_t memlen, struct vm_area_struct *vma)
 {
 	hfi1_cdbg(PROC,
-		  "%u:%u type:%u io/vf/dma:%d/%d/%d, addr:0x%llx, len:%lu(%lu), flags:0x%lx",
-		  ctxt, subctxt, type, mapio, vmf, !!memdma,
+		  "%u:%u type:%u io/vmalloc/dma:%d/%d/%d, addr:0x%llx, len:%lu(%lu), flags:0x%lx",
+		  ctxt, subctxt, type, mapio, is_vmalloc, !!memdma,
 		  memaddr ?: (u64)memvirt, memlen,
 		  vma->vm_end - vma->vm_start, vma->vm_flags);
 }
@@ -325,7 +320,7 @@ static int hfi1_file_mmap(struct file *fp, struct vm_area_struct *vma)
 		memaddr = 0;
 	void *memvirt = NULL;
 	dma_addr_t memdma = 0;
-	u8 subctxt, mapio = 0, vmf = 0, type;
+	u8 subctxt, mapio = 0, is_vmalloc = 0, type;
 	ssize_t memlen = 0;
 	int ret = 0;
 	u16 ctxt;
@@ -347,7 +342,7 @@ static int hfi1_file_mmap(struct file *fp, struct vm_area_struct *vma)
 	/*
 	 * vm_pgoff is used as a buffer selector cookie.  Always mmap from
 	 * the beginning.
-	 */ 
+	 */
 	vma->vm_pgoff = 0;
 	flags = vma->vm_flags;
 
@@ -366,7 +361,7 @@ static int hfi1_file_mmap(struct file *fp, struct vm_area_struct *vma)
 		 */
 		memlen = PAGE_ALIGN(uctxt->sc->credits * PIO_BLOCK_SIZE);
 		flags &= ~VM_MAYREAD;
-		flags |= VM_DONTCOPY | VM_DONTEXPAND;
+		flags |= VM_DONTCOPY;
 		vma->vm_page_prot = pgprot_writecombine(vma->vm_page_prot);
 		mapio = 1;
 		break;
@@ -438,7 +433,7 @@ static int hfi1_file_mmap(struct file *fp, struct vm_area_struct *vma)
 			memvirt = uctxt->egrbufs.buffers[i].addr;
 			memdma = uctxt->egrbufs.buffers[i].dma;
 			vma->vm_end += memlen;
-			mmap_cdbg(ctxt, subctxt, type, mapio, vmf, memaddr,
+			mmap_cdbg(ctxt, subctxt, type, mapio, is_vmalloc, memaddr,
 				  memvirt, memdma, memlen, vma);
 			ret = dma_mmap_coherent(&dd->pcidev->dev, vma,
 						memvirt, memdma, memlen);
@@ -467,7 +462,7 @@ static int hfi1_file_mmap(struct file *fp, struct vm_area_struct *vma)
 		 * user registers.
 		 */
 		memlen = PAGE_SIZE;
-		flags |= VM_DONTCOPY | VM_DONTEXPAND;
+		flags |= VM_DONTCOPY;
 		vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot);
 		mapio = 1;
 		break;
@@ -476,15 +471,10 @@ static int hfi1_file_mmap(struct file *fp, struct vm_area_struct *vma)
 		 * Use the page where this context's flags are. User level
 		 * knows where it's own bitmap is within the page.
 		 */
-		memaddr = (unsigned long)
-			(dd->events + uctxt_offset(uctxt)) & PAGE_MASK;
+		memvirt = dd->events + uctxt_offset(uctxt);
+		memvirt = (void *)(((uintptr_t)memvirt) & PAGE_MASK);
 		memlen = PAGE_SIZE;
-		/*
-		 * v3.7 removes VM_RESERVED but the effect is kept by
-		 * using VM_IO.
-		 */
-		flags |= VM_IO | VM_DONTEXPAND;
-		vmf = 1;
+		is_vmalloc = 1;
 		break;
 	case STATUS:
 		if (flags & VM_WRITE) {
@@ -493,7 +483,6 @@ static int hfi1_file_mmap(struct file *fp, struct vm_area_struct *vma)
 		}
 		memaddr = kvirt_to_phys((void *)dd->status);
 		memlen = PAGE_SIZE;
-		flags |= VM_IO | VM_DONTEXPAND;
 		break;
 	case RTAIL:
 		if (!HFI1_CAP_IS_USET(DMA_RTAIL)) {
@@ -514,23 +503,20 @@ static int hfi1_file_mmap(struct file *fp, struct vm_area_struct *vma)
 		flags &= ~VM_MAYWRITE;
 		break;
 	case SUBCTXT_UREGS:
-		memaddr = (u64)uctxt->subctxt_uregbase;
+		memvirt = uctxt->subctxt_uregbase;
 		memlen = PAGE_SIZE;
-		flags |= VM_IO | VM_DONTEXPAND;
-		vmf = 1;
+		is_vmalloc = 1;
 		break;
 	case SUBCTXT_RCV_HDRQ:
-		memaddr = (u64)uctxt->subctxt_rcvhdr_base;
+		memvirt = uctxt->subctxt_rcvhdr_base;
 		memlen = rcvhdrq_size(uctxt) * uctxt->subctxt_cnt;
-		flags |= VM_IO | VM_DONTEXPAND;
-		vmf = 1;
+		is_vmalloc = 1;
 		break;
 	case SUBCTXT_EGRBUF:
-		memaddr = (u64)uctxt->subctxt_rcvegrbuf;
+		memvirt = uctxt->subctxt_rcvegrbuf;
 		memlen = uctxt->egrbufs.size * uctxt->subctxt_cnt;
-		flags |= VM_IO | VM_DONTEXPAND;
 		flags &= ~VM_MAYWRITE;
-		vmf = 1;
+		is_vmalloc = 1;
 		break;
 	case SDMA_COMP: {
 		struct hfi1_user_sdma_comp_q *cq = fd->cq;
@@ -539,10 +525,9 @@ static int hfi1_file_mmap(struct file *fp, struct vm_area_struct *vma)
 			ret = -EFAULT;
 			goto done;
 		}
-		memaddr = (u64)cq->comps;
+		memvirt = cq->comps;
 		memlen = PAGE_ALIGN(sizeof(*cq->comps) * cq->nentries);
-		flags |= VM_IO | VM_DONTEXPAND;
-		vmf = 1;
+		is_vmalloc = 1;
 		break;
 	}
 	default:
@@ -559,12 +544,10 @@ static int hfi1_file_mmap(struct file *fp, struct vm_area_struct *vma)
 	}
 
 	vm_flags_reset(vma, flags);
-	mmap_cdbg(ctxt, subctxt, type, mapio, vmf, memaddr, memvirt, memdma, 
+	mmap_cdbg(ctxt, subctxt, type, mapio, is_vmalloc, memaddr, memvirt, memdma,
 		  memlen, vma);
-	if (vmf) {
-		vma->vm_pgoff = PFN_DOWN(memaddr);
-		vma->vm_ops = &vm_ops;
-		ret = 0;
+	if (is_vmalloc) {
+		ret = remap_vmalloc_range(vma, memvirt, 0);
 	} else if (memdma) {
 		ret = dma_mmap_coherent(&dd->pcidev->dev, vma,
 					memvirt, memdma, memlen);
@@ -588,24 +571,6 @@ static int hfi1_file_mmap(struct file *fp, struct vm_area_struct *vma)
 	return ret;
 }
 
-/*
- * Local (non-chip) user memory is not mapped right away but as it is
- * accessed by the user-level code.
- */
-static vm_fault_t vma_fault(struct vm_fault *vmf)
-{
-	struct page *page;
-
-	page = vmalloc_to_page((void *)(vmf->pgoff << PAGE_SHIFT));
-	if (!page)
-		return VM_FAULT_SIGBUS;
-
-	get_page(page);
-	vmf->page = page;
-
-	return 0;
-}
-
 static __poll_t hfi1_poll(struct file *fp, struct poll_table_struct *pt)
 {
 	struct hfi1_ctxtdata *uctxt;

-- 
2.55.0


^ permalink raw reply related	[flat|nested] 89+ messages in thread

* [PATCH 11/39] selinux: reject writable opens of policy file, drop mmap shared/write check
  2026-09-08 20:01 [PATCH 00/39] mm: make VMA flag semantics explicit, eliminate VM_SPECIAL Lorenzo Stoakes (ARM)
                   ` (9 preceding siblings ...)
  2026-09-08 20:01 ` [PATCH 10/39] infiniband: update hfi1 to use remap_vmalloc_range() Lorenzo Stoakes (ARM)
@ 2026-09-08 20:01 ` Lorenzo Stoakes (ARM)
  2026-09-08 20:22   ` Jann Horn
                     ` (2 more replies)
  2026-09-08 20:01 ` [PATCH 12/39] ALSA: pcm: use vm_insert_page() to map PCM status page Lorenzo Stoakes (ARM)
                   ` (27 subsequent siblings)
  38 siblings, 3 replies; 89+ messages in thread
From: Lorenzo Stoakes (ARM) @ 2026-09-08 20:01 UTC (permalink / raw)
  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,
	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, linux-kernel, linux-doc, linux-usb, linux-rdma, selinux,
	linux-sound, bpf, linux-scsi, linux-fbdev, dri-devel,
	linux-trace-kernel, linux-perf-users, linux-arch, linux-fsdevel,
	linux-arm-kernel, kvmarm, linuxppc-dev, kvm, kvm-riscv,
	linux-riscv, linux-s390, sparclinux, fuse-devel,
	Lorenzo Stoakes (ARM)

The policy file has no write method and is exposed read-only (S_IRUGO in
selinux_files[]), yet sel_open_policy() performs no open mode check, so a
CAP_DAC_OVERRIDE caller can open it O_RDWR. Reject FMODE_WRITE at open, as
kernfs does.

The file can then never be mapped with FMODE_WRITE, so do_mmap() always
clears VM_MAYWRITE and VM_SHARED for MAP_SHARED mappings and the VM_SHARED
check in sel_mmap_policy() cannot be reached. Remove it.

This also stops sel_mmap_policy() clearing VM_MAYWRITE on a mapping that is
neither a PFN map nor a mixed map, ahead of the core enforcing that only
such mappings may do so.

Signed-off-by: Lorenzo Stoakes (ARM) <ljs@kernel.org>
---
 security/selinux/selinuxfs.c | 11 +++--------
 1 file changed, 3 insertions(+), 8 deletions(-)

diff --git a/security/selinux/selinuxfs.c b/security/selinux/selinuxfs.c
index c7d91476971c..545a6f89f9e7 100644
--- a/security/selinux/selinuxfs.c
+++ b/security/selinux/selinuxfs.c
@@ -340,6 +340,9 @@ static int sel_open_policy(struct inode *inode, struct file *filp)
 	struct policy_load_memory *plm = NULL;
 	int rc;
 
+	if (filp->f_mode & FMODE_WRITE)
+		return -EACCES;
+
 	rc = avc_has_perm(current_sid(), SECINITSID_SECURITY,
 			  SECCLASS_SECURITY, SECURITY__READ_POLICY, NULL);
 	if (rc)
@@ -424,14 +427,6 @@ static const struct vm_operations_struct sel_mmap_policy_ops = {
 
 static int sel_mmap_policy(struct file *filp, struct vm_area_struct *vma)
 {
-	if (vma->vm_flags & VM_SHARED) {
-		/* do not allow mprotect to make mapping writable */
-		vm_flags_clear(vma, VM_MAYWRITE);
-
-		if (vma->vm_flags & VM_WRITE)
-			return -EACCES;
-	}
-
 	vm_flags_set(vma, VM_DONTEXPAND | VM_DONTDUMP);
 	vma->vm_ops = &sel_mmap_policy_ops;
 

-- 
2.55.0


^ permalink raw reply related	[flat|nested] 89+ messages in thread

* [PATCH 12/39] ALSA: pcm: use vm_insert_page() to map PCM status page
  2026-09-08 20:01 [PATCH 00/39] mm: make VMA flag semantics explicit, eliminate VM_SPECIAL Lorenzo Stoakes (ARM)
                   ` (10 preceding siblings ...)
  2026-09-08 20:01 ` [PATCH 11/39] selinux: reject writable opens of policy file, drop mmap shared/write check Lorenzo Stoakes (ARM)
@ 2026-09-08 20:01 ` Lorenzo Stoakes (ARM)
  2026-09-08 20:45   ` sashiko-bot
  2026-09-10 16:15   ` Takashi Iwai
  2026-09-08 20:01 ` [PATCH 13/39] bpf: arena: mark arena_map_mmap() mappings VM_MIXEDMAP Lorenzo Stoakes (ARM)
                   ` (26 subsequent siblings)
  38 siblings, 2 replies; 89+ messages in thread
From: Lorenzo Stoakes (ARM) @ 2026-09-08 20:01 UTC (permalink / raw)
  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,
	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, linux-kernel, linux-doc, linux-usb, linux-rdma, selinux,
	linux-sound, bpf, linux-scsi, linux-fbdev, dri-devel,
	linux-trace-kernel, linux-perf-users, linux-arch, linux-fsdevel,
	linux-arm-kernel, kvmarm, linuxppc-dev, kvm, kvm-riscv,
	linux-riscv, linux-s390, sparclinux, fuse-devel,
	Lorenzo Stoakes (ARM)

There's no need to keep a fault handler around for this, instead map on
mmap.

While we're here, rename area to vma to be consistent.

This correctly makes the mapping a mixed map mapping.

This works towards establishing the invariant that only PFN mapped or mixed
map mappings may clear the VM_MAYWRITE flag. The status page mapping clears
VM_MAYWRITE, so it must be kernel-owned; the control page mapping remains
writable and is left fault-based.

The assumption is made that the struct pcm_mmap_status structure is at most
a page in size, which is asserted as a build bug.

This is safe to assume, as the size of the structure is 56 bytes at most.

Signed-off-by: Lorenzo Stoakes (ARM) <ljs@kernel.org>
---
 sound/core/pcm_native.c | 37 ++++++++++++-------------------------
 1 file changed, 12 insertions(+), 25 deletions(-)

diff --git a/sound/core/pcm_native.c b/sound/core/pcm_native.c
index 62324282fcae..37a157d55832 100644
--- a/sound/core/pcm_native.c
+++ b/sound/core/pcm_native.c
@@ -3760,39 +3760,26 @@ static __poll_t snd_pcm_poll(struct file *file, poll_table *wait)
 /*
  * mmap status record
  */
-static vm_fault_t snd_pcm_mmap_status_fault(struct vm_fault *vmf)
+static int snd_pcm_mmap_status(struct snd_pcm_substream *substream, struct file *file,
+			       struct vm_area_struct *vma)
 {
-	struct snd_pcm_substream *substream = vmf->vma->vm_private_data;
+	const unsigned long size = vma->vm_end - vma->vm_start;
 	struct snd_pcm_runtime *runtime;
-	
-	if (substream == NULL)
-		return VM_FAULT_SIGBUS;
-	runtime = substream->runtime;
-	vmf->page = virt_to_page(runtime->status);
-	get_page(vmf->page);
-	return 0;
-}
+	struct page *page;
 
-static const struct vm_operations_struct snd_pcm_vm_ops_status =
-{
-	.fault =	snd_pcm_mmap_status_fault,
-};
+	BUILD_BUG_ON(sizeof(struct snd_pcm_mmap_status) > PAGE_SIZE);
 
-static int snd_pcm_mmap_status(struct snd_pcm_substream *substream, struct file *file,
-			       struct vm_area_struct *area)
-{
-	long size;
-	if (!(area->vm_flags & VM_READ))
+	if (!(vma->vm_flags & VM_READ))
 		return -EINVAL;
-	size = area->vm_end - area->vm_start;
-	if (size != PAGE_ALIGN(sizeof(struct snd_pcm_mmap_status)))
+	if (size != PAGE_SIZE)
 		return -EINVAL;
-	area->vm_ops = &snd_pcm_vm_ops_status;
-	area->vm_private_data = substream;
-	vm_flags_mod(area, VM_DONTEXPAND | VM_DONTDUMP,
+
+	vm_flags_mod(vma, VM_DONTEXPAND | VM_DONTDUMP,
 		     VM_WRITE | VM_MAYWRITE);
 
-	return 0;
+	runtime = substream->runtime;
+	page = virt_to_page(runtime->status);
+	return vm_insert_page(vma, vma->vm_start, page);
 }
 
 /*

-- 
2.55.0


^ permalink raw reply related	[flat|nested] 89+ messages in thread

* [PATCH 13/39] bpf: arena: mark arena_map_mmap() mappings VM_MIXEDMAP
  2026-09-08 20:01 [PATCH 00/39] mm: make VMA flag semantics explicit, eliminate VM_SPECIAL Lorenzo Stoakes (ARM)
                   ` (11 preceding siblings ...)
  2026-09-08 20:01 ` [PATCH 12/39] ALSA: pcm: use vm_insert_page() to map PCM status page Lorenzo Stoakes (ARM)
@ 2026-09-08 20:01 ` Lorenzo Stoakes (ARM)
  2026-09-08 20:34   ` sashiko-bot
  2026-09-08 20:01 ` [PATCH 14/39] mm/vma: add vma[_flags]_is_kernel_owned() predicates Lorenzo Stoakes (ARM)
                   ` (25 subsequent siblings)
  38 siblings, 1 reply; 89+ messages in thread
From: Lorenzo Stoakes (ARM) @ 2026-09-08 20:01 UTC (permalink / raw)
  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,
	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, linux-kernel, linux-doc, linux-usb, linux-rdma, selinux,
	linux-sound, bpf, linux-scsi, linux-fbdev, dri-devel,
	linux-trace-kernel, linux-perf-users, linux-arch, linux-fsdevel,
	linux-arm-kernel, kvmarm, linuxppc-dev, kvm, kvm-riscv,
	linux-riscv, linux-s390, sparclinux, fuse-devel,
	Lorenzo Stoakes (ARM)

The bpf_map->ops->map_mmap callback invoked by bpf_map_mmap() can be set to
one of ringbuf_map_mmap_kern(), ringbuf_map_mmap_user(), array_map_mmap()
or arena_map_mmap().

It is convention in mm to mark mappings whose pages the kernel manages
itself with VM_MIXEDMAP, so the core mm knows not to treat them as ordinary
page cache or anonymous memory.

The map_mmap callbacks ringbuf_map_mmap_kern() and ringbuf_map_mmap_user()
use remap_vmalloc_range(), which ultimately invokes vm_insert_page() and so
marks the ranges VM_MIXEDMAP, and array_map_mmap() sets VM_MIXEDMAP
explicitly.

However, the exception to this is arena_map_mmap(), which doesn't set the
flag.

This patch corrects this and updates the comment to reflect it.

The pages are refcounted and vm_normal_page() finds them regardless of the
flag, and VM_DONTEXPAND remains set (marking the memory as VM_SPECIAL and
thus unmergeable). The one effect is that NUMA balancing now skips these
VMAs, as it already does for the other bpf map mappings, which is the
reason array_map_mmap() gives for setting the flag.

The intent of this patch is to be able to establish the invariant that only
PFN-mapped or mixed map ranges may clear the VM_MAYWRITE flag, as is done
in bpf_map_mmap().

Signed-off-by: Lorenzo Stoakes (ARM) <ljs@kernel.org>
---
 kernel/bpf/arena.c | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/kernel/bpf/arena.c b/kernel/bpf/arena.c
index 7b6847200b43..b69fe5e34339 100644
--- a/kernel/bpf/arena.c
+++ b/kernel/bpf/arena.c
@@ -620,8 +620,9 @@ static int arena_map_mmap(struct bpf_map *map, struct vm_area_struct *vma)
 	 * clears VM_MAYEXEC. Set VM_DONTEXPAND to avoid potential change
 	 * of user_vm_start. Set VM_DONTCOPY to prevent arena VMA from
 	 * being copied into the child process on fork.
+	 * This is a kernel page so set VM_MIXEDMAP.
 	 */
-	vm_flags_set(vma, VM_DONTEXPAND | VM_DONTCOPY);
+	vm_flags_set(vma, VM_MIXEDMAP | VM_DONTEXPAND | VM_DONTCOPY);
 	vma->vm_ops = &arena_vm_ops;
 	return 0;
 }

-- 
2.55.0


^ permalink raw reply related	[flat|nested] 89+ messages in thread

* [PATCH 14/39] mm/vma: add vma[_flags]_is_kernel_owned() predicates
  2026-09-08 20:01 [PATCH 00/39] mm: make VMA flag semantics explicit, eliminate VM_SPECIAL Lorenzo Stoakes (ARM)
                   ` (12 preceding siblings ...)
  2026-09-08 20:01 ` [PATCH 13/39] bpf: arena: mark arena_map_mmap() mappings VM_MIXEDMAP Lorenzo Stoakes (ARM)
@ 2026-09-08 20:01 ` Lorenzo Stoakes (ARM)
  2026-09-08 20:28   ` sashiko-bot
  2026-09-08 20:01 ` [PATCH 15/39] mm/vma: only allow mmap to clear VMA_MAYWRITE_BIT if kernel-owned Lorenzo Stoakes (ARM)
                   ` (24 subsequent siblings)
  38 siblings, 1 reply; 89+ messages in thread
From: Lorenzo Stoakes (ARM) @ 2026-09-08 20:01 UTC (permalink / raw)
  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,
	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, linux-kernel, linux-doc, linux-usb, linux-rdma, selinux,
	linux-sound, bpf, linux-scsi, linux-fbdev, dri-devel,
	linux-trace-kernel, linux-perf-users, linux-arch, linux-fsdevel,
	linux-arm-kernel, kvmarm, linuxppc-dev, kvm, kvm-riscv,
	linux-riscv, linux-s390, sparclinux, fuse-devel,
	Lorenzo Stoakes (ARM)

Rather than referring to VMA flags with uncertain meaning, add a new
predicate that explicitly describes what possession of the VMA_PFNMAP_BIT
or VMA_MIXEDMAP_BIT flags mean, and then refer to that function for
determining VMA mergeability.

Either flag means the contents of the mapping are owned by the kernel,
usually a driver, rather than by the core mm: the memory may be MMIO,
kernel-allocated pages or even ordinary pages the driver maps itself, but
the core must not populate, reclaim, migrate, copy-on-write or merge the
range on its own initiative.

We initially also include VMA_IO_BIT here, as by implication, these must be
kernel-owned. (mlock() also sets VMA_IO_BIT transiently on ordinary VMAs
while locking them, which is addressed later in this series.)

However the intent is to in future remove this, as no mapping should be
marked as an I/O mapping without also being marked with VMA_PFNMAP_BIT.

This forms the basis of further work intended to improve how we express VMA
properties such as this.

Also update the VMA userland tests to reflect the change.

No functional change intended.

Signed-off-by: Lorenzo Stoakes (ARM) <ljs@kernel.org>
---
 include/linux/mm.h              | 56 ++++++++++++++++++++++++++++++++++++++++-
 tools/testing/vma/include/dup.h | 29 ++++++++++++++++++++-
 2 files changed, 83 insertions(+), 2 deletions(-)

diff --git a/include/linux/mm.h b/include/linux/mm.h
index 4604cd011ca4..45c59474c853 100644
--- a/include/linux/mm.h
+++ b/include/linux/mm.h
@@ -1612,6 +1612,44 @@ static inline bool vma_is_shared_maywrite(const struct vm_area_struct *vma)
 	return is_shared_maywrite(&vma->flags);
 }
 
+/**
+ * vma_flags_is_kernel_owned() - Do the specified VMA flags indicate that the
+ * contents of the VMA are owned by the kernel rather than the core mm?
+ * @flags: The VMA flags to test.
+ *
+ * A kernel-owned mapping is one whose contents are established and controlled
+ * by the kernel, typically a driver, rather than by the core mm's fault and
+ * rmap machinery.
+ *
+ * The mapping may be memory-mapped I/O, kernel-allocated pages or ordinary
+ * pages the owner has chosen to map itself (shmem via a PFN map, for instance).
+ *
+ * But in all cases core mm must not populate, reclaim, migrate, Copy-on-Write
+ * or merge it of its own accord.
+ *
+ * The pages mapped, if any, may or may not be reference counted or map counted.
+ *
+ * Returns: true if the flags indicate a kernel-owned mapping.
+ */
+static inline bool vma_flags_is_kernel_owned(const vma_flags_t *flags)
+{
+	return vma_flags_test_any(flags, VMA_PFNMAP_BIT, VMA_MIXEDMAP_BIT,
+				  VMA_IO_BIT);
+}
+
+/**
+ * vma_is_kernel_owned() - Are the contents of @vma owned by the kernel?
+ * @vma: The VMA to test.
+ *
+ * See vma_flags_is_kernel_owned() for a description of this property.
+ *
+ * Returns: true if the VMA is kernel-owned.
+ */
+static inline bool vma_is_kernel_owned(const struct vm_area_struct *vma)
+{
+	return vma_flags_is_kernel_owned(&vma->flags);
+}
+
 /**
  * vma_flags_can_merge() - Do the specified VMA flags permit the VMA to be
  * merged with another?
@@ -1620,7 +1658,23 @@ static inline bool vma_is_shared_maywrite(const struct vm_area_struct *vma)
  */
 static inline bool vma_flags_can_merge(const vma_flags_t *flags)
 {
-	return !vma_flags_test_any_mask(flags, VMA_SPECIAL_FLAGS);
+	/*
+	 * VMA merging assumes that a VMA's flags and fields completely describe
+	 * its state.
+	 *
+	 * However, kernel-owned mappings may have established state upon mapping
+	 * not embodied in any attribute of the VMA.
+	 *
+	 * Additionally, private (CoW) PFN maps encode the source PFN of the
+	 * range in vma->vm_pgoff, which may otherwise cause spurious merges.
+	 */
+	if (vma_flags_is_kernel_owned(flags))
+		return false;
+	/* VMA explicitly marked as being unmergeable. */
+	if (vma_flags_test(flags, VMA_DONTEXPAND_BIT))
+		return false;
+
+	return true;
 }
 
 /**
diff --git a/tools/testing/vma/include/dup.h b/tools/testing/vma/include/dup.h
index 52eee05e6c32..3fe40e0f4034 100644
--- a/tools/testing/vma/include/dup.h
+++ b/tools/testing/vma/include/dup.h
@@ -1659,7 +1659,34 @@ static inline bool file_is_dev_zero(const struct file *file)
 	return file && file->f_op == &zero_fops;
 }
 
+static inline bool vma_flags_is_kernel_owned(const vma_flags_t *flags)
+{
+	return vma_flags_test_any(flags, VMA_PFNMAP_BIT, VMA_MIXEDMAP_BIT,
+				  VMA_IO_BIT);
+}
+
+static inline bool vma_is_kernel_owned(const struct vm_area_struct *vma)
+{
+	return vma_flags_is_kernel_owned(&vma->flags);
+}
+
 static inline bool vma_flags_can_merge(const vma_flags_t *flags)
 {
-	return !vma_flags_test_any_mask(flags, VMA_SPECIAL_FLAGS);
+	/*
+	 * VMA merging assumes that the properties of a VMA completely describe
+	 * the properties of that VMA.
+	 *
+	 * However, kernel-owned mappings may have established state upon mapping
+	 * not embodied in any attribute of the VMA.
+	 *
+	 * Additionally, PFN maps encode the source PFN of the range in
+	 * vma->vm_pgoff, which may otherwise cause spurious merges.
+	 */
+	if (vma_flags_is_kernel_owned(flags))
+		return false;
+	/* VMA explicitly marked as being unmergeable. */
+	if (vma_flags_test(flags, VMA_DONTEXPAND_BIT))
+		return false;
+
+	return true;
 }

-- 
2.55.0


^ permalink raw reply related	[flat|nested] 89+ messages in thread

* [PATCH 15/39] mm/vma: only allow mmap to clear VMA_MAYWRITE_BIT if kernel-owned
  2026-09-08 20:01 [PATCH 00/39] mm: make VMA flag semantics explicit, eliminate VM_SPECIAL Lorenzo Stoakes (ARM)
                   ` (13 preceding siblings ...)
  2026-09-08 20:01 ` [PATCH 14/39] mm/vma: add vma[_flags]_is_kernel_owned() predicates Lorenzo Stoakes (ARM)
@ 2026-09-08 20:01 ` Lorenzo Stoakes (ARM)
  2026-09-08 20:42   ` sashiko-bot
  2026-09-08 20:01 ` [PATCH 16/39] mm/vma: add and use vma_[flags]_is_fixed_mapping Lorenzo Stoakes (ARM)
                   ` (23 subsequent siblings)
  38 siblings, 1 reply; 89+ messages in thread
From: Lorenzo Stoakes (ARM) @ 2026-09-08 20:01 UTC (permalink / raw)
  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,
	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, linux-kernel, linux-doc, linux-usb, linux-rdma, selinux,
	linux-sound, bpf, linux-scsi, linux-fbdev, dri-devel,
	linux-trace-kernel, linux-perf-users, linux-arch, linux-fsdevel,
	linux-arm-kernel, kvmarm, linuxppc-dev, kvm, kvm-riscv,
	linux-riscv, linux-s390, sparclinux, fuse-devel,
	Lorenzo Stoakes (ARM)

For ordinary files the only way the VMA_MAYWRITE_BIT flag is cleared is if
the underlying file is itself read-only.

This means that mprotect() cannot mark a shared mapping of a read-only file
as read/write, as doing so would violate the read only attribute, and
permit writes.

In general, we do not want file systems to be able to do this for
read/write files.

Doing so would violate fundamental user expectation of file attributes and
likely break userspace.

However, drivers pose a tricky problem here - the /dev/xxx file may be
read/write but provide access to a resource which is fundamentally
read-only.

Therefore we must allow drivers to be able to clear VMA_MAYWRITE_BIT.

To achieve both of these things, restrict this ability to kernel-owned
mappings as identified by vma_flags_is_kernel_owned().

This constrains this ability to drivers which own the mapping's contents,
whether memory-mapped I/O, kernel-allocated pages, or ordinary pages they
map themselves, and so define its semantics.

Every in-tree mmap hook which clears VMA_MAYWRITE_BIT, some twenty sites
across drivers, filesystems and bpf, establishes a kernel-owned mapping,
with usbmon and the ALSA PCM status page converted earlier in this series
to do so.

Note that drivers may, if they do not gate on VMA_SHARED_BIT, be able to
disable MAP_PRIVATE-file-backed mapping CoW semantics.

This is perhaps not always intended, but we retain this capacity to
maintain existing behaviour.

As all drivers which clear VMA_MAYWRITE_BIT establish kernel-owned
mappings, no functional change is intended.

Signed-off-by: Lorenzo Stoakes (ARM) <ljs@kernel.org>
---
 mm/vma.c | 5 +++++
 1 file changed, 5 insertions(+)

diff --git a/mm/vma.c b/mm/vma.c
index 9e45fc83f74c..526428753218 100644
--- a/mm/vma.c
+++ b/mm/vma.c
@@ -2780,6 +2780,11 @@ static int mmap_validate(unsigned long prev_start,
 	if (WARN_ON_ONCE(!was_maywrite && is_maywrite))
 		return -EINVAL;
 
+	/* Only kernel-owned mappings may clear VMA_MAYWRITE_BIT. */
+	if (!vma_flags_is_kernel_owned(curr_flags) &&
+	    WARN_ON_ONCE(was_maywrite && !is_maywrite))
+		return -EINVAL;
+
 	return mmap_validate_vma_flags(curr_flags);
 }
 

-- 
2.55.0


^ permalink raw reply related	[flat|nested] 89+ messages in thread

* [PATCH 16/39] mm/vma: add and use vma_[flags]_is_fixed_mapping
  2026-09-08 20:01 [PATCH 00/39] mm: make VMA flag semantics explicit, eliminate VM_SPECIAL Lorenzo Stoakes (ARM)
                   ` (14 preceding siblings ...)
  2026-09-08 20:01 ` [PATCH 15/39] mm/vma: only allow mmap to clear VMA_MAYWRITE_BIT if kernel-owned Lorenzo Stoakes (ARM)
@ 2026-09-08 20:01 ` Lorenzo Stoakes (ARM)
  2026-09-08 20:42   ` sashiko-bot
  2026-09-08 20:01 ` [PATCH 17/39] scsi: sg: convert mmap hook to mmap_prepare and rework Lorenzo Stoakes (ARM)
                   ` (22 subsequent siblings)
  38 siblings, 1 reply; 89+ messages in thread
From: Lorenzo Stoakes (ARM) @ 2026-09-08 20:01 UTC (permalink / raw)
  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,
	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, linux-kernel, linux-doc, linux-usb, linux-rdma, selinux,
	linux-sound, bpf, linux-scsi, linux-fbdev, dri-devel,
	linux-trace-kernel, linux-perf-users, linux-arch, linux-fsdevel,
	linux-arm-kernel, kvmarm, linuxppc-dev, kvm, kvm-riscv,
	linux-riscv, linux-s390, sparclinux, fuse-devel,
	Lorenzo Stoakes (ARM)

This determines whether a VMA cannot be expanded or merged because what
they mapped was determined to be a set size at mmap time.

This typically refers to kernel-owned mappings, however VMA_DONTEXPAND_BIT
is not reliably set alongside VMA_PFNMAP_BIT or VMA_MIXEDMAP_BIT, so we
must explicitly test for this for now.

We also explicitly test for VMA_PFNMAP_BIT as VMA_DONTEXPAND_BIT may not be
set for VMA_PFNMAP_BIT's despite the one implying the other.

Use this predicate in vma_flags_can_merge() and in check_prep_vma() in the
mremap logic testing to see if mremap() can expand the VMA. The criteria
for khugepaged and MADV_COLLAPSE eligibility in
__thp_vma_allowable_orders() are precisely those for mergeability, so use
vma_can_merge() there (with an expanded comment).

This obviates the need for the VM_NO_KHUGEPAGED mask, so remove it.

Hugetlb VMAs remain excluded from khugepaged as hugetlbfs always sets
VMA_DONTEXPAND_BIT.

No functional change intended.

Signed-off-by: Lorenzo Stoakes (ARM) <ljs@kernel.org>
---
 include/linux/mm.h | 39 +++++++++++++++++++++++++++++++++++----
 mm/huge_memory.c   | 11 +++++++----
 mm/mremap.c        |  5 ++---
 3 files changed, 44 insertions(+), 11 deletions(-)

diff --git a/include/linux/mm.h b/include/linux/mm.h
index 45c59474c853..bca955941212 100644
--- a/include/linux/mm.h
+++ b/include/linux/mm.h
@@ -600,9 +600,6 @@ enum {
 #define VMA_REMAP_FLAGS mk_vma_flags(VMA_IO_BIT, VMA_PFNMAP_BIT,	\
 				     VMA_DONTEXPAND_BIT, VMA_DONTDUMP_BIT)
 
-/* This mask prevents VMA from being scanned with khugepaged */
-#define VM_NO_KHUGEPAGED (VM_SPECIAL | VM_HUGETLB)
-
 /* This mask defines which mm->def_flags a process can inherit its parent */
 #define VM_INIT_DEF_MASK	VM_NOHUGEPAGE
 
@@ -1650,6 +1647,40 @@ static inline bool vma_is_kernel_owned(const struct vm_area_struct *vma)
 	return vma_flags_is_kernel_owned(&vma->flags);
 }
 
+/**
+ * vma_flags_is_fixed_mapping() - Do the specified VMA flags indicate that this
+ * is a fixed mapping that cannot be expanded or merged?
+ * @flags: The VMA flags to test.
+ *
+ * Fixed mappings are those whose size is set at the point of mmap (for
+ * instance, a kernel-owned mapping of a fixed range of memory), and thus
+ * cannot be expanded or merged.
+ *
+ * Returns: true if the flags indicate a fixed mapping.
+ */
+static inline bool vma_flags_is_fixed_mapping(const vma_flags_t *flags)
+{
+	/*
+	 * VMA_PFNMAP_BIT should imply VMA_DONTEXPAND_BIT, but some callers set
+	 * only the former.
+	 */
+	return vma_flags_test_any(flags, VMA_PFNMAP_BIT, VMA_DONTEXPAND_BIT);
+}
+
+/**
+ * vma_is_fixed_mapping() - Is this VMA a fixed mapping that cannot be
+ * expanded or merged?
+ * @vma: The VMA to test.
+ *
+ * See vma_flags_is_fixed_mapping() for a description of this property.
+ *
+ * Returns: true if the VMA maps a fixed mapping.
+ */
+static inline bool vma_is_fixed_mapping(const struct vm_area_struct *vma)
+{
+	return vma_flags_is_fixed_mapping(&vma->flags);
+}
+
 /**
  * vma_flags_can_merge() - Do the specified VMA flags permit the VMA to be
  * merged with another?
@@ -1671,7 +1702,7 @@ static inline bool vma_flags_can_merge(const vma_flags_t *flags)
 	if (vma_flags_is_kernel_owned(flags))
 		return false;
 	/* VMA explicitly marked as being unmergeable. */
-	if (vma_flags_test(flags, VMA_DONTEXPAND_BIT))
+	if (vma_flags_is_fixed_mapping(flags))
 		return false;
 
 	return true;
diff --git a/mm/huge_memory.c b/mm/huge_memory.c
index dd66c6ad5af1..befffadd978e 100644
--- a/mm/huge_memory.c
+++ b/mm/huge_memory.c
@@ -212,11 +212,14 @@ unsigned long __thp_vma_allowable_orders(struct vm_area_struct *vma,
 		return in_pf ? orders : 0;
 
 	/*
-	 * khugepaged special VMA and hugetlb VMA.
-	 * Must be checked after dax since some dax mappings may have
-	 * VM_MIXEDMAP set.
+	 * khugepaged moves data from VMAs once collapsed, after they have been
+	 * faulted in, relying on refaulting for file-backed memory.
+	 *
+	 * Kernel-owned mappings cannot be reliably reconstructed from page
+	 * faults, and fixed mappings (including hugetlb) may not be marked as
+	 * kernel-owned - precisely the mappings which cannot be merged.
 	 */
-	if (!in_pf && !smaps && (vm_flags & VM_NO_KHUGEPAGED))
+	if (!in_pf && !smaps && !vma_can_merge(vma))
 		return 0;
 
 	/*
diff --git a/mm/mremap.c b/mm/mremap.c
index 7c368440fafe..ed19b47c2caf 100644
--- a/mm/mremap.c
+++ b/mm/mremap.c
@@ -1788,8 +1788,7 @@ static int check_prep_vma(struct vma_remap_struct *vrm)
 		return -EINVAL;
 	}
 
-	if ((vrm->flags & MREMAP_DONTUNMAP) &&
-	    vma_test_any(vma, VMA_DONTEXPAND_BIT, VMA_PFNMAP_BIT))
+	if ((vrm->flags & MREMAP_DONTUNMAP) && vma_is_fixed_mapping(vma))
 		return -EINVAL;
 
 	/*
@@ -1827,7 +1826,7 @@ static int check_prep_vma(struct vma_remap_struct *vrm)
 	if (pgoff + (new_len >> PAGE_SHIFT) < pgoff)
 		return -EINVAL;
 
-	if (vma_test_any(vma, VMA_DONTEXPAND_BIT, VMA_PFNMAP_BIT))
+	if (vma_is_fixed_mapping(vma))
 		return -EFAULT;
 
 	if (!mlock_future_ok(mm, vma_test(vma, VMA_LOCKED_BIT), vrm->delta))

-- 
2.55.0


^ permalink raw reply related	[flat|nested] 89+ messages in thread

* [PATCH 17/39] scsi: sg: convert mmap hook to mmap_prepare and rework
  2026-09-08 20:01 [PATCH 00/39] mm: make VMA flag semantics explicit, eliminate VM_SPECIAL Lorenzo Stoakes (ARM)
                   ` (15 preceding siblings ...)
  2026-09-08 20:01 ` [PATCH 16/39] mm/vma: add and use vma_[flags]_is_fixed_mapping Lorenzo Stoakes (ARM)
@ 2026-09-08 20:01 ` Lorenzo Stoakes (ARM)
  2026-09-08 20:37   ` sashiko-bot
  2026-09-08 20:01 ` [PATCH 18/39] fbdev: defio: assert FBINFO_VIRTFB, drop VM_IO, add VM_MIXEDMAP Lorenzo Stoakes (ARM)
                   ` (21 subsequent siblings)
  38 siblings, 1 reply; 89+ messages in thread
From: Lorenzo Stoakes (ARM) @ 2026-09-08 20:01 UTC (permalink / raw)
  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,
	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, linux-kernel, linux-doc, linux-usb, linux-rdma, selinux,
	linux-sound, bpf, linux-scsi, linux-fbdev, dri-devel,
	linux-trace-kernel, linux-perf-users, linux-arch, linux-fsdevel,
	linux-arm-kernel, kvmarm, linuxppc-dev, kvm, kvm-riscv,
	linux-riscv, linux-s390, sparclinux, fuse-devel,
	Lorenzo Stoakes (ARM)

Move from the deprecated mmap hook to the new mmap_prepare hook.

We are mapping kernel pages here, so use the discontiguous kernel mapping
mmap action to do so.

Unwind the rather confusing loop and instead map as many pages as we can at
one time.

Note that we do not need to pay attention to rsv_schp->k_use_sg here, as
the pages are populated for the length of the buffer at
rsv_schp->page_order granularity as compound pages.

The discontiguous kernel page mapping logic handles the compound pages for
us.

sfp->mmap_called keeps the buffer stable for us. As before it is never
cleared, so a failed mmap also leaves it set.

We also remove some useless vma, vma->vm_file NULL checks - these will
always be non-NULL if you reached the mmap hook logic.

We retain log output for consistency, but change what's output on page
mapping to indicate that sg_discontig_get() does the work now.

Note that we drop the VMA_IO_BIT flag for the VMA here. It was never
necessary as we invoke alloc_pages() which gives us refcounted folios that
are fine for GUP to access (VMA_IO_BIT would prevent that).

Signed-off-by: Lorenzo Stoakes (ARM) <ljs@kernel.org>
---
 drivers/scsi/sg.c | 115 ++++++++++++++++++++++++------------------------------
 1 file changed, 51 insertions(+), 64 deletions(-)

diff --git a/drivers/scsi/sg.c b/drivers/scsi/sg.c
index 5408f002e6c0..12837b828b89 100644
--- a/drivers/scsi/sg.c
+++ b/drivers/scsi/sg.c
@@ -1212,85 +1212,72 @@ sg_fasync(int fd, struct file *filp, int mode)
 	return fasync_helper(fd, filp, mode, &sfp->async_qp);
 }
 
-static vm_fault_t
-sg_vma_fault(struct vm_fault *vmf)
+static int sg_discontig_init(void *vm_private_data, void **private)
 {
-	struct vm_area_struct *vma = vmf->vma;
-	Sg_fd *sfp;
-	unsigned long offset, len, sa;
-	Sg_scatter_hold *rsv_schp;
-	int k, length;
-
-	if ((NULL == vma) || (!(sfp = (Sg_fd *) vma->vm_private_data)))
-		return VM_FAULT_SIGBUS;
-	rsv_schp = &sfp->reserve;
-	offset = vmf->pgoff << PAGE_SHIFT;
-	if (offset >= rsv_schp->bufflen)
-		return VM_FAULT_SIGBUS;
-	SCSI_LOG_TIMEOUT(3, sg_printk(KERN_INFO, sfp->parentdp,
-				      "sg_vma_fault: offset=%lu, scatg=%d\n",
-				      offset, rsv_schp->k_use_sg));
-	sa = vma->vm_start;
-	length = 1 << (PAGE_SHIFT + rsv_schp->page_order);
-	for (k = 0; k < rsv_schp->k_use_sg && sa < vma->vm_end; k++) {
-		len = vma->vm_end - sa;
-		len = (len < length) ? len : length;
-		if (offset < len) {
-			struct page *page = rsv_schp->pages[k] + (offset >> PAGE_SHIFT);
-			get_page(page);	/* increment page count */
-			vmf->page = page;
-			return 0; /* success */
-		}
-		sa += len;
-		offset -= len;
+	const unsigned long req_sz = (unsigned long)*private;
+	Sg_fd *sfp = vm_private_data;
+	Sg_scatter_hold *rsv_schp = &sfp->reserve;
+	int err = 0;
+
+	mutex_lock(&sfp->f_mutex);
+	if (req_sz > rsv_schp->bufflen) {
+		err = -ENOMEM;	/* cannot map more than reserved buffer */
+		goto out;
+	}
+	sfp->mmap_called = 1; /* Prevents changes to buffer size. */
+out:
+	mutex_unlock(&sfp->f_mutex);
+	return err;
+}
+
+static int
+sg_discontig_get(struct discontig_kernel_page_state *state)
+{
+	Sg_fd *sfp = state->vm_private_data;
+	Sg_scatter_hold *rsv_schp = &sfp->reserve;
+	const unsigned int order = rsv_schp->page_order;
+	const pgoff_t nr_pages = state->nr_pages_mapped;
+
+	if (nr_pages >= (rsv_schp->bufflen >> PAGE_SHIFT)) {
+		discontig_kernel_map_abort(state);
+		return 0;
 	}
 
-	return VM_FAULT_SIGBUS;
+	SCSI_LOG_TIMEOUT(3, sg_printk(KERN_INFO, sfp->parentdp,
+				      "sg_discontig_get: offset=%lu, scatg=%d\n",
+				      nr_pages << PAGE_SHIFT, rsv_schp->k_use_sg));
+
+	discontig_kernel_map_page(state, rsv_schp->pages[nr_pages >> order]);
+	return 0;
 }
 
-static const struct vm_operations_struct sg_mmap_vm_ops = {
-	.fault = sg_vma_fault,
+static const struct discontig_kernel_page_ops sg_discontig_ops = {
+	.init = sg_discontig_init,
+	.get = sg_discontig_get,
 };
 
 static int
-sg_mmap(struct file *filp, struct vm_area_struct *vma)
+sg_mmap_prepare(struct vm_area_desc *desc)
 {
-	Sg_fd *sfp;
-	unsigned long req_sz, len, sa;
-	Sg_scatter_hold *rsv_schp;
-	int k, length;
-	int ret = 0;
+	Sg_fd *sfp = desc->file->private_data;
+	const unsigned long req_sz = vma_desc_size(desc);
 
-	if ((!filp) || (!vma) || (!(sfp = (Sg_fd *) filp->private_data)))
+	if (!sfp)
 		return -ENXIO;
-	req_sz = vma->vm_end - vma->vm_start;
+
 	SCSI_LOG_TIMEOUT(3, sg_printk(KERN_INFO, sfp->parentdp,
 				      "sg_mmap starting, vm_start=%p, len=%d\n",
-				      (void *) vma->vm_start, (int) req_sz));
-	if (vma->vm_pgoff)
+				      (void *) desc->start, (int) req_sz));
+
+	if (desc->pgoff)
 		return -EINVAL;	/* want no offset */
-	rsv_schp = &sfp->reserve;
-	mutex_lock(&sfp->f_mutex);
-	if (req_sz > rsv_schp->bufflen) {
-		ret = -ENOMEM;	/* cannot map more than reserved buffer */
-		goto out;
-	}
 
-	sa = vma->vm_start;
-	length = 1 << (PAGE_SHIFT + rsv_schp->page_order);
-	for (k = 0; k < rsv_schp->k_use_sg && sa < vma->vm_end; k++) {
-		len = vma->vm_end - sa;
-		len = (len < length) ? len : length;
-		sa += len;
-	}
+	vma_desc_set_flags(desc, VMA_DONTEXPAND_BIT, VMA_DONTDUMP_BIT);
+	desc->private_data = sfp;
 
-	sfp->mmap_called = 1;
-	vm_flags_set(vma, VM_IO | VM_DONTEXPAND | VM_DONTDUMP);
-	vma->vm_private_data = sfp;
-	vma->vm_ops = &sg_mmap_vm_ops;
-out:
-	mutex_unlock(&sfp->f_mutex);
-	return ret;
+	mmap_action_map_discontig_kernel_pages(desc, (void *)req_sz,
+					       &sg_discontig_ops);
+	return 0;
 }
 
 static void
@@ -1415,7 +1402,7 @@ static const struct file_operations sg_fops = {
 	.unlocked_ioctl = sg_ioctl,
 	.compat_ioctl = compat_ptr_ioctl,
 	.open = sg_open,
-	.mmap = sg_mmap,
+	.mmap_prepare = sg_mmap_prepare,
 	.release = sg_release,
 	.fasync = sg_fasync,
 };

-- 
2.55.0


^ permalink raw reply related	[flat|nested] 89+ messages in thread

* [PATCH 18/39] fbdev: defio: assert FBINFO_VIRTFB, drop VM_IO, add VM_MIXEDMAP
  2026-09-08 20:01 [PATCH 00/39] mm: make VMA flag semantics explicit, eliminate VM_SPECIAL Lorenzo Stoakes (ARM)
                   ` (16 preceding siblings ...)
  2026-09-08 20:01 ` [PATCH 17/39] scsi: sg: convert mmap hook to mmap_prepare and rework Lorenzo Stoakes (ARM)
@ 2026-09-08 20:01 ` Lorenzo Stoakes (ARM)
  2026-09-08 20:39   ` sashiko-bot
  2026-09-08 20:01 ` [PATCH 19/39] HSI: cmt_speech: convert mmap hook to mmap_prepare, refactor Lorenzo Stoakes (ARM)
                   ` (20 subsequent siblings)
  38 siblings, 1 reply; 89+ messages in thread
From: Lorenzo Stoakes (ARM) @ 2026-09-08 20:01 UTC (permalink / raw)
  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,
	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, linux-kernel, linux-doc, linux-usb, linux-rdma, selinux,
	linux-sound, bpf, linux-scsi, linux-fbdev, dri-devel,
	linux-trace-kernel, linux-perf-users, linux-arch, linux-fsdevel,
	linux-arm-kernel, kvmarm, linuxppc-dev, kvm, kvm-riscv,
	linux-riscv, linux-s390, sparclinux, fuse-devel,
	Lorenzo Stoakes (ARM)

Currently all drivers which use defio allocate system memory. All of them
also set FBINFO_VIRTFB, other than ssd1307fb, however this driver allocates
system RAM, so simply failed to set this flag when it ought to.

This patch sets FBINFO_VIRTFB on ssd1307fb probe, then drops setting VM_IO
in fb_deferred_io_mmap() and instead requires FBINFO_VIRTFB to be set,
erroring out with a kernel warning if not.

The logic requires a page from the driver and since commit 1ecbc7dd2902
("fbdev/deferred-io: Always call get_page() for framebuffer pages") has
always required it to be refcounted, so this was implicitly already the
case.

Finally this patch sets VM_MIXEDMAP, as the logic is mapping
kernel-allocated memory so this is appropriate.

Signed-off-by: Lorenzo Stoakes (ARM) <ljs@kernel.org>
---
 drivers/video/fbdev/core/fb_defio.c | 6 +++---
 drivers/video/fbdev/ssd1307fb.c     | 2 ++
 2 files changed, 5 insertions(+), 3 deletions(-)

diff --git a/drivers/video/fbdev/core/fb_defio.c b/drivers/video/fbdev/core/fb_defio.c
index fd00b86e1ae6..fb359ecc3966 100644
--- a/drivers/video/fbdev/core/fb_defio.c
+++ b/drivers/video/fbdev/core/fb_defio.c
@@ -366,13 +366,13 @@ int fb_deferred_io_mmap(struct fb_info *info, struct vm_area_struct *vma)
 {
 	vma->vm_page_prot = pgprot_decrypted(vma->vm_page_prot);
 
+	if (WARN_ON_ONCE(!(info->flags & FBINFO_VIRTFB)))
+		return -EINVAL;
 	if (!try_module_get(THIS_MODULE))
 		return -EINVAL;
 
 	vma->vm_ops = &fb_deferred_io_vm_ops;
-	vm_flags_set(vma, VM_DONTEXPAND | VM_DONTDUMP);
-	if (!(info->flags & FBINFO_VIRTFB))
-		vm_flags_set(vma, VM_IO);
+	vm_flags_set(vma, VM_MIXEDMAP | VM_DONTEXPAND | VM_DONTDUMP);
 	vma->vm_private_data = info->fbdefio_state;
 
 	fb_deferred_io_state_get(info->fbdefio_state); /* released in vma->vm_ops->close() */
diff --git a/drivers/video/fbdev/ssd1307fb.c b/drivers/video/fbdev/ssd1307fb.c
index c4fdecafd856..958514a35433 100644
--- a/drivers/video/fbdev/ssd1307fb.c
+++ b/drivers/video/fbdev/ssd1307fb.c
@@ -763,6 +763,8 @@ static int ssd1307fb_probe(struct i2c_client *client)
 	info->fix.smem_start = __pa(vmem);
 	info->fix.smem_len = vmem_size;
 
+	info->flags = FBINFO_VIRTFB;
+
 	fb_deferred_io_init(info);
 
 	i2c_set_clientdata(client, info);

-- 
2.55.0


^ permalink raw reply related	[flat|nested] 89+ messages in thread

* [PATCH 19/39] HSI: cmt_speech: convert mmap hook to mmap_prepare, refactor
  2026-09-08 20:01 [PATCH 00/39] mm: make VMA flag semantics explicit, eliminate VM_SPECIAL Lorenzo Stoakes (ARM)
                   ` (17 preceding siblings ...)
  2026-09-08 20:01 ` [PATCH 18/39] fbdev: defio: assert FBINFO_VIRTFB, drop VM_IO, add VM_MIXEDMAP Lorenzo Stoakes (ARM)
@ 2026-09-08 20:01 ` Lorenzo Stoakes (ARM)
  2026-09-08 20:36   ` sashiko-bot
  2026-09-08 20:01 ` [PATCH 20/39] mm/gup: error out early on !VMA_MAYREAD_BIT VMAs Lorenzo Stoakes (ARM)
                   ` (19 subsequent siblings)
  38 siblings, 1 reply; 89+ messages in thread
From: Lorenzo Stoakes (ARM) @ 2026-09-08 20:01 UTC (permalink / raw)
  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,
	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, linux-kernel, linux-doc, linux-usb, linux-rdma, selinux,
	linux-sound, bpf, linux-scsi, linux-fbdev, dri-devel,
	linux-trace-kernel, linux-perf-users, linux-arch, linux-fsdevel,
	linux-arm-kernel, kvmarm, linuxppc-dev, kvm, kvm-riscv,
	linux-riscv, linux-s390, sparclinux, fuse-devel,
	Lorenzo Stoakes (ARM)

Use the mmap_prepare in favour of the deprecated mmap hook as part of the
work to convert one to another.

Since this is simply a refcounted kernel page that has been allocated, it
should not be marked VM_IO and should be inserted using the kernel page
insertion mechanism, so convert it to do this instead.

Use the VMA descriptor's private data field as a scratch buffer to store
the page in - this stays valid throughout the kernel page mapping
operation.

Signed-off-by: Lorenzo Stoakes (ARM) <ljs@kernel.org>
---
 drivers/hsi/clients/cmt_speech.c | 33 +++++++++------------------------
 1 file changed, 9 insertions(+), 24 deletions(-)

diff --git a/drivers/hsi/clients/cmt_speech.c b/drivers/hsi/clients/cmt_speech.c
index 7226677ebde7..801697b74d4f 100644
--- a/drivers/hsi/clients/cmt_speech.c
+++ b/drivers/hsi/clients/cmt_speech.c
@@ -1084,22 +1084,6 @@ static void cs_hsi_stop(struct cs_hsi_iface *hi)
 	kfree(hi);
 }
 
-static vm_fault_t cs_char_vma_fault(struct vm_fault *vmf)
-{
-	struct cs_char *csdata = vmf->vma->vm_private_data;
-	struct page *page;
-
-	page = virt_to_page((void *)csdata->mmap_base);
-	get_page(page);
-	vmf->page = page;
-
-	return 0;
-}
-
-static const struct vm_operations_struct cs_char_vm_ops = {
-	.fault	= cs_char_vma_fault,
-};
-
 static int cs_char_fasync(int fd, struct file *file, int on)
 {
 	struct cs_char *csdata = file->private_data;
@@ -1256,18 +1240,19 @@ static long cs_char_ioctl(struct file *file, unsigned int cmd,
 	return r;
 }
 
-static int cs_char_mmap(struct file *file, struct vm_area_struct *vma)
+static int cs_char_mmap_prepare(struct vm_area_desc *desc)
 {
-	if (vma->vm_end < vma->vm_start)
-		return -EINVAL;
+	struct file *file = desc->file;
+	struct cs_char *csdata = file->private_data;
+	struct page **pages = (struct page **)&desc->private_data;
 
-	if (vma_pages(vma) != 1)
+	if (vma_desc_pages(desc) != 1)
 		return -EINVAL;
 
-	vm_flags_set(vma, VM_IO | VM_DONTDUMP | VM_DONTEXPAND);
-	vma->vm_ops = &cs_char_vm_ops;
-	vma->vm_private_data = file->private_data;
+	vma_desc_set_flags(desc, VMA_DONTDUMP_BIT, VMA_DONTEXPAND_BIT);
 
+	*pages = virt_to_page((void *)csdata->mmap_base);
+	mmap_action_map_kernel_pages_full(desc, pages);
 	return 0;
 }
 
@@ -1353,7 +1338,7 @@ static const struct file_operations cs_char_fops = {
 	.write		= cs_char_write,
 	.poll		= cs_char_poll,
 	.unlocked_ioctl	= cs_char_ioctl,
-	.mmap		= cs_char_mmap,
+	.mmap_prepare	= cs_char_mmap_prepare,
 	.open		= cs_char_open,
 	.release	= cs_char_release,
 	.fasync		= cs_char_fasync,

-- 
2.55.0


^ permalink raw reply related	[flat|nested] 89+ messages in thread

* [PATCH 20/39] mm/gup: error out early on !VMA_MAYREAD_BIT VMAs
  2026-09-08 20:01 [PATCH 00/39] mm: make VMA flag semantics explicit, eliminate VM_SPECIAL Lorenzo Stoakes (ARM)
                   ` (18 preceding siblings ...)
  2026-09-08 20:01 ` [PATCH 19/39] HSI: cmt_speech: convert mmap hook to mmap_prepare, refactor Lorenzo Stoakes (ARM)
@ 2026-09-08 20:01 ` Lorenzo Stoakes (ARM)
  2026-09-08 20:36   ` sashiko-bot
  2026-09-08 20:01 ` [PATCH 21/39] uprobes: remove VM_IO, set VM_MIXEDMAP for mapped kernel pages Lorenzo Stoakes (ARM)
                   ` (18 subsequent siblings)
  38 siblings, 1 reply; 89+ messages in thread
From: Lorenzo Stoakes (ARM) @ 2026-09-08 20:01 UTC (permalink / raw)
  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,
	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, linux-kernel, linux-doc, linux-usb, linux-rdma, selinux,
	linux-sound, bpf, linux-scsi, linux-fbdev, dri-devel,
	linux-trace-kernel, linux-perf-users, linux-arch, linux-fsdevel,
	linux-arm-kernel, kvmarm, linuxppc-dev, kvm, kvm-riscv,
	linux-riscv, linux-s390, sparclinux, fuse-devel,
	Lorenzo Stoakes (ARM)

When populating a VMA range via the aptly named populate_vma_page_range()
an unreadable VMA will always eventually fail with -EFAULT.

That a VMA is accessible is always checked, however VMA_MAYREAD_BIT is not.

All user mappings always have VMA_MAYREAD_BIT set, so this check only
impacts kernel mappings.

It is implemented specifically to disallow population of uprobes XOL
mappings which are exec-only.

A nasty interaction with these mappings may occur if they are mlocked, so
actively disallow this early.

This allows a subsequent commit to remove the VM_IO check in
__mm_populate() which otherwise requires non-MMIO mappings to be wrongly
flagged simply as a workaround.

Signed-off-by: Lorenzo Stoakes (ARM) <ljs@kernel.org>
---
 mm/gup.c | 4 ++++
 1 file changed, 4 insertions(+)

diff --git a/mm/gup.c b/mm/gup.c
index a4036c02e213..f5dc227bd6e1 100644
--- a/mm/gup.c
+++ b/mm/gup.c
@@ -1836,6 +1836,10 @@ long populate_vma_page_range(struct vm_area_struct *vma,
 	if (!vma_is_accessible(vma))
 		return -EFAULT;
 
+	/* Unreadable VMAs also cannot be faulted in. */
+	if (!vma_test(vma, VMA_MAYREAD_BIT))
+		return -EFAULT;
+
 	gup_flags = FOLL_TOUCH;
 	/*
 	 * We want to touch writable mappings with a write fault in order

-- 
2.55.0


^ permalink raw reply related	[flat|nested] 89+ messages in thread

* [PATCH 21/39] uprobes: remove VM_IO, set VM_MIXEDMAP for mapped kernel pages
  2026-09-08 20:01 [PATCH 00/39] mm: make VMA flag semantics explicit, eliminate VM_SPECIAL Lorenzo Stoakes (ARM)
                   ` (19 preceding siblings ...)
  2026-09-08 20:01 ` [PATCH 20/39] mm/gup: error out early on !VMA_MAYREAD_BIT VMAs Lorenzo Stoakes (ARM)
@ 2026-09-08 20:01 ` Lorenzo Stoakes (ARM)
  2026-09-08 20:36   ` sashiko-bot
  2026-09-08 20:01 ` [PATCH 22/39] mm/mlock: clear VMA_LOCKED_MASK over mmap callback Lorenzo Stoakes (ARM)
                   ` (17 subsequent siblings)
  38 siblings, 1 reply; 89+ messages in thread
From: Lorenzo Stoakes (ARM) @ 2026-09-08 20:01 UTC (permalink / raw)
  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,
	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, linux-kernel, linux-doc, linux-usb, linux-rdma, selinux,
	linux-sound, bpf, linux-scsi, linux-fbdev, dri-devel,
	linux-trace-kernel, linux-perf-users, linux-arch, linux-fsdevel,
	linux-arm-kernel, kvmarm, linuxppc-dev, kvm, kvm-riscv,
	linux-riscv, linux-s390, sparclinux, fuse-devel,
	Lorenzo Stoakes (ARM)

These are not MMIO pages so VMA_IO_BIT is an inappropriate flag to set.

Instead, set them VMA_MIXEDMAP_BIT as they are kernel mappings and this is
the appropriate flag to set for those.

This provides the semantics required - no VMA merging is permitted, but
does not prevent GUP.

However this has no meaningful impact as these are refcounted and thus can
be GUPed.

A previous commit already prevented __mm_populate() from being invoked on
XOL areas which prevents so that is no longer required.

Both VMAs set a VMA name, so always_dump_vma() returns true before
vma_dump_size() reaches its VMA_IO_BIT check, and thus there is no change
in core dump behaviour.

Change this for both the core xol_add_vma() function and the x86-specific
get_uprobe_trampoline() function.

Signed-off-by: Lorenzo Stoakes (ARM) <ljs@kernel.org>
---
 arch/x86/kernel/uprobes.c | 2 +-
 kernel/events/uprobes.c   | 4 ++--
 2 files changed, 3 insertions(+), 3 deletions(-)

diff --git a/arch/x86/kernel/uprobes.c b/arch/x86/kernel/uprobes.c
index 65a2de82ecd2..0f60c0d076b6 100644
--- a/arch/x86/kernel/uprobes.c
+++ b/arch/x86/kernel/uprobes.c
@@ -715,7 +715,7 @@ static struct vm_area_struct *get_uprobe_trampoline(struct mm_struct *mm, unsign
 
 	*new_mapping = true;
 	return _install_special_mapping(mm, vaddr, PAGE_SIZE,
-				VM_READ|VM_EXEC|VM_MAYEXEC|VM_MAYREAD|VM_IO,
+				VM_READ|VM_EXEC|VM_MAYEXEC|VM_MAYREAD|VM_MIXEDMAP,
 				&tramp_mapping);
 }
 
diff --git a/kernel/events/uprobes.c b/kernel/events/uprobes.c
index 7709ea882477..b89cc5cee002 100644
--- a/kernel/events/uprobes.c
+++ b/kernel/events/uprobes.c
@@ -1726,8 +1726,8 @@ static int xol_add_vma(struct mm_struct *mm, struct xol_area *area)
 	}
 
 	vma = _install_special_mapping(mm, area->vaddr, PAGE_SIZE,
-				VM_EXEC|VM_MAYEXEC|VM_DONTCOPY|VM_IO|
-				VM_SEALED_SYSMAP,
+				VM_EXEC|VM_MAYEXEC|VM_DONTCOPY|
+				VM_MIXEDMAP|VM_SEALED_SYSMAP,
 				&xol_mapping);
 	if (IS_ERR(vma)) {
 		ret = PTR_ERR(vma);

-- 
2.55.0


^ permalink raw reply related	[flat|nested] 89+ messages in thread

* [PATCH 22/39] mm/mlock: clear VMA_LOCKED_MASK over mmap callback
  2026-09-08 20:01 [PATCH 00/39] mm: make VMA flag semantics explicit, eliminate VM_SPECIAL Lorenzo Stoakes (ARM)
                   ` (20 preceding siblings ...)
  2026-09-08 20:01 ` [PATCH 21/39] uprobes: remove VM_IO, set VM_MIXEDMAP for mapped kernel pages Lorenzo Stoakes (ARM)
@ 2026-09-08 20:01 ` Lorenzo Stoakes (ARM)
  2026-09-08 20:38   ` sashiko-bot
  2026-09-08 20:01 ` [PATCH 23/39] mm/mlock: eliminate weird VMA_IO_BIT abuse and simplify Lorenzo Stoakes (ARM)
                   ` (16 subsequent siblings)
  38 siblings, 1 reply; 89+ messages in thread
From: Lorenzo Stoakes (ARM) @ 2026-09-08 20:01 UTC (permalink / raw)
  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,
	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, linux-kernel, linux-doc, linux-usb, linux-rdma, selinux,
	linux-sound, bpf, linux-scsi, linux-fbdev, dri-devel,
	linux-trace-kernel, linux-perf-users, linux-arch, linux-fsdevel,
	linux-arm-kernel, kvmarm, linuxppc-dev, kvm, kvm-riscv,
	linux-riscv, linux-s390, sparclinux, fuse-devel,
	Lorenzo Stoakes (ARM)

Currently there's a confusing mess around VMA_LOCKED_BIT and
VMA_LOCKONFAULT_BIT.

It is permitted for drivers to set any flags they like, with the VMA
already possessing lock flags.

This results in the absurd situation of a VMA possessing both
VMA_SPECIAL_FLAGS and VMA_LOCKED_MASK flags, which is not permitted.

This has resulted in mlock_vma_folio() having a very silly check for this
scenario to work around it.

There is no need for this - just clear the flags before invoking the hook
and reinstate them afterwards if they are required.

Nothing relies upon this being set during the mmap operation.

mmap_prepare is unaffected by this so requires no fix.

Signed-off-by: Lorenzo Stoakes (ARM) <ljs@kernel.org>
---
 mm/internal.h |  9 +--------
 mm/vma.c      | 14 ++++++++++++++
 2 files changed, 15 insertions(+), 8 deletions(-)

diff --git a/mm/internal.h b/mm/internal.h
index a86b9803a4c3..6e27d3b10c01 100644
--- a/mm/internal.h
+++ b/mm/internal.h
@@ -975,14 +975,7 @@ void mlock_folio(struct folio *folio);
 static inline void mlock_vma_folio(struct folio *folio,
 				struct vm_area_struct *vma)
 {
-	/*
-	 * The VM_SPECIAL check here serves two purposes.
-	 * 1) VM_IO check prevents migration from double-counting during mlock.
-	 * 2) Although mmap_region() and mlock_fixup() take care that VM_LOCKED
-	 *    is never left set on a VM_SPECIAL vma, there is an interval while
-	 *    file->f_op->mmap() is using vm_insert_page(s), when VM_LOCKED may
-	 *    still be set while VM_SPECIAL bits are added: so ignore it then.
-	 */
+	/* The VM_IO check prevents migration from double-counting during mlock. */
 	if (unlikely((vma->vm_flags & (VM_LOCKED|VM_SPECIAL)) == VM_LOCKED))
 		mlock_folio(folio);
 }
diff --git a/mm/vma.c b/mm/vma.c
index 526428753218..cb0c4c625756 100644
--- a/mm/vma.c
+++ b/mm/vma.c
@@ -2594,6 +2594,11 @@ static int __mmap_new_file_vma(struct mmap_state *map,
 	if (!map->file->f_op->mmap)
 		return 0;
 
+	/*
+	 * Driver-specified flags may make the lock flags invalid, so clear
+	 * VMA_LOCKED_MASK and reinstate it afterwards if appropriate.
+	 */
+	vma_clear_flags_mask(vma, VMA_LOCKED_MASK);
 	error = mmap_file(vma->vm_file, vma);
 	if (error) {
 		UNMAP_STATE(unmap, vmi, vma, vma->vm_start, vma->vm_end,
@@ -2607,6 +2612,15 @@ static int __mmap_new_file_vma(struct mmap_state *map,
 		return error;
 	}
 
+	/* If VMA flags still valid for locked mask, reinstate. */
+	if (vma_supports_mlock(vma)) {
+		const vma_flags_t mask =
+			vma_flags_and_mask(&map->vma_flags,
+					   VMA_LOCKED_MASK);
+
+		vma_set_flags_mask(vma, mask);
+	}
+
 	map->file = vma->vm_file;
 	map->vma_flags = vma->flags;
 

-- 
2.55.0


^ permalink raw reply related	[flat|nested] 89+ messages in thread

* [PATCH 23/39] mm/mlock: eliminate weird VMA_IO_BIT abuse and simplify
  2026-09-08 20:01 [PATCH 00/39] mm: make VMA flag semantics explicit, eliminate VM_SPECIAL Lorenzo Stoakes (ARM)
                   ` (21 preceding siblings ...)
  2026-09-08 20:01 ` [PATCH 22/39] mm/mlock: clear VMA_LOCKED_MASK over mmap callback Lorenzo Stoakes (ARM)
@ 2026-09-08 20:01 ` Lorenzo Stoakes (ARM)
  2026-09-08 20:47   ` sashiko-bot
  2026-09-08 20:01 ` [PATCH 24/39] mm/vma: enforce that only kernel-owned mappings may set VMA_IO_BIT Lorenzo Stoakes (ARM)
                   ` (15 subsequent siblings)
  38 siblings, 1 reply; 89+ messages in thread
From: Lorenzo Stoakes (ARM) @ 2026-09-08 20:01 UTC (permalink / raw)
  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,
	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, linux-kernel, linux-doc, linux-usb, linux-rdma, selinux,
	linux-sound, bpf, linux-scsi, linux-fbdev, dri-devel,
	linux-trace-kernel, linux-perf-users, linux-arch, linux-fsdevel,
	linux-arm-kernel, kvmarm, linuxppc-dev, kvm, kvm-riscv,
	linux-riscv, linux-s390, sparclinux, fuse-devel,
	Lorenzo Stoakes (ARM)

When performing mlock() or munlock() otherwise normal VMAs have VMA_IO_BIT
solely to fix a race with migration which might otherwise double-count
mlock VMAs.

This is unnecessary - at the point of applying folio mlock state, whether
setting or clearing PG_mlocked, we know whether or not we are locking.

Solve this in two ways - thread a boolean through the page table walk
indicating whether a lock or unlock is being performed, and run a locking
walk with VMA_LOCKONFAULT_BIT set and VMA_LOCKED_BIT cleared.

This state never occurs otherwise, as VMA_LOCKONFAULT_BIT always implies
VMA_LOCKED_BIT. These are also always cleared together.

Then, update folio_add_lru_vma() and mlock_folio() to check only for
VMA_LOCKED_BIT, and update try_to_unmap_one() to check for VMA_LOCKED_MASK
instead.

Also remove the useless invocation of allow_mlock_munlock() which simply
returns true if unlocking and instead rename it to allow_mlock() and only
call it when locking.

Finally, with the other mlock abuse of VMA_IO_BIT addressed, update
mlock_vma_folio(), munlock_vma_folio() and folio_add_lru_vma() to simply
test for VMA_LOCKED_BIT.

While here, also replace some deprecated VMA flag predicates.

Signed-off-by: Lorenzo Stoakes (ARM) <ljs@kernel.org>
---
 mm/folio.c    |  2 +-
 mm/internal.h |  5 ++---
 mm/mlock.c    | 51 +++++++++++++++++++--------------------------------
 mm/rmap.c     |  4 +++-
 4 files changed, 25 insertions(+), 37 deletions(-)

diff --git a/mm/folio.c b/mm/folio.c
index 50a6dbe55998..a3f5c463f665 100644
--- a/mm/folio.c
+++ b/mm/folio.c
@@ -502,7 +502,7 @@ void folio_add_lru_vma(struct folio *folio, struct vm_area_struct *vma)
 {
 	VM_BUG_ON_FOLIO(folio_test_lru(folio), folio);
 
-	if (unlikely((vma->vm_flags & (VM_LOCKED | VM_SPECIAL)) == VM_LOCKED))
+	if (vma_test(vma, VMA_LOCKED_BIT))
 		mlock_new_folio(folio);
 	else
 		folio_add_lru(folio);
diff --git a/mm/internal.h b/mm/internal.h
index 6e27d3b10c01..04b1f1d3d960 100644
--- a/mm/internal.h
+++ b/mm/internal.h
@@ -975,8 +975,7 @@ void mlock_folio(struct folio *folio);
 static inline void mlock_vma_folio(struct folio *folio,
 				struct vm_area_struct *vma)
 {
-	/* The VM_IO check prevents migration from double-counting during mlock. */
-	if (unlikely((vma->vm_flags & (VM_LOCKED|VM_SPECIAL)) == VM_LOCKED))
+	if (vma_test(vma, VMA_LOCKED_BIT))
 		mlock_folio(folio);
 }
 
@@ -993,7 +992,7 @@ static inline void munlock_vma_folio(struct folio *folio,
 	 * always munlock the folio and page reclaim will correct it
 	 * if it's wrong.
 	 */
-	if (unlikely(vma->vm_flags & VM_LOCKED))
+	if (unlikely(vma_test(vma, VMA_LOCKED_BIT)))
 		munlock_folio(folio);
 }
 
diff --git a/mm/mlock.c b/mm/mlock.c
index 39215a3eab1f..4235a1518fc9 100644
--- a/mm/mlock.c
+++ b/mm/mlock.c
@@ -316,22 +316,10 @@ static inline unsigned int folio_mlock_step(struct folio *folio,
 	return folio_pte_batch(folio, pte, ptent, count);
 }
 
-static inline bool allow_mlock_munlock(struct folio *folio,
+static inline bool allow_mlock(struct folio *folio,
 		struct vm_area_struct *vma, unsigned long start,
 		unsigned long end, unsigned int step)
 {
-	/*
-	 * For unlock, allow munlock large folio which is partially
-	 * mapped to VMA. As it's possible that large folio is
-	 * mlocked and VMA is split later.
-	 *
-	 * During memory pressure, such kind of large folio can
-	 * be split. And the pages are not in VM_LOCKed VMA
-	 * can be reclaimed.
-	 */
-	if (!vma_test(vma, VMA_LOCKED_BIT))
-		return true;
-
 	/* folio_within_range() cannot take KSM, but any small folio is OK */
 	if (!folio_test_large(folio))
 		return true;
@@ -352,6 +340,7 @@ static int mlock_pte_range(pmd_t *pmd, unsigned long addr,
 
 {
 	struct vm_area_struct *vma = walk->vma;
+	const bool lock = walk->private;
 	spinlock_t *ptl;
 	pte_t *start_pte, *pte;
 	pte_t ptent;
@@ -368,7 +357,7 @@ static int mlock_pte_range(pmd_t *pmd, unsigned long addr,
 		folio = pmd_folio(*pmd);
 		if (folio_is_zone_device(folio))
 			goto out;
-		if (vma_test(vma, VMA_LOCKED_BIT))
+		if (lock)
 			mlock_folio(folio);
 		else
 			munlock_folio(folio);
@@ -390,10 +379,10 @@ static int mlock_pte_range(pmd_t *pmd, unsigned long addr,
 			continue;
 
 		step = folio_mlock_step(folio, pte, addr, end);
-		if (!allow_mlock_munlock(folio, vma, start, end, step))
+		if (lock && !allow_mlock(folio, vma, start, end, step))
 			goto next_entry;
 
-		if (vma_test(vma, VMA_LOCKED_BIT))
+		if (lock)
 			mlock_folio(folio);
 		else
 			munlock_folio(folio);
@@ -428,31 +417,29 @@ static void mlock_vma_pages_range(struct vm_area_struct *vma,
 		.pmd_entry = mlock_pte_range,
 		.walk_lock = PGWALK_WRLOCK_VERIFY,
 	};
+	const bool lock = vma_flags_test(new_vma_flags, VMA_LOCKED_BIT);
+	vma_flags_t walk_flags = *new_vma_flags;
 
 	/*
-	 * There is a slight chance that concurrent page migration,
-	 * or page reclaim finding a page of this now-VMA_LOCKED_BIT vma,
-	 * will call mlock_vma_folio() and raise page's mlock_count:
-	 * double counting, leaving the page unevictable indefinitely.
-	 * Communicate this danger to mlock_vma_folio() with VMA_IO_BIT,
-	 * which is a VMA_SPECIAL_FLAGS flag not allowed on VMA_LOCKED_BIT vmas.
-	 * mmap_lock is held in write mode here, so this weird
-	 * combination should not be visible to other mmap_lock users;
-	 * but WRITE_ONCE so rmap walkers must see VMA_IO_BIT if VMA_LOCKED_BIT.
+	 * LOCKONFAULT without LOCKED never otherwise occurs: it marks a walk in
+	 * progress so that rmap-side callers, which test VMA_LOCKED_BIT, do not
+	 * count folios, while try_to_unmap_one(), which tests VMA_LOCKED_MASK,
+	 * still refuses to unmap them.
 	 */
-	if (vma_flags_test(new_vma_flags, VMA_LOCKED_BIT))
-		vma_flags_set(new_vma_flags, VMA_IO_BIT);
+	if (lock) {
+		vma_flags_clear(&walk_flags, VMA_LOCKED_BIT);
+		vma_flags_set(&walk_flags, VMA_LOCKONFAULT_BIT);
+	}
+
 	vma_start_write(vma);
-	vma_flags_reset_once(vma, new_vma_flags);
+	vma_flags_reset_once(vma, &walk_flags);
 
 	lru_add_drain();
-	walk_page_range_vma(vma, start, end, &mlock_walk_ops, NULL);
+	walk_page_range_vma(vma, start, end, &mlock_walk_ops, (void *)lock);
 	lru_add_drain();
 
-	if (vma_flags_test(new_vma_flags, VMA_IO_BIT)) {
-		vma_flags_clear(new_vma_flags, VMA_IO_BIT);
+	if (lock)
 		vma_flags_reset_once(vma, new_vma_flags);
-	}
 }
 
 /*
diff --git a/mm/rmap.c b/mm/rmap.c
index 5fefe5b060b1..120c894d2dde 100644
--- a/mm/rmap.c
+++ b/mm/rmap.c
@@ -2239,9 +2239,11 @@ static bool try_to_unmap_one(struct folio *folio, struct vm_area_struct *vma,
 
 		/*
 		 * If the folio is in an mlock()d vma, we must not swap it out.
+		 * VMA_LOCKONFAULT_BIT alone marks an mlock walk in progress, see
+		 * mlock_vma_pages_range().
 		 */
 		if (!(flags & TTU_IGNORE_MLOCK) &&
-		    (vma->vm_flags & VM_LOCKED)) {
+		    vma_test_any_mask(vma, VMA_LOCKED_MASK)) {
 			ptes++;
 
 			/*

-- 
2.55.0


^ permalink raw reply related	[flat|nested] 89+ messages in thread

* [PATCH 24/39] mm/vma: enforce that only kernel-owned mappings may set VMA_IO_BIT
  2026-09-08 20:01 [PATCH 00/39] mm: make VMA flag semantics explicit, eliminate VM_SPECIAL Lorenzo Stoakes (ARM)
                   ` (22 preceding siblings ...)
  2026-09-08 20:01 ` [PATCH 23/39] mm/mlock: eliminate weird VMA_IO_BIT abuse and simplify Lorenzo Stoakes (ARM)
@ 2026-09-08 20:01 ` Lorenzo Stoakes (ARM)
  2026-09-08 20:47   ` sashiko-bot
  2026-09-08 20:01 ` [PATCH 25/39] mm: remove VMA_IO_BIT check in vma[_flags]_is_kernel_owned() Lorenzo Stoakes (ARM)
                   ` (14 subsequent siblings)
  38 siblings, 1 reply; 89+ messages in thread
From: Lorenzo Stoakes (ARM) @ 2026-09-08 20:01 UTC (permalink / raw)
  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,
	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, linux-kernel, linux-doc, linux-usb, linux-rdma, selinux,
	linux-sound, bpf, linux-scsi, linux-fbdev, dri-devel,
	linux-trace-kernel, linux-perf-users, linux-arch, linux-fsdevel,
	linux-arm-kernel, kvmarm, linuxppc-dev, kvm, kvm-riscv,
	linux-riscv, linux-s390, sparclinux, fuse-devel,
	Lorenzo Stoakes (ARM)

It makes no sense for a mapping whose contents the kernel does not own to
specify that the range is MMIO.

Prior to this patch, all in-tree drivers which did so have been updated
such that they are marked as kernel-owned. The check WARNs and fails the
mmap for any out-of-tree driver that still sets VMA_IO_BIT without a kernel
mapping.

No functional change intended for in-tree code.

Signed-off-by: Lorenzo Stoakes (ARM) <ljs@kernel.org>
---
 mm/vma.c | 6 ++++++
 1 file changed, 6 insertions(+)

diff --git a/mm/vma.c b/mm/vma.c
index cb0c4c625756..5996757d5aaf 100644
--- a/mm/vma.c
+++ b/mm/vma.c
@@ -2772,6 +2772,12 @@ static int mmap_validate_vma_flags(const vma_flags_t *flags)
 		return -EINVAL;
 #endif
 
+	if (!vma_flags_test_any(flags, VMA_PFNMAP_BIT, VMA_MIXEDMAP_BIT)) {
+		/* Only kernel-owned mappings may set VMA_IO_BIT. */
+		if (WARN_ON_ONCE(vma_flags_test(flags, VMA_IO_BIT)))
+			return -EINVAL;
+	}
+
 	return 0;
 }
 

-- 
2.55.0


^ permalink raw reply related	[flat|nested] 89+ messages in thread

* [PATCH 25/39] mm: remove VMA_IO_BIT check in vma[_flags]_is_kernel_owned()
  2026-09-08 20:01 [PATCH 00/39] mm: make VMA flag semantics explicit, eliminate VM_SPECIAL Lorenzo Stoakes (ARM)
                   ` (23 preceding siblings ...)
  2026-09-08 20:01 ` [PATCH 24/39] mm/vma: enforce that only kernel-owned mappings may set VMA_IO_BIT Lorenzo Stoakes (ARM)
@ 2026-09-08 20:01 ` Lorenzo Stoakes (ARM)
  2026-09-08 20:37   ` sashiko-bot
  2026-09-08 20:01 ` [PATCH 26/39] mm: remove hugetlb_inline.h Lorenzo Stoakes (ARM)
                   ` (13 subsequent siblings)
  38 siblings, 1 reply; 89+ messages in thread
From: Lorenzo Stoakes (ARM) @ 2026-09-08 20:01 UTC (permalink / raw)
  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,
	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, linux-kernel, linux-doc, linux-usb, linux-rdma, selinux,
	linux-sound, bpf, linux-scsi, linux-fbdev, dri-devel,
	linux-trace-kernel, linux-perf-users, linux-arch, linux-fsdevel,
	linux-arm-kernel, kvmarm, linuxppc-dev, kvm, kvm-riscv,
	linux-riscv, linux-s390, sparclinux, fuse-devel,
	Lorenzo Stoakes (ARM)

We have now made it such that every driver which sets VMA_IO_BIT marks it
as kernel-owned.

However, vma_flags_is_kernel_owned() currently checks for VMA_IO_BIT. This
was a product of drivers previously marking a range as kernel-owned by
setting VMA_IO_BIT alone.

Fix this by removing the VMA_IO_BIT check in vma_flags_is_kernel_owned(),
and update mmap_validate_vma_flags() to use vma_flags_is_kernel_owned()
rather than open-coding the VMA_PFNMAP_BIT, VMA_MIXEDMAP_BIT check.

This change means that vma[_flags]_can_merge() doesn't check VMA_IO_BIT any
longer (which is now redundant) as it calls vma_flags_is_kernel_owned().

Now that the predicate means precisely VMA_PFNMAP_BIT or VMA_MIXEDMAP_BIT,
also use it at the other sites which open-code that pair, so the intent is
stated rather than the flags, with no functional change:

zap_special_vma_range() only zaps kernel-owned mappings, as drivers use it
to tear down ranges they established themselves.

The mprotect() arch PFN modification check applies to kernel-owned
mappings, which may map PFNs without struct pages.

NUMA balancing skips VM_MIXEDMAP mappings having already excluded VM_IO
and VM_PFNMAP mappings via vma_migratable(), so it skips exactly the
kernel-owned mappings - say so.

Finally, update the VMA userland merge 'special' flag tests to no longer
assert that VMA_IO_BIT prevents merge as VMA_PFNMAP_BIT, VMA_MIXEDMAP_BIT
now suffices.

Signed-off-by: Lorenzo Stoakes (ARM) <ljs@kernel.org>
---
 include/linux/mm.h              |  3 +--
 kernel/sched/fair.c             |  2 +-
 mm/memory.c                     |  6 +++---
 mm/mprotect.c                   |  3 +--
 mm/vma.c                        |  2 +-
 tools/testing/vma/include/dup.h |  3 +--
 tools/testing/vma/tests/merge.c | 10 ++--------
 7 files changed, 10 insertions(+), 19 deletions(-)

diff --git a/include/linux/mm.h b/include/linux/mm.h
index bca955941212..15fc4509784b 100644
--- a/include/linux/mm.h
+++ b/include/linux/mm.h
@@ -1630,8 +1630,7 @@ static inline bool vma_is_shared_maywrite(const struct vm_area_struct *vma)
  */
 static inline bool vma_flags_is_kernel_owned(const vma_flags_t *flags)
 {
-	return vma_flags_test_any(flags, VMA_PFNMAP_BIT, VMA_MIXEDMAP_BIT,
-				  VMA_IO_BIT);
+	return vma_flags_test_any(flags, VMA_PFNMAP_BIT, VMA_MIXEDMAP_BIT);
 }
 
 /**
diff --git a/kernel/sched/fair.c b/kernel/sched/fair.c
index 8dff37059faf..a71f0ab79bcd 100644
--- a/kernel/sched/fair.c
+++ b/kernel/sched/fair.c
@@ -4212,7 +4212,7 @@ static void task_numa_work(struct callback_head *work)
 
 	for (; vma; vma = vma_next(&vmi)) {
 		if (!vma_migratable(vma) || !vma_policy_mof(vma) ||
-			is_vm_hugetlb_page(vma) || (vma->vm_flags & VM_MIXEDMAP)) {
+			is_vm_hugetlb_page(vma) || vma_is_kernel_owned(vma)) {
 			trace_sched_skip_vma_numa(mm, vma, NUMAB_SKIP_UNSUITABLE);
 			continue;
 		}
diff --git a/mm/memory.c b/mm/memory.c
index 8c9675451d4b..28c1bb7b93af 100644
--- a/mm/memory.c
+++ b/mm/memory.c
@@ -2343,19 +2343,19 @@ void zap_vma_range(struct vm_area_struct *vma, unsigned long address,
 }
 
 /**
- * zap_special_vma_range - zap all page table entries in a special vma range
+ * zap_special_vma_range - zap all page table entries in a kernel-owned VMA
  * @vma: the vma covering the range to zap
  * @address: starting address of the range to zap
  * @size: number of bytes to zap
  *
  * This function does nothing when the provided address range is not fully
- * contained in @vma, or when the @vma is not VM_PFNMAP or VM_MIXEDMAP.
+ * contained in @vma, or when @vma is not kernel-owned.
  */
 void zap_special_vma_range(struct vm_area_struct *vma, unsigned long address,
 		unsigned long size)
 {
 	if (!range_in_vma(vma, address, address + size) ||
-	   !(vma->vm_flags & (VM_PFNMAP | VM_MIXEDMAP)))
+	   !vma_is_kernel_owned(vma))
 		return;
 
 	zap_vma_range(vma, address, size);
diff --git a/mm/mprotect.c b/mm/mprotect.c
index 2888ee638d87..fe32fd87cf5c 100644
--- a/mm/mprotect.c
+++ b/mm/mprotect.c
@@ -783,8 +783,7 @@ mprotect_fixup(struct vma_iterator *vmi, struct mmu_gather *tlb,
 	 * uncommon case, so doesn't need to be very optimized.
 	 */
 	if (arch_has_pfn_modify_check() &&
-	    vma_flags_test_any(&old_vma_flags, VMA_PFNMAP_BIT,
-			       VMA_MIXEDMAP_BIT) &&
+	    vma_flags_is_kernel_owned(&old_vma_flags) &&
 	    !vma_flags_test_any_mask(&new_vma_flags, VMA_ACCESS_FLAGS)) {
 		pgprot_t new_pgprot = vm_get_page_prot(newflags);
 
diff --git a/mm/vma.c b/mm/vma.c
index 5996757d5aaf..eb2b4501a677 100644
--- a/mm/vma.c
+++ b/mm/vma.c
@@ -2772,7 +2772,7 @@ static int mmap_validate_vma_flags(const vma_flags_t *flags)
 		return -EINVAL;
 #endif
 
-	if (!vma_flags_test_any(flags, VMA_PFNMAP_BIT, VMA_MIXEDMAP_BIT)) {
+	if (!vma_flags_is_kernel_owned(flags)) {
 		/* Only kernel-owned mappings may set VMA_IO_BIT. */
 		if (WARN_ON_ONCE(vma_flags_test(flags, VMA_IO_BIT)))
 			return -EINVAL;
diff --git a/tools/testing/vma/include/dup.h b/tools/testing/vma/include/dup.h
index 3fe40e0f4034..e6cb2ea196f2 100644
--- a/tools/testing/vma/include/dup.h
+++ b/tools/testing/vma/include/dup.h
@@ -1661,8 +1661,7 @@ static inline bool file_is_dev_zero(const struct file *file)
 
 static inline bool vma_flags_is_kernel_owned(const vma_flags_t *flags)
 {
-	return vma_flags_test_any(flags, VMA_PFNMAP_BIT, VMA_MIXEDMAP_BIT,
-				  VMA_IO_BIT);
+	return vma_flags_test_any(flags, VMA_PFNMAP_BIT, VMA_MIXEDMAP_BIT);
 }
 
 static inline bool vma_is_kernel_owned(const struct vm_area_struct *vma)
diff --git a/tools/testing/vma/tests/merge.c b/tools/testing/vma/tests/merge.c
index acaab282939c..b26f1a66a170 100644
--- a/tools/testing/vma/tests/merge.c
+++ b/tools/testing/vma/tests/merge.c
@@ -496,17 +496,11 @@ static bool test_vma_merge_special_flags(void)
 		.mm = &mm,
 		.vmi = &vmi,
 	};
-	vma_flag_t special_flags[] = { VMA_IO_BIT, VMA_DONTEXPAND_BIT,
+	vma_flag_t special_flags[] = { VMA_DONTEXPAND_BIT,
 		VMA_PFNMAP_BIT, VMA_MIXEDMAP_BIT };
-	vma_flags_t all_special_flags = EMPTY_VMA_FLAGS;
 	int i;
 	struct vm_area_struct *vma_left, *vma;
 
-	/* Make sure there aren't new VM_SPECIAL flags. */
-	for (i = 0; i < ARRAY_SIZE(special_flags); i++)
-		vma_flags_set(&all_special_flags, special_flags[i]);
-	ASSERT_FLAGS_SAME_MASK(&all_special_flags, VMA_SPECIAL_FLAGS);
-
 	/*
 	 * 01234
 	 * AAA
@@ -520,7 +514,7 @@ static bool test_vma_merge_special_flags(void)
 	 * 01234
 	 * AAA*
 	 *
-	 * This should merge if not for the VM_SPECIAL flag.
+	 * This should merge if not for the 'special' flag.
 	 */
 	vmg_set_range(&vmg, 0x3000, 0x4000, 3, vma_flags);
 	for (i = 0; i < ARRAY_SIZE(special_flags); i++) {

-- 
2.55.0


^ permalink raw reply related	[flat|nested] 89+ messages in thread

* [PATCH 26/39] mm: remove hugetlb_inline.h
  2026-09-08 20:01 [PATCH 00/39] mm: make VMA flag semantics explicit, eliminate VM_SPECIAL Lorenzo Stoakes (ARM)
                   ` (24 preceding siblings ...)
  2026-09-08 20:01 ` [PATCH 25/39] mm: remove VMA_IO_BIT check in vma[_flags]_is_kernel_owned() Lorenzo Stoakes (ARM)
@ 2026-09-08 20:01 ` Lorenzo Stoakes (ARM)
  2026-09-08 20:34   ` sashiko-bot
  2026-09-08 20:01 ` [PATCH 27/39] mm: rename is_vm_hugetlb_page() to vma_is_hugetlb() Lorenzo Stoakes (ARM)
                   ` (12 subsequent siblings)
  38 siblings, 1 reply; 89+ messages in thread
From: Lorenzo Stoakes (ARM) @ 2026-09-08 20:01 UTC (permalink / raw)
  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,
	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, linux-kernel, linux-doc, linux-usb, linux-rdma, selinux,
	linux-sound, bpf, linux-scsi, linux-fbdev, dri-devel,
	linux-trace-kernel, linux-perf-users, linux-arch, linux-fsdevel,
	linux-arm-kernel, kvmarm, linuxppc-dev, kvm, kvm-riscv,
	linux-riscv, linux-s390, sparclinux, fuse-devel,
	Lorenzo Stoakes (ARM)

This header really makes little sense - every place it is included mm.h is
also included, and the header itself includes mm.h, so it does nothing to
reduce header size.

It also oddly does an #ifdef around checking VMA_HUGETLB_BIT, however
VMA_HUGETLB_BIT is unconditionally available, and will never be set if
hugetlb is not enabled.

Simply remove the header, eliminate the odd ifdeffery and place the
predicates in mm.h.

The naming of these predicates is odd, but to keep changes separate, we
will address this in a separate patch.

The file was never put into MAINTAINERS so there's no change required
there.

No functional change intended.

Signed-off-by: Lorenzo Stoakes (ARM) <ljs@kernel.org>
---
 drivers/gpu/drm/drm_gpusvm.c   |  2 +-
 include/asm-generic/tlb.h      |  2 +-
 include/linux/hugetlb.h        |  1 -
 include/linux/hugetlb_inline.h | 28 ----------------------------
 include/linux/mm.h             | 11 +++++++++++
 include/linux/pagemap.h        |  1 -
 include/linux/userfaultfd_k.h  |  1 -
 kernel/sched/fair.c            |  1 -
 mm/vma_internal.h              |  1 -
 9 files changed, 13 insertions(+), 35 deletions(-)

diff --git a/drivers/gpu/drm/drm_gpusvm.c b/drivers/gpu/drm/drm_gpusvm.c
index a93eee7ddb9e..793dacec2100 100644
--- a/drivers/gpu/drm/drm_gpusvm.c
+++ b/drivers/gpu/drm/drm_gpusvm.c
@@ -9,9 +9,9 @@
 #include <linux/dma-mapping.h>
 #include <linux/export.h>
 #include <linux/hmm.h>
-#include <linux/hugetlb_inline.h>
 #include <linux/memremap.h>
 #include <linux/mm_types.h>
+#include <linux/mm.h>
 #include <linux/slab.h>
 
 #include <drm/drm_device.h>
diff --git a/include/asm-generic/tlb.h b/include/asm-generic/tlb.h
index bdcc2778ac64..53ce414d9d81 100644
--- a/include/asm-generic/tlb.h
+++ b/include/asm-generic/tlb.h
@@ -11,9 +11,9 @@
 #ifndef _ASM_GENERIC__TLB_H
 #define _ASM_GENERIC__TLB_H
 
+#include <linux/mm.h>
 #include <linux/mmu_notifier.h>
 #include <linux/swap.h>
-#include <linux/hugetlb_inline.h>
 #include <asm/tlbflush.h>
 #include <asm/cacheflush.h>
 
diff --git a/include/linux/hugetlb.h b/include/linux/hugetlb.h
index 80a5a03e9cee..d7e6563cef75 100644
--- a/include/linux/hugetlb.h
+++ b/include/linux/hugetlb.h
@@ -7,7 +7,6 @@
 #include <linux/mm_types.h>
 #include <linux/mmdebug.h>
 #include <linux/fs.h>
-#include <linux/hugetlb_inline.h>
 #include <linux/cgroup.h>
 #include <linux/page_ref.h>
 #include <linux/list.h>
diff --git a/include/linux/hugetlb_inline.h b/include/linux/hugetlb_inline.h
deleted file mode 100644
index 5c29cd3223a1..000000000000
--- a/include/linux/hugetlb_inline.h
+++ /dev/null
@@ -1,28 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 */
-#ifndef _LINUX_HUGETLB_INLINE_H
-#define _LINUX_HUGETLB_INLINE_H
-
-#include <linux/mm.h>
-
-#ifdef CONFIG_HUGETLB_PAGE
-
-static inline bool is_vma_hugetlb_flags(const vma_flags_t *flags)
-{
-	return vma_flags_test(flags, VMA_HUGETLB_BIT);
-}
-
-#else
-
-static inline bool is_vma_hugetlb_flags(const vma_flags_t *flags)
-{
-	return false;
-}
-
-#endif
-
-static inline bool is_vm_hugetlb_page(const struct vm_area_struct *vma)
-{
-	return is_vma_hugetlb_flags(&vma->flags);
-}
-
-#endif
diff --git a/include/linux/mm.h b/include/linux/mm.h
index 15fc4509784b..d6b38556be36 100644
--- a/include/linux/mm.h
+++ b/include/linux/mm.h
@@ -1609,6 +1609,17 @@ static inline bool vma_is_shared_maywrite(const struct vm_area_struct *vma)
 	return is_shared_maywrite(&vma->flags);
 }
 
+static inline bool is_vma_hugetlb_flags(const vma_flags_t *flags)
+{
+	return IS_ENABLED(CONFIG_HUGETLB_PAGE) &&
+	       vma_flags_test(flags, VMA_HUGETLB_BIT);
+}
+
+static inline bool is_vm_hugetlb_page(const struct vm_area_struct *vma)
+{
+	return is_vma_hugetlb_flags(&vma->flags);
+}
+
 /**
  * vma_flags_is_kernel_owned() - Do the specified VMA flags indicate that the
  * contents of the VMA are owned by the kernel rather than the core mm?
diff --git a/include/linux/pagemap.h b/include/linux/pagemap.h
index 939f3a5e973f..d7d8b312466c 100644
--- a/include/linux/pagemap.h
+++ b/include/linux/pagemap.h
@@ -14,7 +14,6 @@
 #include <linux/gfp.h>
 #include <linux/bitops.h>
 #include <linux/hardirq.h> /* for in_interrupt() */
-#include <linux/hugetlb_inline.h>
 
 struct folio_batch;
 
diff --git a/include/linux/userfaultfd_k.h b/include/linux/userfaultfd_k.h
index a4351cffc60c..a14b8a9ffb7b 100644
--- a/include/linux/userfaultfd_k.h
+++ b/include/linux/userfaultfd_k.h
@@ -18,7 +18,6 @@
 #include <linux/swap.h>
 #include <linux/leafops.h>
 #include <asm-generic/pgtable_uffd.h>
-#include <linux/hugetlb_inline.h>
 
 /* The set of all possible UFFD-related VM flags. */
 #define __VM_UFFD_FLAGS (VM_UFFD_MISSING | VM_UFFD_MINOR | \
diff --git a/kernel/sched/fair.c b/kernel/sched/fair.c
index a71f0ab79bcd..c75b5c50af30 100644
--- a/kernel/sched/fair.c
+++ b/kernel/sched/fair.c
@@ -22,7 +22,6 @@
  */
 #include <linux/energy_model.h>
 #include <linux/mmap_lock.h>
-#include <linux/hugetlb_inline.h>
 #include <linux/jiffies.h>
 #include <linux/mm_api.h>
 #include <linux/highmem.h>
diff --git a/mm/vma_internal.h b/mm/vma_internal.h
index 4d300e7bbaf4..4f73f0a4db79 100644
--- a/mm/vma_internal.h
+++ b/mm/vma_internal.h
@@ -18,7 +18,6 @@
 #include <linux/fs.h>
 #include <linux/huge_mm.h>
 #include <linux/hugetlb.h>
-#include <linux/hugetlb_inline.h>
 #include <linux/kernel.h>
 #include <linux/ksm.h>
 #include <linux/khugepaged.h>

-- 
2.55.0


^ permalink raw reply related	[flat|nested] 89+ messages in thread

* [PATCH 27/39] mm: rename is_vm_hugetlb_page() to vma_is_hugetlb()
  2026-09-08 20:01 [PATCH 00/39] mm: make VMA flag semantics explicit, eliminate VM_SPECIAL Lorenzo Stoakes (ARM)
                   ` (25 preceding siblings ...)
  2026-09-08 20:01 ` [PATCH 26/39] mm: remove hugetlb_inline.h Lorenzo Stoakes (ARM)
@ 2026-09-08 20:01 ` Lorenzo Stoakes (ARM)
  2026-09-08 20:40   ` sashiko-bot
                     ` (3 more replies)
  2026-09-08 20:01 ` [PATCH 28/39] mm: drop some redundant checks around hugetlb VMAs Lorenzo Stoakes (ARM)
                   ` (11 subsequent siblings)
  38 siblings, 4 replies; 89+ messages in thread
From: Lorenzo Stoakes (ARM) @ 2026-09-08 20:01 UTC (permalink / raw)
  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,
	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, linux-kernel, linux-doc, linux-usb, linux-rdma, selinux,
	linux-sound, bpf, linux-scsi, linux-fbdev, dri-devel,
	linux-trace-kernel, linux-perf-users, linux-arch, linux-fsdevel,
	linux-arm-kernel, kvmarm, linuxppc-dev, kvm, kvm-riscv,
	linux-riscv, linux-s390, sparclinux, fuse-devel,
	Lorenzo Stoakes (ARM)

The is_vm_hugetlb_page() predicate is badly named - the mapping can span
more than a page and it is inconsistent with other VMA predicates that
typically are prefixed by vma_.

Rename to vma_is_hugetlb() for consistency, and while we're here update
some VM_BUG_ON_VMA() to VM_WARN_ON_ONCE_VMA() as to avoid unnecessary
oopses.

No functional change intended.

Signed-off-by: Lorenzo Stoakes (ARM) <ljs@kernel.org>
---
 arch/arm64/kvm/mmu.c                      |  4 ++--
 arch/powerpc/mm/book3s64/radix_tlb.c      |  6 +++---
 arch/powerpc/mm/nohash/e500_hugetlbpage.c |  2 +-
 arch/powerpc/mm/nohash/tlb.c              |  2 +-
 arch/riscv/kvm/mmu.c                      |  2 +-
 arch/riscv/mm/tlbflush.c                  |  2 +-
 arch/s390/mm/gmap_helpers.c               |  6 +++---
 arch/sparc/mm/init_64.c                   |  2 +-
 drivers/gpu/drm/drm_gpusvm.c              |  2 +-
 fs/coredump.c                             |  2 +-
 fs/hugetlbfs/inode.c                      |  2 +-
 fs/proc/task_mmu.c                        |  8 ++++----
 include/asm-generic/tlb.h                 |  2 +-
 include/linux/hugetlb.h                   |  4 ++--
 include/linux/mm.h                        | 19 ++++++++++++++++---
 include/linux/rmap.h                      |  2 +-
 kernel/events/core.c                      |  2 +-
 kernel/sched/fair.c                       |  2 +-
 mm/gup.c                                  |  4 ++--
 mm/huge_memory.c                          |  2 +-
 mm/hugetlb.c                              | 14 +++++++-------
 mm/internal.h                             |  2 +-
 mm/madvise.c                              |  4 ++--
 mm/memory.c                               | 12 ++++++------
 mm/mempolicy.c                            |  2 +-
 mm/migrate_device.c                       |  2 +-
 mm/mmap.c                                 |  2 +-
 mm/mmu_gather.c                           |  2 +-
 mm/mprotect.c                             |  2 +-
 mm/mremap.c                               |  6 +++---
 mm/page_vma_mapped.c                      |  4 ++--
 mm/pagewalk.c                             |  2 +-
 mm/swapfile.c                             |  2 +-
 mm/userfaultfd.c                          | 26 +++++++++++++-------------
 mm/vma.c                                  |  8 ++++----
 mm/vmscan.c                               |  2 +-
 tools/testing/vma/include/stubs.h         |  2 +-
 37 files changed, 92 insertions(+), 79 deletions(-)

diff --git a/arch/arm64/kvm/mmu.c b/arch/arm64/kvm/mmu.c
index 9ba86450fe4a..a7968f8d24bf 100644
--- a/arch/arm64/kvm/mmu.c
+++ b/arch/arm64/kvm/mmu.c
@@ -1463,13 +1463,13 @@ static int get_vma_page_shift(struct vm_area_struct *vma, unsigned long hva)
 {
 	unsigned long pa;
 
-	if (is_vm_hugetlb_page(vma) && !(vma->vm_flags & VM_PFNMAP))
+	if (vma_is_hugetlb(vma) && !(vma->vm_flags & VM_PFNMAP))
 		return huge_page_shift(hstate_vma(vma));
 
 	if (!(vma->vm_flags & VM_PFNMAP))
 		return PAGE_SHIFT;
 
-	VM_BUG_ON(is_vm_hugetlb_page(vma));
+	VM_BUG_ON(vma_is_hugetlb(vma));
 
 	pa = (vma->vm_pgoff << PAGE_SHIFT) + (hva - vma->vm_start);
 
diff --git a/arch/powerpc/mm/book3s64/radix_tlb.c b/arch/powerpc/mm/book3s64/radix_tlb.c
index 7de5760164a9..b4603a98224b 100644
--- a/arch/powerpc/mm/book3s64/radix_tlb.c
+++ b/arch/powerpc/mm/book3s64/radix_tlb.c
@@ -627,7 +627,7 @@ void radix__local_flush_tlb_page(struct vm_area_struct *vma, unsigned long vmadd
 {
 #ifdef CONFIG_HUGETLB_PAGE
 	/* need the return fix for nohash.c */
-	if (is_vm_hugetlb_page(vma))
+	if (vma_is_hugetlb(vma))
 		return radix__local_flush_hugetlb_page(vma, vmaddr);
 #endif
 	radix__local_flush_tlb_page_psize(vma->vm_mm, vmaddr, mmu_virtual_psize);
@@ -945,7 +945,7 @@ void radix__flush_tlb_page_psize(struct mm_struct *mm, unsigned long vmaddr,
 void radix__flush_tlb_page(struct vm_area_struct *vma, unsigned long vmaddr)
 {
 #ifdef CONFIG_HUGETLB_PAGE
-	if (is_vm_hugetlb_page(vma))
+	if (vma_is_hugetlb(vma))
 		return radix__flush_hugetlb_page(vma, vmaddr);
 #endif
 	radix__flush_tlb_page_psize(vma->vm_mm, vmaddr, mmu_virtual_psize);
@@ -1113,7 +1113,7 @@ void radix__flush_tlb_range(struct vm_area_struct *vma, unsigned long start,
 
 {
 #ifdef CONFIG_HUGETLB_PAGE
-	if (is_vm_hugetlb_page(vma))
+	if (vma_is_hugetlb(vma))
 		return radix__flush_hugetlb_tlb_range(vma, start, end);
 #endif
 
diff --git a/arch/powerpc/mm/nohash/e500_hugetlbpage.c b/arch/powerpc/mm/nohash/e500_hugetlbpage.c
index a134d28a0e4d..b87623f04be5 100644
--- a/arch/powerpc/mm/nohash/e500_hugetlbpage.c
+++ b/arch/powerpc/mm/nohash/e500_hugetlbpage.c
@@ -180,7 +180,7 @@ book3e_hugetlb_preload(struct vm_area_struct *vma, unsigned long ea, pte_t pte)
  */
 void __update_mmu_cache(struct vm_area_struct *vma, unsigned long address, pte_t *ptep)
 {
-	if (is_vm_hugetlb_page(vma))
+	if (vma_is_hugetlb(vma))
 		book3e_hugetlb_preload(vma, address, *ptep);
 }
 
diff --git a/arch/powerpc/mm/nohash/tlb.c b/arch/powerpc/mm/nohash/tlb.c
index 0a650742f3a0..07a2db16c2b1 100644
--- a/arch/powerpc/mm/nohash/tlb.c
+++ b/arch/powerpc/mm/nohash/tlb.c
@@ -278,7 +278,7 @@ void __flush_tlb_page(struct mm_struct *mm, unsigned long vmaddr,
 void flush_tlb_page(struct vm_area_struct *vma, unsigned long vmaddr)
 {
 #ifdef CONFIG_HUGETLB_PAGE
-	if (vma && is_vm_hugetlb_page(vma))
+	if (vma && vma_is_hugetlb(vma))
 		flush_hugetlb_page(vma, vmaddr);
 #endif
 
diff --git a/arch/riscv/kvm/mmu.c b/arch/riscv/kvm/mmu.c
index 6035b5ec9503..5c5c77f98bf0 100644
--- a/arch/riscv/kvm/mmu.c
+++ b/arch/riscv/kvm/mmu.c
@@ -664,7 +664,7 @@ int kvm_riscv_mmu_map(struct kvm_vcpu *vcpu, struct kvm_memory_slot *memslot,
 		return -EFAULT;
 	}
 
-	is_hugetlb = is_vm_hugetlb_page(vma);
+	is_hugetlb = vma_is_hugetlb(vma);
 	if (is_hugetlb)
 		vma_pageshift = huge_page_shift(hstate_vma(vma));
 	else
diff --git a/arch/riscv/mm/tlbflush.c b/arch/riscv/mm/tlbflush.c
index 962db300a166..a74a7d5258aa 100644
--- a/arch/riscv/mm/tlbflush.c
+++ b/arch/riscv/mm/tlbflush.c
@@ -149,7 +149,7 @@ void flush_tlb_range(struct vm_area_struct *vma, unsigned long start,
 {
 	unsigned long stride_size;
 
-	if (!is_vm_hugetlb_page(vma)) {
+	if (!vma_is_hugetlb(vma)) {
 		stride_size = PAGE_SIZE;
 	} else {
 		stride_size = huge_page_size(hstate_vma(vma));
diff --git a/arch/s390/mm/gmap_helpers.c b/arch/s390/mm/gmap_helpers.c
index ff63ffb1dbd2..3f6783b93e67 100644
--- a/arch/s390/mm/gmap_helpers.c
+++ b/arch/s390/mm/gmap_helpers.c
@@ -102,7 +102,7 @@ __context_unsafe(/* pte_unmap_unlock() not instrumented */)
 
 	/* Find the vm address for the guest address */
 	vma = vma_lookup(mm, vmaddr);
-	if (!vma || is_vm_hugetlb_page(vma))
+	if (!vma || vma_is_hugetlb(vma))
 		return;
 
 	/* Get pointer to the page table entry */
@@ -139,7 +139,7 @@ void gmap_helper_discard(struct mm_struct *mm, unsigned long vmaddr, unsigned lo
 		vma = find_vma_intersection(mm, vmaddr, end);
 		if (!vma)
 			return;
-		if (!is_vm_hugetlb_page(vma))
+		if (!vma_is_hugetlb(vma))
 			zap_vma_range(vma, vmaddr, min(end, vma->vm_end) - vmaddr);
 		vmaddr = vma->vm_end;
 	}
@@ -247,7 +247,7 @@ static int __gmap_helper_unshare_zeropages(struct mm_struct *mm)
 		 * proof to catch unexpected zeropages in other mappings and
 		 * fail.
 		 */
-		if ((vma->vm_flags & VM_PFNMAP) || is_vm_hugetlb_page(vma))
+		if ((vma->vm_flags & VM_PFNMAP) || vma_is_hugetlb(vma))
 			continue;
 		addr = vma->vm_start;
 
diff --git a/arch/sparc/mm/init_64.c b/arch/sparc/mm/init_64.c
index 103db4683b16..9bbccb5d23a8 100644
--- a/arch/sparc/mm/init_64.c
+++ b/arch/sparc/mm/init_64.c
@@ -413,7 +413,7 @@ void update_mmu_cache_range(struct vm_fault *vmf, struct vm_area_struct *vma,
 	if (mm->context.hugetlb_pte_count || mm->context.thp_pte_count) {
 		unsigned long hugepage_size = PAGE_SIZE;
 
-		if (is_vm_hugetlb_page(vma))
+		if (vma_is_hugetlb(vma))
 			hugepage_size = huge_page_size(hstate_vma(vma));
 
 		if (hugepage_size >= PUD_SIZE) {
diff --git a/drivers/gpu/drm/drm_gpusvm.c b/drivers/gpu/drm/drm_gpusvm.c
index 793dacec2100..a1d4989b0b61 100644
--- a/drivers/gpu/drm/drm_gpusvm.c
+++ b/drivers/gpu/drm/drm_gpusvm.c
@@ -1142,7 +1142,7 @@ drm_gpusvm_range_find_or_insert(struct drm_gpusvm *gpusvm,
 	 * have to change.
 	 */
 	migrate_devmem = ctx->devmem_possible &&
-		vma_is_anonymous(vas) && !is_vm_hugetlb_page(vas);
+		vma_is_anonymous(vas) && !vma_is_hugetlb(vas);
 
 	chunk_size = drm_gpusvm_range_chunk_size(gpusvm, notifier, vas,
 						 fault_addr, gpuva_start,
diff --git a/fs/coredump.c b/fs/coredump.c
index ac3cd74808c6..fb21fb6703dd 100644
--- a/fs/coredump.c
+++ b/fs/coredump.c
@@ -1608,7 +1608,7 @@ static unsigned long vma_dump_size(struct vm_area_struct *vma,
 	}
 
 	/* Hugetlb memory check */
-	if (is_vm_hugetlb_page(vma)) {
+	if (vma_is_hugetlb(vma)) {
 		if ((vma->vm_flags & VM_SHARED) && FILTER(HUGETLB_SHARED))
 			goto whole;
 		if (!(vma->vm_flags & VM_SHARED) && FILTER(HUGETLB_PRIVATE))
diff --git a/fs/hugetlbfs/inode.c b/fs/hugetlbfs/inode.c
index 7611a8470ea2..ba7097d5720c 100644
--- a/fs/hugetlbfs/inode.c
+++ b/fs/hugetlbfs/inode.c
@@ -108,7 +108,7 @@ static int hugetlbfs_file_mmap(struct file *file, struct vm_area_struct *vma)
 	 * vma address alignment (but not the pgoff alignment) has
 	 * already been checked by prepare_hugepage_range.  If you add
 	 * any error returns here, do so after setting VM_HUGETLB, so
-	 * is_vm_hugetlb_page tests below unmap_region go the right
+	 * vma_is_hugetlb tests below unmap_region go the right
 	 * way when do_mmap unwinds (may be important on powerpc
 	 * and ia64).
 	 */
diff --git a/fs/proc/task_mmu.c b/fs/proc/task_mmu.c
index e671b4fd8ded..565e6446bd31 100644
--- a/fs/proc/task_mmu.c
+++ b/fs/proc/task_mmu.c
@@ -3015,7 +3015,7 @@ static int pagemap_scan_pte_hole(unsigned long addr, unsigned long end,
 	 * hugetlb differs, see pagemap_hugetlb_category().
 	 */
 	categories = p->cur_vma_category;
-	if (userfaultfd_wp(vma) && !is_vm_hugetlb_page(vma))
+	if (userfaultfd_wp(vma) && !vma_is_hugetlb(vma))
 		categories |= PAGE_IS_WRITTEN;
 
 	if (!pagemap_scan_is_interesting_page(categories, p))
@@ -3028,7 +3028,7 @@ static int pagemap_scan_pte_hole(unsigned long addr, unsigned long end,
 	if (~p->arg.flags & PM_SCAN_WP_MATCHING)
 		return ret;
 
-	if (is_vm_hugetlb_page(vma))
+	if (vma_is_hugetlb(vma))
 		err = pagemap_scan_hugetlb_hole_wp(vma, addr, end);
 	else
 		err = uffd_wp_range(vma, addr, end - addr, true);
@@ -3470,7 +3470,7 @@ static int show_numa_map(struct seq_file *m, void *v)
 		seq_puts(m, " stack");
 	}
 
-	if (is_vm_hugetlb_page(vma))
+	if (vma_is_hugetlb(vma))
 		seq_puts(m, " huge");
 
 	/* Skip walking pages if gate VMA */
@@ -3499,7 +3499,7 @@ static int show_numa_map(struct seq_file *m, void *v)
 	if (md->swapcache)
 		seq_printf(m, " swapcache=%lu", md->swapcache);
 
-	if (md->active < md->pages && !is_vm_hugetlb_page(vma))
+	if (md->active < md->pages && !vma_is_hugetlb(vma))
 		seq_printf(m, " active=%lu", md->active);
 
 	if (md->writeback)
diff --git a/include/asm-generic/tlb.h b/include/asm-generic/tlb.h
index 53ce414d9d81..dfb5dd3bec40 100644
--- a/include/asm-generic/tlb.h
+++ b/include/asm-generic/tlb.h
@@ -486,7 +486,7 @@ tlb_update_vma_flags(struct mmu_gather *tlb, struct vm_area_struct *vma)
 	 * We rely on tlb_end_vma() to issue a flush, such that when we reset
 	 * these values the batch is empty.
 	 */
-	tlb->vma_huge = is_vm_hugetlb_page(vma);
+	tlb->vma_huge = vma_is_hugetlb(vma);
 	tlb->vma_exec = !!(vma->vm_flags & VM_EXEC);
 
 	/*
diff --git a/include/linux/hugetlb.h b/include/linux/hugetlb.h
index d7e6563cef75..24727ece20fe 100644
--- a/include/linux/hugetlb.h
+++ b/include/linux/hugetlb.h
@@ -251,14 +251,14 @@ extern void __hugetlb_zap_end(struct vm_area_struct *vma,
 static inline void hugetlb_zap_begin(struct vm_area_struct *vma,
 				     unsigned long *start, unsigned long *end)
 {
-	if (is_vm_hugetlb_page(vma))
+	if (vma_is_hugetlb(vma))
 		__hugetlb_zap_begin(vma, start, end);
 }
 
 static inline void hugetlb_zap_end(struct vm_area_struct *vma,
 				   struct zap_details *details)
 {
-	if (is_vm_hugetlb_page(vma))
+	if (vma_is_hugetlb(vma))
 		__hugetlb_zap_end(vma, details);
 }
 
diff --git a/include/linux/mm.h b/include/linux/mm.h
index d6b38556be36..d8ee0ca63ccf 100644
--- a/include/linux/mm.h
+++ b/include/linux/mm.h
@@ -1609,15 +1609,28 @@ static inline bool vma_is_shared_maywrite(const struct vm_area_struct *vma)
 	return is_shared_maywrite(&vma->flags);
 }
 
-static inline bool is_vma_hugetlb_flags(const vma_flags_t *flags)
+/**
+ * vma_flags_is_hugetlb() - Do the specified VMA flags indicate that the
+ * VMA is a hugetlb mapping?
+ * @flags: The VMA flags to test.
+ *
+ * Returns: true if the flags indicate a hugetlb mapping, false otherwise.
+ */
+static inline bool vma_flags_is_hugetlb(const vma_flags_t *flags)
 {
 	return IS_ENABLED(CONFIG_HUGETLB_PAGE) &&
 	       vma_flags_test(flags, VMA_HUGETLB_BIT);
 }
 
-static inline bool is_vm_hugetlb_page(const struct vm_area_struct *vma)
+/**
+ * vma_is_hugetlb() - Is @vma a hugetlb mapping?
+ * @vma: The VMA to test.
+ *
+ * Returns: true if @vma is a hugetlb mapping, false otherwise.
+ */
+static inline bool vma_is_hugetlb(const struct vm_area_struct *vma)
 {
-	return is_vma_hugetlb_flags(&vma->flags);
+	return vma_flags_is_hugetlb(&vma->flags);
 }
 
 /**
diff --git a/include/linux/rmap.h b/include/linux/rmap.h
index 0b332770abee..74cca0e3c726 100644
--- a/include/linux/rmap.h
+++ b/include/linux/rmap.h
@@ -888,7 +888,7 @@ struct page_vma_mapped_walk {
 static inline void page_vma_mapped_walk_done(struct page_vma_mapped_walk *pvmw)
 {
 	/* HugeTLB pte is set to the relevant page table entry without pte_mapped. */
-	if (pvmw->pte && !is_vm_hugetlb_page(pvmw->vma))
+	if (pvmw->pte && !vma_is_hugetlb(pvmw->vma))
 		pte_unmap(pvmw->pte);
 	if (pvmw->ptl)
 		spin_unlock(pvmw->ptl);
diff --git a/kernel/events/core.c b/kernel/events/core.c
index a6c8e38a3110..8ca8a6842924 100644
--- a/kernel/events/core.c
+++ b/kernel/events/core.c
@@ -9808,7 +9808,7 @@ static void perf_event_mmap_event(struct perf_mmap_event *mmap_event)
 
 	if (vma->vm_flags & VM_LOCKED)
 		flags |= MAP_LOCKED;
-	if (is_vm_hugetlb_page(vma))
+	if (vma_is_hugetlb(vma))
 		flags |= MAP_HUGETLB;
 
 	if (file) {
diff --git a/kernel/sched/fair.c b/kernel/sched/fair.c
index c75b5c50af30..ae6c1a606eb5 100644
--- a/kernel/sched/fair.c
+++ b/kernel/sched/fair.c
@@ -4211,7 +4211,7 @@ static void task_numa_work(struct callback_head *work)
 
 	for (; vma; vma = vma_next(&vmi)) {
 		if (!vma_migratable(vma) || !vma_policy_mof(vma) ||
-			is_vm_hugetlb_page(vma) || vma_is_kernel_owned(vma)) {
+			vma_is_hugetlb(vma) || vma_is_kernel_owned(vma)) {
 			trace_sched_skip_vma_numa(mm, vma, NUMAB_SKIP_UNSUITABLE);
 			continue;
 		}
diff --git a/mm/gup.c b/mm/gup.c
index f5dc227bd6e1..66b306911703 100644
--- a/mm/gup.c
+++ b/mm/gup.c
@@ -621,7 +621,7 @@ static struct page *no_page_table(struct vm_area_struct *vma,
 	 * But we can only make this optimization where a hole would surely
 	 * be zero-filled if handle_mm_fault() actually did handle it.
 	 */
-	if (is_vm_hugetlb_page(vma)) {
+	if (vma_is_hugetlb(vma)) {
 		struct hstate *h = hstate_vma(vma);
 
 		if (!hugetlbfs_pagecache_present(h, vma, address))
@@ -1213,7 +1213,7 @@ static int check_vma_flags(struct vm_area_struct *vma, unsigned long gup_flags)
 	if ((gup_flags & FOLL_LONGTERM) && vma_is_fsdax(vma))
 		return -EOPNOTSUPP;
 
-	if ((gup_flags & FOLL_SPLIT_PMD) && is_vm_hugetlb_page(vma))
+	if ((gup_flags & FOLL_SPLIT_PMD) && vma_is_hugetlb(vma))
 		return -EOPNOTSUPP;
 
 	if (vma_is_secretmem(vma))
diff --git a/mm/huge_memory.c b/mm/huge_memory.c
index befffadd978e..cf6c50e531f5 100644
--- a/mm/huge_memory.c
+++ b/mm/huge_memory.c
@@ -4754,7 +4754,7 @@ static inline bool vma_not_suitable_for_thp_split(struct vm_area_struct *vma)
 		return true;
 	if (vma_test(vma, VMA_IO_BIT))
 		return true;
-	if (is_vm_hugetlb_page(vma))
+	if (vma_is_hugetlb(vma))
 		return true;
 
 	return false;
diff --git a/mm/hugetlb.c b/mm/hugetlb.c
index a69bd463b1ae..d93235491cbc 100644
--- a/mm/hugetlb.c
+++ b/mm/hugetlb.c
@@ -1146,7 +1146,7 @@ static inline struct resv_map *inode_resv_map(struct inode *inode)
 
 static struct resv_map *vma_resv_map(struct vm_area_struct *vma)
 {
-	VM_BUG_ON_VMA(!is_vm_hugetlb_page(vma), vma);
+	VM_WARN_ON_ONCE_VMA(!vma_is_hugetlb(vma), vma);
 	if (vma->vm_flags & VM_MAYSHARE) {
 		struct address_space *mapping = vma->vm_file->f_mapping;
 		struct inode *inode = mapping->host;
@@ -1161,7 +1161,7 @@ static struct resv_map *vma_resv_map(struct vm_area_struct *vma)
 
 static void set_vma_resv_map(struct vm_area_struct *vma, struct resv_map *map)
 {
-	VM_WARN_ON_ONCE_VMA(!is_vm_hugetlb_page(vma), vma);
+	VM_WARN_ON_ONCE_VMA(!vma_is_hugetlb(vma), vma);
 	VM_WARN_ON_ONCE_VMA(vma_test(vma, VMA_MAYSHARE_BIT), vma);
 
 	set_vma_private_data(vma, (unsigned long)map);
@@ -1169,7 +1169,7 @@ static void set_vma_resv_map(struct vm_area_struct *vma, struct resv_map *map)
 
 static void set_vma_resv_flags(struct vm_area_struct *vma, unsigned long flags)
 {
-	VM_WARN_ON_ONCE_VMA(!is_vm_hugetlb_page(vma), vma);
+	VM_WARN_ON_ONCE_VMA(!vma_is_hugetlb(vma), vma);
 	VM_WARN_ON_ONCE_VMA(vma_test(vma, VMA_MAYSHARE_BIT), vma);
 
 	set_vma_private_data(vma, get_vma_private_data(vma) | flags);
@@ -1177,7 +1177,7 @@ static void set_vma_resv_flags(struct vm_area_struct *vma, unsigned long flags)
 
 static int is_vma_resv_set(struct vm_area_struct *vma, unsigned long flag)
 {
-	VM_BUG_ON_VMA(!is_vm_hugetlb_page(vma), vma);
+	VM_WARN_ON_ONCE_VMA(!vma_is_hugetlb(vma), vma);
 
 	return (get_vma_private_data(vma) & flag) != 0;
 }
@@ -1191,7 +1191,7 @@ bool __vma_private_lock(struct vm_area_struct *vma)
 
 void hugetlb_dup_vma_private(struct vm_area_struct *vma)
 {
-	VM_BUG_ON_VMA(!is_vm_hugetlb_page(vma), vma);
+	VM_WARN_ON_ONCE_VMA(!vma_is_hugetlb(vma), vma);
 	/*
 	 * Clear vm_private_data
 	 * - For shared mappings this is a per-vma semaphore that may be
@@ -5269,7 +5269,7 @@ void __unmap_hugepage_range(struct mmu_gather *tlb, struct vm_area_struct *vma,
 	unsigned long last_addr_mask;
 
 	i_mmap_assert_write_locked(vma->vm_file->f_mapping);
-	WARN_ON(!is_vm_hugetlb_page(vma));
+	WARN_ON(!vma_is_hugetlb(vma));
 	BUG_ON(start & ~huge_page_mask(h));
 	BUG_ON(end & ~huge_page_mask(h));
 
@@ -7495,6 +7495,6 @@ void hugetlb_unshare_all_pmds(struct vm_area_struct *vma)
  */
 void fixup_hugetlb_reservations(struct vm_area_struct *vma)
 {
-	if (is_vm_hugetlb_page(vma))
+	if (vma_is_hugetlb(vma))
 		clear_vma_resv_huge_pages(vma);
 }
diff --git a/mm/internal.h b/mm/internal.h
index 04b1f1d3d960..104bbca1eb57 100644
--- a/mm/internal.h
+++ b/mm/internal.h
@@ -1116,7 +1116,7 @@ static inline bool vma_supports_mlock(const struct vm_area_struct *vma)
 		return false;
 	if (vma_test_single_mask(vma, VMA_DROPPABLE))
 		return false;
-	if (vma_is_dax(vma) || is_vm_hugetlb_page(vma))
+	if (vma_is_dax(vma) || vma_is_hugetlb(vma))
 		return false;
 	return vma != get_gate_vma(current->mm);
 }
diff --git a/mm/madvise.c b/mm/madvise.c
index 73c2901b9adb..2db11c832d0f 100644
--- a/mm/madvise.c
+++ b/mm/madvise.c
@@ -880,7 +880,7 @@ bool madvise_dontneed_free_valid_vma(struct madvise_behavior *madv_behavior)
 	int behavior = madv_behavior->behavior;
 	struct madvise_behavior_range *range = &madv_behavior->range;
 
-	if (!is_vm_hugetlb_page(vma)) {
+	if (!vma_is_hugetlb(vma)) {
 		unsigned int forbidden = VM_PFNMAP;
 
 		if (behavior != MADV_DONTNEED_LOCKED)
@@ -1413,7 +1413,7 @@ static int madvise_vma_behavior(struct madvise_behavior *madv_behavior)
 		new_flags |= VM_DONTDUMP;
 		break;
 	case MADV_DODUMP:
-		if ((!is_vm_hugetlb_page(vma) && (new_flags & VM_SPECIAL)) ||
+		if ((!vma_is_hugetlb(vma) && (new_flags & VM_SPECIAL)) ||
 		    (new_flags & VM_DROPPABLE))
 			return -EINVAL;
 		new_flags &= ~VM_DONTDUMP;
diff --git a/mm/memory.c b/mm/memory.c
index 28c1bb7b93af..9a38c7d4cc40 100644
--- a/mm/memory.c
+++ b/mm/memory.c
@@ -1564,7 +1564,7 @@ copy_page_range(struct vm_area_struct *dst_vma, struct vm_area_struct *src_vma)
 	if (!vma_needs_copy(dst_vma, src_vma))
 		return 0;
 
-	if (is_vm_hugetlb_page(src_vma))
+	if (vma_is_hugetlb(src_vma))
 		return copy_hugetlb_page_range(dst_mm, src_mm, dst_vma, src_vma);
 
 	/*
@@ -2178,7 +2178,7 @@ static void __zap_vma_range(struct mmu_gather *tlb, struct vm_area_struct *vma,
 	if (vma->vm_file && !reaping)
 		uprobe_munmap(vma, start, end);
 
-	if (unlikely(is_vm_hugetlb_page(vma))) {
+	if (unlikely(vma_is_hugetlb(vma))) {
 		zap_flags_t zap_flags = details ? details->zap_flags : 0;
 
 		VM_WARN_ON_ONCE(reaping);
@@ -2313,7 +2313,7 @@ void zap_vma_range_batched(struct mmu_gather *tlb,
 	 */
 	__zap_vma_range(tlb, vma, address, end, details);
 	mmu_notifier_invalidate_range_end(&range);
-	if (is_vm_hugetlb_page(vma)) {
+	if (vma_is_hugetlb(vma)) {
 		/*
 		 * flush tlb and free resources before hugetlb_zap_end(), to
 		 * avoid concurrent page faults' allocation failure.
@@ -6933,7 +6933,7 @@ vm_fault_t handle_mm_fault(struct vm_area_struct *vma, unsigned long address,
 
 	lru_gen_enter_fault(vma);
 
-	if (unlikely(is_vm_hugetlb_page(vma)))
+	if (unlikely(vma_is_hugetlb(vma)))
 		ret = hugetlb_fault(vma->vm_mm, vma, address, flags);
 	else
 		ret = __handle_mm_fault(vma, address, flags);
@@ -7797,12 +7797,12 @@ void ptlock_free(struct ptdesc *ptdesc)
 
 void vma_pgtable_walk_begin(struct vm_area_struct *vma)
 {
-	if (is_vm_hugetlb_page(vma))
+	if (vma_is_hugetlb(vma))
 		hugetlb_vma_lock_read(vma);
 }
 
 void vma_pgtable_walk_end(struct vm_area_struct *vma)
 {
-	if (is_vm_hugetlb_page(vma))
+	if (vma_is_hugetlb(vma))
 		hugetlb_vma_unlock_read(vma);
 }
diff --git a/mm/mempolicy.c b/mm/mempolicy.c
index 2ad0a5f18280..aeb99c5933cb 100644
--- a/mm/mempolicy.c
+++ b/mm/mempolicy.c
@@ -2021,7 +2021,7 @@ bool vma_migratable(struct vm_area_struct *vma)
 	if (vma_is_dax(vma))
 		return false;
 
-	if (is_vm_hugetlb_page(vma) &&
+	if (vma_is_hugetlb(vma) &&
 		!hugepage_migration_supported(hstate_vma(vma)))
 		return false;
 
diff --git a/mm/migrate_device.c b/mm/migrate_device.c
index 0c437004329d..c38cbaaef5a4 100644
--- a/mm/migrate_device.c
+++ b/mm/migrate_device.c
@@ -743,7 +743,7 @@ int migrate_vma_setup(struct migrate_vma *args)
 
 	args->start &= PAGE_MASK;
 	args->end &= PAGE_MASK;
-	if (!args->vma || is_vm_hugetlb_page(args->vma) ||
+	if (!args->vma || vma_is_hugetlb(args->vma) ||
 	    (args->vma->vm_flags & VM_SPECIAL) || vma_is_dax(args->vma))
 		return -EINVAL;
 	if (nr_pages <= 0)
diff --git a/mm/mmap.c b/mm/mmap.c
index 4bf26b0f1e6e..98449f364af1 100644
--- a/mm/mmap.c
+++ b/mm/mmap.c
@@ -1786,7 +1786,7 @@ __latent_entropy int dup_mmap(struct mm_struct *mm, struct mm_struct *oldmm)
 		/*
 		 * Copy/update hugetlb private vma information.
 		 */
-		if (is_vm_hugetlb_page(tmp))
+		if (vma_is_hugetlb(tmp))
 			hugetlb_dup_vma_private(tmp);
 
 		/*
diff --git a/mm/mmu_gather.c b/mm/mmu_gather.c
index 3985d856de7f..506f005adbdc 100644
--- a/mm/mmu_gather.c
+++ b/mm/mmu_gather.c
@@ -500,7 +500,7 @@ void tlb_gather_mmu_vma(struct mmu_gather *tlb, struct vm_area_struct *vma)
 {
 	tlb_gather_mmu(tlb, vma->vm_mm);
 	tlb_update_vma_flags(tlb, vma);
-	if (is_vm_hugetlb_page(vma))
+	if (vma_is_hugetlb(vma))
 		/* All entries have the same size. */
 		tlb_change_page_size(tlb, huge_page_size(hstate_vma(vma)));
 }
diff --git a/mm/mprotect.c b/mm/mprotect.c
index fe32fd87cf5c..a1b6d29bf039 100644
--- a/mm/mprotect.c
+++ b/mm/mprotect.c
@@ -717,7 +717,7 @@ long change_protection(struct mmu_gather *tlb,
 	    (cp_flags & MM_CP_UFFD_RWP))
 		newprot = PAGE_NONE;
 
-	if (is_vm_hugetlb_page(vma))
+	if (vma_is_hugetlb(vma))
 		pages = hugetlb_change_protection(vma, start, end, newprot,
 						  cp_flags);
 	else
diff --git a/mm/mremap.c b/mm/mremap.c
index ed19b47c2caf..1122282a1d6a 100644
--- a/mm/mremap.c
+++ b/mm/mremap.c
@@ -812,7 +812,7 @@ unsigned long move_page_tables(struct pagetable_move_control *pmc)
 	if (!pmc->len_in)
 		return 0;
 
-	if (is_vm_hugetlb_page(pmc->old))
+	if (vma_is_hugetlb(pmc->old))
 		return move_hugetlb_page_tables(pmc->old, pmc->new, pmc->old_addr,
 						pmc->new_addr, pmc->len_in);
 
@@ -1735,7 +1735,7 @@ static bool vma_multi_allowed(struct vm_area_struct *vma)
 	/* Known good. */
 	if (vma_is_shmem(vma))
 		return true;
-	if (is_vm_hugetlb_page(vma))
+	if (vma_is_hugetlb(vma))
 		return true;
 	if (file->f_op->get_unmapped_area == thp_get_unmapped_area)
 		return true;
@@ -1758,7 +1758,7 @@ static int check_prep_vma(struct vma_remap_struct *vrm)
 		return -EPERM;
 
 	/* Align to hugetlb page size, if required. */
-	if (is_vm_hugetlb_page(vma) && !align_hugetlb(vrm))
+	if (vma_is_hugetlb(vma) && !align_hugetlb(vrm))
 		return -EINVAL;
 
 	vrm_set_delta(vrm);
diff --git a/mm/page_vma_mapped.c b/mm/page_vma_mapped.c
index 28e306fdb3a5..8408aee7571b 100644
--- a/mm/page_vma_mapped.c
+++ b/mm/page_vma_mapped.c
@@ -109,7 +109,7 @@ static bool check_pte(struct page_vma_mapped_walk *pvmw, unsigned long pte_nr)
 	unsigned long pfn;
 	pte_t ptent;
 
-	if (is_vm_hugetlb_page(pvmw->vma))
+	if (vma_is_hugetlb(pvmw->vma))
 		ptent = huge_ptep_get(pvmw->vma->vm_mm, pvmw->address,
 				      pvmw->pte);
 	else
@@ -206,7 +206,7 @@ bool page_vma_mapped_walk(struct page_vma_mapped_walk *pvmw)
 	if (pvmw->pmd && !pvmw->pte)
 		return not_found(pvmw);
 
-	if (unlikely(is_vm_hugetlb_page(vma))) {
+	if (unlikely(vma_is_hugetlb(vma))) {
 		struct hstate *hstate = hstate_vma(vma);
 		unsigned long size = huge_page_size(hstate);
 		/* The only possible mapping was handled on last iteration */
diff --git a/mm/pagewalk.c b/mm/pagewalk.c
index 7411702a37f5..e6493bbe6919 100644
--- a/mm/pagewalk.c
+++ b/mm/pagewalk.c
@@ -408,7 +408,7 @@ static int __walk_page_range(unsigned long start, unsigned long end,
 	int err = 0;
 	struct vm_area_struct *vma = walk->vma;
 	const struct mm_walk_ops *ops = walk->ops;
-	bool is_hugetlb = is_vm_hugetlb_page(vma);
+	bool is_hugetlb = vma_is_hugetlb(vma);
 
 	/* We do not support hugetlb PTE installation. */
 	if (ops->install_pte && is_hugetlb)
diff --git a/mm/swapfile.c b/mm/swapfile.c
index 01e7b6b046b6..f90f029bfd5c 100644
--- a/mm/swapfile.c
+++ b/mm/swapfile.c
@@ -2705,7 +2705,7 @@ static int unuse_mm(struct mm_struct *mm, unsigned int type)
 	if (check_stable_address_space(mm))
 		goto unlock;
 	for_each_vma(vmi, vma) {
-		if (vma->anon_vma && !is_vm_hugetlb_page(vma)) {
+		if (vma->anon_vma && !vma_is_hugetlb(vma)) {
 			ret = unuse_vma(vma, type);
 			if (ret)
 				break;
diff --git a/mm/userfaultfd.c b/mm/userfaultfd.c
index 79cc7b546f13..949017e60608 100644
--- a/mm/userfaultfd.c
+++ b/mm/userfaultfd.c
@@ -237,7 +237,7 @@ static int mfill_get_vma(struct mfill_state *state)
 	if ((flags & MFILL_ATOMIC_WP) && !(dst_vma->vm_flags & VM_UFFD_WP))
 		goto out_unlock;
 
-	if (is_vm_hugetlb_page(dst_vma))
+	if (vma_is_hugetlb(dst_vma))
 		return 0;
 
 	ops = vma_uffd_ops(dst_vma);
@@ -804,7 +804,7 @@ static __always_inline ssize_t mfill_atomic_hugetlb(
 		}
 
 		err = -ENOENT;
-		if (!is_vm_hugetlb_page(dst_vma))
+		if (!vma_is_hugetlb(dst_vma))
 			goto out_unlock_vma;
 
 		err = -EINVAL;
@@ -967,7 +967,7 @@ static __always_inline ssize_t mfill_atomic(struct userfaultfd_ctx *ctx,
 	/*
 	 * If this is a HUGETLB vma, pass off to appropriate routine
 	 */
-	if (is_vm_hugetlb_page(state.vma))
+	if (vma_is_hugetlb(state.vma))
 		return  mfill_atomic_hugetlb(ctx, state.vma, dst_start,
 					     src_start, len, flags);
 
@@ -1114,7 +1114,7 @@ static int mwriteprotect_range(struct userfaultfd_ctx *ctx, unsigned long start,
 			break;
 		}
 
-		if (is_vm_hugetlb_page(dst_vma)) {
+		if (vma_is_hugetlb(dst_vma)) {
 			err = -EINVAL;
 			page_mask = vma_kernel_pagesize(dst_vma) - 1;
 			if ((start & page_mask) || (len & page_mask))
@@ -1172,7 +1172,7 @@ int mrwprotect_range(struct userfaultfd_ctx *ctx, unsigned long start,
 		if (!userfaultfd_rwp(dst_vma))
 			return -ENOENT;
 
-		if (is_vm_hugetlb_page(dst_vma)) {
+		if (vma_is_hugetlb(dst_vma)) {
 			unsigned long page_mask;
 
 			page_mask = vma_kernel_pagesize(dst_vma) - 1;
@@ -2149,7 +2149,7 @@ static bool vma_can_userfault(struct vm_area_struct *vma, vm_flags_t vm_flags,
 	if (vma->vm_flags & (VM_DROPPABLE | VM_SHADOW_STACK))
 		return false;
 
-	if (!is_vm_hugetlb_page(vma) && (vma->vm_flags & VM_SPECIAL))
+	if (!vma_is_hugetlb(vma) && (vma->vm_flags & VM_SPECIAL))
 		return false;
 
 	vm_flags &= __VM_UFFD_FLAGS;
@@ -2319,7 +2319,7 @@ static int userfaultfd_register_range(struct userfaultfd_ctx *ctx,
 		 */
 		userfaultfd_set_ctx(vma, ctx, vm_flags);
 
-		if (is_vm_hugetlb_page(vma) && uffd_disable_huge_pmd_share(vma))
+		if (vma_is_hugetlb(vma) && uffd_disable_huge_pmd_share(vma))
 			hugetlb_unshare_all_pmds(vma);
 
 skip:
@@ -2895,7 +2895,7 @@ vm_fault_t handle_userfault(struct vm_fault *vmf, unsigned long reason)
 	 * (sleepable) vma lock can modify the current task state, that
 	 * must be before explicitly calling set_current_state().
 	 */
-	if (is_vm_hugetlb_page(vma))
+	if (vma_is_hugetlb(vma))
 		hugetlb_vma_lock_read(vma);
 
 	spin_lock_irq(&ctx->fault_pending_wqh.lock);
@@ -2912,7 +2912,7 @@ vm_fault_t handle_userfault(struct vm_fault *vmf, unsigned long reason)
 	set_current_state(blocking_state);
 	spin_unlock_irq(&ctx->fault_pending_wqh.lock);
 
-	if (is_vm_hugetlb_page(vma)) {
+	if (vma_is_hugetlb(vma)) {
 		must_wait = userfaultfd_huge_must_wait(ctx, vmf, reason);
 		hugetlb_vma_unlock_read(vma);
 	} else {
@@ -3744,7 +3744,7 @@ static int userfaultfd_register(struct userfaultfd_ctx *ctx,
 	 * If the first vma contains huge pages, make sure start address
 	 * is aligned to huge page size.
 	 */
-	if (is_vm_hugetlb_page(vma)) {
+	if (vma_is_hugetlb(vma)) {
 		unsigned long vma_hpagesize = vma_kernel_pagesize(vma);
 
 		if (start & (vma_hpagesize - 1))
@@ -3795,7 +3795,7 @@ static int userfaultfd_register(struct userfaultfd_ctx *ctx,
 		 * If this vma contains ending address, and huge pages
 		 * check alignment.
 		 */
-		if (is_vm_hugetlb_page(cur) && end <= cur->vm_end &&
+		if (vma_is_hugetlb(cur) && end <= cur->vm_end &&
 		    end > cur->vm_start) {
 			unsigned long vma_hpagesize = vma_kernel_pagesize(cur);
 
@@ -3831,7 +3831,7 @@ static int userfaultfd_register(struct userfaultfd_ctx *ctx,
 		/*
 		 * Note vmas containing huge pages
 		 */
-		if (is_vm_hugetlb_page(cur))
+		if (vma_is_hugetlb(cur))
 			basic_ioctls = true;
 
 		found = true;
@@ -3917,7 +3917,7 @@ static int userfaultfd_unregister(struct userfaultfd_ctx *ctx,
 	 * If the first vma contains huge pages, make sure start address
 	 * is aligned to huge page size.
 	 */
-	if (is_vm_hugetlb_page(vma)) {
+	if (vma_is_hugetlb(vma)) {
 		unsigned long vma_hpagesize = vma_kernel_pagesize(vma);
 
 		if (start & (vma_hpagesize - 1))
diff --git a/mm/vma.c b/mm/vma.c
index eb2b4501a677..ab570e0a7f16 100644
--- a/mm/vma.c
+++ b/mm/vma.c
@@ -599,7 +599,7 @@ __split_vma(struct vma_iterator *vmi, struct vm_area_struct *vma,
 	 * boundary.
 	 */
 	vma_adjust_trans_huge(vma, vma->vm_start, addr, NULL);
-	if (is_vm_hugetlb_page(vma))
+	if (vma_is_hugetlb(vma))
 		hugetlb_split(vma, addr);
 
 	if (new_below) {
@@ -2228,7 +2228,7 @@ bool vma_wants_writenotify(struct vm_area_struct *vma, pgprot_t vm_page_prot)
 	 * Do we need to track softdirty? hugetlb does not support softdirty
 	 * tracking yet.
 	 */
-	if (vma_soft_dirty_enabled(vma) && !is_vm_hugetlb_page(vma))
+	if (vma_soft_dirty_enabled(vma) && !vma_is_hugetlb(vma))
 		return true;
 
 	/* Do we need write faults for uffd-wp tracking? */
@@ -2347,7 +2347,7 @@ int mm_take_all_locks(struct mm_struct *mm)
 		if (signal_pending(current))
 			goto out_unlock;
 		if (vma->vm_file && vma->vm_file->f_mapping &&
-				is_vm_hugetlb_page(vma))
+				vma_is_hugetlb(vma))
 			vm_lock_mapping(mm, vma->vm_file->f_mapping);
 	}
 
@@ -2356,7 +2356,7 @@ int mm_take_all_locks(struct mm_struct *mm)
 		if (signal_pending(current))
 			goto out_unlock;
 		if (vma->vm_file && vma->vm_file->f_mapping &&
-				!is_vm_hugetlb_page(vma))
+				!vma_is_hugetlb(vma))
 			vm_lock_mapping(mm, vma->vm_file->f_mapping);
 	}
 
diff --git a/mm/vmscan.c b/mm/vmscan.c
index 245f68c75b28..9cbfb90b0ad1 100644
--- a/mm/vmscan.c
+++ b/mm/vmscan.c
@@ -3413,7 +3413,7 @@ static int should_skip_vma(unsigned long start, unsigned long end, struct mm_wal
 	if (!vma_is_accessible(vma))
 		return true;
 
-	if (is_vm_hugetlb_page(vma))
+	if (vma_is_hugetlb(vma))
 		return true;
 
 	if (!vma_has_recency(vma))
diff --git a/tools/testing/vma/include/stubs.h b/tools/testing/vma/include/stubs.h
index d6136e19a8af..48d1dc53df42 100644
--- a/tools/testing/vma/include/stubs.h
+++ b/tools/testing/vma/include/stubs.h
@@ -193,7 +193,7 @@ static inline bool mapping_can_writeback(struct address_space *mapping)
 	return true;
 }
 
-static inline bool is_vm_hugetlb_page(struct vm_area_struct *vma)
+static inline bool vma_is_hugetlb(struct vm_area_struct *vma)
 {
 	return false;
 }

-- 
2.55.0


^ permalink raw reply related	[flat|nested] 89+ messages in thread

* [PATCH 28/39] mm: drop some redundant checks around hugetlb VMAs
  2026-09-08 20:01 [PATCH 00/39] mm: make VMA flag semantics explicit, eliminate VM_SPECIAL Lorenzo Stoakes (ARM)
                   ` (26 preceding siblings ...)
  2026-09-08 20:01 ` [PATCH 27/39] mm: rename is_vm_hugetlb_page() to vma_is_hugetlb() Lorenzo Stoakes (ARM)
@ 2026-09-08 20:01 ` Lorenzo Stoakes (ARM)
  2026-09-08 20:39   ` sashiko-bot
  2026-09-09 12:08   ` Marc Zyngier
  2026-09-08 20:01 ` [PATCH 29/39] mm/madvise: update is_valid_guard_vma() to use vma_can_merge() Lorenzo Stoakes (ARM)
                   ` (10 subsequent siblings)
  38 siblings, 2 replies; 89+ messages in thread
From: Lorenzo Stoakes (ARM) @ 2026-09-08 20:01 UTC (permalink / raw)
  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,
	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, linux-kernel, linux-doc, linux-usb, linux-rdma, selinux,
	linux-sound, bpf, linux-scsi, linux-fbdev, dri-devel,
	linux-trace-kernel, linux-perf-users, linux-arch, linux-fsdevel,
	linux-arm-kernel, kvmarm, linuxppc-dev, kvm, kvm-riscv,
	linux-riscv, linux-s390, sparclinux, fuse-devel,
	Lorenzo Stoakes (ARM)

Adjust code which inadvertently perform redundant checks on hugetlb VMAs
and clean them up:

* hugetlb VMAs have VMA_DONTEXPAND_BIT set so a VMA_SPECIAL_FLAGS check
  suffices. (migrate_vma_setup() regains an explicit hugetlb test later in
  the series, once VMA_SPECIAL_FLAGS is removed.)

* hugetlb VMAs unconditionally set vma->vm_ops, so they are never
  anonymous.

* hugetlb VMAs do not set VMA_PFNMAP_BIT so checking for this is redundant.

While we're here also drop a VM_BUG_ON() which the simplified check above
makes unreachable, and use the new VMA flag API.

No functional change intended.

Signed-off-by: Lorenzo Stoakes (ARM) <ljs@kernel.org>
---
 arch/arm64/kvm/mmu.c         | 4 +---
 drivers/gpu/drm/drm_gpusvm.c | 3 +--
 mm/migrate_device.c          | 4 ++--
 3 files changed, 4 insertions(+), 7 deletions(-)

diff --git a/arch/arm64/kvm/mmu.c b/arch/arm64/kvm/mmu.c
index a7968f8d24bf..3c1240ffc38d 100644
--- a/arch/arm64/kvm/mmu.c
+++ b/arch/arm64/kvm/mmu.c
@@ -1463,14 +1463,12 @@ static int get_vma_page_shift(struct vm_area_struct *vma, unsigned long hva)
 {
 	unsigned long pa;
 
-	if (vma_is_hugetlb(vma) && !(vma->vm_flags & VM_PFNMAP))
+	if (vma_is_hugetlb(vma))
 		return huge_page_shift(hstate_vma(vma));
 
 	if (!(vma->vm_flags & VM_PFNMAP))
 		return PAGE_SHIFT;
 
-	VM_BUG_ON(vma_is_hugetlb(vma));
-
 	pa = (vma->vm_pgoff << PAGE_SHIFT) + (hva - vma->vm_start);
 
 #ifndef __PAGETABLE_PMD_FOLDED
diff --git a/drivers/gpu/drm/drm_gpusvm.c b/drivers/gpu/drm/drm_gpusvm.c
index a1d4989b0b61..fab34fea99c2 100644
--- a/drivers/gpu/drm/drm_gpusvm.c
+++ b/drivers/gpu/drm/drm_gpusvm.c
@@ -1141,8 +1141,7 @@ drm_gpusvm_range_find_or_insert(struct drm_gpusvm *gpusvm,
 	 * limitations. If/when migrate_vma_* add more support, this logic will
 	 * have to change.
 	 */
-	migrate_devmem = ctx->devmem_possible &&
-		vma_is_anonymous(vas) && !vma_is_hugetlb(vas);
+	migrate_devmem = ctx->devmem_possible && vma_is_anonymous(vas);
 
 	chunk_size = drm_gpusvm_range_chunk_size(gpusvm, notifier, vas,
 						 fault_addr, gpuva_start,
diff --git a/mm/migrate_device.c b/mm/migrate_device.c
index c38cbaaef5a4..b9c453c28795 100644
--- a/mm/migrate_device.c
+++ b/mm/migrate_device.c
@@ -743,8 +743,8 @@ int migrate_vma_setup(struct migrate_vma *args)
 
 	args->start &= PAGE_MASK;
 	args->end &= PAGE_MASK;
-	if (!args->vma || vma_is_hugetlb(args->vma) ||
-	    (args->vma->vm_flags & VM_SPECIAL) || vma_is_dax(args->vma))
+	if (!args->vma || vma_test_any_mask(args->vma, VMA_SPECIAL_FLAGS) ||
+	    vma_is_dax(args->vma))
 		return -EINVAL;
 	if (nr_pages <= 0)
 		return -EINVAL;

-- 
2.55.0


^ permalink raw reply related	[flat|nested] 89+ messages in thread

* [PATCH 29/39] mm/madvise: update is_valid_guard_vma() to use vma_can_merge()
  2026-09-08 20:01 [PATCH 00/39] mm: make VMA flag semantics explicit, eliminate VM_SPECIAL Lorenzo Stoakes (ARM)
                   ` (27 preceding siblings ...)
  2026-09-08 20:01 ` [PATCH 28/39] mm: drop some redundant checks around hugetlb VMAs Lorenzo Stoakes (ARM)
@ 2026-09-08 20:01 ` Lorenzo Stoakes (ARM)
  2026-09-08 20:45   ` sashiko-bot
  2026-09-08 20:01 ` [PATCH 30/39] mm/vma: introduce vma[_flags]_is_persistent() Lorenzo Stoakes (ARM)
                   ` (9 subsequent siblings)
  38 siblings, 1 reply; 89+ messages in thread
From: Lorenzo Stoakes (ARM) @ 2026-09-08 20:01 UTC (permalink / raw)
  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,
	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, linux-kernel, linux-doc, linux-usb, linux-rdma, selinux,
	linux-sound, bpf, linux-scsi, linux-fbdev, dri-devel,
	linux-trace-kernel, linux-perf-users, linux-arch, linux-fsdevel,
	linux-arm-kernel, kvmarm, linuxppc-dev, kvm, kvm-riscv,
	linux-riscv, linux-s390, sparclinux, fuse-devel,
	Lorenzo Stoakes (ARM)

We currently disallow the installation of lightweight guard regions in VMAs
whose flags intersect VMA_SPECIAL_FLAGS or VMA_HUGETLB_BIT, or
VMA_LOCKED_BIT unless allow_locked is set.

hugetlb VMAs set VMA_DONTEXPAND_BIT so this was already redundant,
VMA_SPECIAL_FLAGS already sufficed.

However, now that VMA_IO_BIT is only set if VMA_PFNMAP or VMA_MIXEDMAP_BIT
is set, this check collapses to being the equivalent of
!vma_can_merge().

Update is_valid_guard_vma() to reflect this.

No functional change intended.

Signed-off-by: Lorenzo Stoakes (ARM) <ljs@kernel.org>
---
 mm/madvise.c | 20 +++++++++++++-------
 1 file changed, 13 insertions(+), 7 deletions(-)

diff --git a/mm/madvise.c b/mm/madvise.c
index 2db11c832d0f..d0b14cfe38a1 100644
--- a/mm/madvise.c
+++ b/mm/madvise.c
@@ -1055,19 +1055,25 @@ static long madvise_remove(struct madvise_behavior *madv_behavior)
 	return error;
 }
 
-static bool is_valid_guard_vma(struct vm_area_struct *vma, bool allow_locked)
+static bool is_valid_guard_vma(const struct vm_area_struct *vma,
+			       bool allow_locked)
 {
-	vm_flags_t disallowed = VM_SPECIAL | VM_HUGETLB;
-
 	/*
-	 * A user could lock after setting a guard range but that's fine, as
+	 * A user could lock after setting a guard range but that's fine as
 	 * they'd not be able to fault in. The issue arises when we try to zap
 	 * existing locked VMAs. We don't want to do that.
 	 */
-	if (!allow_locked)
-		disallowed |= VM_LOCKED;
+	if (!allow_locked && vma_test(vma, VMA_LOCKED_BIT))
+		return false;
+	/*
+	 * Guard regions require a VMA whose page tables are managed solely by
+	 * the core, which is also what merging requires, so disallow any flags
+	 * that would prevent a merge.
+	 */
+	if (!vma_can_merge(vma))
+		return false;
 
-	return !(vma->vm_flags & disallowed);
+	return true;
 }
 
 static bool is_guard_pte_marker(pte_t ptent)

-- 
2.55.0


^ permalink raw reply related	[flat|nested] 89+ messages in thread

* [PATCH 30/39] mm/vma: introduce vma[_flags]_is_persistent()
  2026-09-08 20:01 [PATCH 00/39] mm: make VMA flag semantics explicit, eliminate VM_SPECIAL Lorenzo Stoakes (ARM)
                   ` (28 preceding siblings ...)
  2026-09-08 20:01 ` [PATCH 29/39] mm/madvise: update is_valid_guard_vma() to use vma_can_merge() Lorenzo Stoakes (ARM)
@ 2026-09-08 20:01 ` Lorenzo Stoakes (ARM)
  2026-09-08 20:47   ` sashiko-bot
  2026-09-08 20:01 ` [PATCH 31/39] mm/uffd: use predicates for userfaultfd checks Lorenzo Stoakes (ARM)
                   ` (8 subsequent siblings)
  38 siblings, 1 reply; 89+ messages in thread
From: Lorenzo Stoakes (ARM) @ 2026-09-08 20:01 UTC (permalink / raw)
  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,
	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, linux-kernel, linux-doc, linux-usb, linux-rdma, selinux,
	linux-sound, bpf, linux-scsi, linux-fbdev, dri-devel,
	linux-trace-kernel, linux-perf-users, linux-arch, linux-fsdevel,
	linux-arm-kernel, kvmarm, linuxppc-dev, kvm, kvm-riscv,
	linux-riscv, linux-s390, sparclinux, fuse-devel,
	Lorenzo Stoakes (ARM)

Introduce vma[_flags]_is_persistent() for the purposes of identifying
mappings that are persistent in the sense that bytes to the mapping stay
there, and bytes read from the mapping are the same unless changed by
actions taken by userland.

Kernel-owned mappings do not fall into this category, as their owner may
change the contents without the user having initiated it, and nor of course
does memory-mapped I/O.

We exclude fixed mappings as these are singled out as being unmergeable and
so cannot be guaranteed to persist user data.

hugetlb mappings are fixed mappings, but their contents are entirely the
user's, so they are explicitly carved out as persistent, as the MADV_DODUMP
check already does.

It excludes droppable mappings, which by their nature are ephemeral.

Use this functionality to update the madvise MADV_DODUMP check to test for
persistence rather than open-coding this.

This replaces the VM_SPECIAL check which means it no longer checks for
VMA_IO_BIT, however this is safe as we have established the invariant that
only kernel-owned mappings may set VMA_IO_BIT, so we implicitly include
these.

No functional change intended.

Signed-off-by: Lorenzo Stoakes (ARM) <ljs@kernel.org>
---
 include/linux/mm.h | 44 ++++++++++++++++++++++++++++++++++++++++++++
 mm/madvise.c       |  4 ++--
 2 files changed, 46 insertions(+), 2 deletions(-)

diff --git a/include/linux/mm.h b/include/linux/mm.h
index d8ee0ca63ccf..e6c3ebb09c8d 100644
--- a/include/linux/mm.h
+++ b/include/linux/mm.h
@@ -1741,6 +1741,50 @@ static inline bool vma_can_merge(const struct vm_area_struct *vma)
 	return vma_flags_can_merge(&vma->flags);
 }
 
+/**
+ * vma_flags_is_persistent() - Do the specified VMA flags imply that the VMA
+ * contains persistent data?
+ * @flags: The VMA flags to test.
+ *
+ * Persistent in the sense that - if you write bytes to the mapping - do they
+ * stay written?
+ *
+ * If the kernel or a device could write to the memory independently of
+ * userland, or the kernel could arbitrarily discard it, then it is not
+ * persistent.
+ *
+ * Returns: true if the flags imply this VMA is persistent, otherwise false.
+ */
+static inline bool vma_flags_is_persistent(const vma_flags_t *flags)
+{
+	/* hugetlb is a fixed mapping, but its contents are the user's own. */
+	if (vma_flags_is_hugetlb(flags))
+		return true;
+	/*
+	 * MMIO mappings may not store what is written and may be changed by the
+	 * device. Kernel-owned and fixed mappings may be changed by their owner
+	 * without the user having initiated it.
+	 */
+	if (vma_flags_is_kernel_owned(flags) ||
+	    vma_flags_is_fixed_mapping(flags))
+		return false;
+	/* Droppable memory is discardable by definition. */
+	return !vma_flags_test_single_mask(flags, VMA_DROPPABLE);
+}
+
+/**
+ * vma_is_persistent() - Does the VMA contain persistent data?
+ * @vma: The VMA to test.
+ *
+ * See vma_flags_is_persistent() for details.
+ *
+ * Returns: true if the VMA is persistent, otherwise false.
+ */
+static inline bool vma_is_persistent(const struct vm_area_struct *vma)
+{
+	return vma_flags_is_persistent(&vma->flags);
+}
+
 /**
  * vma_kernel_pagesize - Default page size granularity for this VMA.
  * @vma: The user mapping.
diff --git a/mm/madvise.c b/mm/madvise.c
index d0b14cfe38a1..0fc31835fee1 100644
--- a/mm/madvise.c
+++ b/mm/madvise.c
@@ -1419,8 +1419,8 @@ static int madvise_vma_behavior(struct madvise_behavior *madv_behavior)
 		new_flags |= VM_DONTDUMP;
 		break;
 	case MADV_DODUMP:
-		if ((!vma_is_hugetlb(vma) && (new_flags & VM_SPECIAL)) ||
-		    (new_flags & VM_DROPPABLE))
+		/* Non-persistent memory cannot be dumped. */
+		if (!vma_is_persistent(vma))
 			return -EINVAL;
 		new_flags &= ~VM_DONTDUMP;
 		break;

-- 
2.55.0


^ permalink raw reply related	[flat|nested] 89+ messages in thread

* [PATCH 31/39] mm/uffd: use predicates for userfaultfd checks
  2026-09-08 20:01 [PATCH 00/39] mm: make VMA flag semantics explicit, eliminate VM_SPECIAL Lorenzo Stoakes (ARM)
                   ` (29 preceding siblings ...)
  2026-09-08 20:01 ` [PATCH 30/39] mm/vma: introduce vma[_flags]_is_persistent() Lorenzo Stoakes (ARM)
@ 2026-09-08 20:01 ` Lorenzo Stoakes (ARM)
  2026-09-08 20:45   ` sashiko-bot
  2026-09-08 20:01 ` [PATCH 32/39] mm/madvise: use predicates for madvise(..., MADV_DOFORK) Lorenzo Stoakes (ARM)
                   ` (7 subsequent siblings)
  38 siblings, 1 reply; 89+ messages in thread
From: Lorenzo Stoakes (ARM) @ 2026-09-08 20:01 UTC (permalink / raw)
  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,
	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, linux-kernel, linux-doc, linux-usb, linux-rdma, selinux,
	linux-sound, bpf, linux-scsi, linux-fbdev, dri-devel,
	linux-trace-kernel, linux-perf-users, linux-arch, linux-fsdevel,
	linux-arm-kernel, kvmarm, linuxppc-dev, kvm, kvm-riscv,
	linux-riscv, linux-s390, sparclinux, fuse-devel,
	Lorenzo Stoakes (ARM)

Rather than directly checking VMA flags, use the newly introduced
vma_is_kernel_owned() and vma_is_persistent() helpers in userfaultfd when
assessing VMA suitability for userfaultfd and UFFDIO_MOVE.

Update vma_move_compatible() so it's expressed in terms of VMA
characteristics rather than arbitrary flags.

Additionally, update the use of the deprecated VMA flag API when checking
VMA_SHADOW_STACK_BIT.

A VMA_IO_BIT check is no longer required but that is fine as a hard
invariant has been established that only kernel-owned mappings may set
VMA_IO_BIT so the check is now redundant.

Signed-off-by: Lorenzo Stoakes (ARM) <ljs@kernel.org>
---
 mm/userfaultfd.c | 21 +++++++++++++++------
 1 file changed, 15 insertions(+), 6 deletions(-)

diff --git a/mm/userfaultfd.c b/mm/userfaultfd.c
index 949017e60608..ddf0a4a3d399 100644
--- a/mm/userfaultfd.c
+++ b/mm/userfaultfd.c
@@ -1754,10 +1754,18 @@ static inline bool move_splits_huge_pmd(unsigned long dst_addr,
 }
 #endif
 
-static inline bool vma_move_compatible(struct vm_area_struct *vma)
+static inline bool vma_move_compatible(const struct vm_area_struct *vma)
 {
-	return !(vma->vm_flags & (VM_PFNMAP | VM_IO |  VM_HUGETLB |
-				  VM_MIXEDMAP | VM_SHADOW_STACK));
+	/* uffd is generally incompatible with kernel-owned mappings. */
+	if (vma_is_kernel_owned(vma))
+		return false;
+	/* The shadow stack should not be written to by userspace. */
+	if (vma_test_single_mask(vma, VMA_SHADOW_STACK))
+		return false;
+	/* hugetlb mappings cannot be safely moved. */
+	if (vma_is_hugetlb(vma))
+		return false;
+	return true;
 }
 
 static int validate_move_areas(struct userfaultfd_ctx *ctx,
@@ -2146,10 +2154,11 @@ static bool vma_can_userfault(struct vm_area_struct *vma, vm_flags_t vm_flags,
 {
 	const struct vm_uffd_ops *ops = vma_uffd_ops(vma);
 
-	if (vma->vm_flags & (VM_DROPPABLE | VM_SHADOW_STACK))
+	/* Non-persistent memory is inherently not controllable by userspace. */
+	if (!vma_is_persistent(vma))
 		return false;
-
-	if (!vma_is_hugetlb(vma) && (vma->vm_flags & VM_SPECIAL))
+	/* The shadow stack should not be written to by userspace. */
+	if (vma_test_single_mask(vma, VMA_SHADOW_STACK))
 		return false;
 
 	vm_flags &= __VM_UFFD_FLAGS;

-- 
2.55.0


^ permalink raw reply related	[flat|nested] 89+ messages in thread

* [PATCH 32/39] mm/madvise: use predicates for madvise(..., MADV_DOFORK)
  2026-09-08 20:01 [PATCH 00/39] mm: make VMA flag semantics explicit, eliminate VM_SPECIAL Lorenzo Stoakes (ARM)
                   ` (30 preceding siblings ...)
  2026-09-08 20:01 ` [PATCH 31/39] mm/uffd: use predicates for userfaultfd checks Lorenzo Stoakes (ARM)
@ 2026-09-08 20:01 ` Lorenzo Stoakes (ARM)
  2026-09-08 20:48   ` sashiko-bot
  2026-09-08 20:01 ` [PATCH 33/39] mm: eliminate VMA_SPECIAL_FLAGS usage when hugetlb explicitly tested Lorenzo Stoakes (ARM)
                   ` (6 subsequent siblings)
  38 siblings, 1 reply; 89+ messages in thread
From: Lorenzo Stoakes (ARM) @ 2026-09-08 20:01 UTC (permalink / raw)
  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,
	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, linux-kernel, linux-doc, linux-usb, linux-rdma, selinux,
	linux-sound, bpf, linux-scsi, linux-fbdev, dri-devel,
	linux-trace-kernel, linux-perf-users, linux-arch, linux-fsdevel,
	linux-arm-kernel, kvmarm, linuxppc-dev, kvm, kvm-riscv,
	linux-riscv, linux-s390, sparclinux, fuse-devel,
	Lorenzo Stoakes (ARM)

Make it clear what we're blocking in MADV_DOFORK. Previously we simply
disallowed VM_SPECIAL i.e. kernel-owned mappings, fixed mappings and
VMA_IO_BIT.

Now the invariant is established that only kernel-owned mappings can set
VMA_IO_BIT, the VMA_IO_BIT check is redundant.

The rest is equivalent to testing for a kernel-owned or fixed mapping,
i.e. exactly the same check as whether the VMA is permitted to be merged.

This was established by commit 0b2758f48f22 ("Require (reasonably) normal
mappings for MADV_DOFORK") containing my hands-down favourite call out of
all time.

Express the same thing differently - if we wouldn't be allowed to merge it,
then we aren't allowed to manipulate CoW behaviour on fork.

No functional change intended.

Signed-off-by: Lorenzo Stoakes (ARM) <ljs@kernel.org>
---
 mm/madvise.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/mm/madvise.c b/mm/madvise.c
index 0fc31835fee1..f805a4876c87 100644
--- a/mm/madvise.c
+++ b/mm/madvise.c
@@ -1400,7 +1400,7 @@ static int madvise_vma_behavior(struct madvise_behavior *madv_behavior)
 		new_flags |= VM_DONTCOPY;
 		break;
 	case MADV_DOFORK:
-		if (new_flags & VM_SPECIAL)
+		if (!vma_can_merge(vma))
 			return -EINVAL;
 		new_flags &= ~VM_DONTCOPY;
 		break;

-- 
2.55.0


^ permalink raw reply related	[flat|nested] 89+ messages in thread

* [PATCH 33/39] mm: eliminate VMA_SPECIAL_FLAGS usage when hugetlb explicitly tested
  2026-09-08 20:01 [PATCH 00/39] mm: make VMA flag semantics explicit, eliminate VM_SPECIAL Lorenzo Stoakes (ARM)
                   ` (31 preceding siblings ...)
  2026-09-08 20:01 ` [PATCH 32/39] mm/madvise: use predicates for madvise(..., MADV_DOFORK) Lorenzo Stoakes (ARM)
@ 2026-09-08 20:01 ` Lorenzo Stoakes (ARM)
  2026-09-08 20:42   ` sashiko-bot
  2026-09-08 20:01 ` [PATCH 34/39] mm: eliminate VMA_SPECIAL_FLAGS check in lru_gen_look_around() Lorenzo Stoakes (ARM)
                   ` (5 subsequent siblings)
  38 siblings, 1 reply; 89+ messages in thread
From: Lorenzo Stoakes (ARM) @ 2026-09-08 20:01 UTC (permalink / raw)
  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,
	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, linux-kernel, linux-doc, linux-usb, linux-rdma, selinux,
	linux-sound, bpf, linux-scsi, linux-fbdev, dri-devel,
	linux-trace-kernel, linux-perf-users, linux-arch, linux-fsdevel,
	linux-arm-kernel, kvmarm, linuxppc-dev, kvm, kvm-riscv,
	linux-riscv, linux-s390, sparclinux, fuse-devel,
	Lorenzo Stoakes (ARM)

It is now an invariant that VMA_IO_BIT is not set except by kernel-owned
mappings, so each existing VMA_SPECIAL_FLAGS test need only test for
VMA_DONTEXPAND_BIT, VMA_PFNMAP_BIT and VMA_MIXEDMAP_BIT.

This is precisely a test for a kernel-owned or fixed mapping.

Update a number of callsites which already explicitly handle hugetlb
mappings.

vma_supports_mlock() and ksm_compatible() also explicitly bail on droppable
mappings - detecting kernel-owned, fixed or droppable mappings is handled
by vma_is_persistent(), so in these cases use this predicate.

should_skip_vma() tests for locked, kernel-owned or fixed memory (having
already excluded hugetlb mappings) so simply test for those there.

No functional change intended.

Signed-off-by: Lorenzo Stoakes (ARM) <ljs@kernel.org>
---
 mm/internal.h | 4 +---
 mm/ksm.c      | 4 +---
 mm/vmscan.c   | 3 ++-
 3 files changed, 4 insertions(+), 7 deletions(-)

diff --git a/mm/internal.h b/mm/internal.h
index 104bbca1eb57..6c004037913b 100644
--- a/mm/internal.h
+++ b/mm/internal.h
@@ -1112,9 +1112,7 @@ static inline struct file *maybe_unlock_mmap_for_io(struct vm_fault *vmf,
 
 static inline bool vma_supports_mlock(const struct vm_area_struct *vma)
 {
-	if (vma_test_any_mask(vma, VMA_SPECIAL_FLAGS))
-		return false;
-	if (vma_test_single_mask(vma, VMA_DROPPABLE))
+	if (!vma_is_persistent(vma))
 		return false;
 	if (vma_is_dax(vma) || vma_is_hugetlb(vma))
 		return false;
diff --git a/mm/ksm.c b/mm/ksm.c
index 624f37975e12..f80372bfd4b2 100644
--- a/mm/ksm.c
+++ b/mm/ksm.c
@@ -747,9 +747,7 @@ static bool ksm_compatible(const struct file *file, vma_flags_t vma_flags)
 	if (vma_flags_test_any(&vma_flags, VMA_SHARED_BIT, VMA_MAYSHARE_BIT,
 			       VMA_HUGETLB_BIT))
 		return false;
-	if (vma_flags_test_single_mask(&vma_flags, VMA_DROPPABLE))
-		return false;
-	if (vma_flags_test_any_mask(&vma_flags, VMA_SPECIAL_FLAGS))
+	if (!vma_flags_is_persistent(&vma_flags))
 		return false;
 	if (file_is_dax(file))
 		return false;
diff --git a/mm/vmscan.c b/mm/vmscan.c
index 9cbfb90b0ad1..803754caf4fa 100644
--- a/mm/vmscan.c
+++ b/mm/vmscan.c
@@ -3419,7 +3419,8 @@ static int should_skip_vma(unsigned long start, unsigned long end, struct mm_wal
 	if (!vma_has_recency(vma))
 		return true;
 
-	if (vma->vm_flags & (VM_LOCKED | VM_SPECIAL))
+	if (vma_test(vma, VMA_LOCKED_BIT) || vma_is_kernel_owned(vma) ||
+	    vma_is_fixed_mapping(vma))
 		return true;
 
 	if (vma == get_gate_vma(vma->vm_mm))

-- 
2.55.0


^ permalink raw reply related	[flat|nested] 89+ messages in thread

* [PATCH 34/39] mm: eliminate VMA_SPECIAL_FLAGS check in lru_gen_look_around()
  2026-09-08 20:01 [PATCH 00/39] mm: make VMA flag semantics explicit, eliminate VM_SPECIAL Lorenzo Stoakes (ARM)
                   ` (32 preceding siblings ...)
  2026-09-08 20:01 ` [PATCH 33/39] mm: eliminate VMA_SPECIAL_FLAGS usage when hugetlb explicitly tested Lorenzo Stoakes (ARM)
@ 2026-09-08 20:01 ` Lorenzo Stoakes (ARM)
  2026-09-08 20:45   ` sashiko-bot
  2026-09-08 20:01 ` [PATCH 35/39] mm: avoid use of VMA_SPECIAL_FLAGS in migrate_vma_setup() Lorenzo Stoakes (ARM)
                   ` (4 subsequent siblings)
  38 siblings, 1 reply; 89+ messages in thread
From: Lorenzo Stoakes (ARM) @ 2026-09-08 20:01 UTC (permalink / raw)
  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,
	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, linux-kernel, linux-doc, linux-usb, linux-rdma, selinux,
	linux-sound, bpf, linux-scsi, linux-fbdev, dri-devel,
	linux-trace-kernel, linux-perf-users, linux-arch, linux-fsdevel,
	linux-arm-kernel, kvmarm, linuxppc-dev, kvm, kvm-riscv,
	linux-riscv, linux-s390, sparclinux, fuse-devel,
	Lorenzo Stoakes (ARM)

A kernel-owned or fixed mapping is one which sets VMA_PFNMAP_BIT,
VMA_MIXEDMAP_BIT or VMA_DONTEXPAND_BIT, which is precisely what
VMA_SPECIAL_FLAGS tests for other than VMA_IO_BIT, which is safe to drop as
only kernel-owned mappings may set it.

Using these predicates rather than VMA_SPECIAL_FLAGS makes the check
self-documenting and helps eliminate the confusion around 'special' flags.

No functional change intended.

Signed-off-by: Lorenzo Stoakes (ARM) <ljs@kernel.org>
---
 mm/vmscan.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/mm/vmscan.c b/mm/vmscan.c
index 803754caf4fa..0082afbdbbdd 100644
--- a/mm/vmscan.c
+++ b/mm/vmscan.c
@@ -4364,8 +4364,8 @@ bool lru_gen_look_around(struct page_vma_mapped_walk *pvmw, unsigned int nr)
 	if (spin_is_contended(pvmw->ptl))
 		return true;
 
-	/* exclude special VMAs containing anon pages from COW */
-	if (vma->vm_flags & VM_SPECIAL)
+	/* exclude kernel-owned and fixed VMAs containing anon pages from COW */
+	if (vma_is_kernel_owned(vma) || vma_is_fixed_mapping(vma))
 		return true;
 
 	/* avoid taking the LRU lock under the PTL when possible */

-- 
2.55.0


^ permalink raw reply related	[flat|nested] 89+ messages in thread

* [PATCH 35/39] mm: avoid use of VMA_SPECIAL_FLAGS in migrate_vma_setup()
  2026-09-08 20:01 [PATCH 00/39] mm: make VMA flag semantics explicit, eliminate VM_SPECIAL Lorenzo Stoakes (ARM)
                   ` (33 preceding siblings ...)
  2026-09-08 20:01 ` [PATCH 34/39] mm: eliminate VMA_SPECIAL_FLAGS check in lru_gen_look_around() Lorenzo Stoakes (ARM)
@ 2026-09-08 20:01 ` Lorenzo Stoakes (ARM)
  2026-09-08 20:47   ` sashiko-bot
  2026-09-08 20:01 ` [PATCH 36/39] mm: eliminate VM_SPECIAL, VMA_SPECIAL_FLAGS Lorenzo Stoakes (ARM)
                   ` (3 subsequent siblings)
  38 siblings, 1 reply; 89+ messages in thread
From: Lorenzo Stoakes (ARM) @ 2026-09-08 20:01 UTC (permalink / raw)
  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,
	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, linux-kernel, linux-doc, linux-usb, linux-rdma, selinux,
	linux-sound, bpf, linux-scsi, linux-fbdev, dri-devel,
	linux-trace-kernel, linux-perf-users, linux-arch, linux-fsdevel,
	linux-arm-kernel, kvmarm, linuxppc-dev, kvm, kvm-riscv,
	linux-riscv, linux-s390, sparclinux, fuse-devel,
	Lorenzo Stoakes (ARM)

Now we have the expressive vma_is_kernel_owned() and vma_is_fixed_mapping()
predicates, use them to determine whether to proceed with migration. This
drops the VMA_IO_BIT test, which is safe as only kernel-owned mappings may
set it.

hugetlb mappings remain excluded, as they are fixed mappings.

No functional change intended.

Signed-off-by: Lorenzo Stoakes (ARM) <ljs@kernel.org>
---
 mm/migrate_device.c | 12 +++++++-----
 1 file changed, 7 insertions(+), 5 deletions(-)

diff --git a/mm/migrate_device.c b/mm/migrate_device.c
index b9c453c28795..b74c0ae42768 100644
--- a/mm/migrate_device.c
+++ b/mm/migrate_device.c
@@ -739,19 +739,21 @@ static void migrate_vma_unmap(struct migrate_vma *migrate)
  */
 int migrate_vma_setup(struct migrate_vma *args)
 {
+	const struct vm_area_struct *vma = args->vma;
 	long nr_pages = (args->end - args->start) >> PAGE_SHIFT;
 
 	args->start &= PAGE_MASK;
 	args->end &= PAGE_MASK;
-	if (!args->vma || vma_test_any_mask(args->vma, VMA_SPECIAL_FLAGS) ||
-	    vma_is_dax(args->vma))
+	if (!vma)
+		return -EINVAL;
+	if (vma_is_kernel_owned(vma) || vma_is_fixed_mapping(vma) ||
+	    vma_is_dax(vma))
 		return -EINVAL;
 	if (nr_pages <= 0)
 		return -EINVAL;
-	if (args->start < args->vma->vm_start ||
-	    args->start >= args->vma->vm_end)
+	if (args->start < vma->vm_start || args->start >= vma->vm_end)
 		return -EINVAL;
-	if (args->end <= args->vma->vm_start || args->end > args->vma->vm_end)
+	if (args->end <= vma->vm_start || args->end > vma->vm_end)
 		return -EINVAL;
 	if (!args->src || !args->dst)
 		return -EINVAL;

-- 
2.55.0


^ permalink raw reply related	[flat|nested] 89+ messages in thread

* [PATCH 36/39] mm: eliminate VM_SPECIAL, VMA_SPECIAL_FLAGS
  2026-09-08 20:01 [PATCH 00/39] mm: make VMA flag semantics explicit, eliminate VM_SPECIAL Lorenzo Stoakes (ARM)
                   ` (34 preceding siblings ...)
  2026-09-08 20:01 ` [PATCH 35/39] mm: avoid use of VMA_SPECIAL_FLAGS in migrate_vma_setup() Lorenzo Stoakes (ARM)
@ 2026-09-08 20:01 ` Lorenzo Stoakes (ARM)
  2026-09-08 20:41   ` sashiko-bot
  2026-09-08 20:01 ` [PATCH 37/39] fuse: dax: do not set VM_MIXEDMAP Lorenzo Stoakes (ARM)
                   ` (2 subsequent siblings)
  38 siblings, 1 reply; 89+ messages in thread
From: Lorenzo Stoakes (ARM) @ 2026-09-08 20:01 UTC (permalink / raw)
  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,
	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, linux-kernel, linux-doc, linux-usb, linux-rdma, selinux,
	linux-sound, bpf, linux-scsi, linux-fbdev, dri-devel,
	linux-trace-kernel, linux-perf-users, linux-arch, linux-fsdevel,
	linux-arm-kernel, kvmarm, linuxppc-dev, kvm, kvm-riscv,
	linux-riscv, linux-s390, sparclinux, fuse-devel,
	Lorenzo Stoakes (ARM)

Every user of the VM_SPECIAL or VMA_SPECIAL_FLAGS has now been converted to
predicates which explicitly express what is actually being checked for
rather than the nebulous concept of possessing 'special' VMA flags.

In any case 'special' is not so special a term of art in mm - it includes
VDSO/VVAR mappings, special in the sense of vm_normal_folio() and probably
other cases too.

Therefore make things less special by eliminating these now unused flags.

No functional change intended.

Signed-off-by: Lorenzo Stoakes (ARM) <ljs@kernel.org>
---
 include/linux/mm.h              | 8 --------
 tools/testing/vma/include/dup.h | 8 --------
 2 files changed, 16 deletions(-)

diff --git a/include/linux/mm.h b/include/linux/mm.h
index e6c3ebb09c8d..b5784685272a 100644
--- a/include/linux/mm.h
+++ b/include/linux/mm.h
@@ -576,14 +576,6 @@ enum {
 #define VM_ACCESS_FLAGS (VM_READ | VM_WRITE | VM_EXEC)
 #define VMA_ACCESS_FLAGS mk_vma_flags(VMA_READ_BIT, VMA_WRITE_BIT, VMA_EXEC_BIT)
 
-/*
- * Special vmas that are non-mergable, non-mlock()able.
- */
-
-#define VMA_SPECIAL_FLAGS mk_vma_flags(VMA_IO_BIT, VMA_DONTEXPAND_BIT, \
-				       VMA_PFNMAP_BIT, VMA_MIXEDMAP_BIT)
-#define VM_SPECIAL vma_flags_to_legacy(VMA_SPECIAL_FLAGS)
-
 /*
  * Physically remapped pages are special. Tell the
  * rest of the world about it:
diff --git a/tools/testing/vma/include/dup.h b/tools/testing/vma/include/dup.h
index e6cb2ea196f2..61b08589e592 100644
--- a/tools/testing/vma/include/dup.h
+++ b/tools/testing/vma/include/dup.h
@@ -352,14 +352,6 @@ enum {
 #define VM_ACCESS_FLAGS (VM_READ | VM_WRITE | VM_EXEC)
 #define VMA_ACCESS_FLAGS mk_vma_flags(VMA_READ_BIT, VMA_WRITE_BIT, VMA_EXEC_BIT)
 
-/*
- * Special vmas that are non-mergable, non-mlock()able.
- */
-#define VM_SPECIAL (VM_IO | VM_DONTEXPAND | VM_PFNMAP | VM_MIXEDMAP)
-
-#define VMA_SPECIAL_FLAGS mk_vma_flags(VMA_IO_BIT, VMA_DONTEXPAND_BIT, \
-				       VMA_PFNMAP_BIT, VMA_MIXEDMAP_BIT)
-
 #define VMA_REMAP_FLAGS mk_vma_flags(VMA_IO_BIT, VMA_PFNMAP_BIT,	\
 				     VMA_DONTEXPAND_BIT, VMA_DONTDUMP_BIT)
 

-- 
2.55.0


^ permalink raw reply related	[flat|nested] 89+ messages in thread

* [PATCH 37/39] fuse: dax: do not set VM_MIXEDMAP
  2026-09-08 20:01 [PATCH 00/39] mm: make VMA flag semantics explicit, eliminate VM_SPECIAL Lorenzo Stoakes (ARM)
                   ` (35 preceding siblings ...)
  2026-09-08 20:01 ` [PATCH 36/39] mm: eliminate VM_SPECIAL, VMA_SPECIAL_FLAGS Lorenzo Stoakes (ARM)
@ 2026-09-08 20:01 ` Lorenzo Stoakes (ARM)
  2026-09-08 20:50   ` sashiko-bot
  2026-09-08 20:01 ` [PATCH 38/39] mm/huge_memory: remove vma_is_special_huge() Lorenzo Stoakes (ARM)
  2026-09-08 20:01 ` [PATCH 39/39] mm/vma: introduce and use vma[_flags]_can_gup() Lorenzo Stoakes (ARM)
  38 siblings, 1 reply; 89+ messages in thread
From: Lorenzo Stoakes (ARM) @ 2026-09-08 20:01 UTC (permalink / raw)
  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,
	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, linux-kernel, linux-doc, linux-usb, linux-rdma, selinux,
	linux-sound, bpf, linux-scsi, linux-fbdev, dri-devel,
	linux-trace-kernel, linux-perf-users, linux-arch, linux-fsdevel,
	linux-arm-kernel, kvmarm, linuxppc-dev, kvm, kvm-riscv,
	linux-riscv, linux-s390, sparclinux, fuse-devel,
	Lorenzo Stoakes (ARM)

Commit e1fb4a086495 ("dax: remove VM_MIXEDMAP for fsdax and device dax")
prevented fsdax and device-dax from setting VM_MIXEDMAP, as DAX no longer
relies on it to direct core mm paths.

The fuse DAX implementation, added later, copied the old pattern and still
sets it.

Fuse DAX maps pages the same way fsdax does, via dax_iomap_fault() and
ultimately vmf_insert_page_mkwrite() and vmf_insert_folio_pmd(), which
insert ordinary refcounted pages and so do not require VM_MIXEDMAP.

Setting it only serves to mark the mapping as kernel-owned, making fuse DAX
the sole DAX implementation whose mappings are unmergeable, cannot be
mlock()'d, eagerly copy page tables on fork and reject MADV_DOFORK and
MADV_DODUMP.

It also requires vma_is_special_huge() in mm/huge_memory.c to carve DAX out
of its kernel-owned check explicitly.

There is no reason for fuse DAX to keep on using this flag so drop it.

Signed-off-by: Lorenzo Stoakes (ARM) <ljs@kernel.org>
---
 fs/fuse/dax.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/fs/fuse/dax.c b/fs/fuse/dax.c
index 85cdf0199bc0..a5994f1c637d 100644
--- a/fs/fuse/dax.c
+++ b/fs/fuse/dax.c
@@ -826,7 +826,7 @@ int fuse_dax_mmap(struct file *file, struct vm_area_struct *vma)
 {
 	file_accessed(file);
 	vma->vm_ops = &fuse_dax_vm_ops;
-	vm_flags_set(vma, VM_MIXEDMAP | VM_HUGEPAGE);
+	vma_set_flags(vma, VMA_HUGEPAGE_BIT);
 	return 0;
 }
 

-- 
2.55.0


^ permalink raw reply related	[flat|nested] 89+ messages in thread

* [PATCH 38/39] mm/huge_memory: remove vma_is_special_huge()
  2026-09-08 20:01 [PATCH 00/39] mm: make VMA flag semantics explicit, eliminate VM_SPECIAL Lorenzo Stoakes (ARM)
                   ` (36 preceding siblings ...)
  2026-09-08 20:01 ` [PATCH 37/39] fuse: dax: do not set VM_MIXEDMAP Lorenzo Stoakes (ARM)
@ 2026-09-08 20:01 ` Lorenzo Stoakes (ARM)
  2026-09-08 20:45   ` sashiko-bot
  2026-09-08 20:01 ` [PATCH 39/39] mm/vma: introduce and use vma[_flags]_can_gup() Lorenzo Stoakes (ARM)
  38 siblings, 1 reply; 89+ messages in thread
From: Lorenzo Stoakes (ARM) @ 2026-09-08 20:01 UTC (permalink / raw)
  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,
	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, linux-kernel, linux-doc, linux-usb, linux-rdma, selinux,
	linux-sound, bpf, linux-scsi, linux-fbdev, dri-devel,
	linux-trace-kernel, linux-perf-users, linux-arch, linux-fsdevel,
	linux-arm-kernel, kvmarm, linuxppc-dev, kvm, kvm-riscv,
	linux-riscv, linux-s390, sparclinux, fuse-devel,
	Lorenzo Stoakes (ARM)

vma_is_special_huge() tests whether either the VMA_PFNMAP_BIT or
VMA_MIXEDMAP_BIT is set (i.e. whether the VMA is a kernel-owned mapping),
but with a DAX carve-out.

DAX however no longer sets VMA_MIXEDMAP_BIT, so this carve-out is no longer
required.

Therefore test for vma_is_kernel_owned() instead and also drop the
VMA_IO_BIT check, as it is now redundant since it is enforced that only
kernel-owned mappings can set this flag.

This also eliminates another overloaded use of 'special' within mm.

No functional change intended.

Signed-off-by: Lorenzo Stoakes (ARM) <ljs@kernel.org>
---
 mm/huge_memory.c | 18 ++++--------------
 1 file changed, 4 insertions(+), 14 deletions(-)

diff --git a/mm/huge_memory.c b/mm/huge_memory.c
index cf6c50e531f5..1ec1cd970ce6 100644
--- a/mm/huge_memory.c
+++ b/mm/huge_memory.c
@@ -110,14 +110,6 @@ static inline bool file_thp_enabled(const struct vm_area_struct *vma)
 	return S_ISREG(inode->i_mode);
 }
 
-/* If returns true, we are unable to access the VMA's folios. */
-static bool vma_is_special_huge(const struct vm_area_struct *vma)
-{
-	if (vma_is_dax(vma))
-		return false;
-	return vma_test_any(vma, VMA_PFNMAP_BIT, VMA_MIXEDMAP_BIT);
-}
-
 static bool vma_file_bypass_thp_tuneables(const struct vm_area_struct *vma,
 		enum tva_type type)
 {
@@ -192,7 +184,7 @@ unsigned long __thp_vma_allowable_orders(struct vm_area_struct *vma,
 	/* Check the intersection of requested and supported orders. */
 	if (vma_is_anonymous(vma))
 		supported_orders = THP_ORDERS_ALL_ANON;
-	else if (vma_is_dax(vma) || vma_is_special_huge(vma))
+	else if (vma_is_dax(vma) || vma_is_kernel_owned(vma))
 		supported_orders = THP_ORDERS_ALL_SPECIAL_DAX;
 	else
 		supported_orders = THP_ORDERS_ALL_FILE_DEFAULT;
@@ -3065,7 +3057,7 @@ int zap_huge_pud(struct mmu_gather *tlb, struct vm_area_struct *vma,
 	orig_pud = pudp_huge_get_and_clear_full(vma, addr, pud, tlb->fullmm);
 	arch_check_zapped_pud(vma, orig_pud);
 	tlb_remove_pud_tlb_entry(tlb, pud, addr);
-	if (vma_is_special_huge(vma)) {
+	if (vma_is_kernel_owned(vma)) {
 		spin_unlock(ptl);
 		/* No zero page support yet */
 	} else {
@@ -3221,7 +3213,7 @@ static void __split_huge_pmd_locked(struct vm_area_struct *vma, pmd_t *pmd,
 		 */
 		if (arch_needs_pgtable_deposit())
 			zap_deposited_table(mm, pmd);
-		if (vma_is_special_huge(vma))
+		if (vma_is_kernel_owned(vma))
 			return;
 		if (unlikely(pmd_is_migration_entry(old_pmd))) {
 			const softleaf_t old_entry = softleaf_from_pmd(old_pmd);
@@ -4750,9 +4742,7 @@ static inline bool vma_not_suitable_for_thp_split(struct vm_area_struct *vma)
 {
 	if (vma_is_dax(vma))
 		return true;
-	if (vma_is_special_huge(vma))
-		return true;
-	if (vma_test(vma, VMA_IO_BIT))
+	if (vma_is_kernel_owned(vma))
 		return true;
 	if (vma_is_hugetlb(vma))
 		return true;

-- 
2.55.0


^ permalink raw reply related	[flat|nested] 89+ messages in thread

* [PATCH 39/39] mm/vma: introduce and use vma[_flags]_can_gup()
  2026-09-08 20:01 [PATCH 00/39] mm: make VMA flag semantics explicit, eliminate VM_SPECIAL Lorenzo Stoakes (ARM)
                   ` (37 preceding siblings ...)
  2026-09-08 20:01 ` [PATCH 38/39] mm/huge_memory: remove vma_is_special_huge() Lorenzo Stoakes (ARM)
@ 2026-09-08 20:01 ` Lorenzo Stoakes (ARM)
  2026-09-08 20:44   ` sashiko-bot
  38 siblings, 1 reply; 89+ messages in thread
From: Lorenzo Stoakes (ARM) @ 2026-09-08 20:01 UTC (permalink / raw)
  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,
	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, linux-kernel, linux-doc, linux-usb, linux-rdma, selinux,
	linux-sound, bpf, linux-scsi, linux-fbdev, dri-devel,
	linux-trace-kernel, linux-perf-users, linux-arch, linux-fsdevel,
	linux-arm-kernel, kvmarm, linuxppc-dev, kvm, kvm-riscv,
	linux-riscv, linux-s390, sparclinux, fuse-devel,
	Lorenzo Stoakes (ARM)

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) <ljs@kernel.org>
---
 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


^ permalink raw reply related	[flat|nested] 89+ messages in thread

* Re: [PATCH 11/39] selinux: reject writable opens of policy file, drop mmap shared/write check
  2026-09-08 20:01 ` [PATCH 11/39] selinux: reject writable opens of policy file, drop mmap shared/write check Lorenzo Stoakes (ARM)
@ 2026-09-08 20:22   ` Jann Horn
  2026-09-08 20:36   ` sashiko-bot
  2026-09-10 18:11   ` Stephen Smalley
  2 siblings, 0 replies; 89+ messages in thread
From: Jann Horn @ 2026-09-08 20:22 UTC (permalink / raw)
  To: Lorenzo Stoakes (ARM)
  Cc: Andrew Morton, Liam R. Howlett, Vlastimil Babka, 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, 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, linux-mm,
	linux-kernel, linux-doc, linux-usb, linux-rdma, selinux,
	linux-sound, bpf, linux-scsi, linux-fbdev, dri-devel,
	linux-trace-kernel, linux-perf-users, linux-arch, linux-fsdevel,
	linux-arm-kernel, kvmarm, linuxppc-dev, kvm, kvm-riscv,
	linux-riscv, linux-s390, sparclinux, fuse-devel

On Tue, Sep 8, 2026 at 10:07 PM Lorenzo Stoakes (ARM) <ljs@kernel.org> wrote:
> The policy file has no write method and is exposed read-only (S_IRUGO in
> selinux_files[]), yet sel_open_policy() performs no open mode check, so a
> CAP_DAC_OVERRIDE caller can open it O_RDWR. Reject FMODE_WRITE at open, as
> kernfs does.
>
> The file can then never be mapped with FMODE_WRITE, so do_mmap() always
> clears VM_MAYWRITE and VM_SHARED for MAP_SHARED mappings and the VM_SHARED
> check in sel_mmap_policy() cannot be reached. Remove it.

You should also be able to remove the sel_mmap_policy_ops.page_mkwrite
handler, which is only for shared-writable faults, right?

> This also stops sel_mmap_policy() clearing VM_MAYWRITE on a mapping that is
> neither a PFN map nor a mixed map, ahead of the core enforcing that only
> such mappings may do so.
>
> Signed-off-by: Lorenzo Stoakes (ARM) <ljs@kernel.org>

Reviewed-by: Jann Horn <jannh@google.com>

^ permalink raw reply	[flat|nested] 89+ messages in thread

* Re: [PATCH 05/39] mm: make map_kernel_pages_[prepare,complete] internal and unexported
  2026-09-08 20:01 ` [PATCH 05/39] mm: make map_kernel_pages_[prepare,complete] internal and unexported Lorenzo Stoakes (ARM)
@ 2026-09-08 20:24   ` sashiko-bot
  0 siblings, 0 replies; 89+ messages in thread
From: sashiko-bot @ 2026-09-08 20:24 UTC (permalink / raw)
  To: Lorenzo Stoakes (ARM)
  Cc: Christian Borntraeger, Vasily Gorbik, linux-perf-users,
	Heiko Carstens, selinux, Oliver Upton, kvm, kvmarm, linux-s390,
	bpf, Marc Zyngier, dri-devel, linux-trace-kernel, linux-scsi,
	Alexander Gordeev

> There's no reason to export the symbols for these functions which are only
> called from internal mm logic, additionally there's no reason for them to
> be declared in mm.h.
> 
> This patch therefore removes the exports and moves the declarations to
> mm/internal.h.
> 
> No functional change intended.
> 
> Signed-off-by: Lorenzo Stoakes (ARM) <ljs@kernel.org>

Sashiko has reviewed this patch and found no issues. It looks great!

-- 
Sashiko AI review · https://sashiko.dev/#/patchset/20260908-b4-mmap-prepare-vma-flag-sanify-v1-0-dacf19cce22b@kernel.org?part=5


^ permalink raw reply	[flat|nested] 89+ messages in thread

* Re: [PATCH 02/39] mm/vma: introduce and use vma_[flags_]can_merge()
  2026-09-08 20:01 ` [PATCH 02/39] mm/vma: introduce and use vma_[flags_]can_merge() Lorenzo Stoakes (ARM)
@ 2026-09-08 20:27   ` sashiko-bot
  0 siblings, 0 replies; 89+ messages in thread
From: sashiko-bot @ 2026-09-08 20:27 UTC (permalink / raw)
  To: Lorenzo Stoakes (ARM)
  Cc: Vasily Gorbik, Christian Borntraeger, Alexander Gordeev,
	Marc Zyngier, linux-s390, linux-perf-users, kvmarm, Oliver Upton,
	bpf, linux-scsi, Heiko Carstens, dri-devel, selinux, kvm,
	linux-trace-kernel

> Replace the open-coded VMA_SPECIAL_FLAGS check in the VMA merge logic with
> two new functions vma_flags_can_merge() and vma_can_merge() and update the
> merge logic to use the former.
> 
> This abstracts the check and expresses it in terms of the desired behaviour
> rather than an arbitrary and confusing VMA flag.
> 
> This also lays the groundwork for making further improvements in VMA flag
> usage.
> 
> Also update the userland VMA tests to reflect the change.
> 
> No functional change intended.
> 
> Signed-off-by: Lorenzo Stoakes (ARM) <ljs@kernel.org>

Sashiko has reviewed this patch and found no issues. It looks great!

-- 
Sashiko AI review · https://sashiko.dev/#/patchset/20260908-b4-mmap-prepare-vma-flag-sanify-v1-0-dacf19cce22b@kernel.org?part=2


^ permalink raw reply	[flat|nested] 89+ messages in thread

* Re: [PATCH 06/39] mm/vma: tidy up map kernel pages enum values
  2026-09-08 20:01 ` [PATCH 06/39] mm/vma: tidy up map kernel pages enum values Lorenzo Stoakes (ARM)
@ 2026-09-08 20:27   ` sashiko-bot
  0 siblings, 0 replies; 89+ messages in thread
From: sashiko-bot @ 2026-09-08 20:27 UTC (permalink / raw)
  To: Lorenzo Stoakes (ARM)
  Cc: linux-trace-kernel, kvm, dri-devel, linux-s390, Vasily Gorbik,
	Alexander Gordeev, Christian Borntraeger, kvmarm,
	linux-perf-users, bpf, selinux, Heiko Carstens, Oliver Upton,
	Marc Zyngier, linux-scsi

> MMAP_MAP_KERNEL_PAGES is a mouthful, discard the MAP_ as that's implied by
> MMAP.
> 
> Also while we're here delete useless comments for mmap actions whose names
> clearly indicate what they are for.
> 
> Also update the userland VMA tests to reflect this change.
> 
> No functional change intended.
> 
> Signed-off-by: Lorenzo Stoakes (ARM) <ljs@kernel.org>

Sashiko has reviewed this patch and found no issues. It looks great!

-- 
Sashiko AI review · https://sashiko.dev/#/patchset/20260908-b4-mmap-prepare-vma-flag-sanify-v1-0-dacf19cce22b@kernel.org?part=6


^ permalink raw reply	[flat|nested] 89+ messages in thread

* Re: [PATCH 14/39] mm/vma: add vma[_flags]_is_kernel_owned() predicates
  2026-09-08 20:01 ` [PATCH 14/39] mm/vma: add vma[_flags]_is_kernel_owned() predicates Lorenzo Stoakes (ARM)
@ 2026-09-08 20:28   ` sashiko-bot
  0 siblings, 0 replies; 89+ messages in thread
From: sashiko-bot @ 2026-09-08 20:28 UTC (permalink / raw)
  To: Lorenzo Stoakes (ARM)
  Cc: linux-trace-kernel, Oliver Upton, linux-scsi, linux-s390,
	dri-devel, bpf, Vasily Gorbik, selinux, Christian Borntraeger,
	Heiko Carstens, linux-perf-users, kvm, kvmarm, Alexander Gordeev,
	Marc Zyngier

> Rather than referring to VMA flags with uncertain meaning, add a new
> predicate that explicitly describes what possession of the VMA_PFNMAP_BIT
> or VMA_MIXEDMAP_BIT flags mean, and then refer to that function for
> determining VMA mergeability.
> 
> Either flag means the contents of the mapping are owned by the kernel,
> usually a driver, rather than by the core mm: the memory may be MMIO,
> kernel-allocated pages or even ordinary pages the driver maps itself, but
> the core must not populate, reclaim, migrate, copy-on-write or merge the
> range on its own initiative.
> 
> We initially also include VMA_IO_BIT here, as by implication, these must be
> kernel-owned. (mlock() also sets VMA_IO_BIT transiently on ordinary VMAs
> while locking them, which is addressed later in this series.)
> 
> However the intent is to in future remove this, as no mapping should be
> marked as an I/O mapping without also being marked with VMA_PFNMAP_BIT.
> 
> This forms the basis of further work intended to improve how we express VMA
> properties such as this.
> 
> Also update the VMA userland tests to reflect the change.
> 
> No functional change intended.
> 
> Signed-off-by: Lorenzo Stoakes (ARM) <ljs@kernel.org>

Sashiko has reviewed this patch and found no issues. It looks great!

-- 
Sashiko AI review · https://sashiko.dev/#/patchset/20260908-b4-mmap-prepare-vma-flag-sanify-v1-0-dacf19cce22b@kernel.org?part=14


^ permalink raw reply	[flat|nested] 89+ messages in thread

* Re: [PATCH 07/39] mm: add mmap action for discontiguous kernel page mapping
  2026-09-08 20:01 ` [PATCH 07/39] mm: add mmap action for discontiguous kernel page mapping Lorenzo Stoakes (ARM)
@ 2026-09-08 20:34   ` sashiko-bot
  0 siblings, 0 replies; 89+ messages in thread
From: sashiko-bot @ 2026-09-08 20:34 UTC (permalink / raw)
  To: Lorenzo Stoakes (ARM)
  Cc: Alexander Gordeev, bpf, linux-scsi, Christian Borntraeger,
	linux-s390, Heiko Carstens, Vasily Gorbik, dri-devel,
	linux-trace-kernel, selinux, kvmarm, linux-perf-users,
	Marc Zyngier, Oliver Upton, kvm

Thank you for your contribution! Sashiko AI review found 1 potential issue(s) to consider:
- [Low] The userland VMA testing header `dup.h` was not fully updated; the `map_kernel_discontig` field is missing from `struct mmap_action`.
--

commit 0017a54bcba2043c3f552b308a32a39be664f463
Author: Lorenzo Stoakes (ARM) <ljs@kernel.org>

mm: add mmap action for discontiguous kernel page mapping

This commit introduces a new mmap action, MMAP_DISCONTIG_KERNEL_PAGES, to
allow drivers to map discontiguous ranges of struct page pointers. It provides
discontig_kernel_page_ops for drivers to specify how page batches should be
retrieved, and updates the core mm and VMA test headers accordingly.

> diff --git a/include/linux/mm_types.h b/include/linux/mm_types.h
> index 9ca2ea3664bc1..0cb4f96039568 100644
> --- a/include/linux/mm_types.h
> +++ b/include/linux/mm_types.h

[ ... ]

> @@ -844,6 +880,10 @@ struct mmap_action {
>  			unsigned long nr_pages;
>  			pgoff_t pgoff;
>  		} map_kernel;
> +		struct {
> +			void *init_private;
> +			const struct discontig_kernel_page_ops *ops;
> +		} map_kernel_discontig;
>  	};
>  	enum mmap_action_type type;

[ ... ]

> diff --git a/tools/testing/vma/include/dup.h b/tools/testing/vma/include/dup.h
> index 1098655a5f4a3..52eee05e6c322 100644
> --- a/tools/testing/vma/include/dup.h
> +++ b/tools/testing/vma/include/dup.h
> @@ -457,8 +457,9 @@ enum mmap_action_type {
>  	MMAP_NOTHING,
>  	MMAP_REMAP_PFN,
>  	MMAP_IO_REMAP_PFN,
> -	MMAP_SIMPLE_IO_REMAP,	/* I/O remap with guardrails. */
> -	MMAP_KERNEL_PAGES,	/* Map kernel page range from array. */
> +	MMAP_SIMPLE_IO_REMAP,		/* I/O remap with guardrails. */
> +	MMAP_KERNEL_PAGES,		/* Map kernel page range from array. */
> +	MMAP_DISCONTIG_KERNEL_PAGES,	/* Map kernel discontig page range. */
>  };
>  
>  /*

[Severity: Low]
Does struct mmap_action in this userland VMA testing header also need
to be updated?

The map_kernel_discontig field was added to the kernel's mm_types.h, but
it appears to be missing from the corresponding struct mmap_action defined
in tools/testing/vma/include/dup.h. 

If a selftest attempts to access the map_kernel_discontig union member of 
struct mmap_action for MMAP_DISCONTIG_KERNEL_PAGES, it will fail to compile.

-- 
Sashiko AI review · https://sashiko.dev/#/patchset/20260908-b4-mmap-prepare-vma-flag-sanify-v1-0-dacf19cce22b@kernel.org?part=7

^ permalink raw reply	[flat|nested] 89+ messages in thread

* Re: [PATCH 26/39] mm: remove hugetlb_inline.h
  2026-09-08 20:01 ` [PATCH 26/39] mm: remove hugetlb_inline.h Lorenzo Stoakes (ARM)
@ 2026-09-08 20:34   ` sashiko-bot
  0 siblings, 0 replies; 89+ messages in thread
From: sashiko-bot @ 2026-09-08 20:34 UTC (permalink / raw)
  To: Lorenzo Stoakes (ARM)
  Cc: Vasily Gorbik, linux-trace-kernel, bpf, selinux,
	Christian Borntraeger, linux-s390, linux-scsi, kvmarm,
	Marc Zyngier, dri-devel, kvm, Oliver Upton, Heiko Carstens,
	Alexander Gordeev, linux-perf-users

> This header really makes little sense - every place it is included mm.h is
> also included, and the header itself includes mm.h, so it does nothing to
> reduce header size.
> 
> It also oddly does an #ifdef around checking VMA_HUGETLB_BIT, however
> VMA_HUGETLB_BIT is unconditionally available, and will never be set if
> hugetlb is not enabled.
> 
> Simply remove the header, eliminate the odd ifdeffery and place the
> predicates in mm.h.
> 
> The naming of these predicates is odd, but to keep changes separate, we
> will address this in a separate patch.
> 
> The file was never put into MAINTAINERS so there's no change required
> there.
> 
> No functional change intended.
> 
> Signed-off-by: Lorenzo Stoakes (ARM) <ljs@kernel.org>

Sashiko has reviewed this patch and found no issues. It looks great!

-- 
Sashiko AI review · https://sashiko.dev/#/patchset/20260908-b4-mmap-prepare-vma-flag-sanify-v1-0-dacf19cce22b@kernel.org?part=26


^ permalink raw reply	[flat|nested] 89+ messages in thread

* Re: [PATCH 13/39] bpf: arena: mark arena_map_mmap() mappings VM_MIXEDMAP
  2026-09-08 20:01 ` [PATCH 13/39] bpf: arena: mark arena_map_mmap() mappings VM_MIXEDMAP Lorenzo Stoakes (ARM)
@ 2026-09-08 20:34   ` sashiko-bot
  0 siblings, 0 replies; 89+ messages in thread
From: sashiko-bot @ 2026-09-08 20:34 UTC (permalink / raw)
  To: Lorenzo Stoakes (ARM)
  Cc: kvm, linux-perf-users, Marc Zyngier, Vasily Gorbik,
	linux-trace-kernel, Oliver Upton, Heiko Carstens, selinux,
	Alexander Gordeev, bpf, dri-devel, linux-s390, linux-scsi,
	Christian Borntraeger, kvmarm

> The bpf_map->ops->map_mmap callback invoked by bpf_map_mmap() can be set to
> one of ringbuf_map_mmap_kern(), ringbuf_map_mmap_user(), array_map_mmap()
> or arena_map_mmap().
> 
> It is convention in mm to mark mappings whose pages the kernel manages
> itself with VM_MIXEDMAP, so the core mm knows not to treat them as ordinary
> page cache or anonymous memory.
> 
> The map_mmap callbacks ringbuf_map_mmap_kern() and ringbuf_map_mmap_user()
> use remap_vmalloc_range(), which ultimately invokes vm_insert_page() and so
> marks the ranges VM_MIXEDMAP, and array_map_mmap() sets VM_MIXEDMAP
> explicitly.
> 
> However, the exception to this is arena_map_mmap(), which doesn't set the
> flag.
> 
> This patch corrects this and updates the comment to reflect it.
> 
> The pages are refcounted and vm_normal_page() finds them regardless of the
> flag, and VM_DONTEXPAND remains set (marking the memory as VM_SPECIAL and
> thus unmergeable). The one effect is that NUMA balancing now skips these
> VMAs, as it already does for the other bpf map mappings, which is the
> reason array_map_mmap() gives for setting the flag.
> 
> The intent of this patch is to be able to establish the invariant that only
> PFN-mapped or mixed map ranges may clear the VM_MAYWRITE flag, as is done
> in bpf_map_mmap().
> 
> Signed-off-by: Lorenzo Stoakes (ARM) <ljs@kernel.org>

Sashiko has reviewed this patch and found no issues. It looks great!

-- 
Sashiko AI review · https://sashiko.dev/#/patchset/20260908-b4-mmap-prepare-vma-flag-sanify-v1-0-dacf19cce22b@kernel.org?part=13


^ permalink raw reply	[flat|nested] 89+ messages in thread

* Re: [PATCH 09/39] drivers/usb/mon: update to use mmap_prepare + map kernel pages
  2026-09-08 20:01 ` [PATCH 09/39] drivers/usb/mon: update to use mmap_prepare + map kernel pages Lorenzo Stoakes (ARM)
@ 2026-09-08 20:35   ` sashiko-bot
  2026-09-09  7:37   ` Greg Kroah-Hartman
  1 sibling, 0 replies; 89+ messages in thread
From: sashiko-bot @ 2026-09-08 20:35 UTC (permalink / raw)
  To: Lorenzo Stoakes (ARM)
  Cc: selinux, bpf, linux-s390, linux-perf-users, Alexander Gordeev,
	kvmarm, Marc Zyngier, kvm, Heiko Carstens, Vasily Gorbik,
	linux-trace-kernel, linux-scsi, Christian Borntraeger, dri-devel,
	Oliver Upton

> Replace the deprecated .mmap hook with its replacement .mmap_prepare. As
> part of this change, additionally take the approach of mapping pages upon
> mmap rather than providing a fault handler.
> 
> The page span cannot be mutated when an mmap mapping is in place, so this
> is safe to do in advance (the MON_IOCT_RING_SIZE ioctl operation exits
> -EBUSY if it's attempted, gated by the rp->mmap_active reference count).
> 
> Utilise the newly introduced mmap_action_map_discontig_kernel_pages() to do
> this, which allows for iteration over pages in mon_bin_discontig_get().
> 
> mon_bin_discontig_init() increments the rp->mmap_active reference count to
> stabilise page spans. Should an error arise the core unmaps the VMA and
> mon_bin_vma_close() drops the reference again.
> 
> [ ... ]
> One behavioural difference: pages are no longer faulted in on demand, so a
> page discarded with MADV_DONTNEED is not repopulated and a subsequent
> access raises SIGBUS, as with other pre-populated kernel mappings.
> 
> Signed-off-by: Lorenzo Stoakes (ARM) <ljs@kernel.org>

Sashiko has reviewed this patch and found no issues. It looks great!

-- 
Sashiko AI review · https://sashiko.dev/#/patchset/20260908-b4-mmap-prepare-vma-flag-sanify-v1-0-dacf19cce22b@kernel.org?part=9


^ permalink raw reply	[flat|nested] 89+ messages in thread

* Re: [PATCH 11/39] selinux: reject writable opens of policy file, drop mmap shared/write check
  2026-09-08 20:01 ` [PATCH 11/39] selinux: reject writable opens of policy file, drop mmap shared/write check Lorenzo Stoakes (ARM)
  2026-09-08 20:22   ` Jann Horn
@ 2026-09-08 20:36   ` sashiko-bot
  2026-09-10 18:11   ` Stephen Smalley
  2 siblings, 0 replies; 89+ messages in thread
From: sashiko-bot @ 2026-09-08 20:36 UTC (permalink / raw)
  To: Lorenzo Stoakes (ARM)
  Cc: dri-devel, Alexander Gordeev, selinux, Marc Zyngier, kvm,
	linux-s390, Heiko Carstens, linux-scsi, Oliver Upton,
	linux-trace-kernel, bpf, linux-perf-users, kvmarm,
	Christian Borntraeger, Vasily Gorbik

> The policy file has no write method and is exposed read-only (S_IRUGO in
> selinux_files[]), yet sel_open_policy() performs no open mode check, so a
> CAP_DAC_OVERRIDE caller can open it O_RDWR. Reject FMODE_WRITE at open, as
> kernfs does.
> 
> The file can then never be mapped with FMODE_WRITE, so do_mmap() always
> clears VM_MAYWRITE and VM_SHARED for MAP_SHARED mappings and the VM_SHARED
> check in sel_mmap_policy() cannot be reached. Remove it.
> 
> This also stops sel_mmap_policy() clearing VM_MAYWRITE on a mapping that is
> neither a PFN map nor a mixed map, ahead of the core enforcing that only
> such mappings may do so.
> 
> Signed-off-by: Lorenzo Stoakes (ARM) <ljs@kernel.org>

Sashiko has reviewed this patch and found no issues. It looks great!

-- 
Sashiko AI review · https://sashiko.dev/#/patchset/20260908-b4-mmap-prepare-vma-flag-sanify-v1-0-dacf19cce22b@kernel.org?part=11


^ permalink raw reply	[flat|nested] 89+ messages in thread

* Re: [PATCH 19/39] HSI: cmt_speech: convert mmap hook to mmap_prepare, refactor
  2026-09-08 20:01 ` [PATCH 19/39] HSI: cmt_speech: convert mmap hook to mmap_prepare, refactor Lorenzo Stoakes (ARM)
@ 2026-09-08 20:36   ` sashiko-bot
  0 siblings, 0 replies; 89+ messages in thread
From: sashiko-bot @ 2026-09-08 20:36 UTC (permalink / raw)
  To: Lorenzo Stoakes (ARM)
  Cc: Alexander Gordeev, Christian Borntraeger, Marc Zyngier, selinux,
	linux-trace-kernel, dri-devel, linux-s390, Vasily Gorbik,
	Oliver Upton, linux-scsi, bpf, kvmarm, Heiko Carstens, kvm,
	linux-perf-users

> Use the mmap_prepare in favour of the deprecated mmap hook as part of the
> work to convert one to another.
> 
> Since this is simply a refcounted kernel page that has been allocated, it
> should not be marked VM_IO and should be inserted using the kernel page
> insertion mechanism, so convert it to do this instead.
> 
> Use the VMA descriptor's private data field as a scratch buffer to store
> the page in - this stays valid throughout the kernel page mapping
> operation.
> 
> Signed-off-by: Lorenzo Stoakes (ARM) <ljs@kernel.org>

Sashiko has reviewed this patch and found no issues. It looks great!

-- 
Sashiko AI review · https://sashiko.dev/#/patchset/20260908-b4-mmap-prepare-vma-flag-sanify-v1-0-dacf19cce22b@kernel.org?part=19


^ permalink raw reply	[flat|nested] 89+ messages in thread

* Re: [PATCH 20/39] mm/gup: error out early on !VMA_MAYREAD_BIT VMAs
  2026-09-08 20:01 ` [PATCH 20/39] mm/gup: error out early on !VMA_MAYREAD_BIT VMAs Lorenzo Stoakes (ARM)
@ 2026-09-08 20:36   ` sashiko-bot
  0 siblings, 0 replies; 89+ messages in thread
From: sashiko-bot @ 2026-09-08 20:36 UTC (permalink / raw)
  To: Lorenzo Stoakes (ARM)
  Cc: Christian Borntraeger, linux-s390, bpf, Oliver Upton, dri-devel,
	kvm, selinux, linux-perf-users, Marc Zyngier, Alexander Gordeev,
	linux-trace-kernel, Vasily Gorbik, Heiko Carstens, kvmarm,
	linux-scsi

> When populating a VMA range via the aptly named populate_vma_page_range()
> an unreadable VMA will always eventually fail with -EFAULT.
> 
> That a VMA is accessible is always checked, however VMA_MAYREAD_BIT is not.
> 
> All user mappings always have VMA_MAYREAD_BIT set, so this check only
> impacts kernel mappings.
> 
> It is implemented specifically to disallow population of uprobes XOL
> mappings which are exec-only.
> 
> A nasty interaction with these mappings may occur if they are mlocked, so
> actively disallow this early.
> 
> This allows a subsequent commit to remove the VM_IO check in
> __mm_populate() which otherwise requires non-MMIO mappings to be wrongly
> flagged simply as a workaround.
> 
> Signed-off-by: Lorenzo Stoakes (ARM) <ljs@kernel.org>

Sashiko has reviewed this patch and found no issues. It looks great!

-- 
Sashiko AI review · https://sashiko.dev/#/patchset/20260908-b4-mmap-prepare-vma-flag-sanify-v1-0-dacf19cce22b@kernel.org?part=20


^ permalink raw reply	[flat|nested] 89+ messages in thread

* Re: [PATCH 21/39] uprobes: remove VM_IO, set VM_MIXEDMAP for mapped kernel pages
  2026-09-08 20:01 ` [PATCH 21/39] uprobes: remove VM_IO, set VM_MIXEDMAP for mapped kernel pages Lorenzo Stoakes (ARM)
@ 2026-09-08 20:36   ` sashiko-bot
  0 siblings, 0 replies; 89+ messages in thread
From: sashiko-bot @ 2026-09-08 20:36 UTC (permalink / raw)
  To: Lorenzo Stoakes (ARM)
  Cc: Vasily Gorbik, Alexander Gordeev, kvm, linux-trace-kernel,
	Marc Zyngier, bpf, kvmarm, linux-perf-users, linux-s390,
	Christian Borntraeger, Heiko Carstens, selinux, dri-devel,
	linux-scsi, Oliver Upton

> These are not MMIO pages so VMA_IO_BIT is an inappropriate flag to set.
> 
> Instead, set them VMA_MIXEDMAP_BIT as they are kernel mappings and this is
> the appropriate flag to set for those.
> 
> This provides the semantics required - no VMA merging is permitted, but
> does not prevent GUP.
> 
> However this has no meaningful impact as these are refcounted and thus can
> be GUPed.
> 
> A previous commit already prevented __mm_populate() from being invoked on
> XOL areas which prevents so that is no longer required.
> 
> Both VMAs set a VMA name, so always_dump_vma() returns true before
> vma_dump_size() reaches its VMA_IO_BIT check, and thus there is no change
> in core dump behaviour.
> 
> Change this for both the core xol_add_vma() function and the x86-specific
> get_uprobe_trampoline() function.
> 
> Signed-off-by: Lorenzo Stoakes (ARM) <ljs@kernel.org>

Sashiko has reviewed this patch and found no issues. It looks great!

-- 
Sashiko AI review · https://sashiko.dev/#/patchset/20260908-b4-mmap-prepare-vma-flag-sanify-v1-0-dacf19cce22b@kernel.org?part=21


^ permalink raw reply	[flat|nested] 89+ messages in thread

* Re: [PATCH 04/39] mm/vma: ensure mmap_prepare doesn't set actions on a mergeable vma
  2026-09-08 20:01 ` [PATCH 04/39] mm/vma: ensure mmap_prepare doesn't set actions on a mergeable vma Lorenzo Stoakes (ARM)
@ 2026-09-08 20:36   ` sashiko-bot
  0 siblings, 0 replies; 89+ messages in thread
From: sashiko-bot @ 2026-09-08 20:36 UTC (permalink / raw)
  To: Lorenzo Stoakes (ARM)
  Cc: linux-s390, dri-devel, linux-scsi, Christian Borntraeger,
	Heiko Carstens, linux-trace-kernel, bpf, kvm, selinux,
	Vasily Gorbik, Marc Zyngier, kvmarm, linux-perf-users,
	Oliver Upton, Alexander Gordeev

Thank you for your contribution! Sashiko AI review found 1 potential issue(s) to consider:

Pre-existing issues:
- [High] File reference leak in error paths of `call_mmap_prepare()` and `__compat_vma_mmap()` when validation fails after file replacement.
--

commit c2c06e31f69acde90d013dcbd918472d63f3996c
Author: Lorenzo Stoakes (ARM) <ljs@kernel.org>

mm/vma: ensure mmap_prepare doesn't set actions on a mergeable vma

This commit adds validation to mmap_prepare_validate() to ensure that mmap
actions are not set on VMAs that can be merged. It returns -EINVAL if such an
action is detected.

> diff --git a/mm/vma.c b/mm/vma.c
> index a24f04428580b..9e45fc83f74c6 100644
> --- a/mm/vma.c
> +++ b/mm/vma.c
> @@ -2794,6 +2794,15 @@ static int mmap_validate(unsigned long prev_start,
>  int mmap_prepare_validate(const struct vm_area_desc *prev_desc,
>  			  const struct vm_area_desc *desc)
>  {
> +	/*
> +	 * It is not valid to execute mmap actions for VMAs which can be merged,
> +	 * as any such merge would leave portions of the mapping incorrectly
> +	 * unmapped.
> +	 */
> +	if (vma_flags_can_merge(&desc->vma_flags) &&
> +	    WARN_ON_ONCE(desc->action.type != MMAP_NOTHING))
> +		return -EINVAL;
> +

[Severity: High]
This is a pre-existing issue, but by expanding the validation checks here, does
this increase the surface area of a struct file leak in the error paths of
call_mmap_prepare() and __compat_vma_mmap()?

If a driver's mmap_prepare hook replaces the mapping's backing file, it returns
a new file in desc->vm_file with an elevated refcount.

If this newly added validation step fails, call_mmap_prepare() returns early:

mm/vma.c:call_mmap_prepare() {
	...
	err = mmap_prepare_validate(&prev_desc, desc);
	if (err)
		return err;

This skips the crucial handoff that ensures the cleanup code in abort_munmap()
will drop the reference to the new file:

	if (desc->vm_file != map->file) {
		map->file_doesnt_need_get = true;
		map->file = desc->vm_file;
	}
	...
}

Since map->file and map->file_doesnt_need_get are not updated on error, the
caller's cleanup code ignores the new file reference, leading to a permanent
leak of the struct file.

The same early return leak applies to __compat_vma_mmap() in mm/util.c, where
desc is a stack variable and desc->vm_file is lost on error.

Should these error paths handle fput() on desc->vm_file if it was replaced?

>  	return mmap_validate(prev_desc->start, desc->start,
>  			     &prev_desc->vma_flags, &desc->vma_flags);
>  }

-- 
Sashiko AI review · https://sashiko.dev/#/patchset/20260908-b4-mmap-prepare-vma-flag-sanify-v1-0-dacf19cce22b@kernel.org?part=4

^ permalink raw reply	[flat|nested] 89+ messages in thread

* Re: [PATCH 25/39] mm: remove VMA_IO_BIT check in vma[_flags]_is_kernel_owned()
  2026-09-08 20:01 ` [PATCH 25/39] mm: remove VMA_IO_BIT check in vma[_flags]_is_kernel_owned() Lorenzo Stoakes (ARM)
@ 2026-09-08 20:37   ` sashiko-bot
  0 siblings, 0 replies; 89+ messages in thread
From: sashiko-bot @ 2026-09-08 20:37 UTC (permalink / raw)
  To: Lorenzo Stoakes (ARM)
  Cc: dri-devel, linux-s390, kvm, Marc Zyngier, bpf, linux-scsi,
	selinux, Oliver Upton, Heiko Carstens, Vasily Gorbik,
	Alexander Gordeev, linux-perf-users, linux-trace-kernel,
	Christian Borntraeger, kvmarm

> We have now made it such that every driver which sets VMA_IO_BIT marks it
> as kernel-owned.
> 
> However, vma_flags_is_kernel_owned() currently checks for VMA_IO_BIT. This
> was a product of drivers previously marking a range as kernel-owned by
> setting VMA_IO_BIT alone.
> 
> Fix this by removing the VMA_IO_BIT check in vma_flags_is_kernel_owned(),
> and update mmap_validate_vma_flags() to use vma_flags_is_kernel_owned()
> rather than open-coding the VMA_PFNMAP_BIT, VMA_MIXEDMAP_BIT check.
> 
> This change means that vma[_flags]_can_merge() doesn't check VMA_IO_BIT any
> longer (which is now redundant) as it calls vma_flags_is_kernel_owned().
> 
> Now that the predicate means precisely VMA_PFNMAP_BIT or VMA_MIXEDMAP_BIT,
> [ ... ]
> Finally, update the VMA userland merge 'special' flag tests to no longer
> assert that VMA_IO_BIT prevents merge as VMA_PFNMAP_BIT, VMA_MIXEDMAP_BIT
> now suffices.
> 
> Signed-off-by: Lorenzo Stoakes (ARM) <ljs@kernel.org>

Sashiko has reviewed this patch and found no issues. It looks great!

-- 
Sashiko AI review · https://sashiko.dev/#/patchset/20260908-b4-mmap-prepare-vma-flag-sanify-v1-0-dacf19cce22b@kernel.org?part=25


^ permalink raw reply	[flat|nested] 89+ messages in thread

* Re: [PATCH 17/39] scsi: sg: convert mmap hook to mmap_prepare and rework
  2026-09-08 20:01 ` [PATCH 17/39] scsi: sg: convert mmap hook to mmap_prepare and rework Lorenzo Stoakes (ARM)
@ 2026-09-08 20:37   ` sashiko-bot
  0 siblings, 0 replies; 89+ messages in thread
From: sashiko-bot @ 2026-09-08 20:37 UTC (permalink / raw)
  To: Lorenzo Stoakes (ARM)
  Cc: dri-devel, Christian Borntraeger, Marc Zyngier, Vasily Gorbik,
	linux-scsi, Oliver Upton, kvm, selinux, Alexander Gordeev,
	Heiko Carstens, kvmarm, linux-s390, bpf, linux-trace-kernel,
	linux-perf-users

> Move from the deprecated mmap hook to the new mmap_prepare hook.
> 
> We are mapping kernel pages here, so use the discontiguous kernel mapping
> mmap action to do so.
> 
> Unwind the rather confusing loop and instead map as many pages as we can at
> one time.
> 
> Note that we do not need to pay attention to rsv_schp->k_use_sg here, as
> the pages are populated for the length of the buffer at
> rsv_schp->page_order granularity as compound pages.
> 
> The discontiguous kernel page mapping logic handles the compound pages for
> us.
> 
> sfp->mmap_called keeps the buffer stable for us. As before it is never
> cleared, so a failed mmap also leaves it set.
> 
> We also remove some useless vma, vma->vm_file NULL checks - these will
> always be non-NULL if you reached the mmap hook logic.
> 
> We retain log output for consistency, but change what's output on page
> mapping to indicate that sg_discontig_get() does the work now.
> 
> Note that we drop the VMA_IO_BIT flag for the VMA here. It was never
> necessary as we invoke alloc_pages() which gives us refcounted folios that
> are fine for GUP to access (VMA_IO_BIT would prevent that).
> 
> Signed-off-by: Lorenzo Stoakes (ARM) <ljs@kernel.org>

Sashiko has reviewed this patch and found no issues. It looks great!

-- 
Sashiko AI review · https://sashiko.dev/#/patchset/20260908-b4-mmap-prepare-vma-flag-sanify-v1-0-dacf19cce22b@kernel.org?part=17


^ permalink raw reply	[flat|nested] 89+ messages in thread

* Re: [PATCH 22/39] mm/mlock: clear VMA_LOCKED_MASK over mmap callback
  2026-09-08 20:01 ` [PATCH 22/39] mm/mlock: clear VMA_LOCKED_MASK over mmap callback Lorenzo Stoakes (ARM)
@ 2026-09-08 20:38   ` sashiko-bot
  0 siblings, 0 replies; 89+ messages in thread
From: sashiko-bot @ 2026-09-08 20:38 UTC (permalink / raw)
  To: Lorenzo Stoakes (ARM)
  Cc: linux-perf-users, Oliver Upton, kvm, Alexander Gordeev, selinux,
	kvmarm, dri-devel, Christian Borntraeger, bpf, Vasily Gorbik,
	linux-scsi, Marc Zyngier, linux-trace-kernel, Heiko Carstens,
	linux-s390

> Currently there's a confusing mess around VMA_LOCKED_BIT and
> VMA_LOCKONFAULT_BIT.
> 
> It is permitted for drivers to set any flags they like, with the VMA
> already possessing lock flags.
> 
> This results in the absurd situation of a VMA possessing both
> VMA_SPECIAL_FLAGS and VMA_LOCKED_MASK flags, which is not permitted.
> 
> This has resulted in mlock_vma_folio() having a very silly check for this
> scenario to work around it.
> 
> There is no need for this - just clear the flags before invoking the hook
> and reinstate them afterwards if they are required.
> 
> Nothing relies upon this being set during the mmap operation.
> 
> mmap_prepare is unaffected by this so requires no fix.
> 
> Signed-off-by: Lorenzo Stoakes (ARM) <ljs@kernel.org>

Sashiko has reviewed this patch and found no issues. It looks great!

-- 
Sashiko AI review · https://sashiko.dev/#/patchset/20260908-b4-mmap-prepare-vma-flag-sanify-v1-0-dacf19cce22b@kernel.org?part=22


^ permalink raw reply	[flat|nested] 89+ messages in thread

* Re: [PATCH 08/39] docs: filesystems: update mmap_prepare docs for discontig kernel pgs
  2026-09-08 20:01 ` [PATCH 08/39] docs: filesystems: update mmap_prepare docs for discontig kernel pgs Lorenzo Stoakes (ARM)
@ 2026-09-08 20:38   ` sashiko-bot
  0 siblings, 0 replies; 89+ messages in thread
From: sashiko-bot @ 2026-09-08 20:38 UTC (permalink / raw)
  To: Lorenzo Stoakes (ARM)
  Cc: linux-perf-users, bpf, linux-s390, linux-scsi, linux-trace-kernel,
	Heiko Carstens, Oliver Upton, kvm, dri-devel, kvmarm,
	Alexander Gordeev, selinux, Christian Borntraeger, Marc Zyngier,
	Vasily Gorbik

Thank you for your contribution! Sashiko AI review found 1 potential issue(s) to consider:
- [High] Insufficient Validation of nr_pages (Integer Overflow and Zero-Page Hang)
--

commit 0017a54bcba2043c3f552b308a32a39be664f463
Author: Lorenzo Stoakes (ARM) <ljs@kernel.org>

mm: add mmap action for discontiguous kernel page mapping

The existing kernel page mapping mmap actions allow for partial and full
mapping of an array of struct page pointers.

However some drivers require the mapping of discontiguous ranges. Permit
this by providing discontig_kernel_page_ops which allows a driver to
specify how the operation should begin and how batches of pages should be
retrieved.

> diff --git a/mm/memory.c b/mm/memory.c
> index dc38cad1dcb7e..8c9675451d4ba 100644
> --- a/mm/memory.c
> +++ b/mm/memory.c

[ ... ]

>  int map_kernel_pages_prepare(struct vm_area_desc *desc)
>  {
>  	const struct mmap_action *action = &desc->action;
>  	const unsigned long addr = action->map_kernel.start;
>  	unsigned long nr_pages, end;
>  
> -	if (!vma_desc_test(desc, VMA_MIXEDMAP_BIT)) {
> -		VM_WARN_ON_ONCE(mmap_read_trylock(desc->mm));
> -		VM_WARN_ON_ONCE(vma_desc_test(desc, VMA_PFNMAP_BIT));
> -		vma_desc_set_flags(desc, VMA_MIXEDMAP_BIT);
> -	}
> +	__map_kernel_pages_prepare(desc);
>  
>  	nr_pages = action->map_kernel.nr_pages;
>  	end = addr + PAGE_SIZE * nr_pages;
>  	if (!range_in_vma_desc(desc, addr, end))
>  		return -EFAULT;

[Severity: High]
Can the end calculation overflow here if nr_pages is exceptionally large?

If a driver supplies an overly large nr_pages, PAGE_SIZE * nr_pages
could wrap to a small value. Because range_is_subset() lacks an
inner_start <= inner_end validation, this wrapped end value would
incorrectly pass the range_in_vma_desc() bounds check.

This could lead to inserting PTEs far out of VMA bounds and corrupting page
tables.

[ ... ]

> +int map_discontig_kernel_pages_complete(struct vm_area_struct *vma,
> +					struct mmap_action *action)
> +{

[ ... ]

> +	do {
> +		unsigned long end, pgoff_end;
> +		unsigned long nr_pages;
> +
> +		/* Default to abort. */
> +		state.action = DISCONTIG_KERNEL_PAGE_ABORT;
> +		err = ops->get(&state);
> +		if (err || state.action == DISCONTIG_KERNEL_PAGE_ABORT)
> +			return err;
> +		nr_pages = state.__nr_pages;
> +
> +		end = state.addr + PAGE_SIZE * nr_pages;
> +		if (end > vma->vm_end)
> +			return -EINVAL;

[Severity: High]
Does this bounds check handle a huge nr_pages value correctly?

Similar to the check in map_kernel_pages_prepare(), if nr_pages is
huge, end will wrap to a small value. This bypasses the end > vma->vm_end
check, potentially allowing page table corruption.

> +		pgoff_end = state.pgoff + nr_pages;
> +
> +		err = apply_discontig_action(vma, &state);
> +		if (err)
> +			return err;
> +
> +		state.addr = end;
> +		state.pgoff = pgoff_end;
> +		state.nr_pages_mapped += nr_pages;
> +		state.nr_pages_remain -= nr_pages;
> +	} while (state.addr < vma->vm_end);

[Severity: High]
Could this result in an infinite loop if nr_pages is 0?

If a driver provides 0 pages (for instance, via
discontig_kernel_map_page_range(..., 0)), end will equal state.addr.

state.addr is then updated with a 0 increment, causing the
while (state.addr < vma->vm_end) loop to execute infinitely and hang
the kernel.

-- 
Sashiko AI review · https://sashiko.dev/#/patchset/20260908-b4-mmap-prepare-vma-flag-sanify-v1-0-dacf19cce22b@kernel.org?part=8

^ permalink raw reply	[flat|nested] 89+ messages in thread

* Re: [PATCH 18/39] fbdev: defio: assert FBINFO_VIRTFB, drop VM_IO, add VM_MIXEDMAP
  2026-09-08 20:01 ` [PATCH 18/39] fbdev: defio: assert FBINFO_VIRTFB, drop VM_IO, add VM_MIXEDMAP Lorenzo Stoakes (ARM)
@ 2026-09-08 20:39   ` sashiko-bot
  0 siblings, 0 replies; 89+ messages in thread
From: sashiko-bot @ 2026-09-08 20:39 UTC (permalink / raw)
  To: Lorenzo Stoakes (ARM)
  Cc: Alexander Gordeev, linux-s390, linux-scsi, Marc Zyngier,
	Vasily Gorbik, linux-perf-users, kvmarm, bpf,
	Christian Borntraeger, dri-devel, selinux, kvm,
	linux-trace-kernel, Oliver Upton, Heiko Carstens

Thank you for your contribution! Sashiko AI review found 1 potential issue(s) to consider:

Pre-existing issues:
- [High] Unchecked return value of fb_deferred_io_init() in ssd1307fb_probe() leads to a NULL pointer dereference in fb_deferred_io_mmap().
--

commit 20b4c9f03621ce152d836b82e0b4d3c3cda114ce
Author: Lorenzo Stoakes (ARM) <ljs@kernel.org>
fbdev: defio: assert FBINFO_VIRTFB, drop VM_IO, add VM_MIXEDMAP

This commit updates defio drivers to assert the FBINFO_VIRTFB flag, drops
the VM_IO flag, and sets VM_MIXEDMAP since kernel-allocated memory is mapped.
It also ensures the ssd1307fb driver sets FBINFO_VIRTFB during its probe.

> diff --git a/drivers/video/fbdev/core/fb_defio.c b/drivers/video/fbdev/core/fb_defio.c
> index fd00b86e1ae60..fb359ecc39661 100644
> --- a/drivers/video/fbdev/core/fb_defio.c
> +++ b/drivers/video/fbdev/core/fb_defio.c
> @@ -366,13 +366,13 @@ int fb_deferred_io_mmap(struct fb_info *info, struct vm_area_struct *vma)
>  {
>  	vma->vm_page_prot = pgprot_decrypted(vma->vm_page_prot);
>  
> +	if (WARN_ON_ONCE(!(info->flags & FBINFO_VIRTFB)))
> +		return -EINVAL;
>  	if (!try_module_get(THIS_MODULE))
>  		return -EINVAL;
>  
>  	vma->vm_ops = &fb_deferred_io_vm_ops;
> -	vm_flags_set(vma, VM_DONTEXPAND | VM_DONTDUMP);
> -	if (!(info->flags & FBINFO_VIRTFB))
> -		vm_flags_set(vma, VM_IO);
> +	vm_flags_set(vma, VM_MIXEDMAP | VM_DONTEXPAND | VM_DONTDUMP);
>  	vma->vm_private_data = info->fbdefio_state;
>  
>  	fb_deferred_io_state_get(info->fbdefio_state); /* released in vma->vm_ops->close() */

[Severity: High]
This isn't a bug introduced by this patch, but could this lead to a NULL
pointer dereference if fb_deferred_io_init() previously failed?

If memory allocation fails during fb_deferred_io_init() in the driver probe,
it returns an error code and leaves info->fbdefio_state as NULL. When a
userspace program maps the framebuffer, fb_deferred_io_mmap() unconditionally
passes the NULL info->fbdefio_state to fb_deferred_io_state_get(), which will
subsequently dereference it via kref_get().

[ ... ]

> diff --git a/drivers/video/fbdev/ssd1307fb.c b/drivers/video/fbdev/ssd1307fb.c
> index c4fdecafd8560..958514a354338 100644
> --- a/drivers/video/fbdev/ssd1307fb.c
> +++ b/drivers/video/fbdev/ssd1307fb.c
> @@ -763,6 +763,8 @@ static int ssd1307fb_probe(struct i2c_client *client)
>  	info->fix.smem_start = __pa(vmem);
>  	info->fix.smem_len = vmem_size;
>  
> +	info->flags = FBINFO_VIRTFB;
> +
>  	fb_deferred_io_init(info);

[Severity: High]
This is a pre-existing issue, but the return value of fb_deferred_io_init()
is ignored here in ssd1307fb_probe().

Should we check the return value of fb_deferred_io_init() and handle the
potential allocation failure so we don't proceed with a NULL
info->fbdefio_state?

-- 
Sashiko AI review · https://sashiko.dev/#/patchset/20260908-b4-mmap-prepare-vma-flag-sanify-v1-0-dacf19cce22b@kernel.org?part=18

^ permalink raw reply	[flat|nested] 89+ messages in thread

* Re: [PATCH 28/39] mm: drop some redundant checks around hugetlb VMAs
  2026-09-08 20:01 ` [PATCH 28/39] mm: drop some redundant checks around hugetlb VMAs Lorenzo Stoakes (ARM)
@ 2026-09-08 20:39   ` sashiko-bot
  2026-09-09 12:08   ` Marc Zyngier
  1 sibling, 0 replies; 89+ messages in thread
From: sashiko-bot @ 2026-09-08 20:39 UTC (permalink / raw)
  To: Lorenzo Stoakes (ARM)
  Cc: dri-devel, linux-trace-kernel, linux-s390, linux-perf-users,
	linux-scsi, Vasily Gorbik, bpf, Heiko Carstens, selinux,
	Christian Borntraeger, Marc Zyngier, Alexander Gordeev, kvm,
	Oliver Upton, kvmarm

> Adjust code which inadvertently perform redundant checks on hugetlb VMAs
> and clean them up:
> 
> * hugetlb VMAs have VMA_DONTEXPAND_BIT set so a VMA_SPECIAL_FLAGS check
>   suffices. (migrate_vma_setup() regains an explicit hugetlb test later in
>   the series, once VMA_SPECIAL_FLAGS is removed.)
> 
> * hugetlb VMAs unconditionally set vma->vm_ops, so they are never
>   anonymous.
> 
> * hugetlb VMAs do not set VMA_PFNMAP_BIT so checking for this is redundant.
> 
> While we're here also drop a VM_BUG_ON() which the simplified check above
> makes unreachable, and use the new VMA flag API.
> 
> No functional change intended.
> 
> Signed-off-by: Lorenzo Stoakes (ARM) <ljs@kernel.org>

Sashiko has reviewed this patch and found no issues. It looks great!

-- 
Sashiko AI review · https://sashiko.dev/#/patchset/20260908-b4-mmap-prepare-vma-flag-sanify-v1-0-dacf19cce22b@kernel.org?part=28


^ permalink raw reply	[flat|nested] 89+ messages in thread

* Re: [PATCH 27/39] mm: rename is_vm_hugetlb_page() to vma_is_hugetlb()
  2026-09-08 20:01 ` [PATCH 27/39] mm: rename is_vm_hugetlb_page() to vma_is_hugetlb() Lorenzo Stoakes (ARM)
@ 2026-09-08 20:40   ` sashiko-bot
  2026-09-09 11:09   ` Anup Patel
                     ` (2 subsequent siblings)
  3 siblings, 0 replies; 89+ messages in thread
From: sashiko-bot @ 2026-09-08 20:40 UTC (permalink / raw)
  To: Lorenzo Stoakes (ARM)
  Cc: bpf, Heiko Carstens, linux-trace-kernel, linux-perf-users, kvm,
	Marc Zyngier, linux-s390, Christian Borntraeger, Vasily Gorbik,
	dri-devel, selinux, Oliver Upton, kvmarm, Alexander Gordeev,
	linux-scsi

> The is_vm_hugetlb_page() predicate is badly named - the mapping can span
> more than a page and it is inconsistent with other VMA predicates that
> typically are prefixed by vma_.
> 
> Rename to vma_is_hugetlb() for consistency, and while we're here update
> some VM_BUG_ON_VMA() to VM_WARN_ON_ONCE_VMA() as to avoid unnecessary
> oopses.
> 
> No functional change intended.
> 
> Signed-off-by: Lorenzo Stoakes (ARM) <ljs@kernel.org>

Sashiko has reviewed this patch and found no issues. It looks great!

-- 
Sashiko AI review · https://sashiko.dev/#/patchset/20260908-b4-mmap-prepare-vma-flag-sanify-v1-0-dacf19cce22b@kernel.org?part=27


^ permalink raw reply	[flat|nested] 89+ messages in thread

* Re: [PATCH 03/39] mm: consistently validate VMA state after mmap[_prepare] hooks
  2026-09-08 20:01 ` [PATCH 03/39] mm: consistently validate VMA state after mmap[_prepare] hooks Lorenzo Stoakes (ARM)
@ 2026-09-08 20:40   ` sashiko-bot
  0 siblings, 0 replies; 89+ messages in thread
From: sashiko-bot @ 2026-09-08 20:40 UTC (permalink / raw)
  To: Lorenzo Stoakes (ARM)
  Cc: linux-scsi, selinux, Oliver Upton, Christian Borntraeger,
	Heiko Carstens, linux-s390, dri-devel, kvm, Alexander Gordeev,
	kvmarm, linux-trace-kernel, bpf, Marc Zyngier, Vasily Gorbik,
	linux-perf-users

Thank you for your contribution! Sashiko AI review found 2 potential issue(s) to consider:
- [High] Error cleanup path unmaps arbitrary memory if a driver illegally alters vma->vm_start.
- [High] Driver resources and file reference are leaked when mmap_prepare_validate() fails after a successful hook.
--

commit 7871b5bece83247c9fe3efaac4b928710f478390
Author: Lorenzo Stoakes (ARM) <ljs@kernel.org>

mm: consistently validate VMA state after mmap[_prepare] hooks

This commit introduces mmap_prepare_validate() and mmap_hook_validate() to
verify that mmap hooks do not perform unauthorized operations, such as
modifying the VMA start address. It applies these checks uniformly across
VMA creation paths.

> diff --git a/mm/internal.h b/mm/internal.h
> --- a/mm/internal.h
> +++ b/mm/internal.h
[ ... ]
> @@ -238,26 +259,14 @@ static inline int mmap_file(struct file *file, struct vm_area_struct *vma)
>  	 */
>  	if (unlikely(err || !vma->vm_ops))
>  		vma->vm_ops = &vma_dummy_vm_ops;
> +	if (unlikely(err))
> +		return err;
>  
> +	err = mmap_hook_validate(prev_start, &prev_flags, vma);
> +	if (unlikely(err))
> +		vma_close(vma);
>  
> +	return err;
>  }

[Severity: High]
If a driver illegally alters vma->vm_start, mmap_hook_validate() will
correctly catch the violation and return -EINVAL. However, does this leave
the corrupted vma->vm_start in place when returning to the caller?

Looking at __mmap_new_file_vma(), the error handling path relies on
vma->vm_start:

	error = mmap_file(vma->vm_file, vma);
	if (error) {
		UNMAP_STATE(unmap, vmi, vma, vma->vm_start, vma->vm_end,
			    map->prev, map->next);
		...
		unmap_region(&unmap);
		return error;
	}

If mmap_file() fails because the driver altered vma->vm_start, could
unmap_region() accidentally unmap arbitrary user memory using the corrupted
start address?

> diff --git a/mm/util.c b/mm/util.c
> --- a/mm/util.c
> +++ b/mm/util.c
[ ... ]
> @@ -1224,10 +1224,17 @@ EXPORT_SYMBOL(compat_set_desc_from_vma);
>  int __compat_vma_mmap(struct vm_area_desc *desc,
>  		      struct vm_area_struct *vma)
>  {
> +	struct vm_area_desc prev_desc;
>  	int err;
>  
> +	/* Derive state prior to mmap_prepare hook. */
> +	compat_set_desc_from_vma(&prev_desc, desc->file, vma);
>  	/* Perform any preparatory tasks for mmap action. */
>  	err = mmap_action_prepare(desc);
> +	if (err)
> +		return err;
> +	/* Check the caller did nothing crazy. */
> +	err = mmap_prepare_validate(&prev_desc, desc);
>  	if (err)
>  		return err;

[Severity: High]
If mmap_prepare_validate() detects an invariant violation and returns an
error here, does this early return leak driver resources and the file
reference?

If the driver's mmap_prepare() hook succeeded, it may have allocated
resources (expecting them to be freed later via vm_ops->close) or placed
a new file reference in desc->vm_file. Since vma_close() is never called
and the local desc structure is discarded, it appears these resources
might be leaked.

> diff --git a/mm/vma.c b/mm/vma.c
> --- a/mm/vma.c
> +++ b/mm/vma.c
[ ... ]
> @@ -2800,10 +2855,16 @@ static int call_mmap_prepare(struct mmap_state *map,
>  	if (!desc->vm_ops)
>  		return -EINVAL;
>  
> +	/* Perform any preparatory tasks for mmap action. */
>  	err = call_action_prepare(map, desc);
>  	if (err)
>  		return err;
>  
> +	/* Check the caller did nothing crazy. */
> +	err = mmap_prepare_validate(&prev_desc, desc);
> +	if (err)
> +		return err;
> +
>  	/* Update fields permitted to be changed. */
>  	map->pgoff = desc->pgoff;

[Severity: High]
This early return appears to have the same resource leak behavior as
__compat_vma_mmap() above. Would a validation failure here also skip
releasing driver resources or a newly assigned desc->vm_file before the VMA
is fully established?

-- 
Sashiko AI review · https://sashiko.dev/#/patchset/20260908-b4-mmap-prepare-vma-flag-sanify-v1-0-dacf19cce22b@kernel.org?part=3

^ permalink raw reply	[flat|nested] 89+ messages in thread

* Re: [PATCH 36/39] mm: eliminate VM_SPECIAL, VMA_SPECIAL_FLAGS
  2026-09-08 20:01 ` [PATCH 36/39] mm: eliminate VM_SPECIAL, VMA_SPECIAL_FLAGS Lorenzo Stoakes (ARM)
@ 2026-09-08 20:41   ` sashiko-bot
  0 siblings, 0 replies; 89+ messages in thread
From: sashiko-bot @ 2026-09-08 20:41 UTC (permalink / raw)
  To: Lorenzo Stoakes (ARM)
  Cc: Christian Borntraeger, Heiko Carstens, Oliver Upton,
	Alexander Gordeev, bpf, linux-s390, linux-perf-users,
	Vasily Gorbik, kvm, linux-scsi, linux-trace-kernel, selinux,
	Marc Zyngier, kvmarm, dri-devel

> Every user of the VM_SPECIAL or VMA_SPECIAL_FLAGS has now been converted to
> predicates which explicitly express what is actually being checked for
> rather than the nebulous concept of possessing 'special' VMA flags.
> 
> In any case 'special' is not so special a term of art in mm - it includes
> VDSO/VVAR mappings, special in the sense of vm_normal_folio() and probably
> other cases too.
> 
> Therefore make things less special by eliminating these now unused flags.
> 
> No functional change intended.
> 
> Signed-off-by: Lorenzo Stoakes (ARM) <ljs@kernel.org>

Sashiko has reviewed this patch and found no issues. It looks great!

-- 
Sashiko AI review · https://sashiko.dev/#/patchset/20260908-b4-mmap-prepare-vma-flag-sanify-v1-0-dacf19cce22b@kernel.org?part=36


^ permalink raw reply	[flat|nested] 89+ messages in thread

* Re: [PATCH 16/39] mm/vma: add and use vma_[flags]_is_fixed_mapping
  2026-09-08 20:01 ` [PATCH 16/39] mm/vma: add and use vma_[flags]_is_fixed_mapping Lorenzo Stoakes (ARM)
@ 2026-09-08 20:42   ` sashiko-bot
  0 siblings, 0 replies; 89+ messages in thread
From: sashiko-bot @ 2026-09-08 20:42 UTC (permalink / raw)
  To: Lorenzo Stoakes (ARM)
  Cc: Marc Zyngier, Christian Borntraeger, Alexander Gordeev,
	linux-s390, Heiko Carstens, kvm, linux-trace-kernel, Oliver Upton,
	kvmarm, linux-scsi, bpf, Vasily Gorbik, linux-perf-users, selinux,
	dri-devel

> This determines whether a VMA cannot be expanded or merged because what
> they mapped was determined to be a set size at mmap time.
> 
> This typically refers to kernel-owned mappings, however VMA_DONTEXPAND_BIT
> is not reliably set alongside VMA_PFNMAP_BIT or VMA_MIXEDMAP_BIT, so we
> must explicitly test for this for now.
> 
> We also explicitly test for VMA_PFNMAP_BIT as VMA_DONTEXPAND_BIT may not be
> set for VMA_PFNMAP_BIT's despite the one implying the other.
> 
> Use this predicate in vma_flags_can_merge() and in check_prep_vma() in the
> mremap logic testing to see if mremap() can expand the VMA. The criteria
> for khugepaged and MADV_COLLAPSE eligibility in
> __thp_vma_allowable_orders() are precisely those for mergeability, so use
> vma_can_merge() there (with an expanded comment).
> 
> This obviates the need for the VM_NO_KHUGEPAGED mask, so remove it.
> 
> Hugetlb VMAs remain excluded from khugepaged as hugetlbfs always sets
> VMA_DONTEXPAND_BIT.
> 
> No functional change intended.
> 
> Signed-off-by: Lorenzo Stoakes (ARM) <ljs@kernel.org>

Sashiko has reviewed this patch and found no issues. It looks great!

-- 
Sashiko AI review · https://sashiko.dev/#/patchset/20260908-b4-mmap-prepare-vma-flag-sanify-v1-0-dacf19cce22b@kernel.org?part=16


^ permalink raw reply	[flat|nested] 89+ messages in thread

* Re: [PATCH 15/39] mm/vma: only allow mmap to clear VMA_MAYWRITE_BIT if kernel-owned
  2026-09-08 20:01 ` [PATCH 15/39] mm/vma: only allow mmap to clear VMA_MAYWRITE_BIT if kernel-owned Lorenzo Stoakes (ARM)
@ 2026-09-08 20:42   ` sashiko-bot
  0 siblings, 0 replies; 89+ messages in thread
From: sashiko-bot @ 2026-09-08 20:42 UTC (permalink / raw)
  To: Lorenzo Stoakes (ARM)
  Cc: kvm, selinux, Vasily Gorbik, linux-trace-kernel, kvmarm,
	Christian Borntraeger, linux-perf-users, Alexander Gordeev,
	Oliver Upton, Marc Zyngier, bpf, linux-scsi, dri-devel,
	linux-s390, Heiko Carstens

Thank you for your contribution! Sashiko AI review found 1 potential issue(s) to consider:

Pre-existing issues:
- [High] Leaked struct file reference when a driver replaces desc->vm_file but mmap_prepare_validate() subsequently fails.
--

commit bf1e56ed42b1d9fbc6eb9edeebea26ac54edd5c4
Author: Lorenzo Stoakes (ARM) <ljs@kernel.org>

mm/vma: only allow mmap to clear VMA_MAYWRITE_BIT if kernel-owned

This commit restricts the ability to clear the VMA_MAYWRITE_BIT to
kernel-owned mappings. It ensures that drivers which do not own the
mapping's contents cannot violate file system semantics by altering file
attributes. Any mmap hook attempting to do so without establishing a
kernel-owned mapping will now fail validation.

> diff --git a/mm/vma.c b/mm/vma.c
> index 9e45fc83f74c6..5264287532182 100644
> --- a/mm/vma.c
> +++ b/mm/vma.c
> @@ -2780,6 +2780,11 @@ static int mmap_validate(unsigned long prev_start,
>  	if (WARN_ON_ONCE(!was_maywrite && is_maywrite))
>  		return -EINVAL;
>  
> +	/* Only kernel-owned mappings may clear VMA_MAYWRITE_BIT. */
> +	if (!vma_flags_is_kernel_owned(curr_flags) &&
> +	    WARN_ON_ONCE(was_maywrite && !is_maywrite))
> +		return -EINVAL;
> +

[Severity: High]
This isn't a bug introduced by this patch, but this new validation failure
exposes a pre-existing resource leak. Does this code leak the struct file
reference if the driver legitimately replaced desc->vm_file during the
mmap_prepare hook?

If a driver's f_op->mmap_prepare hook swaps desc->vm_file (acquiring a new
file reference via split ownership) and then fails this new validation
step (e.g., clearing VMA_MAYWRITE_BIT without being kernel-owned),
call_mmap_prepare() will return early:

mm/vma.c:call_mmap_prepare() {
        ...
        err = mmap_prepare_validate(&prev_desc, desc);
        if (err)
                return err;
                
        map->pgoff = desc->pgoff;
        if (desc->vm_file != map->file) {
                map->file_doesnt_need_get = true;
                map->file = desc->vm_file;
        }
        ...
}

Because the early return happens before map->file and
map->file_doesnt_need_get are updated, the core cleanup path in
__mmap_region() remains unaware of the new file and fails to fput() it,
leaking the file reference and pinning the mount.

>  	return mmap_validate_vma_flags(curr_flags);
>  }

-- 
Sashiko AI review · https://sashiko.dev/#/patchset/20260908-b4-mmap-prepare-vma-flag-sanify-v1-0-dacf19cce22b@kernel.org?part=15

^ permalink raw reply	[flat|nested] 89+ messages in thread

* Re: [PATCH 01/39] mm/vma: predicate setting mmap_prepare VMA fields on new vma alloc
  2026-09-08 20:01 ` [PATCH 01/39] mm/vma: predicate setting mmap_prepare VMA fields on new vma alloc Lorenzo Stoakes (ARM)
@ 2026-09-08 20:42   ` sashiko-bot
  0 siblings, 0 replies; 89+ messages in thread
From: sashiko-bot @ 2026-09-08 20:42 UTC (permalink / raw)
  To: Lorenzo Stoakes (ARM)
  Cc: dri-devel, linux-perf-users, Heiko Carstens, linux-scsi, kvm,
	Alexander Gordeev, selinux, bpf, Marc Zyngier, linux-trace-kernel,
	kvmarm, Oliver Upton, linux-s390, Vasily Gorbik,
	Christian Borntraeger

Thank you for your contribution! Sashiko AI review found 2 potential issue(s) to consider:

Pre-existing issues:
- [High] File reference leak when a file is swapped during mmap_prepare and the mapping is subsequently merged.
- [High] File reference leak in call_mmap_prepare() error paths when validation fails after file replacement.
--

commit 8df6960e843adc0f8e640f756781ceaed05911b5
Author: Lorenzo Stoakes (ARM) <ljs@kernel.org>

mm/vma: predicate setting mmap_prepare VMA fields on new vma alloc

This commit ensures that VMA fields are only manipulated if a new VMA is
allocated, rather than merged, as VMA merging preserves existing fields.
It also constifies have_mmap_prepare.

> diff --git a/mm/vma.c b/mm/vma.c
> index 97567fb7ef33d..2a90c509bb312 100644
> --- a/mm/vma.c
> +++ b/mm/vma.c
[ ... ]
> @@ -2909,7 +2909,7 @@ static unsigned long __mmap_region(struct file *file, unsigned long addr,
>  		allocated_new = true;
>  	}
>  
> -	if (have_mmap_prepare && !map_is_anon(&map))
> +	if (have_mmap_prepare && allocated_new && !map_is_anon(&map))

[Severity: High]
This is a pre-existing issue, but does __mmap_region() leak a file reference
if the mapping is successfully merged after the file is swapped?

If the VMA is successfully merged with an adjacent mapping:

mm/vma.c:__mmap_region() {
    ...
    if (map.prev || map.next) {
        VMG_MMAP_STATE(vmg, &map, /* vma = */ NULL);
        vma = vma_merge_new_range(&vmg);
    }
    ...
}

allocated_new remains false, bypassing __mmap_new_vma() and the normal
consumption of the swapped file reference.

The function then returns on success without executing an fput(map.file) to
clean up the unconsumed extra reference when map.file_doesnt_need_get is
true and allocated_new is false.

[Severity: High]
This is also a pre-existing issue, but does call_mmap_prepare() leak a file
reference in its error paths when validation fails after a file replacement?

If vfs_mmap_prepare() successfully replaces desc->vm_file, but a subsequent
validation check fails:

mm/vma.c:call_mmap_prepare() {
    ...
    err = vfs_mmap_prepare(map->file, desc);
    if (err)
        return err;

    if (!desc->vm_ops)
        return -EINVAL;

    err = call_action_prepare(map, desc);
    if (err)
        return err;
    ...
}

The function returns early without updating map->file_doesnt_need_get. This
leaves the newly acquired desc->vm_file unreferenced by the error teardown
logic in __mmap_region(), leading to a leak.

>  		set_vma_user_defined_fields(vma, &map);
>  
>  	__mmap_complete(&map, vma);

-- 
Sashiko AI review · https://sashiko.dev/#/patchset/20260908-b4-mmap-prepare-vma-flag-sanify-v1-0-dacf19cce22b@kernel.org?part=1

^ permalink raw reply	[flat|nested] 89+ messages in thread

* Re: [PATCH 33/39] mm: eliminate VMA_SPECIAL_FLAGS usage when hugetlb explicitly tested
  2026-09-08 20:01 ` [PATCH 33/39] mm: eliminate VMA_SPECIAL_FLAGS usage when hugetlb explicitly tested Lorenzo Stoakes (ARM)
@ 2026-09-08 20:42   ` sashiko-bot
  0 siblings, 0 replies; 89+ messages in thread
From: sashiko-bot @ 2026-09-08 20:42 UTC (permalink / raw)
  To: Lorenzo Stoakes (ARM)
  Cc: bpf, kvm, Heiko Carstens, dri-devel, linux-s390,
	Alexander Gordeev, linux-trace-kernel, linux-scsi,
	linux-perf-users, kvmarm, Oliver Upton, Vasily Gorbik, selinux,
	Marc Zyngier, Christian Borntraeger

> It is now an invariant that VMA_IO_BIT is not set except by kernel-owned
> mappings, so each existing VMA_SPECIAL_FLAGS test need only test for
> VMA_DONTEXPAND_BIT, VMA_PFNMAP_BIT and VMA_MIXEDMAP_BIT.
> 
> This is precisely a test for a kernel-owned or fixed mapping.
> 
> Update a number of callsites which already explicitly handle hugetlb
> mappings.
> 
> vma_supports_mlock() and ksm_compatible() also explicitly bail on droppable
> mappings - detecting kernel-owned, fixed or droppable mappings is handled
> by vma_is_persistent(), so in these cases use this predicate.
> 
> should_skip_vma() tests for locked, kernel-owned or fixed memory (having
> already excluded hugetlb mappings) so simply test for those there.
> 
> No functional change intended.
> 
> Signed-off-by: Lorenzo Stoakes (ARM) <ljs@kernel.org>

Sashiko has reviewed this patch and found no issues. It looks great!

-- 
Sashiko AI review · https://sashiko.dev/#/patchset/20260908-b4-mmap-prepare-vma-flag-sanify-v1-0-dacf19cce22b@kernel.org?part=33


^ permalink raw reply	[flat|nested] 89+ messages in thread

* Re: [PATCH 10/39] infiniband: update hfi1 to use remap_vmalloc_range()
  2026-09-08 20:01 ` [PATCH 10/39] infiniband: update hfi1 to use remap_vmalloc_range() Lorenzo Stoakes (ARM)
@ 2026-09-08 20:42   ` sashiko-bot
  0 siblings, 0 replies; 89+ messages in thread
From: sashiko-bot @ 2026-09-08 20:42 UTC (permalink / raw)
  To: Lorenzo Stoakes (ARM)
  Cc: Vasily Gorbik, Alexander Gordeev, selinux, Christian Borntraeger,
	bpf, kvm, kvmarm, linux-s390, Marc Zyngier, linux-perf-users,
	linux-trace-kernel, Heiko Carstens, Oliver Upton, linux-scsi,
	dri-devel

Thank you for your contribution! Sashiko AI review found 2 potential issue(s) to consider:

New issues:
- [Medium] RTAIL mmap command loses VM_DONTEXPAND when mapped via dma_mmap_coherent() on IOMMU-DMA paths.

Pre-existing issues:
- [High] Incomplete restriction of memory mapping permissions allows unintended read or write access.
--

commit 0ae54391480b6bdd96d1db0cbfbacb99d957dcc1
Author: Lorenzo Stoakes (ARM) <ljs@kernel.org>

infiniband: update hfi1 to use remap_vmalloc_range()

This patch converts the hfi1 infiniband driver to use remap_vmalloc_range()
for mapping chip memory from vmalloc'd ranges instead of using a custom fault
handler. It also updates flag handling and sets the virtual kernel address
for various mapping types.

> diff --git a/drivers/infiniband/hw/hfi1/file_ops.c b/drivers/infiniband/hw/hfi1/file_ops.c
> --- a/drivers/infiniband/hw/hfi1/file_ops.c
> +++ b/drivers/infiniband/hw/hfi1/file_ops.c
[ ... ]
> @@ -366,7 +361,7 @@ static int hfi1_file_mmap(struct file *fp, struct vm_area_struct *vma)
>  		 */
>  		memlen = PAGE_ALIGN(uctxt->sc->credits * PIO_BLOCK_SIZE);
>  		flags &= ~VM_MAYREAD;
> -		flags |= VM_DONTCOPY | VM_DONTEXPAND;
> +		flags |= VM_DONTCOPY;

[Severity: High]
This is a pre-existing issue, but does this incomplete restriction of memory
permissions in hfi1_file_mmap() allow unintended read access to PIO buffers?

When a user calls mmap() on PIO_BUFS requesting PROT_READ, the driver clears
VM_MAYREAD from the flags but fails to check and reject the call if VM_READ
is already set. Because vma->vm_page_prot is computed before this callback
based on the initial VM_READ flag, the PTEs will be populated with read
permissions. This potentially allows reading of sensitive data written by
other subcontexts.

[ ... ]
>  	case RTAIL:
[ ... ]
>  		memlen = PAGE_SIZE;
>  		memvirt = (void *)hfi1_rcvhdrtail_kvaddr(uctxt);
>  		memdma = uctxt->rcvhdrqtailaddr_dma;
>  		flags &= ~VM_MAYWRITE;
>  		break;

[Severity: Medium]
Is it intentional that the VM_DONTEXPAND flag was removed from the RTAIL
path here?

The RTAIL path was converted to rely on dma_mmap_coherent(), but the
VM_DONTEXPAND flag was dropped. When a user maps the RTAIL buffer and then
calls mremap() to expand the VMA, the expansion could succeed incorrectly
because dma_mmap_coherent() does not set VM_DONTEXPAND on IOMMU-DMA paths.
When expanded on an IOMMU-DMA path, the new PTEs will not be populated,
leading to a SIGBUS or page fault on access.

Note that the commit message explicitly documented retaining VM_DONTEXPAND
for PIO_CRED because of this exact dma_mmap_coherent() behavior, but it
appears it was not retained for RTAIL.

[ ... ]
>  	case SUBCTXT_EGRBUF:
> -		memaddr = (u64)uctxt->subctxt_rcvegrbuf;
> +		memvirt = uctxt->subctxt_rcvegrbuf;
>  		memlen = uctxt->egrbufs.size * uctxt->subctxt_cnt;
> -		flags |= VM_IO | VM_DONTEXPAND;
>  		flags &= ~VM_MAYWRITE;
> -		vmf = 1;
> +		is_vmalloc = 1;
>  		break;

[Severity: High]
This is a pre-existing issue, but does this incomplete restriction of memory
permissions in hfi1_file_mmap() allow unintended write access to the shared
subcontext eager receive buffers?

Similar to the PIO_BUFS case above, when a user calls mmap() on
SUBCTXT_EGRBUF requesting PROT_WRITE, the driver clears VM_MAYWRITE from the
flags but fails to check and reject the call if VM_WRITE is already set.

Because vma->vm_page_prot is computed before this callback based on the
initial VM_WRITE flag, the PTEs will be populated with write permissions.
Write access to read-only eager buffers allows a process to corrupt or spoof
incoming network packets for other subcontexts sharing the hardware context.

-- 
Sashiko AI review · https://sashiko.dev/#/patchset/20260908-b4-mmap-prepare-vma-flag-sanify-v1-0-dacf19cce22b@kernel.org?part=10

^ permalink raw reply	[flat|nested] 89+ messages in thread

* Re: [PATCH 39/39] mm/vma: introduce and use vma[_flags]_can_gup()
  2026-09-08 20:01 ` [PATCH 39/39] mm/vma: introduce and use vma[_flags]_can_gup() Lorenzo Stoakes (ARM)
@ 2026-09-08 20:44   ` sashiko-bot
  0 siblings, 0 replies; 89+ messages in thread
From: sashiko-bot @ 2026-09-08 20:44 UTC (permalink / raw)
  To: Lorenzo Stoakes (ARM)
  Cc: kvm, linux-s390, Vasily Gorbik, Alexander Gordeev,
	linux-trace-kernel, dri-devel, Christian Borntraeger,
	Heiko Carstens, linux-scsi, Oliver Upton, linux-perf-users,
	selinux, Marc Zyngier, bpf, kvmarm

> 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) <ljs@kernel.org>

Sashiko has reviewed this patch and found no issues. It looks great!

-- 
Sashiko AI review · https://sashiko.dev/#/patchset/20260908-b4-mmap-prepare-vma-flag-sanify-v1-0-dacf19cce22b@kernel.org?part=39


^ permalink raw reply	[flat|nested] 89+ messages in thread

* Re: [PATCH 38/39] mm/huge_memory: remove vma_is_special_huge()
  2026-09-08 20:01 ` [PATCH 38/39] mm/huge_memory: remove vma_is_special_huge() Lorenzo Stoakes (ARM)
@ 2026-09-08 20:45   ` sashiko-bot
  0 siblings, 0 replies; 89+ messages in thread
From: sashiko-bot @ 2026-09-08 20:45 UTC (permalink / raw)
  To: Lorenzo Stoakes (ARM)
  Cc: kvmarm, Alexander Gordeev, bpf, linux-perf-users, selinux,
	Christian Borntraeger, linux-scsi, Vasily Gorbik, dri-devel, kvm,
	linux-s390, linux-trace-kernel, Oliver Upton, Heiko Carstens,
	Marc Zyngier

> vma_is_special_huge() tests whether either the VMA_PFNMAP_BIT or
> VMA_MIXEDMAP_BIT is set (i.e. whether the VMA is a kernel-owned mapping),
> but with a DAX carve-out.
> 
> DAX however no longer sets VMA_MIXEDMAP_BIT, so this carve-out is no longer
> required.
> 
> Therefore test for vma_is_kernel_owned() instead and also drop the
> VMA_IO_BIT check, as it is now redundant since it is enforced that only
> kernel-owned mappings can set this flag.
> 
> This also eliminates another overloaded use of 'special' within mm.
> 
> No functional change intended.
> 
> Signed-off-by: Lorenzo Stoakes (ARM) <ljs@kernel.org>

Sashiko has reviewed this patch and found no issues. It looks great!

-- 
Sashiko AI review · https://sashiko.dev/#/patchset/20260908-b4-mmap-prepare-vma-flag-sanify-v1-0-dacf19cce22b@kernel.org?part=38


^ permalink raw reply	[flat|nested] 89+ messages in thread

* Re: [PATCH 34/39] mm: eliminate VMA_SPECIAL_FLAGS check in lru_gen_look_around()
  2026-09-08 20:01 ` [PATCH 34/39] mm: eliminate VMA_SPECIAL_FLAGS check in lru_gen_look_around() Lorenzo Stoakes (ARM)
@ 2026-09-08 20:45   ` sashiko-bot
  0 siblings, 0 replies; 89+ messages in thread
From: sashiko-bot @ 2026-09-08 20:45 UTC (permalink / raw)
  To: Lorenzo Stoakes (ARM)
  Cc: kvmarm, linux-s390, Oliver Upton, bpf, linux-scsi, Heiko Carstens,
	Christian Borntraeger, linux-perf-users, linux-trace-kernel,
	selinux, Vasily Gorbik, Marc Zyngier, Alexander Gordeev, kvm,
	dri-devel

> A kernel-owned or fixed mapping is one which sets VMA_PFNMAP_BIT,
> VMA_MIXEDMAP_BIT or VMA_DONTEXPAND_BIT, which is precisely what
> VMA_SPECIAL_FLAGS tests for other than VMA_IO_BIT, which is safe to drop as
> only kernel-owned mappings may set it.
> 
> Using these predicates rather than VMA_SPECIAL_FLAGS makes the check
> self-documenting and helps eliminate the confusion around 'special' flags.
> 
> No functional change intended.
> 
> Signed-off-by: Lorenzo Stoakes (ARM) <ljs@kernel.org>

Sashiko has reviewed this patch and found no issues. It looks great!

-- 
Sashiko AI review · https://sashiko.dev/#/patchset/20260908-b4-mmap-prepare-vma-flag-sanify-v1-0-dacf19cce22b@kernel.org?part=34


^ permalink raw reply	[flat|nested] 89+ messages in thread

* Re: [PATCH 12/39] ALSA: pcm: use vm_insert_page() to map PCM status page
  2026-09-08 20:01 ` [PATCH 12/39] ALSA: pcm: use vm_insert_page() to map PCM status page Lorenzo Stoakes (ARM)
@ 2026-09-08 20:45   ` sashiko-bot
  2026-09-10 16:15   ` Takashi Iwai
  1 sibling, 0 replies; 89+ messages in thread
From: sashiko-bot @ 2026-09-08 20:45 UTC (permalink / raw)
  To: Lorenzo Stoakes (ARM)
  Cc: kvmarm, dri-devel, linux-trace-kernel, Vasily Gorbik,
	Marc Zyngier, bpf, linux-s390, Heiko Carstens, Oliver Upton,
	selinux, linux-scsi, Christian Borntraeger, Alexander Gordeev,
	kvm, linux-perf-users

Thank you for your contribution! Sashiko AI review found 1 potential issue(s) to consider:
- [High] Eager PTE insertion via `vm_insert_page()` during the `mmap` callback uses a stale `vm_page_prot`, inadvertently granting userspace write access to the kernel-owned ALSA status page.
--

commit 31ad2114dee595c7dfa978aa004add8157e4aa43
Author: Lorenzo Stoakes (ARM) <ljs@kernel.org>

ALSA: pcm: use vm_insert_page() to map PCM status page

This commit replaces the fault handler for the PCM status page mapping
with a direct vm_insert_page() call during the mmap callback. It also
ensures the VM_MAYWRITE flag is cleared so the status page remains
kernel-owned and read-only to userspace.

> diff --git a/sound/core/pcm_native.c b/sound/core/pcm_native.c
> index 62324282fcae9..37a157d558325 100644
> --- a/sound/core/pcm_native.c
> +++ b/sound/core/pcm_native.c
[ ... ]
> @@ -3760,39 +3760,26 @@ static __poll_t snd_pcm_poll(struct file *file, poll_table *wait)
[ ... ]
> -static int snd_pcm_mmap_status(struct snd_pcm_substream *substream, struct file *file,
> -			       struct vm_area_struct *area)
> +static int snd_pcm_mmap_status(struct snd_pcm_substream *substream, struct file *file,
> +			       struct vm_area_struct *vma)
>  {
[ ... ]
> -	vm_flags_mod(area, VM_DONTEXPAND | VM_DONTDUMP,
> +
> +	vm_flags_mod(vma, VM_DONTEXPAND | VM_DONTDUMP,
>  		     VM_WRITE | VM_MAYWRITE);
>  
> -	return 0;
> +	runtime = substream->runtime;
> +	page = virt_to_page(runtime->status);
> +	return vm_insert_page(vma, vma->vm_start, page);

[Severity: High]
Does this eager PTE insertion inadvertently grant userspace write access to
the kernel-owned ALSA status page?

When a user requests mmap with PROT_WRITE, the core MM's mmap_region()
initializes vma->vm_page_prot with hardware write permissions.

This driver callback clears VM_WRITE and VM_MAYWRITE from vma->vm_flags
using vm_flags_mod(). However, vm_flags_mod() modifies only the software
VMA flags and does not update vma->vm_page_prot.

The callback then eagerly populates the page table by calling
vm_insert_page(). This function reads the unmodified, still-writable
vma->vm_page_prot and installs a writable hardware PTE.

Only after the driver callback returns does the core MM invoke
vma_set_page_prot() via __mmap_complete() to recalculate the protection
based on the new flags. But by then, the PTE is already populated with the
stale writable protection, allowing kernel state corruption.

>  }

-- 
Sashiko AI review · https://sashiko.dev/#/patchset/20260908-b4-mmap-prepare-vma-flag-sanify-v1-0-dacf19cce22b@kernel.org?part=12

^ permalink raw reply	[flat|nested] 89+ messages in thread

* Re: [PATCH 31/39] mm/uffd: use predicates for userfaultfd checks
  2026-09-08 20:01 ` [PATCH 31/39] mm/uffd: use predicates for userfaultfd checks Lorenzo Stoakes (ARM)
@ 2026-09-08 20:45   ` sashiko-bot
  0 siblings, 0 replies; 89+ messages in thread
From: sashiko-bot @ 2026-09-08 20:45 UTC (permalink / raw)
  To: Lorenzo Stoakes (ARM)
  Cc: linux-trace-kernel, Heiko Carstens, selinux, Alexander Gordeev,
	Christian Borntraeger, dri-devel, bpf, Vasily Gorbik,
	linux-perf-users, kvmarm, kvm, Oliver Upton, linux-scsi,
	Marc Zyngier, linux-s390

> Rather than directly checking VMA flags, use the newly introduced
> vma_is_kernel_owned() and vma_is_persistent() helpers in userfaultfd when
> assessing VMA suitability for userfaultfd and UFFDIO_MOVE.
> 
> Update vma_move_compatible() so it's expressed in terms of VMA
> characteristics rather than arbitrary flags.
> 
> Additionally, update the use of the deprecated VMA flag API when checking
> VMA_SHADOW_STACK_BIT.
> 
> A VMA_IO_BIT check is no longer required but that is fine as a hard
> invariant has been established that only kernel-owned mappings may set
> VMA_IO_BIT so the check is now redundant.
> 
> Signed-off-by: Lorenzo Stoakes (ARM) <ljs@kernel.org>

Sashiko has reviewed this patch and found no issues. It looks great!

-- 
Sashiko AI review · https://sashiko.dev/#/patchset/20260908-b4-mmap-prepare-vma-flag-sanify-v1-0-dacf19cce22b@kernel.org?part=31


^ permalink raw reply	[flat|nested] 89+ messages in thread

* Re: [PATCH 29/39] mm/madvise: update is_valid_guard_vma() to use vma_can_merge()
  2026-09-08 20:01 ` [PATCH 29/39] mm/madvise: update is_valid_guard_vma() to use vma_can_merge() Lorenzo Stoakes (ARM)
@ 2026-09-08 20:45   ` sashiko-bot
  0 siblings, 0 replies; 89+ messages in thread
From: sashiko-bot @ 2026-09-08 20:45 UTC (permalink / raw)
  To: Lorenzo Stoakes (ARM)
  Cc: Alexander Gordeev, linux-s390, selinux, kvmarm, Oliver Upton,
	Christian Borntraeger, bpf, linux-scsi, linux-trace-kernel,
	dri-devel, Heiko Carstens, Marc Zyngier, kvm, Vasily Gorbik,
	linux-perf-users

> We currently disallow the installation of lightweight guard regions in VMAs
> whose flags intersect VMA_SPECIAL_FLAGS or VMA_HUGETLB_BIT, or
> VMA_LOCKED_BIT unless allow_locked is set.
> 
> hugetlb VMAs set VMA_DONTEXPAND_BIT so this was already redundant,
> VMA_SPECIAL_FLAGS already sufficed.
> 
> However, now that VMA_IO_BIT is only set if VMA_PFNMAP or VMA_MIXEDMAP_BIT
> is set, this check collapses to being the equivalent of
> !vma_can_merge().
> 
> Update is_valid_guard_vma() to reflect this.
> 
> No functional change intended.
> 
> Signed-off-by: Lorenzo Stoakes (ARM) <ljs@kernel.org>

Sashiko has reviewed this patch and found no issues. It looks great!

-- 
Sashiko AI review · https://sashiko.dev/#/patchset/20260908-b4-mmap-prepare-vma-flag-sanify-v1-0-dacf19cce22b@kernel.org?part=29


^ permalink raw reply	[flat|nested] 89+ messages in thread

* Re: [PATCH 30/39] mm/vma: introduce vma[_flags]_is_persistent()
  2026-09-08 20:01 ` [PATCH 30/39] mm/vma: introduce vma[_flags]_is_persistent() Lorenzo Stoakes (ARM)
@ 2026-09-08 20:47   ` sashiko-bot
  0 siblings, 0 replies; 89+ messages in thread
From: sashiko-bot @ 2026-09-08 20:47 UTC (permalink / raw)
  To: Lorenzo Stoakes (ARM)
  Cc: kvmarm, Vasily Gorbik, dri-devel, Heiko Carstens,
	linux-trace-kernel, Alexander Gordeev, linux-scsi, kvm,
	linux-s390, Christian Borntraeger, Marc Zyngier, selinux,
	Oliver Upton, bpf, linux-perf-users

> Introduce vma[_flags]_is_persistent() for the purposes of identifying
> mappings that are persistent in the sense that bytes to the mapping stay
> there, and bytes read from the mapping are the same unless changed by
> actions taken by userland.
> 
> Kernel-owned mappings do not fall into this category, as their owner may
> change the contents without the user having initiated it, and nor of course
> does memory-mapped I/O.
> 
> We exclude fixed mappings as these are singled out as being unmergeable and
> so cannot be guaranteed to persist user data.
> 
> hugetlb mappings are fixed mappings, but their contents are entirely the
> user's, so they are explicitly carved out as persistent, as the MADV_DODUMP
> check already does.
> 
> It excludes droppable mappings, which by their nature are ephemeral.
> 
> Use this functionality to update the madvise MADV_DODUMP check to test for
> persistence rather than open-coding this.
> 
> This replaces the VM_SPECIAL check which means it no longer checks for
> VMA_IO_BIT, however this is safe as we have established the invariant that
> only kernel-owned mappings may set VMA_IO_BIT, so we implicitly include
> these.
> 
> No functional change intended.
> 
> Signed-off-by: Lorenzo Stoakes (ARM) <ljs@kernel.org>

Sashiko has reviewed this patch and found no issues. It looks great!

-- 
Sashiko AI review · https://sashiko.dev/#/patchset/20260908-b4-mmap-prepare-vma-flag-sanify-v1-0-dacf19cce22b@kernel.org?part=30


^ permalink raw reply	[flat|nested] 89+ messages in thread

* Re: [PATCH 35/39] mm: avoid use of VMA_SPECIAL_FLAGS in migrate_vma_setup()
  2026-09-08 20:01 ` [PATCH 35/39] mm: avoid use of VMA_SPECIAL_FLAGS in migrate_vma_setup() Lorenzo Stoakes (ARM)
@ 2026-09-08 20:47   ` sashiko-bot
  0 siblings, 0 replies; 89+ messages in thread
From: sashiko-bot @ 2026-09-08 20:47 UTC (permalink / raw)
  To: Lorenzo Stoakes (ARM)
  Cc: selinux, linux-scsi, linux-s390, Marc Zyngier, Alexander Gordeev,
	Heiko Carstens, Christian Borntraeger, kvmarm, Oliver Upton,
	dri-devel, Vasily Gorbik, linux-trace-kernel, kvm,
	linux-perf-users, bpf

> Now we have the expressive vma_is_kernel_owned() and vma_is_fixed_mapping()
> predicates, use them to determine whether to proceed with migration. This
> drops the VMA_IO_BIT test, which is safe as only kernel-owned mappings may
> set it.
> 
> hugetlb mappings remain excluded, as they are fixed mappings.
> 
> No functional change intended.
> 
> Signed-off-by: Lorenzo Stoakes (ARM) <ljs@kernel.org>

Sashiko has reviewed this patch and found no issues. It looks great!

-- 
Sashiko AI review · https://sashiko.dev/#/patchset/20260908-b4-mmap-prepare-vma-flag-sanify-v1-0-dacf19cce22b@kernel.org?part=35


^ permalink raw reply	[flat|nested] 89+ messages in thread

* Re: [PATCH 24/39] mm/vma: enforce that only kernel-owned mappings may set VMA_IO_BIT
  2026-09-08 20:01 ` [PATCH 24/39] mm/vma: enforce that only kernel-owned mappings may set VMA_IO_BIT Lorenzo Stoakes (ARM)
@ 2026-09-08 20:47   ` sashiko-bot
  0 siblings, 0 replies; 89+ messages in thread
From: sashiko-bot @ 2026-09-08 20:47 UTC (permalink / raw)
  To: Lorenzo Stoakes (ARM)
  Cc: Alexander Gordeev, Christian Borntraeger, Oliver Upton, selinux,
	bpf, Heiko Carstens, Vasily Gorbik, kvmarm, kvm, Marc Zyngier,
	linux-scsi, linux-s390, linux-trace-kernel, linux-perf-users,
	dri-devel

Thank you for your contribution! Sashiko AI review found 3 potential issue(s) to consider:

New issues:
- [Medium] Denial of Service

Pre-existing issues:
- [High] Memory Leak
- [High] Use-After-Free / Double Free
--

commit 12d56e2f89cf46c2631f51c17242ae01f2acd00b
Author: Lorenzo Stoakes (ARM) <ljs@kernel.org>

mm/vma: enforce that only kernel-owned mappings may set VMA_IO_BIT

This patch updates mmap_validate_vma_flags to warn and fail if a mapping sets
VMA_IO_BIT without being marked as kernel-owned.

> diff --git a/mm/vma.c b/mm/vma.c
> index cb0c4c6257567..5996757d5aaf4 100644
> --- a/mm/vma.c
> +++ b/mm/vma.c
> @@ -2772,6 +2772,12 @@ static int mmap_validate_vma_flags(const vma_flags_t *flags)
>  		return -EINVAL;
>  #endif
>  
> +	if (!vma_flags_test_any(flags, VMA_PFNMAP_BIT, VMA_MIXEDMAP_BIT)) {
> +		/* Only kernel-owned mappings may set VMA_IO_BIT. */
> +		if (WARN_ON_ONCE(vma_flags_test(flags, VMA_IO_BIT)))

[Severity: Medium]
Can this warning be triggered by an unprivileged user intentionally mapping
a device exposed by a buggy or out-of-tree driver?

If a user interacts with a buggy driver that sets VMA_IO_BIT improperly,
triggering this warning will crash the system if panic_on_warn=1 is
configured. Is there a way to validate this without the warning to
prevent a local denial of service?

> +			return -EINVAL;

[Severity: High]
This is a pre-existing issue, but does returning an error here expose a
resource leak in call_mmap_prepare()?

If __mmap_region() handles an mmap call for a driver that implements the
.mmap_prepare hook, the driver may replace the mapping file:

mm/vma.c:call_mmap_prepare() {
    ...
	err = mmap_prepare_validate(&prev_desc, desc);
	if (err)
		return err;

	/* Update fields permitted to be changed. */
	map->pgoff = desc->pgoff;
	if (desc->vm_file != map->file) {
...
		map->file = desc->vm_file;
		map->file_doesnt_need_get = true;
	}
    ...
}

If mmap_prepare_validate() fails because of this new VMA_IO_BIT check returning
an error, call_mmap_prepare() returns early. The state updates to map->file and
map->file_doesnt_need_get are bypassed.

When __mmap_region() aborts, it evaluates map.file_doesnt_need_get to decide
whether to clean up the new file:

mm/vma.c:__mmap_region() {
...
	if (map.file_doesnt_need_get)
		fput(map.file);
...
}

Since map.file_doesnt_need_get evaluates to false, is the reference to the
newly allocated file permanently lost?


[Severity: High]
This is also a pre-existing issue, but can this failure path also lead to a
double-free when mmap_file() fails?

If a driver's .mmap_prepare hook successfully replaces the mapping file,
call_mmap_prepare() sets map->file_doesnt_need_get = true. In
__mmap_new_file_vma(), the get_file() call is skipped.

If mmap_file() then fails (either because the driver's .mmap hook returns an
error, or this validation fails), the error path unconditionally drops the
reference:

mm/vma.c:__mmap_new_file_vma() {
...
	error = mmap_file(map->file, vma, vmg);
	if (error) {
...
		fput(vma->vm_file);
		vma->vm_file = NULL;
		return error;
	}
...
}

The error propagates back to __mmap_region(), which executes the abort_munmap
block:

mm/vma.c:__mmap_region() {
...
abort_munmap:
...
	if (map.file_doesnt_need_get)
		fput(map.file);
...
}

Because map.file_doesnt_need_get is still true, it calls fput() on the exact
same file pointer, leading to a double-free. Does this new validation step
make this sequence more reachable by unprivileged users interacting with
out-of-tree drivers?

> +	}
> +
>  	return 0;
>  }

-- 
Sashiko AI review · https://sashiko.dev/#/patchset/20260908-b4-mmap-prepare-vma-flag-sanify-v1-0-dacf19cce22b@kernel.org?part=24

^ permalink raw reply	[flat|nested] 89+ messages in thread

* Re: [PATCH 23/39] mm/mlock: eliminate weird VMA_IO_BIT abuse and simplify
  2026-09-08 20:01 ` [PATCH 23/39] mm/mlock: eliminate weird VMA_IO_BIT abuse and simplify Lorenzo Stoakes (ARM)
@ 2026-09-08 20:47   ` sashiko-bot
  0 siblings, 0 replies; 89+ messages in thread
From: sashiko-bot @ 2026-09-08 20:47 UTC (permalink / raw)
  To: Lorenzo Stoakes (ARM)
  Cc: linux-scsi, kvm, dri-devel, Heiko Carstens, Christian Borntraeger,
	Marc Zyngier, selinux, bpf, kvmarm, linux-s390,
	linux-trace-kernel, Vasily Gorbik, linux-perf-users,
	Alexander Gordeev, Oliver Upton

Thank you for your contribution! Sashiko AI review found 1 potential issue(s) to consider:
- [High] Missing munlock during concurrent unmap due to vma flag check regression
--

commit 2a2d17538653740326938f5e55760a431c727840
Author: Lorenzo Stoakes (ARM) <ljs@kernel.org>

mm/mlock: eliminate weird VMA_IO_BIT abuse and simplify

This patch simplifies the mlock implementation by eliminating the use of
the VMA_IO_BIT flag. Instead, it temporarily sets VMA_LOCKONFAULT_BIT and
clears VMA_LOCKED_BIT during page table walks to prevent double counting.
It also updates various mlock functions to check the new VMA lock state.

> diff --git a/mm/internal.h b/mm/internal.h
> index 6e27d3b10c015..04b1f1d3d9604 100644
> --- a/mm/internal.h
> +++ b/mm/internal.h
> @@ -993,7 +992,7 @@ static inline void munlock_vma_folio(struct folio *folio,
>  	 * always munlock the folio and page reclaim will correct it
>  	 * if it's wrong.
>  	 */
> -	if (unlikely(vma->vm_flags & VM_LOCKED))
> +	if (unlikely(vma_test(vma, VMA_LOCKED_BIT)))

[Severity: High]
Does this change leak the mlock_count if a concurrent unmap occurs?

If a process calls mlock(), mlock_vma_pages_range() now clears
VMA_LOCKED_BIT and sets VMA_LOCKONFAULT_BIT during the walk. If another
process concurrently unmaps a file-backed page in this VMA (for example,
via ftruncate() which only takes i_mmap_rwsem), the unmap path calls
folio_remove_rmap_pte() -> munlock_vma_folio().

Because VMA_LOCKED_BIT is temporarily clear during the mlock walk, this
check evaluates to false and skips calling munlock_folio(). This leaves
the folio pinned on the unevictable LRU with an elevated mlock_count.

Would it be better to check for VMA_LOCKED_MASK here, similar to how
try_to_unmap_one() was updated in this patch?

>  		munlock_folio(folio);
>  }
>  
> diff --git a/mm/mlock.c b/mm/mlock.c
> index 39215a3eab1fb..4235a1518fc9e 100644
> --- a/mm/mlock.c
> +++ b/mm/mlock.c

[ ... ]

> @@ -428,31 +417,29 @@ static void mlock_vma_pages_range(struct vm_area_struct *vma,
>  		.pmd_entry = mlock_pte_range,
>  		.walk_lock = PGWALK_WRLOCK_VERIFY,
>  	};
> +	const bool lock = vma_flags_test(new_vma_flags, VMA_LOCKED_BIT);
> +	vma_flags_t walk_flags = *new_vma_flags;
>  
>  	/*
> -	 * There is a slight chance that concurrent page migration,
> -	 * or page reclaim finding a page of this now-VMA_LOCKED_BIT vma,
> -	 * will call mlock_vma_folio() and raise page's mlock_count:
> -	 * double counting, leaving the page unevictable indefinitely.
> -	 * Communicate this danger to mlock_vma_folio() with VMA_IO_BIT,
> -	 * which is a VMA_SPECIAL_FLAGS flag not allowed on VMA_LOCKED_BIT vmas.
> -	 * mmap_lock is held in write mode here, so this weird
> -	 * combination should not be visible to other mmap_lock users;
> -	 * but WRITE_ONCE so rmap walkers must see VMA_IO_BIT if VMA_LOCKED_BIT.
> +	 * LOCKONFAULT without LOCKED never otherwise occurs: it marks a walk in
> +	 * progress so that rmap-side callers, which test VMA_LOCKED_BIT, do not
> +	 * count folios, while try_to_unmap_one(), which tests VMA_LOCKED_MASK,
> +	 * still refuses to unmap them.
>  	 */
> -	if (vma_flags_test(new_vma_flags, VMA_LOCKED_BIT))
> -		vma_flags_set(new_vma_flags, VMA_IO_BIT);
> +	if (lock) {
> +		vma_flags_clear(&walk_flags, VMA_LOCKED_BIT);
> +		vma_flags_set(&walk_flags, VMA_LOCKONFAULT_BIT);
> +	}

[Severity: High]
Because VMA_LOCKED_BIT is temporarily cleared here, any concurrent rmap
walks (like a truncation unmapping pages) that rely on munlock_vma_folio()
will see a cleared lock bit and fail to drop the mlock_count.

> +
>  	vma_start_write(vma);
> -	vma_flags_reset_once(vma, new_vma_flags);
> +	vma_flags_reset_once(vma, &walk_flags);

-- 
Sashiko AI review · https://sashiko.dev/#/patchset/20260908-b4-mmap-prepare-vma-flag-sanify-v1-0-dacf19cce22b@kernel.org?part=23

^ permalink raw reply	[flat|nested] 89+ messages in thread

* Re: [PATCH 32/39] mm/madvise: use predicates for madvise(..., MADV_DOFORK)
  2026-09-08 20:01 ` [PATCH 32/39] mm/madvise: use predicates for madvise(..., MADV_DOFORK) Lorenzo Stoakes (ARM)
@ 2026-09-08 20:48   ` sashiko-bot
  0 siblings, 0 replies; 89+ messages in thread
From: sashiko-bot @ 2026-09-08 20:48 UTC (permalink / raw)
  To: Lorenzo Stoakes (ARM)
  Cc: kvmarm, Heiko Carstens, linux-perf-users, Vasily Gorbik,
	linux-trace-kernel, linux-scsi, Marc Zyngier, linux-s390,
	Christian Borntraeger, dri-devel, kvm, bpf, Alexander Gordeev,
	Oliver Upton, selinux

Thank you for your contribution! Sashiko AI review found 1 potential issue(s) to consider:

Pre-existing issues:
- [High] MADV_WIPEONFORK and __MADV_SET_ANON_VMA_NAME incorrectly use vma->vm_file to classify anonymous VMAs, falsely rejecting private /dev/zero mappings.
--

commit eca1ad64ddd91aa6f5fb87e2a56f40c30ef8259e
Author: Lorenzo Stoakes (ARM) <ljs@kernel.org>

mm/madvise: use predicates for madvise(..., MADV_DOFORK)

This commit updates MADV_DOFORK to use vma_can_merge() instead of manually
checking for VM_SPECIAL flags. This clarifies the intent, ensuring that if a
mapping isn't allowed to be merged, its CoW behavior cannot be manipulated on
fork. No functional change is intended.

> diff --git a/mm/madvise.c b/mm/madvise.c
> index 0fc31835fee1a..f805a4876c875 100644
> --- a/mm/madvise.c
> +++ b/mm/madvise.c
> @@ -1400,7 +1400,7 @@ static int madvise_vma_behavior(struct madvise_behavior *madv_behavior)
>  		new_flags |= VM_DONTCOPY;
>  		break;
>  	case MADV_DOFORK:
> -		if (new_flags & VM_SPECIAL)
> +		if (!vma_can_merge(vma))
>  			return -EINVAL;
>  		new_flags &= ~VM_DONTCOPY;
>  		break;

[Severity: High]
This isn't a bug introduced by this patch, but just below this in
madvise_vma_behavior(), MADV_WIPEONFORK incorrectly uses vma->vm_file to
classify anonymous VMAs:

	case MADV_WIPEONFORK:
		/* MADV_WIPEONFORK is only supported on anonymous memory. */
		if (vma->vm_file || new_flags & VM_SHARED)
			return -EINVAL;

Does this condition falsely reject private /dev/zero mappings because they
retain a file reference?

If userspace ignores this failure, wouldn't memory intended to be wiped
(such as cryptographic secrets) be copied to child processes during fork,
resulting in a cross-process information leak?

Should this use vma_is_anonymous(vma) instead?

[Severity: High]
This is also a pre-existing issue, but further down in the same function,
__MADV_SET_ANON_VMA_NAME has a similar check:

	case __MADV_SET_ANON_VMA_NAME:
		/* Only anonymous mappings can be named */
		if (vma->vm_file && !vma_is_anon_shmem(vma))
			return -EBADF;
		break;

Does this also falsely reject private /dev/zero mappings by relying on
vma->vm_file to enforce the anonymous mapping restriction?

-- 
Sashiko AI review · https://sashiko.dev/#/patchset/20260908-b4-mmap-prepare-vma-flag-sanify-v1-0-dacf19cce22b@kernel.org?part=32

^ permalink raw reply	[flat|nested] 89+ messages in thread

* Re: [PATCH 37/39] fuse: dax: do not set VM_MIXEDMAP
  2026-09-08 20:01 ` [PATCH 37/39] fuse: dax: do not set VM_MIXEDMAP Lorenzo Stoakes (ARM)
@ 2026-09-08 20:50   ` sashiko-bot
  0 siblings, 0 replies; 89+ messages in thread
From: sashiko-bot @ 2026-09-08 20:50 UTC (permalink / raw)
  To: Lorenzo Stoakes (ARM)
  Cc: Vasily Gorbik, bpf, linux-scsi, kvmarm, Heiko Carstens, kvm,
	Marc Zyngier, Oliver Upton, linux-s390, Alexander Gordeev,
	Christian Borntraeger, dri-devel, selinux, linux-perf-users,
	linux-trace-kernel

> Commit e1fb4a086495 ("dax: remove VM_MIXEDMAP for fsdax and device dax")
> prevented fsdax and device-dax from setting VM_MIXEDMAP, as DAX no longer
> relies on it to direct core mm paths.
> 
> The fuse DAX implementation, added later, copied the old pattern and still
> sets it.
> 
> Fuse DAX maps pages the same way fsdax does, via dax_iomap_fault() and
> ultimately vmf_insert_page_mkwrite() and vmf_insert_folio_pmd(), which
> insert ordinary refcounted pages and so do not require VM_MIXEDMAP.
> 
> Setting it only serves to mark the mapping as kernel-owned, making fuse DAX
> the sole DAX implementation whose mappings are unmergeable, cannot be
> mlock()'d, eagerly copy page tables on fork and reject MADV_DOFORK and
> MADV_DODUMP.
> 
> It also requires vma_is_special_huge() in mm/huge_memory.c to carve DAX out
> of its kernel-owned check explicitly.
> 
> There is no reason for fuse DAX to keep on using this flag so drop it.
> 
> Signed-off-by: Lorenzo Stoakes (ARM) <ljs@kernel.org>

Sashiko has reviewed this patch and found no issues. It looks great!

-- 
Sashiko AI review · https://sashiko.dev/#/patchset/20260908-b4-mmap-prepare-vma-flag-sanify-v1-0-dacf19cce22b@kernel.org?part=37


^ permalink raw reply	[flat|nested] 89+ messages in thread

* Re: [PATCH 09/39] drivers/usb/mon: update to use mmap_prepare + map kernel pages
  2026-09-08 20:01 ` [PATCH 09/39] drivers/usb/mon: update to use mmap_prepare + map kernel pages Lorenzo Stoakes (ARM)
  2026-09-08 20:35   ` sashiko-bot
@ 2026-09-09  7:37   ` Greg Kroah-Hartman
  1 sibling, 0 replies; 89+ messages in thread
From: Greg Kroah-Hartman @ 2026-09-09  7:37 UTC (permalink / raw)
  To: Lorenzo Stoakes (ARM)
  Cc: Andrew Morton, Liam R. Howlett, Vlastimil Babka, Jann Horn,
	Pedro Falcato, David Hildenbrand, Mike Rapoport,
	Suren Baghdasaryan, Michal Hocko, Jonathan Corbet,
	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, 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, linux-mm,
	linux-kernel, linux-doc, linux-usb, linux-rdma, selinux,
	linux-sound, bpf, linux-scsi, linux-fbdev, dri-devel,
	linux-trace-kernel, linux-perf-users, linux-arch, linux-fsdevel,
	linux-arm-kernel, kvmarm, linuxppc-dev, kvm, kvm-riscv,
	linux-riscv, linux-s390, sparclinux, fuse-devel

On Tue, Sep 08, 2026 at 09:01:13PM +0100, Lorenzo Stoakes (ARM) wrote:
> Replace the deprecated .mmap hook with its replacement .mmap_prepare. As
> part of this change, additionally take the approach of mapping pages upon
> mmap rather than providing a fault handler.
> 
> The page span cannot be mutated when an mmap mapping is in place, so this
> is safe to do in advance (the MON_IOCT_RING_SIZE ioctl operation exits
> -EBUSY if it's attempted, gated by the rp->mmap_active reference count).
> 
> Utilise the newly introduced mmap_action_map_discontig_kernel_pages() to do
> this, which allows for iteration over pages in mon_bin_discontig_get().
> 
> mon_bin_discontig_init() increments the rp->mmap_active reference count to
> stabilise page spans. Should an error arise the core unmaps the VMA and
> mon_bin_vma_close() drops the reference again.
> 
> The vm_ops->close hook implemented in mon_bin_vma_close() will ensure
> correct reference count arithmetic upon unmap (with mon_bin_vma_open()
> accounting for splitting).
> 
> The existing semantics are all retained, including not mapping past the
> range of available pages, with a SIGBUS being raised in a userland process
> that attempts to access past this point.
> 
> Ultimately insert_page() is invoked to insert each page, which increments
> the reference count on each mapped page. This mimics what was being done
> previously, only we pre-map the entire range rather than doing so on
> demand.
> 
> The existing fault handler did nothing that required demand paging, and was
> presumably implemented this way due for historic reasons.
> 
> One behavioural difference: pages are no longer faulted in on demand, so a
> page discarded with MADV_DONTNEED is not repopulated and a subsequent
> access raises SIGBUS, as with other pre-populated kernel mappings.
> 
> Signed-off-by: Lorenzo Stoakes (ARM) <ljs@kernel.org>

Acked-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>

^ permalink raw reply	[flat|nested] 89+ messages in thread

* Re: [PATCH 27/39] mm: rename is_vm_hugetlb_page() to vma_is_hugetlb()
  2026-09-08 20:01 ` [PATCH 27/39] mm: rename is_vm_hugetlb_page() to vma_is_hugetlb() Lorenzo Stoakes (ARM)
  2026-09-08 20:40   ` sashiko-bot
@ 2026-09-09 11:09   ` Anup Patel
  2026-09-09 11:22   ` Claudio Imbrenda
  2026-09-09 12:07   ` Marc Zyngier
  3 siblings, 0 replies; 89+ messages in thread
From: Anup Patel @ 2026-09-09 11:09 UTC (permalink / raw)
  To: Lorenzo Stoakes (ARM)
  Cc: 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,
	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,
	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, linux-mm,
	linux-kernel, linux-doc, linux-usb, linux-rdma, selinux,
	linux-sound, bpf, linux-scsi, linux-fbdev, dri-devel,
	linux-trace-kernel, linux-perf-users, linux-arch, linux-fsdevel,
	linux-arm-kernel, kvmarm, linuxppc-dev, kvm, kvm-riscv,
	linux-riscv, linux-s390, sparclinux, fuse-devel

On Wed, Sep 9, 2026 at 1:45 AM Lorenzo Stoakes (ARM) <ljs@kernel.org> wrote:
>
> The is_vm_hugetlb_page() predicate is badly named - the mapping can span
> more than a page and it is inconsistent with other VMA predicates that
> typically are prefixed by vma_.
>
> Rename to vma_is_hugetlb() for consistency, and while we're here update
> some VM_BUG_ON_VMA() to VM_WARN_ON_ONCE_VMA() as to avoid unnecessary
> oopses.
>
> No functional change intended.
>
> Signed-off-by: Lorenzo Stoakes (ARM) <ljs@kernel.org>

For KVM RISC-V:
Acked-by: Anup Patel <anup@brainfault.org>

Regards,
Anup

> ---
>  arch/arm64/kvm/mmu.c                      |  4 ++--
>  arch/powerpc/mm/book3s64/radix_tlb.c      |  6 +++---
>  arch/powerpc/mm/nohash/e500_hugetlbpage.c |  2 +-
>  arch/powerpc/mm/nohash/tlb.c              |  2 +-
>  arch/riscv/kvm/mmu.c                      |  2 +-
>  arch/riscv/mm/tlbflush.c                  |  2 +-
>  arch/s390/mm/gmap_helpers.c               |  6 +++---
>  arch/sparc/mm/init_64.c                   |  2 +-
>  drivers/gpu/drm/drm_gpusvm.c              |  2 +-
>  fs/coredump.c                             |  2 +-
>  fs/hugetlbfs/inode.c                      |  2 +-
>  fs/proc/task_mmu.c                        |  8 ++++----
>  include/asm-generic/tlb.h                 |  2 +-
>  include/linux/hugetlb.h                   |  4 ++--
>  include/linux/mm.h                        | 19 ++++++++++++++++---
>  include/linux/rmap.h                      |  2 +-
>  kernel/events/core.c                      |  2 +-
>  kernel/sched/fair.c                       |  2 +-
>  mm/gup.c                                  |  4 ++--
>  mm/huge_memory.c                          |  2 +-
>  mm/hugetlb.c                              | 14 +++++++-------
>  mm/internal.h                             |  2 +-
>  mm/madvise.c                              |  4 ++--
>  mm/memory.c                               | 12 ++++++------
>  mm/mempolicy.c                            |  2 +-
>  mm/migrate_device.c                       |  2 +-
>  mm/mmap.c                                 |  2 +-
>  mm/mmu_gather.c                           |  2 +-
>  mm/mprotect.c                             |  2 +-
>  mm/mremap.c                               |  6 +++---
>  mm/page_vma_mapped.c                      |  4 ++--
>  mm/pagewalk.c                             |  2 +-
>  mm/swapfile.c                             |  2 +-
>  mm/userfaultfd.c                          | 26 +++++++++++++-------------
>  mm/vma.c                                  |  8 ++++----
>  mm/vmscan.c                               |  2 +-
>  tools/testing/vma/include/stubs.h         |  2 +-
>  37 files changed, 92 insertions(+), 79 deletions(-)
>
> diff --git a/arch/arm64/kvm/mmu.c b/arch/arm64/kvm/mmu.c
> index 9ba86450fe4a..a7968f8d24bf 100644
> --- a/arch/arm64/kvm/mmu.c
> +++ b/arch/arm64/kvm/mmu.c
> @@ -1463,13 +1463,13 @@ static int get_vma_page_shift(struct vm_area_struct *vma, unsigned long hva)
>  {
>         unsigned long pa;
>
> -       if (is_vm_hugetlb_page(vma) && !(vma->vm_flags & VM_PFNMAP))
> +       if (vma_is_hugetlb(vma) && !(vma->vm_flags & VM_PFNMAP))
>                 return huge_page_shift(hstate_vma(vma));
>
>         if (!(vma->vm_flags & VM_PFNMAP))
>                 return PAGE_SHIFT;
>
> -       VM_BUG_ON(is_vm_hugetlb_page(vma));
> +       VM_BUG_ON(vma_is_hugetlb(vma));
>
>         pa = (vma->vm_pgoff << PAGE_SHIFT) + (hva - vma->vm_start);
>
> diff --git a/arch/powerpc/mm/book3s64/radix_tlb.c b/arch/powerpc/mm/book3s64/radix_tlb.c
> index 7de5760164a9..b4603a98224b 100644
> --- a/arch/powerpc/mm/book3s64/radix_tlb.c
> +++ b/arch/powerpc/mm/book3s64/radix_tlb.c
> @@ -627,7 +627,7 @@ void radix__local_flush_tlb_page(struct vm_area_struct *vma, unsigned long vmadd
>  {
>  #ifdef CONFIG_HUGETLB_PAGE
>         /* need the return fix for nohash.c */
> -       if (is_vm_hugetlb_page(vma))
> +       if (vma_is_hugetlb(vma))
>                 return radix__local_flush_hugetlb_page(vma, vmaddr);
>  #endif
>         radix__local_flush_tlb_page_psize(vma->vm_mm, vmaddr, mmu_virtual_psize);
> @@ -945,7 +945,7 @@ void radix__flush_tlb_page_psize(struct mm_struct *mm, unsigned long vmaddr,
>  void radix__flush_tlb_page(struct vm_area_struct *vma, unsigned long vmaddr)
>  {
>  #ifdef CONFIG_HUGETLB_PAGE
> -       if (is_vm_hugetlb_page(vma))
> +       if (vma_is_hugetlb(vma))
>                 return radix__flush_hugetlb_page(vma, vmaddr);
>  #endif
>         radix__flush_tlb_page_psize(vma->vm_mm, vmaddr, mmu_virtual_psize);
> @@ -1113,7 +1113,7 @@ void radix__flush_tlb_range(struct vm_area_struct *vma, unsigned long start,
>
>  {
>  #ifdef CONFIG_HUGETLB_PAGE
> -       if (is_vm_hugetlb_page(vma))
> +       if (vma_is_hugetlb(vma))
>                 return radix__flush_hugetlb_tlb_range(vma, start, end);
>  #endif
>
> diff --git a/arch/powerpc/mm/nohash/e500_hugetlbpage.c b/arch/powerpc/mm/nohash/e500_hugetlbpage.c
> index a134d28a0e4d..b87623f04be5 100644
> --- a/arch/powerpc/mm/nohash/e500_hugetlbpage.c
> +++ b/arch/powerpc/mm/nohash/e500_hugetlbpage.c
> @@ -180,7 +180,7 @@ book3e_hugetlb_preload(struct vm_area_struct *vma, unsigned long ea, pte_t pte)
>   */
>  void __update_mmu_cache(struct vm_area_struct *vma, unsigned long address, pte_t *ptep)
>  {
> -       if (is_vm_hugetlb_page(vma))
> +       if (vma_is_hugetlb(vma))
>                 book3e_hugetlb_preload(vma, address, *ptep);
>  }
>
> diff --git a/arch/powerpc/mm/nohash/tlb.c b/arch/powerpc/mm/nohash/tlb.c
> index 0a650742f3a0..07a2db16c2b1 100644
> --- a/arch/powerpc/mm/nohash/tlb.c
> +++ b/arch/powerpc/mm/nohash/tlb.c
> @@ -278,7 +278,7 @@ void __flush_tlb_page(struct mm_struct *mm, unsigned long vmaddr,
>  void flush_tlb_page(struct vm_area_struct *vma, unsigned long vmaddr)
>  {
>  #ifdef CONFIG_HUGETLB_PAGE
> -       if (vma && is_vm_hugetlb_page(vma))
> +       if (vma && vma_is_hugetlb(vma))
>                 flush_hugetlb_page(vma, vmaddr);
>  #endif
>
> diff --git a/arch/riscv/kvm/mmu.c b/arch/riscv/kvm/mmu.c
> index 6035b5ec9503..5c5c77f98bf0 100644
> --- a/arch/riscv/kvm/mmu.c
> +++ b/arch/riscv/kvm/mmu.c
> @@ -664,7 +664,7 @@ int kvm_riscv_mmu_map(struct kvm_vcpu *vcpu, struct kvm_memory_slot *memslot,
>                 return -EFAULT;
>         }
>
> -       is_hugetlb = is_vm_hugetlb_page(vma);
> +       is_hugetlb = vma_is_hugetlb(vma);
>         if (is_hugetlb)
>                 vma_pageshift = huge_page_shift(hstate_vma(vma));
>         else
> diff --git a/arch/riscv/mm/tlbflush.c b/arch/riscv/mm/tlbflush.c
> index 962db300a166..a74a7d5258aa 100644
> --- a/arch/riscv/mm/tlbflush.c
> +++ b/arch/riscv/mm/tlbflush.c
> @@ -149,7 +149,7 @@ void flush_tlb_range(struct vm_area_struct *vma, unsigned long start,
>  {
>         unsigned long stride_size;
>
> -       if (!is_vm_hugetlb_page(vma)) {
> +       if (!vma_is_hugetlb(vma)) {
>                 stride_size = PAGE_SIZE;
>         } else {
>                 stride_size = huge_page_size(hstate_vma(vma));
> diff --git a/arch/s390/mm/gmap_helpers.c b/arch/s390/mm/gmap_helpers.c
> index ff63ffb1dbd2..3f6783b93e67 100644
> --- a/arch/s390/mm/gmap_helpers.c
> +++ b/arch/s390/mm/gmap_helpers.c
> @@ -102,7 +102,7 @@ __context_unsafe(/* pte_unmap_unlock() not instrumented */)
>
>         /* Find the vm address for the guest address */
>         vma = vma_lookup(mm, vmaddr);
> -       if (!vma || is_vm_hugetlb_page(vma))
> +       if (!vma || vma_is_hugetlb(vma))
>                 return;
>
>         /* Get pointer to the page table entry */
> @@ -139,7 +139,7 @@ void gmap_helper_discard(struct mm_struct *mm, unsigned long vmaddr, unsigned lo
>                 vma = find_vma_intersection(mm, vmaddr, end);
>                 if (!vma)
>                         return;
> -               if (!is_vm_hugetlb_page(vma))
> +               if (!vma_is_hugetlb(vma))
>                         zap_vma_range(vma, vmaddr, min(end, vma->vm_end) - vmaddr);
>                 vmaddr = vma->vm_end;
>         }
> @@ -247,7 +247,7 @@ static int __gmap_helper_unshare_zeropages(struct mm_struct *mm)
>                  * proof to catch unexpected zeropages in other mappings and
>                  * fail.
>                  */
> -               if ((vma->vm_flags & VM_PFNMAP) || is_vm_hugetlb_page(vma))
> +               if ((vma->vm_flags & VM_PFNMAP) || vma_is_hugetlb(vma))
>                         continue;
>                 addr = vma->vm_start;
>
> diff --git a/arch/sparc/mm/init_64.c b/arch/sparc/mm/init_64.c
> index 103db4683b16..9bbccb5d23a8 100644
> --- a/arch/sparc/mm/init_64.c
> +++ b/arch/sparc/mm/init_64.c
> @@ -413,7 +413,7 @@ void update_mmu_cache_range(struct vm_fault *vmf, struct vm_area_struct *vma,
>         if (mm->context.hugetlb_pte_count || mm->context.thp_pte_count) {
>                 unsigned long hugepage_size = PAGE_SIZE;
>
> -               if (is_vm_hugetlb_page(vma))
> +               if (vma_is_hugetlb(vma))
>                         hugepage_size = huge_page_size(hstate_vma(vma));
>
>                 if (hugepage_size >= PUD_SIZE) {
> diff --git a/drivers/gpu/drm/drm_gpusvm.c b/drivers/gpu/drm/drm_gpusvm.c
> index 793dacec2100..a1d4989b0b61 100644
> --- a/drivers/gpu/drm/drm_gpusvm.c
> +++ b/drivers/gpu/drm/drm_gpusvm.c
> @@ -1142,7 +1142,7 @@ drm_gpusvm_range_find_or_insert(struct drm_gpusvm *gpusvm,
>          * have to change.
>          */
>         migrate_devmem = ctx->devmem_possible &&
> -               vma_is_anonymous(vas) && !is_vm_hugetlb_page(vas);
> +               vma_is_anonymous(vas) && !vma_is_hugetlb(vas);
>
>         chunk_size = drm_gpusvm_range_chunk_size(gpusvm, notifier, vas,
>                                                  fault_addr, gpuva_start,
> diff --git a/fs/coredump.c b/fs/coredump.c
> index ac3cd74808c6..fb21fb6703dd 100644
> --- a/fs/coredump.c
> +++ b/fs/coredump.c
> @@ -1608,7 +1608,7 @@ static unsigned long vma_dump_size(struct vm_area_struct *vma,
>         }
>
>         /* Hugetlb memory check */
> -       if (is_vm_hugetlb_page(vma)) {
> +       if (vma_is_hugetlb(vma)) {
>                 if ((vma->vm_flags & VM_SHARED) && FILTER(HUGETLB_SHARED))
>                         goto whole;
>                 if (!(vma->vm_flags & VM_SHARED) && FILTER(HUGETLB_PRIVATE))
> diff --git a/fs/hugetlbfs/inode.c b/fs/hugetlbfs/inode.c
> index 7611a8470ea2..ba7097d5720c 100644
> --- a/fs/hugetlbfs/inode.c
> +++ b/fs/hugetlbfs/inode.c
> @@ -108,7 +108,7 @@ static int hugetlbfs_file_mmap(struct file *file, struct vm_area_struct *vma)
>          * vma address alignment (but not the pgoff alignment) has
>          * already been checked by prepare_hugepage_range.  If you add
>          * any error returns here, do so after setting VM_HUGETLB, so
> -        * is_vm_hugetlb_page tests below unmap_region go the right
> +        * vma_is_hugetlb tests below unmap_region go the right
>          * way when do_mmap unwinds (may be important on powerpc
>          * and ia64).
>          */
> diff --git a/fs/proc/task_mmu.c b/fs/proc/task_mmu.c
> index e671b4fd8ded..565e6446bd31 100644
> --- a/fs/proc/task_mmu.c
> +++ b/fs/proc/task_mmu.c
> @@ -3015,7 +3015,7 @@ static int pagemap_scan_pte_hole(unsigned long addr, unsigned long end,
>          * hugetlb differs, see pagemap_hugetlb_category().
>          */
>         categories = p->cur_vma_category;
> -       if (userfaultfd_wp(vma) && !is_vm_hugetlb_page(vma))
> +       if (userfaultfd_wp(vma) && !vma_is_hugetlb(vma))
>                 categories |= PAGE_IS_WRITTEN;
>
>         if (!pagemap_scan_is_interesting_page(categories, p))
> @@ -3028,7 +3028,7 @@ static int pagemap_scan_pte_hole(unsigned long addr, unsigned long end,
>         if (~p->arg.flags & PM_SCAN_WP_MATCHING)
>                 return ret;
>
> -       if (is_vm_hugetlb_page(vma))
> +       if (vma_is_hugetlb(vma))
>                 err = pagemap_scan_hugetlb_hole_wp(vma, addr, end);
>         else
>                 err = uffd_wp_range(vma, addr, end - addr, true);
> @@ -3470,7 +3470,7 @@ static int show_numa_map(struct seq_file *m, void *v)
>                 seq_puts(m, " stack");
>         }
>
> -       if (is_vm_hugetlb_page(vma))
> +       if (vma_is_hugetlb(vma))
>                 seq_puts(m, " huge");
>
>         /* Skip walking pages if gate VMA */
> @@ -3499,7 +3499,7 @@ static int show_numa_map(struct seq_file *m, void *v)
>         if (md->swapcache)
>                 seq_printf(m, " swapcache=%lu", md->swapcache);
>
> -       if (md->active < md->pages && !is_vm_hugetlb_page(vma))
> +       if (md->active < md->pages && !vma_is_hugetlb(vma))
>                 seq_printf(m, " active=%lu", md->active);
>
>         if (md->writeback)
> diff --git a/include/asm-generic/tlb.h b/include/asm-generic/tlb.h
> index 53ce414d9d81..dfb5dd3bec40 100644
> --- a/include/asm-generic/tlb.h
> +++ b/include/asm-generic/tlb.h
> @@ -486,7 +486,7 @@ tlb_update_vma_flags(struct mmu_gather *tlb, struct vm_area_struct *vma)
>          * We rely on tlb_end_vma() to issue a flush, such that when we reset
>          * these values the batch is empty.
>          */
> -       tlb->vma_huge = is_vm_hugetlb_page(vma);
> +       tlb->vma_huge = vma_is_hugetlb(vma);
>         tlb->vma_exec = !!(vma->vm_flags & VM_EXEC);
>
>         /*
> diff --git a/include/linux/hugetlb.h b/include/linux/hugetlb.h
> index d7e6563cef75..24727ece20fe 100644
> --- a/include/linux/hugetlb.h
> +++ b/include/linux/hugetlb.h
> @@ -251,14 +251,14 @@ extern void __hugetlb_zap_end(struct vm_area_struct *vma,
>  static inline void hugetlb_zap_begin(struct vm_area_struct *vma,
>                                      unsigned long *start, unsigned long *end)
>  {
> -       if (is_vm_hugetlb_page(vma))
> +       if (vma_is_hugetlb(vma))
>                 __hugetlb_zap_begin(vma, start, end);
>  }
>
>  static inline void hugetlb_zap_end(struct vm_area_struct *vma,
>                                    struct zap_details *details)
>  {
> -       if (is_vm_hugetlb_page(vma))
> +       if (vma_is_hugetlb(vma))
>                 __hugetlb_zap_end(vma, details);
>  }
>
> diff --git a/include/linux/mm.h b/include/linux/mm.h
> index d6b38556be36..d8ee0ca63ccf 100644
> --- a/include/linux/mm.h
> +++ b/include/linux/mm.h
> @@ -1609,15 +1609,28 @@ static inline bool vma_is_shared_maywrite(const struct vm_area_struct *vma)
>         return is_shared_maywrite(&vma->flags);
>  }
>
> -static inline bool is_vma_hugetlb_flags(const vma_flags_t *flags)
> +/**
> + * vma_flags_is_hugetlb() - Do the specified VMA flags indicate that the
> + * VMA is a hugetlb mapping?
> + * @flags: The VMA flags to test.
> + *
> + * Returns: true if the flags indicate a hugetlb mapping, false otherwise.
> + */
> +static inline bool vma_flags_is_hugetlb(const vma_flags_t *flags)
>  {
>         return IS_ENABLED(CONFIG_HUGETLB_PAGE) &&
>                vma_flags_test(flags, VMA_HUGETLB_BIT);
>  }
>
> -static inline bool is_vm_hugetlb_page(const struct vm_area_struct *vma)
> +/**
> + * vma_is_hugetlb() - Is @vma a hugetlb mapping?
> + * @vma: The VMA to test.
> + *
> + * Returns: true if @vma is a hugetlb mapping, false otherwise.
> + */
> +static inline bool vma_is_hugetlb(const struct vm_area_struct *vma)
>  {
> -       return is_vma_hugetlb_flags(&vma->flags);
> +       return vma_flags_is_hugetlb(&vma->flags);
>  }
>
>  /**
> diff --git a/include/linux/rmap.h b/include/linux/rmap.h
> index 0b332770abee..74cca0e3c726 100644
> --- a/include/linux/rmap.h
> +++ b/include/linux/rmap.h
> @@ -888,7 +888,7 @@ struct page_vma_mapped_walk {
>  static inline void page_vma_mapped_walk_done(struct page_vma_mapped_walk *pvmw)
>  {
>         /* HugeTLB pte is set to the relevant page table entry without pte_mapped. */
> -       if (pvmw->pte && !is_vm_hugetlb_page(pvmw->vma))
> +       if (pvmw->pte && !vma_is_hugetlb(pvmw->vma))
>                 pte_unmap(pvmw->pte);
>         if (pvmw->ptl)
>                 spin_unlock(pvmw->ptl);
> diff --git a/kernel/events/core.c b/kernel/events/core.c
> index a6c8e38a3110..8ca8a6842924 100644
> --- a/kernel/events/core.c
> +++ b/kernel/events/core.c
> @@ -9808,7 +9808,7 @@ static void perf_event_mmap_event(struct perf_mmap_event *mmap_event)
>
>         if (vma->vm_flags & VM_LOCKED)
>                 flags |= MAP_LOCKED;
> -       if (is_vm_hugetlb_page(vma))
> +       if (vma_is_hugetlb(vma))
>                 flags |= MAP_HUGETLB;
>
>         if (file) {
> diff --git a/kernel/sched/fair.c b/kernel/sched/fair.c
> index c75b5c50af30..ae6c1a606eb5 100644
> --- a/kernel/sched/fair.c
> +++ b/kernel/sched/fair.c
> @@ -4211,7 +4211,7 @@ static void task_numa_work(struct callback_head *work)
>
>         for (; vma; vma = vma_next(&vmi)) {
>                 if (!vma_migratable(vma) || !vma_policy_mof(vma) ||
> -                       is_vm_hugetlb_page(vma) || vma_is_kernel_owned(vma)) {
> +                       vma_is_hugetlb(vma) || vma_is_kernel_owned(vma)) {
>                         trace_sched_skip_vma_numa(mm, vma, NUMAB_SKIP_UNSUITABLE);
>                         continue;
>                 }
> diff --git a/mm/gup.c b/mm/gup.c
> index f5dc227bd6e1..66b306911703 100644
> --- a/mm/gup.c
> +++ b/mm/gup.c
> @@ -621,7 +621,7 @@ static struct page *no_page_table(struct vm_area_struct *vma,
>          * But we can only make this optimization where a hole would surely
>          * be zero-filled if handle_mm_fault() actually did handle it.
>          */
> -       if (is_vm_hugetlb_page(vma)) {
> +       if (vma_is_hugetlb(vma)) {
>                 struct hstate *h = hstate_vma(vma);
>
>                 if (!hugetlbfs_pagecache_present(h, vma, address))
> @@ -1213,7 +1213,7 @@ static int check_vma_flags(struct vm_area_struct *vma, unsigned long gup_flags)
>         if ((gup_flags & FOLL_LONGTERM) && vma_is_fsdax(vma))
>                 return -EOPNOTSUPP;
>
> -       if ((gup_flags & FOLL_SPLIT_PMD) && is_vm_hugetlb_page(vma))
> +       if ((gup_flags & FOLL_SPLIT_PMD) && vma_is_hugetlb(vma))
>                 return -EOPNOTSUPP;
>
>         if (vma_is_secretmem(vma))
> diff --git a/mm/huge_memory.c b/mm/huge_memory.c
> index befffadd978e..cf6c50e531f5 100644
> --- a/mm/huge_memory.c
> +++ b/mm/huge_memory.c
> @@ -4754,7 +4754,7 @@ static inline bool vma_not_suitable_for_thp_split(struct vm_area_struct *vma)
>                 return true;
>         if (vma_test(vma, VMA_IO_BIT))
>                 return true;
> -       if (is_vm_hugetlb_page(vma))
> +       if (vma_is_hugetlb(vma))
>                 return true;
>
>         return false;
> diff --git a/mm/hugetlb.c b/mm/hugetlb.c
> index a69bd463b1ae..d93235491cbc 100644
> --- a/mm/hugetlb.c
> +++ b/mm/hugetlb.c
> @@ -1146,7 +1146,7 @@ static inline struct resv_map *inode_resv_map(struct inode *inode)
>
>  static struct resv_map *vma_resv_map(struct vm_area_struct *vma)
>  {
> -       VM_BUG_ON_VMA(!is_vm_hugetlb_page(vma), vma);
> +       VM_WARN_ON_ONCE_VMA(!vma_is_hugetlb(vma), vma);
>         if (vma->vm_flags & VM_MAYSHARE) {
>                 struct address_space *mapping = vma->vm_file->f_mapping;
>                 struct inode *inode = mapping->host;
> @@ -1161,7 +1161,7 @@ static struct resv_map *vma_resv_map(struct vm_area_struct *vma)
>
>  static void set_vma_resv_map(struct vm_area_struct *vma, struct resv_map *map)
>  {
> -       VM_WARN_ON_ONCE_VMA(!is_vm_hugetlb_page(vma), vma);
> +       VM_WARN_ON_ONCE_VMA(!vma_is_hugetlb(vma), vma);
>         VM_WARN_ON_ONCE_VMA(vma_test(vma, VMA_MAYSHARE_BIT), vma);
>
>         set_vma_private_data(vma, (unsigned long)map);
> @@ -1169,7 +1169,7 @@ static void set_vma_resv_map(struct vm_area_struct *vma, struct resv_map *map)
>
>  static void set_vma_resv_flags(struct vm_area_struct *vma, unsigned long flags)
>  {
> -       VM_WARN_ON_ONCE_VMA(!is_vm_hugetlb_page(vma), vma);
> +       VM_WARN_ON_ONCE_VMA(!vma_is_hugetlb(vma), vma);
>         VM_WARN_ON_ONCE_VMA(vma_test(vma, VMA_MAYSHARE_BIT), vma);
>
>         set_vma_private_data(vma, get_vma_private_data(vma) | flags);
> @@ -1177,7 +1177,7 @@ static void set_vma_resv_flags(struct vm_area_struct *vma, unsigned long flags)
>
>  static int is_vma_resv_set(struct vm_area_struct *vma, unsigned long flag)
>  {
> -       VM_BUG_ON_VMA(!is_vm_hugetlb_page(vma), vma);
> +       VM_WARN_ON_ONCE_VMA(!vma_is_hugetlb(vma), vma);
>
>         return (get_vma_private_data(vma) & flag) != 0;
>  }
> @@ -1191,7 +1191,7 @@ bool __vma_private_lock(struct vm_area_struct *vma)
>
>  void hugetlb_dup_vma_private(struct vm_area_struct *vma)
>  {
> -       VM_BUG_ON_VMA(!is_vm_hugetlb_page(vma), vma);
> +       VM_WARN_ON_ONCE_VMA(!vma_is_hugetlb(vma), vma);
>         /*
>          * Clear vm_private_data
>          * - For shared mappings this is a per-vma semaphore that may be
> @@ -5269,7 +5269,7 @@ void __unmap_hugepage_range(struct mmu_gather *tlb, struct vm_area_struct *vma,
>         unsigned long last_addr_mask;
>
>         i_mmap_assert_write_locked(vma->vm_file->f_mapping);
> -       WARN_ON(!is_vm_hugetlb_page(vma));
> +       WARN_ON(!vma_is_hugetlb(vma));
>         BUG_ON(start & ~huge_page_mask(h));
>         BUG_ON(end & ~huge_page_mask(h));
>
> @@ -7495,6 +7495,6 @@ void hugetlb_unshare_all_pmds(struct vm_area_struct *vma)
>   */
>  void fixup_hugetlb_reservations(struct vm_area_struct *vma)
>  {
> -       if (is_vm_hugetlb_page(vma))
> +       if (vma_is_hugetlb(vma))
>                 clear_vma_resv_huge_pages(vma);
>  }
> diff --git a/mm/internal.h b/mm/internal.h
> index 04b1f1d3d960..104bbca1eb57 100644
> --- a/mm/internal.h
> +++ b/mm/internal.h
> @@ -1116,7 +1116,7 @@ static inline bool vma_supports_mlock(const struct vm_area_struct *vma)
>                 return false;
>         if (vma_test_single_mask(vma, VMA_DROPPABLE))
>                 return false;
> -       if (vma_is_dax(vma) || is_vm_hugetlb_page(vma))
> +       if (vma_is_dax(vma) || vma_is_hugetlb(vma))
>                 return false;
>         return vma != get_gate_vma(current->mm);
>  }
> diff --git a/mm/madvise.c b/mm/madvise.c
> index 73c2901b9adb..2db11c832d0f 100644
> --- a/mm/madvise.c
> +++ b/mm/madvise.c
> @@ -880,7 +880,7 @@ bool madvise_dontneed_free_valid_vma(struct madvise_behavior *madv_behavior)
>         int behavior = madv_behavior->behavior;
>         struct madvise_behavior_range *range = &madv_behavior->range;
>
> -       if (!is_vm_hugetlb_page(vma)) {
> +       if (!vma_is_hugetlb(vma)) {
>                 unsigned int forbidden = VM_PFNMAP;
>
>                 if (behavior != MADV_DONTNEED_LOCKED)
> @@ -1413,7 +1413,7 @@ static int madvise_vma_behavior(struct madvise_behavior *madv_behavior)
>                 new_flags |= VM_DONTDUMP;
>                 break;
>         case MADV_DODUMP:
> -               if ((!is_vm_hugetlb_page(vma) && (new_flags & VM_SPECIAL)) ||
> +               if ((!vma_is_hugetlb(vma) && (new_flags & VM_SPECIAL)) ||
>                     (new_flags & VM_DROPPABLE))
>                         return -EINVAL;
>                 new_flags &= ~VM_DONTDUMP;
> diff --git a/mm/memory.c b/mm/memory.c
> index 28c1bb7b93af..9a38c7d4cc40 100644
> --- a/mm/memory.c
> +++ b/mm/memory.c
> @@ -1564,7 +1564,7 @@ copy_page_range(struct vm_area_struct *dst_vma, struct vm_area_struct *src_vma)
>         if (!vma_needs_copy(dst_vma, src_vma))
>                 return 0;
>
> -       if (is_vm_hugetlb_page(src_vma))
> +       if (vma_is_hugetlb(src_vma))
>                 return copy_hugetlb_page_range(dst_mm, src_mm, dst_vma, src_vma);
>
>         /*
> @@ -2178,7 +2178,7 @@ static void __zap_vma_range(struct mmu_gather *tlb, struct vm_area_struct *vma,
>         if (vma->vm_file && !reaping)
>                 uprobe_munmap(vma, start, end);
>
> -       if (unlikely(is_vm_hugetlb_page(vma))) {
> +       if (unlikely(vma_is_hugetlb(vma))) {
>                 zap_flags_t zap_flags = details ? details->zap_flags : 0;
>
>                 VM_WARN_ON_ONCE(reaping);
> @@ -2313,7 +2313,7 @@ void zap_vma_range_batched(struct mmu_gather *tlb,
>          */
>         __zap_vma_range(tlb, vma, address, end, details);
>         mmu_notifier_invalidate_range_end(&range);
> -       if (is_vm_hugetlb_page(vma)) {
> +       if (vma_is_hugetlb(vma)) {
>                 /*
>                  * flush tlb and free resources before hugetlb_zap_end(), to
>                  * avoid concurrent page faults' allocation failure.
> @@ -6933,7 +6933,7 @@ vm_fault_t handle_mm_fault(struct vm_area_struct *vma, unsigned long address,
>
>         lru_gen_enter_fault(vma);
>
> -       if (unlikely(is_vm_hugetlb_page(vma)))
> +       if (unlikely(vma_is_hugetlb(vma)))
>                 ret = hugetlb_fault(vma->vm_mm, vma, address, flags);
>         else
>                 ret = __handle_mm_fault(vma, address, flags);
> @@ -7797,12 +7797,12 @@ void ptlock_free(struct ptdesc *ptdesc)
>
>  void vma_pgtable_walk_begin(struct vm_area_struct *vma)
>  {
> -       if (is_vm_hugetlb_page(vma))
> +       if (vma_is_hugetlb(vma))
>                 hugetlb_vma_lock_read(vma);
>  }
>
>  void vma_pgtable_walk_end(struct vm_area_struct *vma)
>  {
> -       if (is_vm_hugetlb_page(vma))
> +       if (vma_is_hugetlb(vma))
>                 hugetlb_vma_unlock_read(vma);
>  }
> diff --git a/mm/mempolicy.c b/mm/mempolicy.c
> index 2ad0a5f18280..aeb99c5933cb 100644
> --- a/mm/mempolicy.c
> +++ b/mm/mempolicy.c
> @@ -2021,7 +2021,7 @@ bool vma_migratable(struct vm_area_struct *vma)
>         if (vma_is_dax(vma))
>                 return false;
>
> -       if (is_vm_hugetlb_page(vma) &&
> +       if (vma_is_hugetlb(vma) &&
>                 !hugepage_migration_supported(hstate_vma(vma)))
>                 return false;
>
> diff --git a/mm/migrate_device.c b/mm/migrate_device.c
> index 0c437004329d..c38cbaaef5a4 100644
> --- a/mm/migrate_device.c
> +++ b/mm/migrate_device.c
> @@ -743,7 +743,7 @@ int migrate_vma_setup(struct migrate_vma *args)
>
>         args->start &= PAGE_MASK;
>         args->end &= PAGE_MASK;
> -       if (!args->vma || is_vm_hugetlb_page(args->vma) ||
> +       if (!args->vma || vma_is_hugetlb(args->vma) ||
>             (args->vma->vm_flags & VM_SPECIAL) || vma_is_dax(args->vma))
>                 return -EINVAL;
>         if (nr_pages <= 0)
> diff --git a/mm/mmap.c b/mm/mmap.c
> index 4bf26b0f1e6e..98449f364af1 100644
> --- a/mm/mmap.c
> +++ b/mm/mmap.c
> @@ -1786,7 +1786,7 @@ __latent_entropy int dup_mmap(struct mm_struct *mm, struct mm_struct *oldmm)
>                 /*
>                  * Copy/update hugetlb private vma information.
>                  */
> -               if (is_vm_hugetlb_page(tmp))
> +               if (vma_is_hugetlb(tmp))
>                         hugetlb_dup_vma_private(tmp);
>
>                 /*
> diff --git a/mm/mmu_gather.c b/mm/mmu_gather.c
> index 3985d856de7f..506f005adbdc 100644
> --- a/mm/mmu_gather.c
> +++ b/mm/mmu_gather.c
> @@ -500,7 +500,7 @@ void tlb_gather_mmu_vma(struct mmu_gather *tlb, struct vm_area_struct *vma)
>  {
>         tlb_gather_mmu(tlb, vma->vm_mm);
>         tlb_update_vma_flags(tlb, vma);
> -       if (is_vm_hugetlb_page(vma))
> +       if (vma_is_hugetlb(vma))
>                 /* All entries have the same size. */
>                 tlb_change_page_size(tlb, huge_page_size(hstate_vma(vma)));
>  }
> diff --git a/mm/mprotect.c b/mm/mprotect.c
> index fe32fd87cf5c..a1b6d29bf039 100644
> --- a/mm/mprotect.c
> +++ b/mm/mprotect.c
> @@ -717,7 +717,7 @@ long change_protection(struct mmu_gather *tlb,
>             (cp_flags & MM_CP_UFFD_RWP))
>                 newprot = PAGE_NONE;
>
> -       if (is_vm_hugetlb_page(vma))
> +       if (vma_is_hugetlb(vma))
>                 pages = hugetlb_change_protection(vma, start, end, newprot,
>                                                   cp_flags);
>         else
> diff --git a/mm/mremap.c b/mm/mremap.c
> index ed19b47c2caf..1122282a1d6a 100644
> --- a/mm/mremap.c
> +++ b/mm/mremap.c
> @@ -812,7 +812,7 @@ unsigned long move_page_tables(struct pagetable_move_control *pmc)
>         if (!pmc->len_in)
>                 return 0;
>
> -       if (is_vm_hugetlb_page(pmc->old))
> +       if (vma_is_hugetlb(pmc->old))
>                 return move_hugetlb_page_tables(pmc->old, pmc->new, pmc->old_addr,
>                                                 pmc->new_addr, pmc->len_in);
>
> @@ -1735,7 +1735,7 @@ static bool vma_multi_allowed(struct vm_area_struct *vma)
>         /* Known good. */
>         if (vma_is_shmem(vma))
>                 return true;
> -       if (is_vm_hugetlb_page(vma))
> +       if (vma_is_hugetlb(vma))
>                 return true;
>         if (file->f_op->get_unmapped_area == thp_get_unmapped_area)
>                 return true;
> @@ -1758,7 +1758,7 @@ static int check_prep_vma(struct vma_remap_struct *vrm)
>                 return -EPERM;
>
>         /* Align to hugetlb page size, if required. */
> -       if (is_vm_hugetlb_page(vma) && !align_hugetlb(vrm))
> +       if (vma_is_hugetlb(vma) && !align_hugetlb(vrm))
>                 return -EINVAL;
>
>         vrm_set_delta(vrm);
> diff --git a/mm/page_vma_mapped.c b/mm/page_vma_mapped.c
> index 28e306fdb3a5..8408aee7571b 100644
> --- a/mm/page_vma_mapped.c
> +++ b/mm/page_vma_mapped.c
> @@ -109,7 +109,7 @@ static bool check_pte(struct page_vma_mapped_walk *pvmw, unsigned long pte_nr)
>         unsigned long pfn;
>         pte_t ptent;
>
> -       if (is_vm_hugetlb_page(pvmw->vma))
> +       if (vma_is_hugetlb(pvmw->vma))
>                 ptent = huge_ptep_get(pvmw->vma->vm_mm, pvmw->address,
>                                       pvmw->pte);
>         else
> @@ -206,7 +206,7 @@ bool page_vma_mapped_walk(struct page_vma_mapped_walk *pvmw)
>         if (pvmw->pmd && !pvmw->pte)
>                 return not_found(pvmw);
>
> -       if (unlikely(is_vm_hugetlb_page(vma))) {
> +       if (unlikely(vma_is_hugetlb(vma))) {
>                 struct hstate *hstate = hstate_vma(vma);
>                 unsigned long size = huge_page_size(hstate);
>                 /* The only possible mapping was handled on last iteration */
> diff --git a/mm/pagewalk.c b/mm/pagewalk.c
> index 7411702a37f5..e6493bbe6919 100644
> --- a/mm/pagewalk.c
> +++ b/mm/pagewalk.c
> @@ -408,7 +408,7 @@ static int __walk_page_range(unsigned long start, unsigned long end,
>         int err = 0;
>         struct vm_area_struct *vma = walk->vma;
>         const struct mm_walk_ops *ops = walk->ops;
> -       bool is_hugetlb = is_vm_hugetlb_page(vma);
> +       bool is_hugetlb = vma_is_hugetlb(vma);
>
>         /* We do not support hugetlb PTE installation. */
>         if (ops->install_pte && is_hugetlb)
> diff --git a/mm/swapfile.c b/mm/swapfile.c
> index 01e7b6b046b6..f90f029bfd5c 100644
> --- a/mm/swapfile.c
> +++ b/mm/swapfile.c
> @@ -2705,7 +2705,7 @@ static int unuse_mm(struct mm_struct *mm, unsigned int type)
>         if (check_stable_address_space(mm))
>                 goto unlock;
>         for_each_vma(vmi, vma) {
> -               if (vma->anon_vma && !is_vm_hugetlb_page(vma)) {
> +               if (vma->anon_vma && !vma_is_hugetlb(vma)) {
>                         ret = unuse_vma(vma, type);
>                         if (ret)
>                                 break;
> diff --git a/mm/userfaultfd.c b/mm/userfaultfd.c
> index 79cc7b546f13..949017e60608 100644
> --- a/mm/userfaultfd.c
> +++ b/mm/userfaultfd.c
> @@ -237,7 +237,7 @@ static int mfill_get_vma(struct mfill_state *state)
>         if ((flags & MFILL_ATOMIC_WP) && !(dst_vma->vm_flags & VM_UFFD_WP))
>                 goto out_unlock;
>
> -       if (is_vm_hugetlb_page(dst_vma))
> +       if (vma_is_hugetlb(dst_vma))
>                 return 0;
>
>         ops = vma_uffd_ops(dst_vma);
> @@ -804,7 +804,7 @@ static __always_inline ssize_t mfill_atomic_hugetlb(
>                 }
>
>                 err = -ENOENT;
> -               if (!is_vm_hugetlb_page(dst_vma))
> +               if (!vma_is_hugetlb(dst_vma))
>                         goto out_unlock_vma;
>
>                 err = -EINVAL;
> @@ -967,7 +967,7 @@ static __always_inline ssize_t mfill_atomic(struct userfaultfd_ctx *ctx,
>         /*
>          * If this is a HUGETLB vma, pass off to appropriate routine
>          */
> -       if (is_vm_hugetlb_page(state.vma))
> +       if (vma_is_hugetlb(state.vma))
>                 return  mfill_atomic_hugetlb(ctx, state.vma, dst_start,
>                                              src_start, len, flags);
>
> @@ -1114,7 +1114,7 @@ static int mwriteprotect_range(struct userfaultfd_ctx *ctx, unsigned long start,
>                         break;
>                 }
>
> -               if (is_vm_hugetlb_page(dst_vma)) {
> +               if (vma_is_hugetlb(dst_vma)) {
>                         err = -EINVAL;
>                         page_mask = vma_kernel_pagesize(dst_vma) - 1;
>                         if ((start & page_mask) || (len & page_mask))
> @@ -1172,7 +1172,7 @@ int mrwprotect_range(struct userfaultfd_ctx *ctx, unsigned long start,
>                 if (!userfaultfd_rwp(dst_vma))
>                         return -ENOENT;
>
> -               if (is_vm_hugetlb_page(dst_vma)) {
> +               if (vma_is_hugetlb(dst_vma)) {
>                         unsigned long page_mask;
>
>                         page_mask = vma_kernel_pagesize(dst_vma) - 1;
> @@ -2149,7 +2149,7 @@ static bool vma_can_userfault(struct vm_area_struct *vma, vm_flags_t vm_flags,
>         if (vma->vm_flags & (VM_DROPPABLE | VM_SHADOW_STACK))
>                 return false;
>
> -       if (!is_vm_hugetlb_page(vma) && (vma->vm_flags & VM_SPECIAL))
> +       if (!vma_is_hugetlb(vma) && (vma->vm_flags & VM_SPECIAL))
>                 return false;
>
>         vm_flags &= __VM_UFFD_FLAGS;
> @@ -2319,7 +2319,7 @@ static int userfaultfd_register_range(struct userfaultfd_ctx *ctx,
>                  */
>                 userfaultfd_set_ctx(vma, ctx, vm_flags);
>
> -               if (is_vm_hugetlb_page(vma) && uffd_disable_huge_pmd_share(vma))
> +               if (vma_is_hugetlb(vma) && uffd_disable_huge_pmd_share(vma))
>                         hugetlb_unshare_all_pmds(vma);
>
>  skip:
> @@ -2895,7 +2895,7 @@ vm_fault_t handle_userfault(struct vm_fault *vmf, unsigned long reason)
>          * (sleepable) vma lock can modify the current task state, that
>          * must be before explicitly calling set_current_state().
>          */
> -       if (is_vm_hugetlb_page(vma))
> +       if (vma_is_hugetlb(vma))
>                 hugetlb_vma_lock_read(vma);
>
>         spin_lock_irq(&ctx->fault_pending_wqh.lock);
> @@ -2912,7 +2912,7 @@ vm_fault_t handle_userfault(struct vm_fault *vmf, unsigned long reason)
>         set_current_state(blocking_state);
>         spin_unlock_irq(&ctx->fault_pending_wqh.lock);
>
> -       if (is_vm_hugetlb_page(vma)) {
> +       if (vma_is_hugetlb(vma)) {
>                 must_wait = userfaultfd_huge_must_wait(ctx, vmf, reason);
>                 hugetlb_vma_unlock_read(vma);
>         } else {
> @@ -3744,7 +3744,7 @@ static int userfaultfd_register(struct userfaultfd_ctx *ctx,
>          * If the first vma contains huge pages, make sure start address
>          * is aligned to huge page size.
>          */
> -       if (is_vm_hugetlb_page(vma)) {
> +       if (vma_is_hugetlb(vma)) {
>                 unsigned long vma_hpagesize = vma_kernel_pagesize(vma);
>
>                 if (start & (vma_hpagesize - 1))
> @@ -3795,7 +3795,7 @@ static int userfaultfd_register(struct userfaultfd_ctx *ctx,
>                  * If this vma contains ending address, and huge pages
>                  * check alignment.
>                  */
> -               if (is_vm_hugetlb_page(cur) && end <= cur->vm_end &&
> +               if (vma_is_hugetlb(cur) && end <= cur->vm_end &&
>                     end > cur->vm_start) {
>                         unsigned long vma_hpagesize = vma_kernel_pagesize(cur);
>
> @@ -3831,7 +3831,7 @@ static int userfaultfd_register(struct userfaultfd_ctx *ctx,
>                 /*
>                  * Note vmas containing huge pages
>                  */
> -               if (is_vm_hugetlb_page(cur))
> +               if (vma_is_hugetlb(cur))
>                         basic_ioctls = true;
>
>                 found = true;
> @@ -3917,7 +3917,7 @@ static int userfaultfd_unregister(struct userfaultfd_ctx *ctx,
>          * If the first vma contains huge pages, make sure start address
>          * is aligned to huge page size.
>          */
> -       if (is_vm_hugetlb_page(vma)) {
> +       if (vma_is_hugetlb(vma)) {
>                 unsigned long vma_hpagesize = vma_kernel_pagesize(vma);
>
>                 if (start & (vma_hpagesize - 1))
> diff --git a/mm/vma.c b/mm/vma.c
> index eb2b4501a677..ab570e0a7f16 100644
> --- a/mm/vma.c
> +++ b/mm/vma.c
> @@ -599,7 +599,7 @@ __split_vma(struct vma_iterator *vmi, struct vm_area_struct *vma,
>          * boundary.
>          */
>         vma_adjust_trans_huge(vma, vma->vm_start, addr, NULL);
> -       if (is_vm_hugetlb_page(vma))
> +       if (vma_is_hugetlb(vma))
>                 hugetlb_split(vma, addr);
>
>         if (new_below) {
> @@ -2228,7 +2228,7 @@ bool vma_wants_writenotify(struct vm_area_struct *vma, pgprot_t vm_page_prot)
>          * Do we need to track softdirty? hugetlb does not support softdirty
>          * tracking yet.
>          */
> -       if (vma_soft_dirty_enabled(vma) && !is_vm_hugetlb_page(vma))
> +       if (vma_soft_dirty_enabled(vma) && !vma_is_hugetlb(vma))
>                 return true;
>
>         /* Do we need write faults for uffd-wp tracking? */
> @@ -2347,7 +2347,7 @@ int mm_take_all_locks(struct mm_struct *mm)
>                 if (signal_pending(current))
>                         goto out_unlock;
>                 if (vma->vm_file && vma->vm_file->f_mapping &&
> -                               is_vm_hugetlb_page(vma))
> +                               vma_is_hugetlb(vma))
>                         vm_lock_mapping(mm, vma->vm_file->f_mapping);
>         }
>
> @@ -2356,7 +2356,7 @@ int mm_take_all_locks(struct mm_struct *mm)
>                 if (signal_pending(current))
>                         goto out_unlock;
>                 if (vma->vm_file && vma->vm_file->f_mapping &&
> -                               !is_vm_hugetlb_page(vma))
> +                               !vma_is_hugetlb(vma))
>                         vm_lock_mapping(mm, vma->vm_file->f_mapping);
>         }
>
> diff --git a/mm/vmscan.c b/mm/vmscan.c
> index 245f68c75b28..9cbfb90b0ad1 100644
> --- a/mm/vmscan.c
> +++ b/mm/vmscan.c
> @@ -3413,7 +3413,7 @@ static int should_skip_vma(unsigned long start, unsigned long end, struct mm_wal
>         if (!vma_is_accessible(vma))
>                 return true;
>
> -       if (is_vm_hugetlb_page(vma))
> +       if (vma_is_hugetlb(vma))
>                 return true;
>
>         if (!vma_has_recency(vma))
> diff --git a/tools/testing/vma/include/stubs.h b/tools/testing/vma/include/stubs.h
> index d6136e19a8af..48d1dc53df42 100644
> --- a/tools/testing/vma/include/stubs.h
> +++ b/tools/testing/vma/include/stubs.h
> @@ -193,7 +193,7 @@ static inline bool mapping_can_writeback(struct address_space *mapping)
>         return true;
>  }
>
> -static inline bool is_vm_hugetlb_page(struct vm_area_struct *vma)
> +static inline bool vma_is_hugetlb(struct vm_area_struct *vma)
>  {
>         return false;
>  }
>
> --
> 2.55.0
>

^ permalink raw reply	[flat|nested] 89+ messages in thread

* Re: [PATCH 27/39] mm: rename is_vm_hugetlb_page() to vma_is_hugetlb()
  2026-09-08 20:01 ` [PATCH 27/39] mm: rename is_vm_hugetlb_page() to vma_is_hugetlb() Lorenzo Stoakes (ARM)
  2026-09-08 20:40   ` sashiko-bot
  2026-09-09 11:09   ` Anup Patel
@ 2026-09-09 11:22   ` Claudio Imbrenda
  2026-09-09 11:30     ` Lorenzo Stoakes (ARM)
  2026-09-09 12:07   ` Marc Zyngier
  3 siblings, 1 reply; 89+ messages in thread
From: Claudio Imbrenda @ 2026-09-09 11:22 UTC (permalink / raw)
  To: Lorenzo Stoakes (ARM)
  Cc: Andrew Morton, David Hildenbrand, Mike Rapoport, Jonathan Corbet,
	Greg Kroah-Hartman, Jason Gunthorpe, John Hubbard, Peter Zijlstra,
	Thomas Gleixner, Ingo Molnar, Borislav Petkov, Mark Rutland,
	Nick Piggin, Arnd Bergmann, Matthew Wilcox (Oracle), Marc Zyngier,
	Christian Borntraeger, Janosch Frank, Alexander Gordeev,
	Gerald Schaefer, Heiko Carstens, Vasily Gorbik, David S. Miller,
	Alexander Viro, linux-mm, linux-kernel, kvm, linux-s390

On Tue, 08 Sep 2026 21:01:31 +0100
"Lorenzo Stoakes (ARM)" <ljs@kernel.org> wrote:

[please note that I had to prune the CC list quite aggressively because
my SMTP server was not happy]

> The is_vm_hugetlb_page() predicate is badly named - the mapping can span
> more than a page and it is inconsistent with other VMA predicates that
> typically are prefixed by vma_.
> 
> Rename to vma_is_hugetlb() for consistency, and while we're here update
> some VM_BUG_ON_VMA() to VM_WARN_ON_ONCE_VMA() as to avoid unnecessary
> oopses.
> 
> No functional change intended.
> 
> Signed-off-by: Lorenzo Stoakes (ARM) <ljs@kernel.org>

for s390:

Acked-by: Claudio Imbrenda <imbrenda@linux.ibm.com>

but please see the comment below

> ---
>  arch/arm64/kvm/mmu.c                      |  4 ++--
>  arch/powerpc/mm/book3s64/radix_tlb.c      |  6 +++---
>  arch/powerpc/mm/nohash/e500_hugetlbpage.c |  2 +-
>  arch/powerpc/mm/nohash/tlb.c              |  2 +-
>  arch/riscv/kvm/mmu.c                      |  2 +-
>  arch/riscv/mm/tlbflush.c                  |  2 +-
>  arch/s390/mm/gmap_helpers.c               |  6 +++---
>  arch/sparc/mm/init_64.c                   |  2 +-
>  drivers/gpu/drm/drm_gpusvm.c              |  2 +-
>  fs/coredump.c                             |  2 +-
>  fs/hugetlbfs/inode.c                      |  2 +-
>  fs/proc/task_mmu.c                        |  8 ++++----
>  include/asm-generic/tlb.h                 |  2 +-
>  include/linux/hugetlb.h                   |  4 ++--
>  include/linux/mm.h                        | 19 ++++++++++++++++---
>  include/linux/rmap.h                      |  2 +-
>  kernel/events/core.c                      |  2 +-
>  kernel/sched/fair.c                       |  2 +-
>  mm/gup.c                                  |  4 ++--
>  mm/huge_memory.c                          |  2 +-
>  mm/hugetlb.c                              | 14 +++++++-------
>  mm/internal.h                             |  2 +-
>  mm/madvise.c                              |  4 ++--
>  mm/memory.c                               | 12 ++++++------
>  mm/mempolicy.c                            |  2 +-
>  mm/migrate_device.c                       |  2 +-
>  mm/mmap.c                                 |  2 +-
>  mm/mmu_gather.c                           |  2 +-
>  mm/mprotect.c                             |  2 +-
>  mm/mremap.c                               |  6 +++---
>  mm/page_vma_mapped.c                      |  4 ++--
>  mm/pagewalk.c                             |  2 +-
>  mm/swapfile.c                             |  2 +-
>  mm/userfaultfd.c                          | 26 +++++++++++++-------------
>  mm/vma.c                                  |  8 ++++----
>  mm/vmscan.c                               |  2 +-
>  tools/testing/vma/include/stubs.h         |  2 +-
>  37 files changed, 92 insertions(+), 79 deletions(-)

[...]

> diff --git a/arch/s390/mm/gmap_helpers.c b/arch/s390/mm/gmap_helpers.c
> index ff63ffb1dbd2..3f6783b93e67 100644
> --- a/arch/s390/mm/gmap_helpers.c
> +++ b/arch/s390/mm/gmap_helpers.c
> @@ -102,7 +102,7 @@ __context_unsafe(/* pte_unmap_unlock() not instrumented */)
>  
>  	/* Find the vm address for the guest address */
>  	vma = vma_lookup(mm, vmaddr);
> -	if (!vma || is_vm_hugetlb_page(vma))
> +	if (!vma || vma_is_hugetlb(vma))
>  		return;
>  
>  	/* Get pointer to the page table entry */
> @@ -139,7 +139,7 @@ void gmap_helper_discard(struct mm_struct *mm, unsigned long vmaddr, unsigned lo
>  		vma = find_vma_intersection(mm, vmaddr, end);
>  		if (!vma)
>  			return;
> -		if (!is_vm_hugetlb_page(vma))
> +		if (!vma_is_hugetlb(vma))
>  			zap_vma_range(vma, vmaddr, min(end, vma->vm_end) - vmaddr);
>  		vmaddr = vma->vm_end;
>  	}
> @@ -247,7 +247,7 @@ static int __gmap_helper_unshare_zeropages(struct mm_struct *mm)
>  		 * proof to catch unexpected zeropages in other mappings and
>  		 * fail.
>  		 */
> -		if ((vma->vm_flags & VM_PFNMAP) || is_vm_hugetlb_page(vma))
> +		if ((vma->vm_flags & VM_PFNMAP) || vma_is_hugetlb(vma))

Would it be possible to replace this ^ with !vma_can_gup() ?

(obviously not in this patch, since vma_can_gup() is only introduced at
the end of the series)

>  			continue;
>  		addr = vma->vm_start;
>  

[...]

^ permalink raw reply	[flat|nested] 89+ messages in thread

* Re: [PATCH 27/39] mm: rename is_vm_hugetlb_page() to vma_is_hugetlb()
  2026-09-09 11:22   ` Claudio Imbrenda
@ 2026-09-09 11:30     ` Lorenzo Stoakes (ARM)
  2026-09-09 13:20       ` Claudio Imbrenda
  0 siblings, 1 reply; 89+ messages in thread
From: Lorenzo Stoakes (ARM) @ 2026-09-09 11:30 UTC (permalink / raw)
  To: Claudio Imbrenda
  Cc: Andrew Morton, David Hildenbrand, Mike Rapoport, Jonathan Corbet,
	Greg Kroah-Hartman, Jason Gunthorpe, John Hubbard, Peter Zijlstra,
	Thomas Gleixner, Ingo Molnar, Borislav Petkov, Mark Rutland,
	Nick Piggin, Arnd Bergmann, Matthew Wilcox (Oracle), Marc Zyngier,
	Christian Borntraeger, Janosch Frank, Alexander Gordeev,
	Gerald Schaefer, Heiko Carstens, Vasily Gorbik, David S. Miller,
	Alexander Viro, linux-mm, linux-kernel, kvm, linux-s390

On Wed, Sep 09, 2026 at 01:22:07PM +0200, Claudio Imbrenda wrote:
> On Tue, 08 Sep 2026 21:01:31 +0100
> "Lorenzo Stoakes (ARM)" <ljs@kernel.org> wrote:
>
> [please note that I had to prune the CC list quite aggressively because
> my SMTP server was not happy]

Yeah sorry about that, I already pruned the list a LOT from what b4 wanted, and
still ended up with a ton of people (I consider maintainers for stuff I touch
the minimum cc, but also added mm reviewers).

>
> > The is_vm_hugetlb_page() predicate is badly named - the mapping can span
> > more than a page and it is inconsistent with other VMA predicates that
> > typically are prefixed by vma_.
> >
> > Rename to vma_is_hugetlb() for consistency, and while we're here update
> > some VM_BUG_ON_VMA() to VM_WARN_ON_ONCE_VMA() as to avoid unnecessary
> > oopses.
> >
> > No functional change intended.
> >
> > Signed-off-by: Lorenzo Stoakes (ARM) <ljs@kernel.org>
>
> for s390:
>
> Acked-by: Claudio Imbrenda <imbrenda@linux.ibm.com>

Thanks!

>
> but please see the comment below
>
> > ---
> >  arch/arm64/kvm/mmu.c                      |  4 ++--
> >  arch/powerpc/mm/book3s64/radix_tlb.c      |  6 +++---
> >  arch/powerpc/mm/nohash/e500_hugetlbpage.c |  2 +-
> >  arch/powerpc/mm/nohash/tlb.c              |  2 +-
> >  arch/riscv/kvm/mmu.c                      |  2 +-
> >  arch/riscv/mm/tlbflush.c                  |  2 +-
> >  arch/s390/mm/gmap_helpers.c               |  6 +++---
> >  arch/sparc/mm/init_64.c                   |  2 +-
> >  drivers/gpu/drm/drm_gpusvm.c              |  2 +-
> >  fs/coredump.c                             |  2 +-
> >  fs/hugetlbfs/inode.c                      |  2 +-
> >  fs/proc/task_mmu.c                        |  8 ++++----
> >  include/asm-generic/tlb.h                 |  2 +-
> >  include/linux/hugetlb.h                   |  4 ++--
> >  include/linux/mm.h                        | 19 ++++++++++++++++---
> >  include/linux/rmap.h                      |  2 +-
> >  kernel/events/core.c                      |  2 +-
> >  kernel/sched/fair.c                       |  2 +-
> >  mm/gup.c                                  |  4 ++--
> >  mm/huge_memory.c                          |  2 +-
> >  mm/hugetlb.c                              | 14 +++++++-------
> >  mm/internal.h                             |  2 +-
> >  mm/madvise.c                              |  4 ++--
> >  mm/memory.c                               | 12 ++++++------
> >  mm/mempolicy.c                            |  2 +-
> >  mm/migrate_device.c                       |  2 +-
> >  mm/mmap.c                                 |  2 +-
> >  mm/mmu_gather.c                           |  2 +-
> >  mm/mprotect.c                             |  2 +-
> >  mm/mremap.c                               |  6 +++---
> >  mm/page_vma_mapped.c                      |  4 ++--
> >  mm/pagewalk.c                             |  2 +-
> >  mm/swapfile.c                             |  2 +-
> >  mm/userfaultfd.c                          | 26 +++++++++++++-------------
> >  mm/vma.c                                  |  8 ++++----
> >  mm/vmscan.c                               |  2 +-
> >  tools/testing/vma/include/stubs.h         |  2 +-
> >  37 files changed, 92 insertions(+), 79 deletions(-)
>
> [...]
>
> > diff --git a/arch/s390/mm/gmap_helpers.c b/arch/s390/mm/gmap_helpers.c
> > index ff63ffb1dbd2..3f6783b93e67 100644
> > --- a/arch/s390/mm/gmap_helpers.c
> > +++ b/arch/s390/mm/gmap_helpers.c
> > @@ -102,7 +102,7 @@ __context_unsafe(/* pte_unmap_unlock() not instrumented */)
> >
> >  	/* Find the vm address for the guest address */
> >  	vma = vma_lookup(mm, vmaddr);
> > -	if (!vma || is_vm_hugetlb_page(vma))
> > +	if (!vma || vma_is_hugetlb(vma))
> >  		return;
> >
> >  	/* Get pointer to the page table entry */
> > @@ -139,7 +139,7 @@ void gmap_helper_discard(struct mm_struct *mm, unsigned long vmaddr, unsigned lo
> >  		vma = find_vma_intersection(mm, vmaddr, end);
> >  		if (!vma)
> >  			return;
> > -		if (!is_vm_hugetlb_page(vma))
> > +		if (!vma_is_hugetlb(vma))
> >  			zap_vma_range(vma, vmaddr, min(end, vma->vm_end) - vmaddr);
> >  		vmaddr = vma->vm_end;
> >  	}
> > @@ -247,7 +247,7 @@ static int __gmap_helper_unshare_zeropages(struct mm_struct *mm)
> >  		 * proof to catch unexpected zeropages in other mappings and
> >  		 * fail.
> >  		 */
> > -		if ((vma->vm_flags & VM_PFNMAP) || is_vm_hugetlb_page(vma))
> > +		if ((vma->vm_flags & VM_PFNMAP) || vma_is_hugetlb(vma))
>
> Would it be possible to replace this ^ with !vma_can_gup() ?
>
> (obviously not in this patch, since vma_can_gup() is only introduced at
> the end of the series)

Sure, I could squash that into the 'use and apply vma_can_gup()' patch. Will do
on next respin!

>
> >  			continue;
> >  		addr = vma->vm_start;
> >
>
> [...]

--
Cheers, Lorenzo

^ permalink raw reply	[flat|nested] 89+ messages in thread

* Re: [PATCH 27/39] mm: rename is_vm_hugetlb_page() to vma_is_hugetlb()
  2026-09-08 20:01 ` [PATCH 27/39] mm: rename is_vm_hugetlb_page() to vma_is_hugetlb() Lorenzo Stoakes (ARM)
                     ` (2 preceding siblings ...)
  2026-09-09 11:22   ` Claudio Imbrenda
@ 2026-09-09 12:07   ` Marc Zyngier
  3 siblings, 0 replies; 89+ messages in thread
From: Marc Zyngier @ 2026-09-09 12:07 UTC (permalink / raw)
  To: Lorenzo Stoakes (ARM)
  Cc: 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,
	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,
	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, linux-mm,
	linux-kernel, linux-doc, linux-usb, linux-rdma, selinux,
	linux-sound, bpf, linux-scsi, linux-fbdev, dri-devel,
	linux-trace-kernel, linux-perf-users, linux-arch, linux-fsdevel,
	linux-arm-kernel, kvmarm, linuxppc-dev, kvm, kvm-riscv,
	linux-riscv, linux-s390, sparclinux, fuse-devel

On Tue, 08 Sep 2026 21:01:31 +0100,
"Lorenzo Stoakes (ARM)" <ljs@kernel.org> wrote:
> 
> The is_vm_hugetlb_page() predicate is badly named - the mapping can span
> more than a page and it is inconsistent with other VMA predicates that
> typically are prefixed by vma_.
> 
> Rename to vma_is_hugetlb() for consistency, and while we're here update
> some VM_BUG_ON_VMA() to VM_WARN_ON_ONCE_VMA() as to avoid unnecessary
> oopses.
> 
> No functional change intended.
> 
> Signed-off-by: Lorenzo Stoakes (ARM) <ljs@kernel.org>
> ---
>  arch/arm64/kvm/mmu.c                      |  4 ++--
>  arch/powerpc/mm/book3s64/radix_tlb.c      |  6 +++---
>  arch/powerpc/mm/nohash/e500_hugetlbpage.c |  2 +-
>  arch/powerpc/mm/nohash/tlb.c              |  2 +-
>  arch/riscv/kvm/mmu.c                      |  2 +-
>  arch/riscv/mm/tlbflush.c                  |  2 +-
>  arch/s390/mm/gmap_helpers.c               |  6 +++---
>  arch/sparc/mm/init_64.c                   |  2 +-
>  drivers/gpu/drm/drm_gpusvm.c              |  2 +-
>  fs/coredump.c                             |  2 +-
>  fs/hugetlbfs/inode.c                      |  2 +-
>  fs/proc/task_mmu.c                        |  8 ++++----
>  include/asm-generic/tlb.h                 |  2 +-
>  include/linux/hugetlb.h                   |  4 ++--
>  include/linux/mm.h                        | 19 ++++++++++++++++---
>  include/linux/rmap.h                      |  2 +-
>  kernel/events/core.c                      |  2 +-
>  kernel/sched/fair.c                       |  2 +-
>  mm/gup.c                                  |  4 ++--
>  mm/huge_memory.c                          |  2 +-
>  mm/hugetlb.c                              | 14 +++++++-------
>  mm/internal.h                             |  2 +-
>  mm/madvise.c                              |  4 ++--
>  mm/memory.c                               | 12 ++++++------
>  mm/mempolicy.c                            |  2 +-
>  mm/migrate_device.c                       |  2 +-
>  mm/mmap.c                                 |  2 +-
>  mm/mmu_gather.c                           |  2 +-
>  mm/mprotect.c                             |  2 +-
>  mm/mremap.c                               |  6 +++---
>  mm/page_vma_mapped.c                      |  4 ++--
>  mm/pagewalk.c                             |  2 +-
>  mm/swapfile.c                             |  2 +-
>  mm/userfaultfd.c                          | 26 +++++++++++++-------------
>  mm/vma.c                                  |  8 ++++----
>  mm/vmscan.c                               |  2 +-
>  tools/testing/vma/include/stubs.h         |  2 +-
>  37 files changed, 92 insertions(+), 79 deletions(-)
> 
> diff --git a/arch/arm64/kvm/mmu.c b/arch/arm64/kvm/mmu.c
> index 9ba86450fe4a..a7968f8d24bf 100644
> --- a/arch/arm64/kvm/mmu.c
> +++ b/arch/arm64/kvm/mmu.c
> @@ -1463,13 +1463,13 @@ static int get_vma_page_shift(struct vm_area_struct *vma, unsigned long hva)
>  {
>  	unsigned long pa;
>  
> -	if (is_vm_hugetlb_page(vma) && !(vma->vm_flags & VM_PFNMAP))
> +	if (vma_is_hugetlb(vma) && !(vma->vm_flags & VM_PFNMAP))
>  		return huge_page_shift(hstate_vma(vma));
>  
>  	if (!(vma->vm_flags & VM_PFNMAP))
>  		return PAGE_SHIFT;
>  
> -	VM_BUG_ON(is_vm_hugetlb_page(vma));
> +	VM_BUG_ON(vma_is_hugetlb(vma));
>  
>  	pa = (vma->vm_pgoff << PAGE_SHIFT) + (hva - vma->vm_start);
>  

Acked-by: Marc Zyngier <maz@kernel.org>

	M.

-- 
Without deviation from the norm, progress is not possible.

^ permalink raw reply	[flat|nested] 89+ messages in thread

* Re: [PATCH 28/39] mm: drop some redundant checks around hugetlb VMAs
  2026-09-08 20:01 ` [PATCH 28/39] mm: drop some redundant checks around hugetlb VMAs Lorenzo Stoakes (ARM)
  2026-09-08 20:39   ` sashiko-bot
@ 2026-09-09 12:08   ` Marc Zyngier
  1 sibling, 0 replies; 89+ messages in thread
From: Marc Zyngier @ 2026-09-09 12:08 UTC (permalink / raw)
  To: Lorenzo Stoakes (ARM)
  Cc: 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,
	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,
	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, linux-mm,
	linux-kernel, linux-doc, linux-usb, linux-rdma, selinux,
	linux-sound, bpf, linux-scsi, linux-fbdev, dri-devel,
	linux-trace-kernel, linux-perf-users, linux-arch, linux-fsdevel,
	linux-arm-kernel, kvmarm, linuxppc-dev, kvm, kvm-riscv,
	linux-riscv, linux-s390, sparclinux, fuse-devel

On Tue, 08 Sep 2026 21:01:32 +0100,
"Lorenzo Stoakes (ARM)" <ljs@kernel.org> wrote:
> 
> Adjust code which inadvertently perform redundant checks on hugetlb VMAs
> and clean them up:
> 
> * hugetlb VMAs have VMA_DONTEXPAND_BIT set so a VMA_SPECIAL_FLAGS check
>   suffices. (migrate_vma_setup() regains an explicit hugetlb test later in
>   the series, once VMA_SPECIAL_FLAGS is removed.)
> 
> * hugetlb VMAs unconditionally set vma->vm_ops, so they are never
>   anonymous.
> 
> * hugetlb VMAs do not set VMA_PFNMAP_BIT so checking for this is redundant.
> 
> While we're here also drop a VM_BUG_ON() which the simplified check above
> makes unreachable, and use the new VMA flag API.
> 
> No functional change intended.
> 
> Signed-off-by: Lorenzo Stoakes (ARM) <ljs@kernel.org>
> ---
>  arch/arm64/kvm/mmu.c         | 4 +---
>  drivers/gpu/drm/drm_gpusvm.c | 3 +--
>  mm/migrate_device.c          | 4 ++--
>  3 files changed, 4 insertions(+), 7 deletions(-)
> 
> diff --git a/arch/arm64/kvm/mmu.c b/arch/arm64/kvm/mmu.c
> index a7968f8d24bf..3c1240ffc38d 100644
> --- a/arch/arm64/kvm/mmu.c
> +++ b/arch/arm64/kvm/mmu.c
> @@ -1463,14 +1463,12 @@ static int get_vma_page_shift(struct vm_area_struct *vma, unsigned long hva)
>  {
>  	unsigned long pa;
>  
> -	if (vma_is_hugetlb(vma) && !(vma->vm_flags & VM_PFNMAP))
> +	if (vma_is_hugetlb(vma))
>  		return huge_page_shift(hstate_vma(vma));
>  
>  	if (!(vma->vm_flags & VM_PFNMAP))
>  		return PAGE_SHIFT;
>  
> -	VM_BUG_ON(vma_is_hugetlb(vma));
> -
>  	pa = (vma->vm_pgoff << PAGE_SHIFT) + (hva - vma->vm_start);
>  
>  #ifndef __PAGETABLE_PMD_FOLDED

Acked-by: Marc Zyngier <maz@kernel.org>

	M.

-- 
Without deviation from the norm, progress is not possible.

^ permalink raw reply	[flat|nested] 89+ messages in thread

* Re: [PATCH 27/39] mm: rename is_vm_hugetlb_page() to vma_is_hugetlb()
  2026-09-09 11:30     ` Lorenzo Stoakes (ARM)
@ 2026-09-09 13:20       ` Claudio Imbrenda
  0 siblings, 0 replies; 89+ messages in thread
From: Claudio Imbrenda @ 2026-09-09 13:20 UTC (permalink / raw)
  To: Lorenzo Stoakes (ARM)
  Cc: Andrew Morton, David Hildenbrand, Mike Rapoport, Jonathan Corbet,
	Greg Kroah-Hartman, Jason Gunthorpe, John Hubbard, Peter Zijlstra,
	Thomas Gleixner, Ingo Molnar, Borislav Petkov, Mark Rutland,
	Nick Piggin, Arnd Bergmann, Matthew Wilcox (Oracle), Marc Zyngier,
	Christian Borntraeger, Janosch Frank, Alexander Gordeev,
	Gerald Schaefer, Heiko Carstens, Vasily Gorbik, David S. Miller,
	Alexander Viro, linux-mm, linux-kernel, kvm, linux-s390

On Wed, 9 Sep 2026 12:30:45 +0100
"Lorenzo Stoakes (ARM)" <ljs@kernel.org> wrote:

> On Wed, Sep 09, 2026 at 01:22:07PM +0200, Claudio Imbrenda wrote:
> > On Tue, 08 Sep 2026 21:01:31 +0100
> > "Lorenzo Stoakes (ARM)" <ljs@kernel.org> wrote:
> >
> > [please note that I had to prune the CC list quite aggressively because
> > my SMTP server was not happy]  
> 
> Yeah sorry about that, I already pruned the list a LOT from what b4 wanted, and
> still ended up with a ton of people (I consider maintainers for stuff I touch
> the minimum cc, but also added mm reviewers).

yeah I did not mean to fault you, I understand why the list was so
long. mine was just a courtesy warning in case people reply to this

[...]

> > > @@ -247,7 +247,7 @@ static int __gmap_helper_unshare_zeropages(struct mm_struct *mm)
> > >  		 * proof to catch unexpected zeropages in other mappings and
> > >  		 * fail.
> > >  		 */
> > > -		if ((vma->vm_flags & VM_PFNMAP) || is_vm_hugetlb_page(vma))
> > > +		if ((vma->vm_flags & VM_PFNMAP) || vma_is_hugetlb(vma))  
> >
> > Would it be possible to replace this ^ with !vma_can_gup() ?
> >
> > (obviously not in this patch, since vma_can_gup() is only introduced at
> > the end of the series)  
> 
> Sure, I could squash that into the 'use and apply vma_can_gup()' patch. Will do
> on next respin!

excellent, thanks!

> 
> >  
> > >  			continue;
> > >  		addr = vma->vm_start;
> > >  
> >
> > [...]  
> 
> --
> Cheers, Lorenzo


^ permalink raw reply	[flat|nested] 89+ messages in thread

* Re: [PATCH 12/39] ALSA: pcm: use vm_insert_page() to map PCM status page
  2026-09-08 20:01 ` [PATCH 12/39] ALSA: pcm: use vm_insert_page() to map PCM status page Lorenzo Stoakes (ARM)
  2026-09-08 20:45   ` sashiko-bot
@ 2026-09-10 16:15   ` Takashi Iwai
  1 sibling, 0 replies; 89+ messages in thread
From: Takashi Iwai @ 2026-09-10 16:15 UTC (permalink / raw)
  To: Lorenzo Stoakes (ARM)
  Cc: 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,
	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, linux-mm, linux-kernel, linux-doc,
	linux-usb, linux-rdma, selinux, linux-sound, bpf, linux-scsi,
	linux-fbdev, dri-devel, linux-trace-kernel, linux-perf-users,
	linux-arch, linux-fsdevel, linux-arm-kernel, kvmarm, linuxppc-dev,
	kvm, kvm-riscv, linux-riscv, linux-s390, sparclinux, fuse-devel

On Tue, 08 Sep 2026 22:01:16 +0200,
Lorenzo Stoakes (ARM) wrote:
> 
> There's no need to keep a fault handler around for this, instead map on
> mmap.
> 
> While we're here, rename area to vma to be consistent.
> 
> This correctly makes the mapping a mixed map mapping.
> 
> This works towards establishing the invariant that only PFN mapped or mixed
> map mappings may clear the VM_MAYWRITE flag. The status page mapping clears
> VM_MAYWRITE, so it must be kernel-owned; the control page mapping remains
> writable and is left fault-based.
> 
> The assumption is made that the struct pcm_mmap_status structure is at most
> a page in size, which is asserted as a build bug.
> 
> This is safe to assume, as the size of the structure is 56 bytes at most.
> 
> Signed-off-by: Lorenzo Stoakes (ARM) <ljs@kernel.org>

Acked-by: Takashi Iwai <tiwai@suse.de>


thanks,

Takashi

^ permalink raw reply	[flat|nested] 89+ messages in thread

* Re: [PATCH 11/39] selinux: reject writable opens of policy file, drop mmap shared/write check
  2026-09-08 20:01 ` [PATCH 11/39] selinux: reject writable opens of policy file, drop mmap shared/write check Lorenzo Stoakes (ARM)
  2026-09-08 20:22   ` Jann Horn
  2026-09-08 20:36   ` sashiko-bot
@ 2026-09-10 18:11   ` Stephen Smalley
  2 siblings, 0 replies; 89+ messages in thread
From: Stephen Smalley @ 2026-09-10 18:11 UTC (permalink / raw)
  To: Lorenzo Stoakes (ARM)
  Cc: 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, 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, 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, linux-mm,
	linux-kernel, linux-doc, linux-usb, linux-rdma, selinux,
	linux-sound, bpf, linux-scsi, linux-fbdev, dri-devel,
	linux-trace-kernel, linux-perf-users, linux-arch, linux-fsdevel,
	linux-arm-kernel, kvmarm, linuxppc-dev, kvm, kvm-riscv,
	linux-riscv, linux-s390, sparclinux, fuse-devel

On Tue, Sep 8, 2026 at 4:07 PM Lorenzo Stoakes (ARM) <ljs@kernel.org> wrote:
>
> The policy file has no write method and is exposed read-only (S_IRUGO in
> selinux_files[]), yet sel_open_policy() performs no open mode check, so a
> CAP_DAC_OVERRIDE caller can open it O_RDWR. Reject FMODE_WRITE at open, as
> kernfs does.
>
> The file can then never be mapped with FMODE_WRITE, so do_mmap() always
> clears VM_MAYWRITE and VM_SHARED for MAP_SHARED mappings and the VM_SHARED
> check in sel_mmap_policy() cannot be reached. Remove it.
>
> This also stops sel_mmap_policy() clearing VM_MAYWRITE on a mapping that is
> neither a PFN map nor a mixed map, ahead of the core enforcing that only
> such mappings may do so.
>
> Signed-off-by: Lorenzo Stoakes (ARM) <ljs@kernel.org>

We should likely do something similar for the other sel_open_*() and
sel_mmap_*() functions too.
In particular, truncation of the status file can bring down systemd
since it is mapped by libselinux.

Acked-by: Stephen Smalley <stephen.smalley.work@gmail.com>

> ---
>  security/selinux/selinuxfs.c | 11 +++--------
>  1 file changed, 3 insertions(+), 8 deletions(-)
>
> diff --git a/security/selinux/selinuxfs.c b/security/selinux/selinuxfs.c
> index c7d91476971c..545a6f89f9e7 100644
> --- a/security/selinux/selinuxfs.c
> +++ b/security/selinux/selinuxfs.c
> @@ -340,6 +340,9 @@ static int sel_open_policy(struct inode *inode, struct file *filp)
>         struct policy_load_memory *plm = NULL;
>         int rc;
>
> +       if (filp->f_mode & FMODE_WRITE)
> +               return -EACCES;
> +
>         rc = avc_has_perm(current_sid(), SECINITSID_SECURITY,
>                           SECCLASS_SECURITY, SECURITY__READ_POLICY, NULL);
>         if (rc)
> @@ -424,14 +427,6 @@ static const struct vm_operations_struct sel_mmap_policy_ops = {
>
>  static int sel_mmap_policy(struct file *filp, struct vm_area_struct *vma)
>  {
> -       if (vma->vm_flags & VM_SHARED) {
> -               /* do not allow mprotect to make mapping writable */
> -               vm_flags_clear(vma, VM_MAYWRITE);
> -
> -               if (vma->vm_flags & VM_WRITE)
> -                       return -EACCES;
> -       }
> -
>         vm_flags_set(vma, VM_DONTEXPAND | VM_DONTDUMP);
>         vma->vm_ops = &sel_mmap_policy_ops;
>
>
> --
> 2.55.0
>

^ permalink raw reply	[flat|nested] 89+ messages in thread

end of thread, other threads:[~2026-09-10 18:11 UTC | newest]

Thread overview: 89+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-09-08 20:01 [PATCH 00/39] mm: make VMA flag semantics explicit, eliminate VM_SPECIAL Lorenzo Stoakes (ARM)
2026-09-08 20:01 ` [PATCH 01/39] mm/vma: predicate setting mmap_prepare VMA fields on new vma alloc Lorenzo Stoakes (ARM)
2026-09-08 20:42   ` sashiko-bot
2026-09-08 20:01 ` [PATCH 02/39] mm/vma: introduce and use vma_[flags_]can_merge() Lorenzo Stoakes (ARM)
2026-09-08 20:27   ` sashiko-bot
2026-09-08 20:01 ` [PATCH 03/39] mm: consistently validate VMA state after mmap[_prepare] hooks Lorenzo Stoakes (ARM)
2026-09-08 20:40   ` sashiko-bot
2026-09-08 20:01 ` [PATCH 04/39] mm/vma: ensure mmap_prepare doesn't set actions on a mergeable vma Lorenzo Stoakes (ARM)
2026-09-08 20:36   ` sashiko-bot
2026-09-08 20:01 ` [PATCH 05/39] mm: make map_kernel_pages_[prepare,complete] internal and unexported Lorenzo Stoakes (ARM)
2026-09-08 20:24   ` sashiko-bot
2026-09-08 20:01 ` [PATCH 06/39] mm/vma: tidy up map kernel pages enum values Lorenzo Stoakes (ARM)
2026-09-08 20:27   ` sashiko-bot
2026-09-08 20:01 ` [PATCH 07/39] mm: add mmap action for discontiguous kernel page mapping Lorenzo Stoakes (ARM)
2026-09-08 20:34   ` sashiko-bot
2026-09-08 20:01 ` [PATCH 08/39] docs: filesystems: update mmap_prepare docs for discontig kernel pgs Lorenzo Stoakes (ARM)
2026-09-08 20:38   ` sashiko-bot
2026-09-08 20:01 ` [PATCH 09/39] drivers/usb/mon: update to use mmap_prepare + map kernel pages Lorenzo Stoakes (ARM)
2026-09-08 20:35   ` sashiko-bot
2026-09-09  7:37   ` Greg Kroah-Hartman
2026-09-08 20:01 ` [PATCH 10/39] infiniband: update hfi1 to use remap_vmalloc_range() Lorenzo Stoakes (ARM)
2026-09-08 20:42   ` sashiko-bot
2026-09-08 20:01 ` [PATCH 11/39] selinux: reject writable opens of policy file, drop mmap shared/write check Lorenzo Stoakes (ARM)
2026-09-08 20:22   ` Jann Horn
2026-09-08 20:36   ` sashiko-bot
2026-09-10 18:11   ` Stephen Smalley
2026-09-08 20:01 ` [PATCH 12/39] ALSA: pcm: use vm_insert_page() to map PCM status page Lorenzo Stoakes (ARM)
2026-09-08 20:45   ` sashiko-bot
2026-09-10 16:15   ` Takashi Iwai
2026-09-08 20:01 ` [PATCH 13/39] bpf: arena: mark arena_map_mmap() mappings VM_MIXEDMAP Lorenzo Stoakes (ARM)
2026-09-08 20:34   ` sashiko-bot
2026-09-08 20:01 ` [PATCH 14/39] mm/vma: add vma[_flags]_is_kernel_owned() predicates Lorenzo Stoakes (ARM)
2026-09-08 20:28   ` sashiko-bot
2026-09-08 20:01 ` [PATCH 15/39] mm/vma: only allow mmap to clear VMA_MAYWRITE_BIT if kernel-owned Lorenzo Stoakes (ARM)
2026-09-08 20:42   ` sashiko-bot
2026-09-08 20:01 ` [PATCH 16/39] mm/vma: add and use vma_[flags]_is_fixed_mapping Lorenzo Stoakes (ARM)
2026-09-08 20:42   ` sashiko-bot
2026-09-08 20:01 ` [PATCH 17/39] scsi: sg: convert mmap hook to mmap_prepare and rework Lorenzo Stoakes (ARM)
2026-09-08 20:37   ` sashiko-bot
2026-09-08 20:01 ` [PATCH 18/39] fbdev: defio: assert FBINFO_VIRTFB, drop VM_IO, add VM_MIXEDMAP Lorenzo Stoakes (ARM)
2026-09-08 20:39   ` sashiko-bot
2026-09-08 20:01 ` [PATCH 19/39] HSI: cmt_speech: convert mmap hook to mmap_prepare, refactor Lorenzo Stoakes (ARM)
2026-09-08 20:36   ` sashiko-bot
2026-09-08 20:01 ` [PATCH 20/39] mm/gup: error out early on !VMA_MAYREAD_BIT VMAs Lorenzo Stoakes (ARM)
2026-09-08 20:36   ` sashiko-bot
2026-09-08 20:01 ` [PATCH 21/39] uprobes: remove VM_IO, set VM_MIXEDMAP for mapped kernel pages Lorenzo Stoakes (ARM)
2026-09-08 20:36   ` sashiko-bot
2026-09-08 20:01 ` [PATCH 22/39] mm/mlock: clear VMA_LOCKED_MASK over mmap callback Lorenzo Stoakes (ARM)
2026-09-08 20:38   ` sashiko-bot
2026-09-08 20:01 ` [PATCH 23/39] mm/mlock: eliminate weird VMA_IO_BIT abuse and simplify Lorenzo Stoakes (ARM)
2026-09-08 20:47   ` sashiko-bot
2026-09-08 20:01 ` [PATCH 24/39] mm/vma: enforce that only kernel-owned mappings may set VMA_IO_BIT Lorenzo Stoakes (ARM)
2026-09-08 20:47   ` sashiko-bot
2026-09-08 20:01 ` [PATCH 25/39] mm: remove VMA_IO_BIT check in vma[_flags]_is_kernel_owned() Lorenzo Stoakes (ARM)
2026-09-08 20:37   ` sashiko-bot
2026-09-08 20:01 ` [PATCH 26/39] mm: remove hugetlb_inline.h Lorenzo Stoakes (ARM)
2026-09-08 20:34   ` sashiko-bot
2026-09-08 20:01 ` [PATCH 27/39] mm: rename is_vm_hugetlb_page() to vma_is_hugetlb() Lorenzo Stoakes (ARM)
2026-09-08 20:40   ` sashiko-bot
2026-09-09 11:09   ` Anup Patel
2026-09-09 11:22   ` Claudio Imbrenda
2026-09-09 11:30     ` Lorenzo Stoakes (ARM)
2026-09-09 13:20       ` Claudio Imbrenda
2026-09-09 12:07   ` Marc Zyngier
2026-09-08 20:01 ` [PATCH 28/39] mm: drop some redundant checks around hugetlb VMAs Lorenzo Stoakes (ARM)
2026-09-08 20:39   ` sashiko-bot
2026-09-09 12:08   ` Marc Zyngier
2026-09-08 20:01 ` [PATCH 29/39] mm/madvise: update is_valid_guard_vma() to use vma_can_merge() Lorenzo Stoakes (ARM)
2026-09-08 20:45   ` sashiko-bot
2026-09-08 20:01 ` [PATCH 30/39] mm/vma: introduce vma[_flags]_is_persistent() Lorenzo Stoakes (ARM)
2026-09-08 20:47   ` sashiko-bot
2026-09-08 20:01 ` [PATCH 31/39] mm/uffd: use predicates for userfaultfd checks Lorenzo Stoakes (ARM)
2026-09-08 20:45   ` sashiko-bot
2026-09-08 20:01 ` [PATCH 32/39] mm/madvise: use predicates for madvise(..., MADV_DOFORK) Lorenzo Stoakes (ARM)
2026-09-08 20:48   ` sashiko-bot
2026-09-08 20:01 ` [PATCH 33/39] mm: eliminate VMA_SPECIAL_FLAGS usage when hugetlb explicitly tested Lorenzo Stoakes (ARM)
2026-09-08 20:42   ` sashiko-bot
2026-09-08 20:01 ` [PATCH 34/39] mm: eliminate VMA_SPECIAL_FLAGS check in lru_gen_look_around() Lorenzo Stoakes (ARM)
2026-09-08 20:45   ` sashiko-bot
2026-09-08 20:01 ` [PATCH 35/39] mm: avoid use of VMA_SPECIAL_FLAGS in migrate_vma_setup() Lorenzo Stoakes (ARM)
2026-09-08 20:47   ` sashiko-bot
2026-09-08 20:01 ` [PATCH 36/39] mm: eliminate VM_SPECIAL, VMA_SPECIAL_FLAGS Lorenzo Stoakes (ARM)
2026-09-08 20:41   ` sashiko-bot
2026-09-08 20:01 ` [PATCH 37/39] fuse: dax: do not set VM_MIXEDMAP Lorenzo Stoakes (ARM)
2026-09-08 20:50   ` sashiko-bot
2026-09-08 20:01 ` [PATCH 38/39] mm/huge_memory: remove vma_is_special_huge() Lorenzo Stoakes (ARM)
2026-09-08 20:45   ` sashiko-bot
2026-09-08 20:01 ` [PATCH 39/39] mm/vma: introduce and use vma[_flags]_can_gup() Lorenzo Stoakes (ARM)
2026-09-08 20:44   ` sashiko-bot

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox