[PATCH v2 0/2] virtio_balloon: fix Use-After-Free bugs during PM freeze

From: Link Lin

Date: Thu Jul 16 2026 - 20:24:49 EST


This patch series addresses a class of Use-After-Free vulnerabilities
in the virtio_balloon driver that can occur during system power management
freeze (e.g., suspend or hibernation).

The core issue is a lifecycle mismatch: when the system enters freeze,
virtballoon_freeze() resets the virtio device and deletes its virtqueues.
However, several asynchronous or event-driven components of the driver and
related subsystems (Free Page Reporting and Shrinker) remain registered
and active. If they trigger during the freeze/suspend process, they
attempt to access the now-deleted virtqueues, causing kernel crashes
(General Protection Faults or UAF).

To fix this:
1. Migrate Free Page Reporting to use the system_freezable_wq, ensuring
its worker is frozen before driver freeze callbacks run. (Suggested
by David Hildenbrand).
2. Avoid shrinker execution while the device is suspended by adding a
suspended flag to struct virtio_balloon. Wrap lockless reads of this
flag in READ_ONCE() and writes in WRITE_ONCE() to prevent data races and
KCSAN warnings.

Note: The OOM notifier (virtio_balloon_oom_notify) is also registered, but
since the PM core disables the OOM killer (via oom_killer_disable()) during
freeze_processes() before device drivers are frozen, it cannot trigger
while the device is frozen. Thus, it does not require a fix.

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.

RFC: https://lore.kernel.org/r/20260709224330.946683-1-linkl@xxxxxxxxxx
---
RFC -> v2:
- Switched page reporting fix from unregister/re-register in driver to
using system_freezable_wq in mm/page_reporting.c, which avoids complex
restore rollback logic for that component.
- Switched shrinker fix from unregister/re-register to using a simple
suspended boolean flag to avoid complex rollback logic. Wrap its reads
and writes with READ_ONCE()/WRITE_ONCE() to prevent KCSAN data race
warnings.
- Dropped OOM notifier fix since it's already protected by the PM core's
oom_killer_disable().

Link Lin (2):
mm/page_reporting: use system_freezable_wq to fix UAF during suspend
virtio_balloon: avoid shrinker execution during PM suspend

drivers/virtio/virtio_balloon.c | 49 +++++++++++++++++++++++++++------
mm/page_reporting.c | 6 ++--
2 files changed, 45 insertions(+), 10 deletions(-)
--
2.55.0.229.g6434b31f56-goog