linux/mm
David Hildenbrand (Arm) ffef67b93a mm/memory: fix PMD/PUD checks in follow_pfnmap_start()
follow_pfnmap_start() suffers from two problems:

(1) We are not re-fetching the pmd/pud after taking the PTL

Therefore, we are not properly stabilizing what the lock actually
protects.  If there is concurrent zapping, we would indicate to the
caller that we found an entry, however, that entry might already have
been invalidated, or contain a different PFN after taking the lock.

Properly use pmdp_get() / pudp_get() after taking the lock.

(2) pmd_leaf() / pud_leaf() are not well defined on non-present entries

pmd_leaf()/pud_leaf() could wrongly trigger on non-present entries.

There is no real guarantee that pmd_leaf()/pud_leaf() returns something
reasonable on non-present entries.  Most architectures indeed either
perform a present check or make it work by smart use of flags.

However, for example loongarch checks the _PAGE_HUGE flag in pmd_leaf(),
and always sets the _PAGE_HUGE flag in __swp_entry_to_pmd().  Whereby
pmd_trans_huge() explicitly checks pmd_present(), pmd_leaf() does not do
that.

Let's check pmd_present()/pud_present() before assuming "the is a present
PMD leaf" when spotting pmd_leaf()/pud_leaf(), like other page table
handling code that traverses user page tables does.

Given that non-present PMD entries are likely rare in VM_IO|VM_PFNMAP, (1)
is likely more relevant than (2).  It is questionable how often (1) would
actually trigger, but let's CC stable to be sure.

This was found by code inspection.

Link: https://lkml.kernel.org/r/20260323-follow_pfnmap_fix-v1-1-5b0ec10872b3@kernel.org
Fixes: 6da8e9634b ("mm: new follow_pfnmap API")
Signed-off-by: David Hildenbrand (Arm) <david@kernel.org>
Acked-by: Mike Rapoport (Microsoft) <rppt@kernel.org>
Reviewed-by: Lorenzo Stoakes (Oracle) <ljs@kernel.org>
Cc: Liam Howlett <liam.howlett@oracle.com>
Cc: Michal Hocko <mhocko@suse.com>
Cc: Peter Xu <peterx@redhat.com>
Cc: Suren Baghdasaryan <surenb@google.com>
Cc: Vlastimil Babka <vbabka@kernel.org>
Cc: <stable@vger.kernel.org>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
2026-03-27 20:48:38 -07:00
..
damon mm/damon/sysfs: check contexts->nr in repeat_call_fn 2026-03-27 20:48:38 -07:00
kasan Convert 'alloc_obj' family to use the new default GFP_KERNEL argument 2026-02-21 17:09:51 -08:00
kfence mm/kfence: fix KASAN hardware tag faults during late enablement 2026-02-24 11:13:27 -08:00
kmsan Convert 'alloc_obj' family to use the new default GFP_KERNEL argument 2026-02-21 17:09:51 -08:00
tests sparc/mm: export symbols for lazy_mmu_mode KUnit tests 2026-01-31 14:22:40 -08:00
Kconfig mm.git review status for linus..mm-stable 2026-02-12 11:32:37 -08:00
Kconfig.debug
Makefile mm.git review status for linus..mm-nonmm-stable 2026-02-12 12:13:01 -08:00
backing-dev.c treewide: Replace kmalloc with kmalloc_obj for non-scalar types 2026-02-21 01:02:28 -08:00
balloon.c mm: rename CONFIG_BALLOON_COMPACTION to CONFIG_BALLOON_MIGRATION 2026-01-31 14:22:36 -08:00
bootmem_info.c
bpf_memcontrol.c bpf: Revert "bpf: drop KF_ACQUIRE flag on BPF kfunc bpf_get_root_mem_cgroup()" 2026-01-21 09:38:16 -08:00
cma.c mm/cma: move put_page_testzero() out of VM_WARN_ON in cma_release() 2026-03-04 09:44:22 -08:00
cma.h
cma_debug.c Convert 'alloc_obj' family to use the new default GFP_KERNEL argument 2026-02-21 17:09:51 -08:00
cma_sysfs.c Convert 'alloc_obj' family to use the new default GFP_KERNEL argument 2026-02-21 17:09:51 -08:00
compaction.c
debug.c
debug_page_alloc.c
debug_page_ref.c
debug_vm_pgtable.c mm: debug_vm_pgtable: add debug_vm_pgtable_free_huge_page() 2026-01-26 20:02:27 -08:00
dmapool.c
dmapool_test.c Convert 'alloc_obj' family to use the new default GFP_KERNEL argument 2026-02-21 17:09:51 -08:00
early_ioremap.c mm/early_ioremap: clean up the use of WARN() for debugging 2026-01-26 20:02:26 -08:00
execmem.c
fadvise.c
fail_page_alloc.c
failslab.c
filemap.c mm: Fix a hmm_range_fault() livelock / starvation problem 2026-03-02 11:51:51 -05:00
folio-compat.c mm: add SPDX id lines to some mm source files 2026-02-06 15:47:16 -08:00
gup.c mm/gup: remove no longer used gup_fast_undo_dev_pagemap 2026-01-20 19:24:49 -08:00
gup_test.c mm: add SPDX id lines to some mm source files 2026-02-06 15:47:16 -08:00
gup_test.h
highmem.c mm/highmem: fix __kmap_to_page() build error 2026-01-31 14:22:38 -08:00
hmm.c treewide: Replace kmalloc with kmalloc_obj for non-scalar types 2026-02-21 01:02:28 -08:00
huge_memory.c mm/huge_memory: fix use of NULL folio in move_pages_huge_pmd() 2026-03-10 16:01:49 -07:00
hugetlb.c mm/hugetlb.c: use __pa() instead of virt_to_phys() in early bootmem alloc code 2026-03-04 09:44:23 -08:00
hugetlb_cgroup.c Convert 'alloc_flex' family to use the new default GFP_KERNEL argument 2026-02-21 17:09:51 -08:00
hugetlb_cma.c mm: hugetlb_cma: mark hugetlb_cma{_only} as __ro_after_init 2026-01-31 14:22:43 -08:00
hugetlb_cma.h mm: hugetlb: allocate frozen pages for gigantic allocation 2026-01-26 20:02:28 -08:00
hugetlb_internal.h
hugetlb_sysctl.c mm, hugetlb: implement movable_gigantic_pages sysctl 2026-01-20 19:24:50 -08:00
hugetlb_sysfs.c
hugetlb_vmemmap.c Revert "mm/hugetlb: deal with multiple calls to hugetlb_bootmem_alloc" 2026-01-26 20:02:20 -08:00
hugetlb_vmemmap.h
hwpoison-inject.c
init-mm.c mm: rename cpu_bitmap field to flexible_array 2026-01-19 12:30:00 -08:00
internal.h mm.git review status for linus..mm-stable 2026-02-18 20:50:32 -08:00
interval_tree.c
ioremap.c
khugepaged.c Convert 'alloc_obj' family to use the new default GFP_KERNEL argument 2026-02-21 17:09:51 -08:00
kmemleak.c slab updates for 7.0 part2 2026-02-16 13:41:38 -08:00
ksm.c Convert more 'alloc_obj' cases to default GFP_KERNEL arguments 2026-02-21 20:03:00 -08:00
list_lru.c Convert 'alloc_obj' family to use the new default GFP_KERNEL argument 2026-02-21 17:09:51 -08:00
maccess.c
madvise.c Require (reasonably) normal mappings for MADV_DOFORK 2026-03-06 09:10:36 -08:00
mapping_dirty_helpers.c
memblock.c memblock: updates for 7.0-rc1 2026-02-14 12:39:34 -08:00
memcontrol-v1.c treewide: Replace kmalloc with kmalloc_obj for non-scalar types 2026-02-21 01:02:28 -08:00
memcontrol-v1.h mm.git review status for linus..mm-stable 2026-02-12 11:32:37 -08:00
memcontrol.c memcg: fix slab accounting in refill_obj_stock() trylock path 2026-03-04 09:44:23 -08:00
memfd.c mm: update shmem_[kernel]_file_*() functions to use vma_flags_t 2026-02-12 15:42:58 -08:00
memfd_luo.c mm: memfd_luo: always dirty all folios 2026-03-04 09:44:21 -08:00
memory-failure.c treewide: Replace kmalloc with kmalloc_obj for non-scalar types 2026-02-21 01:02:28 -08:00
memory-tiers.c Convert more 'alloc_obj' cases to default GFP_KERNEL arguments 2026-02-21 20:03:00 -08:00
memory.c mm/memory: fix PMD/PUD checks in follow_pfnmap_start() 2026-03-27 20:48:38 -07:00
memory_hotplug.c mm: rename CONFIG_BALLOON_COMPACTION to CONFIG_BALLOON_MIGRATION 2026-01-31 14:22:36 -08:00
mempolicy.c Convert more 'alloc_obj' cases to default GFP_KERNEL arguments 2026-02-21 20:03:00 -08:00
mempool.c Convert 'alloc_obj' family to use the new default GFP_KERNEL argument 2026-02-21 17:09:51 -08:00
memremap.c mm/zone_device: reinitialize large zone device private folios 2026-01-26 19:03:48 -08:00
memtest.c mm/memtest: add underflow detection for size calculation 2026-01-09 11:53:51 +02:00
migrate.c mm: Fix a hmm_range_fault() livelock / starvation problem 2026-03-02 11:51:51 -05:00
migrate_device.c mm: Fix a hmm_range_fault() livelock / starvation problem 2026-03-02 11:51:51 -05:00
mincore.c
mlock.c
mm_init.c mm: fix NULL NODE_DATA dereference for memoryless nodes on boot 2026-02-24 11:13:28 -08:00
mm_slot.h
mmap.c mm: update secretmem to use VMA flags on mmap_prepare 2026-02-12 15:42:58 -08:00
mmap_lock.c mm/vma: improve and document __is_vma_write_locked() 2026-01-31 14:22:51 -08:00
mmu_gather.c mm: add SPDX id lines to some mm source files 2026-02-06 15:47:16 -08:00
mmu_notifier.c Convert more 'alloc_obj' cases to default GFP_KERNEL arguments 2026-02-21 20:03:00 -08:00
mmzone.c
mprotect.c mm: introduce generic lazy_mmu helpers 2026-01-20 19:24:33 -08:00
mremap.c mm: update secretmem to use VMA flags on mmap_prepare 2026-02-12 15:42:58 -08:00
mseal.c mm: fix minor spelling mistakes in comments 2026-01-20 19:24:48 -08:00
msync.c
nommu.c
numa.c
numa_emulation.c
numa_memblks.c memblock: numa_memblks: fix detection of NUMA node for CXL windows 2026-02-21 09:58:22 -08:00
oom_kill.c mm: fix OOM killer inaccuracy on large many-core systems 2026-01-31 14:22:37 -08:00
page-writeback.c mm/block/fs: remove laptop_mode 2026-01-20 19:24:47 -08:00
page_alloc.c mm/kfence: fix KASAN hardware tag faults during late enablement 2026-02-24 11:13:27 -08:00
page_counter.c
page_ext.c mm/page_ext: Add page_ext_get_from_phys() 2026-01-21 12:51:48 +01:00
page_frag_cache.c
page_idle.c
page_io.c mm: fix minor spelling mistakes in comments 2026-01-20 19:24:48 -08:00
page_isolation.c mm: page_isolation: introduce page_is_unmovable() 2026-01-31 14:22:42 -08:00
page_owner.c treewide: Replace kmalloc with kmalloc_obj for non-scalar types 2026-02-21 01:02:28 -08:00
page_poison.c
page_reporting.c Convert 'alloc_obj' family to use the new default GFP_KERNEL argument 2026-02-21 17:09:51 -08:00
page_reporting.h
page_table_check.c mm: provide address parameter to p{te,md,ud}_user_accessible_page() 2026-01-26 20:02:35 -08:00
page_vma_mapped.c
pagewalk.c mm/pagewalk: use min() to simplify the code 2026-01-31 14:22:52 -08:00
percpu-internal.h
percpu-km.c
percpu-stats.c
percpu-vm.c
percpu.c percpu: add double free check to pcpu_free_area() 2026-01-31 14:22:52 -08:00
pgalloc-track.h
pgtable-generic.c compiler-context-analysis: Remove __cond_lock() function-like helper 2026-01-05 16:43:33 +01:00
process_vm_access.c
ptdump.c
readahead.c mm.git review status for linus..mm-stable 2026-02-12 11:32:37 -08:00
rmap.c mm/rmap: clear vma->anon_vma on error 2026-03-21 17:36:33 -07:00
rodata_test.c
secretmem.c mm: update secretmem to use VMA flags on mmap_prepare 2026-02-12 15:42:58 -08:00
shmem.c Convert 'alloc_obj' family to use the new default GFP_KERNEL argument 2026-02-21 17:09:51 -08:00
shmem_quota.c treewide: Replace kmalloc with kmalloc_obj for non-scalar types 2026-02-21 01:02:28 -08:00
show_mem.c mm/vmscan: add tracepoint and reason for kswapd_failures reset 2026-01-31 14:22:38 -08:00
shrinker.c Convert 'alloc_obj' family to use the new default GFP_KERNEL argument 2026-02-21 17:09:51 -08:00
shrinker_debug.c memcg: rename mem_cgroup_ino() to mem_cgroup_id() 2026-01-26 20:02:25 -08:00
shuffle.c
shuffle.h
slab.h mm/slab: change stride type from unsigned short to unsigned int 2026-03-04 11:05:57 +01:00
slab_common.c Merge branch 'slab/for-7.0/sheaves' into slab/for-next 2026-02-10 09:10:00 +01:00
slub.c slab: fix memory leak when refill_sheaf() fails 2026-03-11 17:55:26 +01:00
sparse-vmemmap.c
sparse.c
swap.c mm: fix minor spelling mistakes in comments 2026-01-20 19:24:48 -08:00
swap.h mm, swap: drop the SWAP_HAS_CACHE flag 2026-01-31 14:22:57 -08:00
swap_cgroup.c
swap_state.c mm/swap: fix swap cache memcg accounting 2026-03-27 20:48:37 -07:00
swap_table.h
swapfile.c Convert more 'alloc_obj' cases to default GFP_KERNEL arguments 2026-02-21 20:03:00 -08:00
truncate.c
usercopy.c
userfaultfd.c mm, swap: check swap table directly for checking cache 2026-01-31 14:22:57 -08:00
util.c mm: make vm_area_desc utilise vma_flags_t only 2026-02-12 15:42:59 -08:00
vma.c mm: make vm_area_desc utilise vma_flags_t only 2026-02-12 15:42:59 -08:00
vma.h mm: make vm_area_desc utilise vma_flags_t only 2026-02-12 15:42:59 -08:00
vma_exec.c
vma_init.c
vma_internal.h mm: relocate the page table ceiling and floor definitions 2026-02-12 15:42:53 -08:00
vmalloc.c Convert 'alloc_obj' family to use the new default GFP_KERNEL argument 2026-02-21 17:09:51 -08:00
vmpressure.c Convert 'alloc_obj' family to use the new default GFP_KERNEL argument 2026-02-21 17:09:51 -08:00
vmscan.c treewide: Replace kmalloc with kmalloc_obj for non-scalar types 2026-02-21 01:02:28 -08:00
vmstat.c mm.git review status for linus..mm-stable 2026-02-12 11:32:37 -08:00
workingset.c memcg: introduce private id API for in-kernel users 2026-01-26 20:02:23 -08:00
zpdesc.h
zsmalloc.c Convert 'alloc_obj' family to use the new default GFP_KERNEL argument 2026-02-21 17:09:51 -08:00
zswap.c mm/zswap: add missing kunmap_local() 2026-03-23 09:35:05 -07:00