linux/mm
Link Lin 0b45f6927a mm/page_reporting: use system_freezable_wq to fix UAF during suspend
During PM freeze (e.g.  S3 suspend or S4 hibernation), device drivers like
virtio_balloon reset their underlying virtio devices and delete their
virtqueues via vdev->config->del_vqs().

However, page reporting work (page_reporting_process) was scheduled on the
global system_wq.  Because system_wq lacks the WQ_FREEZABLE flag, the PM
freezer skips it, leaving page_reporting_process active during suspend.

If pages are freed into the buddy allocator while suspending (for example,
when core MM invokes the balloon shrinker during S4 hibernation image
saving), page reporting triggers virtballoon_free_page_report() on deleted
virtqueues, resulting in a Use-After-Free / General Protection Fault:

    [  196.795226] general protection fault, probably for non-canonical address 0xaa1436fe70dae6df: 0000 [#1] SMP NOPTI
    [  196.825967] Workqueue: events page_reporting_process
    [  196.831038] RIP: 0010:virtqueue_add_split+0x233/0x4c0 [virtio_ring]
    [  196.927073] virtballoon_free_page_report+0x3a/0xe0 [virtio_balloon]
    [  196.946943] page_reporting_process+0x370/0x4f0

Fix this by switching page reporting work to system_freezable_wq.  This
ensures that the PM freezer pauses page_reporting_process before device
drivers destroy their reporting virtqueues.  Because the reporting worker
is frozen, memory reclamation/freeing (e.g.  via shrinker execution) can
safely return pages to MM during freeze without triggering unfrozen
reporting work on deleted virtqueues.

This aligns with the driver's existing design. The comment in
virtballoon_freeze() states:
    /*
     * The workqueue is already frozen by the PM core before this
     * function is called.
     */

Testing:
I have verified these fixes using Google’s virtualization infrastructure
by running continuous suspend/resume iterations (40+ cycles) while
churning memory using stress-ng (`stress-ng --vm 4 --vm-bytes 60%
--timeout 1`) to constantly create free pages for the buddy allocator.  We
also set the `page_reporting_order` parameter to 0 to make the page
reporting worker highly sensitive, forcing it to pick up any 4K free
pages.  This confirmed that the UAF crashes are no longer reproducible.

Link: https://lore.kernel.org/20260721005603.1710551-1-linkl@google.com
Fixes: 36e66c554b ("mm: introduce Reported pages")
Signed-off-by: Link Lin <linkl@google.com>
Suggested-by: David Hildenbrand (Arm) <david@kernel.org>
Suggested-by: Michael S. Tsirkin <mst@redhat.com>
Acked-by: David Rientjes <rientjes@google.com>
Acked-by: David Hildenbrand (Arm) <david@kernel.org>
Acked-by: Michael S. Tsirkin <mst@redhat.com>
Cc: Alexander Duyck <alexander.duyck@gmail.com>
Cc: Greg Thelen <gthelen@google.com>
Cc: James Houghton <jthoughton@google.com>
Cc: Jason Wang <jasowang@redhat.com>
Cc: Jiaqi Yan <jiaqiyan@google.com>
Cc: Vlastimil Babka <vbabka@kernel.org>
Cc: Xuan Zhuo <xuanzhuo@linux.alibaba.com>
Cc: <stable@vger.kernel.org>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
2026-07-28 17:37:33 -07:00
..
damon mm/damon/core: disallow overlapping input ranges for damon_set_regions() 2026-07-09 15:48:55 -07:00
kasan mm.git review status for mm-hotfixes-stable..mm-stable 2026-06-19 10:14:34 -07:00
kfence slab changes for 7.2 - part 2 2026-06-22 08:28:48 -07: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
backing-dev.c mm: blk-cgroup: fix use-after-free in cgwb_release_workfn() 2026-04-18 23:24:27 -07:00
balloon.c mm: rename CONFIG_BALLOON_COMPACTION to CONFIG_BALLOON_MIGRATION 2026-01-31 14:22:36 -08:00
bootmem_info.c mm/bootmem_info: stop marking mem_section_usage as MIX_SECTION_INFO 2026-06-02 15:22:11 -07:00
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_debug.c mm/cma_debug: fix invalid accesses for inactive CMA areas 2026-05-28 20:50:33 -07:00
cma_sysfs.c mm/cma_sysfs: skip inactive CMA areas in sysfs 2026-06-03 16:25:49 -07:00
cma.c mm/cma: fix reserved page leak on activation failure 2026-05-28 20:50:34 -07:00
cma.h mm: cma: set early_pfn and bitmap as a union in cma_memrange 2025-05-22 14:55:36 -07:00
compaction.c mm/compaction: handle free_pages_prepare() properly in compaction_free() 2026-07-01 19:02:53 -07:00
debug_page_alloc.c mm/debug_page_alloc: improve error message for invalid guardpage minorder 2025-05-12 23:50:38 -07:00
debug_page_ref.c
debug_vm_pgtable.c mm/debug_vm_pgtable: replace WRITE_ONCE() with pxd_clear() 2026-04-05 13:53:11 -07:00
debug.c mm: constify __dump_folio() arguments 2025-11-20 13:43:57 -08:00
dmapool_test.c Convert 'alloc_obj' family to use the new default GFP_KERNEL argument 2026-02-21 17:09:51 -08:00
dmapool.c docs: dma-api: replace consistent with coherent 2025-07-01 13:25:36 -06: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 mm/execmem: make the populate and alloc atomic 2026-04-05 13:53:34 -07:00
fadvise.c mm/fadvise: validate offset in generic_fadvise 2026-04-05 13:52:53 -07:00
fail_page_alloc.c fault-inject: improve build for CONFIG_FAULT_INJECTION=n 2024-09-01 20:43:33 -07:00
failslab.c fault-inject: improve build for CONFIG_FAULT_INJECTION=n 2024-09-01 20:43:33 -07:00
filemap.c mm: do file ownership checks with the proper mount idmap 2026-07-01 19:02:56 -07:00
folio-compat.c mm: add SPDX id lines to some mm source files 2026-02-06 15:47:16 -08:00
gup_test.c mm/gup_test: reject wrapped user ranges 2026-06-21 11:37:37 -07:00
gup_test.h
gup.c mm/gup: cleanup pgtable entry accessors 2026-05-28 21:04:41 -07:00
highmem.c mm/highmem: fix __kmap_to_page() build error 2026-01-31 14:22:38 -08:00
hmm.c driver core: Replace dev->dma_skip_sync with dev_dma_skip_sync() 2026-04-26 23:38:57 +02:00
huge_memory.c mm/huge_memory: unlock i_mmap_rwsem before releasing after-split folios 2026-07-28 17:37:32 -07: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: restrict hugetlb_cma parameter to gigantic-page alignment 2026-06-02 15:22:16 -07:00
hugetlb_cma.h mm: hugetlb: allocate frozen pages for gigantic allocation 2026-01-26 20:02:28 -08:00
hugetlb_internal.h mm/hugetlb: extract sysctl into hugetlb_sysctl.c 2025-11-20 13:43:57 -08:00
hugetlb_sysctl.c mm, hugetlb: implement movable_gigantic_pages sysctl 2026-01-20 19:24:50 -08:00
hugetlb_sysfs.c mm/hugetlb: extract sysfs into hugetlb_sysfs.c 2025-11-20 13:43:57 -08:00
hugetlb_vmemmap.c mm/hugetlb_vmemmap: fix incorrect vmemmap restore in rollback 2026-05-31 21:50:24 -07:00
hugetlb_vmemmap.h mm/hugetlb: do pre-HVO for bootmem allocated pages 2025-03-16 22:06:29 -07:00
hugetlb.c mm/hugetlb: fix list corruption in allocate_file_region_entries() 2026-07-20 17:41:28 -07:00
hwpoison-inject.c mm/hwpoison: decouple hwpoison_filter from mm/memory-failure.c 2025-09-21 14:22:21 -07:00
init-mm.c exec_state: relocate dumpable information 2026-05-26 11:02:01 +02:00
internal.h mm: switch deferred split shrinker to list_lru 2026-06-08 18:21:25 -07:00
interval_tree.c mm/memory: simplify calculation in unmap_mapping_range_tree() 2026-04-05 13:53:13 -07:00
ioremap.c mm/ioremap: pass pgprot_t to ioremap_prot() instead of unsigned long 2025-03-16 22:06:23 -07:00
Kconfig mm.git review status for linus..mm-stable 2026-06-23 12:03:44 -07:00
Kconfig.debug mm: kmemleak: add CONFIG_DEBUG_KMEMLEAK_VERBOSE build option 2026-04-18 00:10:48 -07:00
khugepaged.c mm/khugepaged: avoid underflow in madvise_collapse for sub-PMD MADV_COLLAPSE 2026-06-21 11:37:31 -07:00
kmemleak.c mm/kmemleak: fix checksum computation for per-cpu objects 2026-07-09 15:48:55 -07:00
ksm.c mm: convert do_brk_flags() to use vma_flags_t 2026-04-05 13:53:40 -07:00
list_lru.c mm.git review status for mm-hotfixes-stable..mm-stable 2026-06-19 10:14:34 -07:00
maccess.c mm: unexport globally copy_to_kernel_nofault 2025-07-09 22:42:22 -07:00
madvise.c mm: do file ownership checks with the proper mount idmap 2026-07-01 19:02:56 -07:00
Makefile mm/memcg: remove no longer used swap cgroup array 2026-06-02 15:22:23 -07:00
mapping_dirty_helpers.c mm/dirty: replace READ_ONCE() with pudp_get() 2025-11-16 17:27:58 -08:00
memblock.c kho: fix deferred initialization of scratch areas 2026-06-01 02:31:37 +03:00
memcontrol-v1.c mm/memcg: remove no longer used swap cgroup array 2026-06-02 15:22:23 -07:00
memcontrol-v1.h mm: memcg: initialize *locked in memcg1_oom_prepare() stub 2026-07-28 17:37:31 -07:00
memcontrol.c slab changes for 7.2 - part 2 2026-06-22 08:28:48 -07:00
memfd_luo.c mm/memfd_luo: document preservation of file seals 2026-05-04 14:03:16 +00:00
memfd.c memfd: deny writeable mappings when implying SEAL_WRITE 2026-05-21 19:06:11 -07:00
memory_hotplug.c drivers/base/memory: make memory block get/put explicit 2026-06-02 15:22:12 -07:00
memory-failure.c mm/memory-failure: use zone_pcp_disable() for poison handling 2026-06-02 15:22:33 -07:00
memory-tiers.c mm: introduce CONFIG_NUMA_MIGRATION and simplify CONFIG_MIGRATION 2026-04-05 13:53:33 -07:00
memory.c mm: use mapping_mapped to simplify the code 2026-06-21 11:37:38 -07:00
mempolicy.c mm/nodemask: correctly describe nodemask operation return types 2026-06-08 18:21:23 -07:00
mempool.c mm: simplify the mempool_alloc_bulk API 2026-06-03 18:20:47 +02:00
memremap.c mm: decrement MTHP_STAT_NR_ANON in free_zone_device_folio() 2026-07-28 17:37:31 -07:00
memtest.c mm/memtest: add underflow detection for size calculation 2026-01-09 11:53:51 +02:00
migrate_device.c mm: migrate_device: fix pte_pfn/pte_dirty called on non-present PTE 2026-07-20 17:41:27 -07:00
migrate.c mm/migrate: exclude hugetlb folios from MTHP_STAT_NR_ANON accounting 2026-07-28 17:37:31 -07:00
mincore.c mm: do file ownership checks with the proper mount idmap 2026-07-01 19:02:56 -07:00
mlock.c mm: rename unlock_page_lruvec_irq and its variants 2026-04-18 00:10:44 -07:00
mm_init.c mm/vmstat: fold stranded per-cpu node stats when a node comes online 2026-07-20 17:41:25 -07:00
mm_slot.h
mmap_lock.c mm/vma: improve and document __is_vma_write_locked() 2026-01-31 14:22:51 -08:00
mmap.c mm: fix mmap errno value when MAP_DROPPABLE is not supported 2026-05-28 21:04:48 -07:00
mmu_gather.c mm/mmu_gather: replace IPI with synchronize_rcu() when batch allocation fails 2026-04-05 13:53:05 -07:00
mmu_notifier.c mm.git review status for linus..mm-stable 2026-04-15 12:59:16 -07:00
mmzone.c mm: introduce memdesc_flags_t 2025-09-13 16:55:07 -07:00
mprotect.c mm/mprotect: special-case small folios when applying permissions 2026-04-18 00:10:55 -07:00
mremap.c mm: convert do_brk_flags() to use vma_flags_t 2026-04-05 13:53:40 -07:00
mseal.c mm/mseal: use min/max in mseal_apply 2026-06-02 15:22:15 -07:00
msync.c
nommu.c mm: abstract reading sysctl_max_map_count, and READ_ONCE() 2026-04-05 13:53:28 -07:00
numa_emulation.c mm/fake-numa: fix under-allocation detection in uniform split 2026-06-02 08:34:03 +03:00
numa_memblks.c memblock: numa_memblks: fix detection of NUMA node for CXL windows 2026-02-21 09:58:22 -08:00
numa.c mm/numa: remove unnecessary local variable in alloc_node_data() 2025-05-12 23:50:38 -07:00
oom_kill.c mm/oom_kill.c: simpilfy rcu call with guard(rcu) 2026-04-05 13:53:17 -07:00
page_alloc.c mm/page_alloc: only update NUMA min ratios on sysctl write 2026-06-21 11:31:29 -07:00
page_counter.c page_counter: track failcnt only for legacy cgroups 2025-03-17 00:05:35 -07:00
page_ext.c mm/page_ext: Add page_ext_get_from_phys() 2026-01-21 12:51:48 +01:00
page_frag_cache.c mm/page_alloc: export free_frozen_pages() instead of free_unref_page() 2025-01-13 22:40:31 -08:00
page_idle.c mm/page_idle.c: remove redundant mmu notifier in aging code 2026-04-05 13:53:02 -07:00
page_io.c block-7.2-20260625 2026-06-25 09:56:47 -07:00
page_isolation.c mm: page_isolation: avoid unsafe folio reads while scanning compound pages 2026-06-21 11:37:36 -07:00
page_owner.c mm/page_owner: fix %pGp format specifier argument type 2026-05-28 21:04:48 -07:00
page_poison.c
page_reporting.c mm/page_reporting: use system_freezable_wq to fix UAF during suspend 2026-07-28 17:37:33 -07:00
page_reporting.h
page_table_check.c mm/page_table_check: Pass mm_struct to pxx_user_accessible_page() 2026-03-13 00:07:47 +01:00
page_vma_mapped.c mm/page_vma_mapped: fix device-private PMD handling 2026-07-09 15:48:54 -07:00
page-writeback.c vfs-7.2-rc1.writeback 2026-06-15 03:30:45 +05:30
pagewalk.c mm/pagewalk: fix race between concurrent split and refault 2026-04-05 13:53:37 -07:00
percpu-internal.h mm/percpu-internal.h: optimise pcpu_chunk struct to save memory 2026-06-02 15:22:13 -07:00
percpu-km.c mm/percpu-km: fix bitmap overflow and accounting in pcpu_create_chunk() 2026-07-20 17:41:27 -07:00
percpu-stats.c mm: remove outdated filename comment in percpu-stats.c 2025-07-13 16:38:23 -07:00
percpu-vm.c kmsan: remove hard-coded GFP_KERNEL flags 2025-11-16 17:27:54 -08:00
percpu.c mm: memcontrol: return root object cgroup for root memory cgroup 2026-04-18 00:10:44 -07:00
pgalloc-track.h
pgtable-generic.c mm: change to return bool for pmdp_clear_flush_young() 2026-04-05 13:53:35 -07:00
process_vm_access.c mm: refactor mm_access() to not return NULL 2024-11-05 16:56:23 -08:00
ptdump.c mm/ptdump: replace READ_ONCE() with standard page table accessors 2025-11-16 17:27:52 -08:00
readahead.c Revert "mm: limit filemap_fault readahead to VMA boundaries" 2026-06-21 11:37:38 -07:00
rmap.c mm: remove page_mapped() 2026-05-28 21:04:57 -07:00
rodata_test.c mm/rodata_test: verify test data is unchanged, rather than non-zero 2025-01-13 22:40:38 -08:00
secretmem.c libfs: drop redundant SB_I_NOEXEC/SB_I_NODEV in init_pseudo() callers 2026-06-04 10:10:49 +02:00
shmem_quota.c treewide: Replace kmalloc with kmalloc_obj for non-scalar types 2026-02-21 01:02:28 -08:00
shmem.c fs: push nr_cached_objects memcg gating into individual filesystems 2026-07-23 11:35:02 +02:00
show_mem.c mm: add gpu active/reclaim per-node stat counters (v2) 2026-04-08 06:52:47 +10:00
shrinker_debug.c mm: shrinker: fix NULL pointer dereference in debugfs 2026-07-01 19:02:52 -07:00
shrinker.c mm: shrinker: fix shrinker_info teardown race with expansion 2026-07-01 19:02:52 -07:00
shuffle.c
shuffle.h
slab_common.c mm/slab: prevent unbounded recursion in free path with new kmalloc type 2026-07-14 17:22:40 +02:00
slab.h mm/slab: prevent unbounded recursion in free path with new kmalloc type 2026-07-14 17:22:40 +02:00
slub.c mm/slab: prevent unbounded recursion in free path with new kmalloc type 2026-07-14 17:22:40 +02:00
sparse-vmemmap.c mm/sparse-vmemmap: flush_cache_vmap() after hotplugging vmemmap 2026-07-13 11:29:52 -06:00
sparse.c mm/sparse: remove sparse buffer pre-allocation mechanism 2026-05-28 21:04:49 -07:00
swap_state.c mm: switch deferred split shrinker to list_lru 2026-06-08 18:21:25 -07:00
swap_table.h mm, swap: merge zeromap into swap table 2026-06-02 15:22:23 -07:00
swap.c mm/mglru: use folio_mark_accessed to replace folio_set_active 2026-06-04 14:45:02 -07:00
swap.h mm, swap: merge zeromap into swap table 2026-06-02 15:22:23 -07:00
swapfile.c mm/swap: remove redundant swap device reference in alloc/free 2026-06-08 18:21:32 -07:00
truncate.c mm/truncate: use folio_split() in truncate_inode_partial_folio() 2026-06-21 11:37:16 -07:00
usercopy.c usercopy: Remove folio references from check_heap_object() 2025-11-13 11:01:08 +01:00
userfaultfd.c userfaultfd: prevent registration of special VMAs 2026-07-09 15:48:53 -07:00
util.c mm/util: don't read __page_2 for order-1 folios in snapshot_page() 2026-07-20 17:41:27 -07:00
vma_exec.c mm: convert do_brk_flags() to use vma_flags_t 2026-04-05 13:53:40 -07:00
vma_init.c Summary of significant series in this pull request: 2025-10-02 18:18:33 -07:00
vma_internal.h mm: relocate the page table ceiling and floor definitions 2026-02-12 15:42:53 -08:00
vma.c drivers/char/mem: eliminate unnecessary use of success_hook 2026-06-04 14:44:59 -07:00
vma.h mm: allow handling of stacked mmap_prepare hooks in more drivers 2026-04-05 13:53:44 -07:00
vmalloc.c mm/vmalloc: free unused pages on vrealloc() shrink 2026-06-02 15:22:32 -07:00
vmpressure.c mm/vmpressure: skip socket pressure for costly order reclaim 2026-05-28 21:04:50 -07:00
vmscan.c mm: vmscan: abort proactive reclaim early when freezing for suspend 2026-07-28 17:37:33 -07:00
vmstat.c mm.git review status for linus..mm-stable 2026-04-19 08:01:17 -07:00
workingset.c mm/mglru: use folio_mark_accessed to replace folio_set_active 2026-06-04 14:45:02 -07:00
zpdesc.h mm: zpdesc: minor naming and comment corrections 2025-09-21 14:21:59 -07:00
zsmalloc.c zsmalloc: simplify data output in zs_stats_size_show() 2026-06-21 11:31:28 -07:00
zswap.c mm, swap: add support for stable large allocation in swap cache directly 2026-06-02 15:22:21 -07:00