The Linux Kernel Mailing List
 help / color / mirror / Atom feed
* [RFC] virtio_balloon: fix Use-After-Free in page reporting during PM freeze
@ 2026-07-09 22:43 Link Lin
  2026-07-09 23:12 ` Andrew Morton
  2026-07-14 13:17 ` David Hildenbrand (Arm)
  0 siblings, 2 replies; 10+ messages in thread
From: Link Lin @ 2026-07-09 22:43 UTC (permalink / raw)
  To: Andrew Morton, Vlastimil Babka, Michael S . Tsirkin,
	David Hildenbrand
  Cc: virtualization, linux-mm, linux-kernel, prasin, rientjes, duenwen,
	jasowang, xuanzhuo, Ammar Faizi, jiaqiyan, ahwilkins, Greg Thelen,
	Alexander Duyck, Link Lin, stable

During system power management freeze (e.g. ACPI S3 suspend or S4
hibernation), virtballoon_freeze() calls remove_common() to reset the
virtio device and delete all virtqueues via vdev->config->del_vqs().
However, unlike virtballoon_remove(), virtballoon_freeze() fails to call
page_reporting_unregister(&vb->pr_dev_info).

The comment in virtballoon_freeze() states:
    /*
     * The workqueue is already frozen by the PM core before this
     * function is called.
     */

While this comment was accurate in 2011 for balloon-internal workqueues
(such as balloon_wq, which was created with WQ_FREEZABLE and is paused
by the PM freezer), it is invalid for Free Page Reporting.

Free Page Reporting (mm/page_reporting.c) schedules its delayed work
(prdev->work) on the global system_wq. Because system_wq lacks the
WQ_FREEZABLE flag, the PM freezer (freeze_workqueues_busy()) explicitly
skips it. Consequently, page_reporting_process() on system_wq remains
active and unfrozen throughout device suspend.

If memory is freed into the buddy allocator or a delayed work timer
expires while the device is being frozen, page_reporting_process() fires
on system_wq and calls virtballoon_free_page_report(). This function
passes vb->reporting_vq into virtqueue_add_inbuf() / virtqueue_add_split().
Because the virtqueues were already destroyed by del_vqs(), this results
in a Use-After-Free / General Protection Fault:

    [  250.709271] general protection fault, probably for non-canonical address 0x7f728084daf08d5e: 0000 [#1] SMP PTI
    [  250.732967] CPU: 2 PID: 38 Comm: kworker/2:1 Not tainted 5.10.0-44-cloud-amd64 #1 Debian 5.10.257-1
    [  250.751575] Workqueue: events page_reporting_process
    [  250.756665] RIP: 0010:virtqueue_add_split+0x233/0x4c0 [virtio_ring]
    ...
    [  250.867678] virtballoon_free_page_report+0x3a/0xe0 [virtio_balloon]
    [  250.883446] page_reporting_process+0x225/0x4f0

(Note: The OOM Notifier and Shrinker/Free Page Hinting features suffer
from an identical lifecycle flaw and are also vulnerable to UAFs during
S4 hibernation when memory pressure spikes. This patch focuses on Free
Page Reporting, which runs periodically, to ensure clean backports to
stable kernels).

Fix this by:
1. Unregistering page reporting in virtballoon_freeze() prior to calling
   remove_common(). This clears the RCU pr_dev_info pointer and flushes/
   cancels prdev->work on system_wq via cancel_delayed_work_sync().
2. Re-registering page reporting in virtballoon_restore() after the
   virtqueues are re-initialized and virtio_device_ready() has been called.
3. Unwinding virtqueue initialization via remove_common() in 
   virtballoon_restore() if page_reporting_register() fails.

Fixes: 924a663f75e2 ("virtio-balloon: Reporting free page reservations")
Cc: stable@vger.kernel.org
Cc: jasowang@redhat.com
Cc: xuanzhuo@linux.alibaba.com
Cc: Ammar Faizi <ammarfaizi2@openresty.com>
Cc: jiaqiyan@google.com
Cc: ahwilkins@google.com
Cc: Greg Thelen <gthelen@google.com>
Cc: Alexander Duyck <alexander.duyck@gmail.com>
Signed-off-by: Link Lin <linkl@google.com>
---
 drivers/virtio/virtio_balloon.c | 11 +++++++++++
 1 file changed, 11 insertions(+)

diff --git a/drivers/virtio/virtio_balloon.c b/drivers/virtio/virtio_balloon.c
index a1b2c3d4e5f6..45a90fb3abf8 100640
--- a/drivers/virtio/virtio_balloon.c
+++ b/drivers/virtio/virtio_balloon.c
@@ -1055,6 +1055,9 @@ static int virtballoon_freeze(struct virtio_device *vdev)
 	 * The workqueue is already frozen by the PM core before this
 	 * function is called.
 	 */
+	if (virtio_has_feature(vb->vdev, VIRTIO_BALLOON_F_REPORTING))
+		page_reporting_unregister(&vb->pr_dev_info);
+
 	remove_common(vb);
 	return 0;
 }
 
 static int virtballoon_restore(struct virtio_device *vdev)
 {
 	struct virtio_balloon *vb = vdev->priv;
 	int ret;
 
 	ret = init_vqs(vdev->priv);
 	if (ret)
 		return ret;
 
 	virtio_device_ready(vdev);
 
+	if (virtio_has_feature(vb->vdev, VIRTIO_BALLOON_F_REPORTING)) {
+		ret = page_reporting_register(&vb->pr_dev_info);
+		if (ret)
+			goto out_remove_vqs;
+	}
+
 	if (towards_target(vb))
 		virtballoon_changed(vdev);
 	update_balloon_size(vb);
 	return 0;
+
+out_remove_vqs:
+	remove_common(vb);
+	return ret;
 }
-- 
2.45.0

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

* Re: [RFC] virtio_balloon: fix Use-After-Free in page reporting during PM freeze
  2026-07-09 22:43 [RFC] virtio_balloon: fix Use-After-Free in page reporting during PM freeze Link Lin
@ 2026-07-09 23:12 ` Andrew Morton
  2026-07-10  0:45   ` Link Lin
  2026-07-14 13:17 ` David Hildenbrand (Arm)
  1 sibling, 1 reply; 10+ messages in thread
From: Andrew Morton @ 2026-07-09 23:12 UTC (permalink / raw)
  To: Link Lin
  Cc: Vlastimil Babka, Michael S . Tsirkin, David Hildenbrand,
	virtualization, linux-mm, linux-kernel, prasin, rientjes, duenwen,
	jasowang, xuanzhuo, Ammar Faizi, jiaqiyan, ahwilkins, Greg Thelen,
	Alexander Duyck, stable

On Thu,  9 Jul 2026 22:43:30 +0000 Link Lin <linkl@google.com> wrote:

> During system power management freeze (e.g. ACPI S3 suspend or S4
> hibernation), virtballoon_freeze() calls remove_common() to reset the
> virtio device and delete all virtqueues via vdev->config->del_vqs().
> However, unlike virtballoon_remove(), virtballoon_freeze() fails to call
> page_reporting_unregister(&vb->pr_dev_info).
> 
> ...
>
> If memory is freed into the buddy allocator or a delayed work timer
> expires while the device is being frozen, page_reporting_process() fires
> on system_wq and calls virtballoon_free_page_report(). This function
> passes vb->reporting_vq into virtqueue_add_inbuf() / virtqueue_add_split().
> Because the virtqueues were already destroyed by del_vqs(), this results
> in a Use-After-Free / General Protection Fault:
> 
>     [  250.709271] general protection fault, probably for non-canonical address 0x7f728084daf08d5e: 0000 [#1] SMP PTI
>     [  250.732967] CPU: 2 PID: 38 Comm: kworker/2:1 Not tainted 5.10.0-44-cloud-amd64 #1 Debian 5.10.257-1
>     [  250.751575] Workqueue: events page_reporting_process
>     [  250.756665] RIP: 0010:virtqueue_add_split+0x233/0x4c0 [virtio_ring]
>     ...
>     [  250.867678] virtballoon_free_page_report+0x3a/0xe0 [virtio_balloon]
>     [  250.883446] page_reporting_process+0x225/0x4f0

whoops

> Fix this by:
> 1. Unregistering page reporting in virtballoon_freeze() prior to calling
>    remove_common(). This clears the RCU pr_dev_info pointer and flushes/
>    cancels prdev->work on system_wq via cancel_delayed_work_sync().
> 2. Re-registering page reporting in virtballoon_restore() after the
>    virtqueues are re-initialized and virtio_device_ready() has been called.
> 3. Unwinding virtqueue initialization via remove_common() in 
>    virtballoon_restore() if page_reporting_register() fails.

AI review thinks the patch didn't do the above:
	https://sashiko.dev/#/patchset/20260709224330.946683-1-linkl@google.com

It also might have found a couple of pre-existing bugs in there.

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

* Re: [RFC] virtio_balloon: fix Use-After-Free in page reporting during PM freeze
  2026-07-09 23:12 ` Andrew Morton
@ 2026-07-10  0:45   ` Link Lin
  2026-07-13 19:41     ` David Rientjes
  0 siblings, 1 reply; 10+ messages in thread
From: Link Lin @ 2026-07-10  0:45 UTC (permalink / raw)
  To: Andrew Morton
  Cc: Vlastimil Babka, Michael S . Tsirkin, David Hildenbrand,
	virtualization, linux-mm, linux-kernel, prasin, rientjes, duenwen,
	jasowang, xuanzhuo, Ammar Faizi, jiaqiyan, ahwilkins, Greg Thelen,
	Alexander Duyck, stable

On Thu, 9 Jul 2026 at 16:12, Andrew Morton <akpm@linux-foundation.org> wrote:
>
> On Thu,  9 Jul 2026 22:43:30 +0000 Link Lin <linkl@google.com> wrote:
>
> > Fix this by:
> > 1. Unregistering page reporting in virtballoon_freeze() prior to calling
> >    remove_common(). This clears the RCU pr_dev_info pointer and flushes/
> >    cancels prdev->work on system_wq via cancel_delayed_work_sync().
> > 2. Re-registering page reporting in virtballoon_restore() after the
> >    virtqueues are re-initialized and virtio_device_ready() has been called.
> > 3. Unwinding virtqueue initialization via remove_common() in
> >    virtballoon_restore() if page_reporting_register() fails.
>
> AI review thinks the patch didn't do the above:
>         https://sashiko.dev/#/patchset/20260709224330.946683-1-linkl@google.com

The AI reviewer might not have parsed the entirety of the fix I proposed.
The patch submitted definitely includes the changes to virtballoon_restore()
for steps 2 and 3 (re-registering page reporting and unwinding init_vqs
on failure). It seems the AI failed to parse the diff correctly. See:

+       if (virtio_has_feature(vb->vdev, VIRTIO_BALLOON_F_REPORTING)) {
+               ret = page_reporting_register(&vb->pr_dev_info);
+               if (ret)
+                       goto out_remove_vqs;
+       }
+
        if (towards_target(vb))
                virtballoon_changed(vdev);
        update_balloon_size(vb);
        return 0;
+
+out_remove_vqs:
+       remove_common(vb);
+       return ret;
 }

> It also might have found a couple of pre-existing bugs in there.

Indeed. Regarding the first pre-existing bug found by the AI (leaving the
OOM notifier registered during suspend, leading to a UAF if memory pressure
spikes during S4 hibernation):

I actually addressed this in the commit message:

  "(Note: The OOM Notifier and Shrinker/Free Page Hinting features suffer
  from an identical lifecycle flaw and are also vulnerable to UAFs during
  S4 hibernation when memory pressure spikes. This patch focuses on Free
  Page Reporting, which runs periodically, to ensure clean backports to
  stable kernels)."

Regarding the second pre-existing bug the AI flagged (leaving uncancelled
works on system_freezable_wq if virtballoon_restore fails on the cold path):
the AI is correct that this asynchronous work cancellation failure exists.

Since these are separate, pre-existing lifecycle bugs, would you prefer I
roll fixes for the OOM notifier, shrinker/free page hinting, and work
cancellations into a v2 of this patch, or submit them as a separate patch
series to keep the stable backports clean?

Thanks,
Link

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

* Re: [RFC] virtio_balloon: fix Use-After-Free in page reporting during PM freeze
  2026-07-10  0:45   ` Link Lin
@ 2026-07-13 19:41     ` David Rientjes
  2026-07-13 19:43       ` Michael S. Tsirkin
  0 siblings, 1 reply; 10+ messages in thread
From: David Rientjes @ 2026-07-13 19:41 UTC (permalink / raw)
  To: Link Lin
  Cc: Andrew Morton, Vlastimil Babka, Michael S . Tsirkin,
	David Hildenbrand, virtualization, linux-mm, linux-kernel, prasin,
	duenwen, jasowang, xuanzhuo, Ammar Faizi, jiaqiyan, ahwilkins,
	Greg Thelen, Alexander Duyck, stable

On Thu, 9 Jul 2026, Link Lin wrote:

> > > Fix this by:
> > > 1. Unregistering page reporting in virtballoon_freeze() prior to calling
> > >    remove_common(). This clears the RCU pr_dev_info pointer and flushes/
> > >    cancels prdev->work on system_wq via cancel_delayed_work_sync().
> > > 2. Re-registering page reporting in virtballoon_restore() after the
> > >    virtqueues are re-initialized and virtio_device_ready() has been called.
> > > 3. Unwinding virtqueue initialization via remove_common() in
> > >    virtballoon_restore() if page_reporting_register() fails.
> >
> > AI review thinks the patch didn't do the above:
> >         https://sashiko.dev/#/patchset/20260709224330.946683-1-linkl@google.com
> 
> The AI reviewer might not have parsed the entirety of the fix I proposed.
> The patch submitted definitely includes the changes to virtballoon_restore()
> for steps 2 and 3 (re-registering page reporting and unwinding init_vqs
> on failure). It seems the AI failed to parse the diff correctly. See:
> 
> +       if (virtio_has_feature(vb->vdev, VIRTIO_BALLOON_F_REPORTING)) {
> +               ret = page_reporting_register(&vb->pr_dev_info);
> +               if (ret)
> +                       goto out_remove_vqs;
> +       }
> +
>         if (towards_target(vb))
>                 virtballoon_changed(vdev);
>         update_balloon_size(vb);
>         return 0;
> +
> +out_remove_vqs:
> +       remove_common(vb);
> +       return ret;
>  }
> 
> > It also might have found a couple of pre-existing bugs in there.
> 
> Indeed. Regarding the first pre-existing bug found by the AI (leaving the
> OOM notifier registered during suspend, leading to a UAF if memory pressure
> spikes during S4 hibernation):
> 
> I actually addressed this in the commit message:
> 
>   "(Note: The OOM Notifier and Shrinker/Free Page Hinting features suffer
>   from an identical lifecycle flaw and are also vulnerable to UAFs during
>   S4 hibernation when memory pressure spikes. This patch focuses on Free
>   Page Reporting, which runs periodically, to ensure clean backports to
>   stable kernels)."
> 
> Regarding the second pre-existing bug the AI flagged (leaving uncancelled
> works on system_freezable_wq if virtballoon_restore fails on the cold path):
> the AI is correct that this asynchronous work cancellation failure exists.
> 
> Since these are separate, pre-existing lifecycle bugs, would you prefer I
> roll fixes for the OOM notifier, shrinker/free page hinting, and work
> cancellations into a v2 of this patch, or submit them as a separate patch
> series to keep the stable backports clean?
> 

I think it would be best to have separate patches for each fix; Andrew, 
please correct me if you'd prefer one patch to address everything.

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

* Re: [RFC] virtio_balloon: fix Use-After-Free in page reporting during PM freeze
  2026-07-13 19:41     ` David Rientjes
@ 2026-07-13 19:43       ` Michael S. Tsirkin
  0 siblings, 0 replies; 10+ messages in thread
From: Michael S. Tsirkin @ 2026-07-13 19:43 UTC (permalink / raw)
  To: David Rientjes
  Cc: Link Lin, Andrew Morton, Vlastimil Babka, David Hildenbrand,
	virtualization, linux-mm, linux-kernel, prasin, duenwen, jasowang,
	xuanzhuo, Ammar Faizi, jiaqiyan, ahwilkins, Greg Thelen,
	Alexander Duyck, stable

On Mon, Jul 13, 2026 at 12:41:07PM -0700, David Rientjes wrote:
> On Thu, 9 Jul 2026, Link Lin wrote:
> 
> > > > Fix this by:
> > > > 1. Unregistering page reporting in virtballoon_freeze() prior to calling
> > > >    remove_common(). This clears the RCU pr_dev_info pointer and flushes/
> > > >    cancels prdev->work on system_wq via cancel_delayed_work_sync().
> > > > 2. Re-registering page reporting in virtballoon_restore() after the
> > > >    virtqueues are re-initialized and virtio_device_ready() has been called.
> > > > 3. Unwinding virtqueue initialization via remove_common() in
> > > >    virtballoon_restore() if page_reporting_register() fails.
> > >
> > > AI review thinks the patch didn't do the above:
> > >         https://sashiko.dev/#/patchset/20260709224330.946683-1-linkl@google.com
> > 
> > The AI reviewer might not have parsed the entirety of the fix I proposed.
> > The patch submitted definitely includes the changes to virtballoon_restore()
> > for steps 2 and 3 (re-registering page reporting and unwinding init_vqs
> > on failure). It seems the AI failed to parse the diff correctly. See:
> > 
> > +       if (virtio_has_feature(vb->vdev, VIRTIO_BALLOON_F_REPORTING)) {
> > +               ret = page_reporting_register(&vb->pr_dev_info);
> > +               if (ret)
> > +                       goto out_remove_vqs;
> > +       }
> > +
> >         if (towards_target(vb))
> >                 virtballoon_changed(vdev);
> >         update_balloon_size(vb);
> >         return 0;
> > +
> > +out_remove_vqs:
> > +       remove_common(vb);
> > +       return ret;
> >  }
> > 
> > > It also might have found a couple of pre-existing bugs in there.
> > 
> > Indeed. Regarding the first pre-existing bug found by the AI (leaving the
> > OOM notifier registered during suspend, leading to a UAF if memory pressure
> > spikes during S4 hibernation):
> > 
> > I actually addressed this in the commit message:
> > 
> >   "(Note: The OOM Notifier and Shrinker/Free Page Hinting features suffer
> >   from an identical lifecycle flaw and are also vulnerable to UAFs during
> >   S4 hibernation when memory pressure spikes. This patch focuses on Free
> >   Page Reporting, which runs periodically, to ensure clean backports to
> >   stable kernels)."
> > 
> > Regarding the second pre-existing bug the AI flagged (leaving uncancelled
> > works on system_freezable_wq if virtballoon_restore fails on the cold path):
> > the AI is correct that this asynchronous work cancellation failure exists.
> > 
> > Since these are separate, pre-existing lifecycle bugs, would you prefer I
> > roll fixes for the OOM notifier, shrinker/free page hinting, and work
> > cancellations into a v2 of this patch, or submit them as a separate patch
> > series to keep the stable backports clean?
> > 
> 
> I think it would be best to have separate patches for each fix; Andrew, 
> please correct me if you'd prefer one patch to address everything.

It does not matter much but yes separate ones are a bit better if
each can be applied independently.


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

* Re: [RFC] virtio_balloon: fix Use-After-Free in page reporting during PM freeze
  2026-07-09 22:43 [RFC] virtio_balloon: fix Use-After-Free in page reporting during PM freeze Link Lin
  2026-07-09 23:12 ` Andrew Morton
@ 2026-07-14 13:17 ` David Hildenbrand (Arm)
  2026-07-14 13:24   ` Michael S. Tsirkin
  1 sibling, 1 reply; 10+ messages in thread
From: David Hildenbrand (Arm) @ 2026-07-14 13:17 UTC (permalink / raw)
  To: Link Lin, Andrew Morton, Vlastimil Babka, Michael S . Tsirkin
  Cc: virtualization, linux-mm, linux-kernel, prasin, rientjes, duenwen,
	jasowang, xuanzhuo, Ammar Faizi, jiaqiyan, ahwilkins, Greg Thelen,
	Alexander Duyck, stable

On 7/10/26 00:43, Link Lin wrote:
> During system power management freeze (e.g. ACPI S3 suspend or S4
> hibernation), virtballoon_freeze() calls remove_common() to reset the
> virtio device and delete all virtqueues via vdev->config->del_vqs().
> However, unlike virtballoon_remove(), virtballoon_freeze() fails to call
> page_reporting_unregister(&vb->pr_dev_info).
> 
> The comment in virtballoon_freeze() states:
>     /*
>      * The workqueue is already frozen by the PM core before this
>      * function is called.
>      */
> 
> While this comment was accurate in 2011 for balloon-internal workqueues
> (such as balloon_wq, which was created with WQ_FREEZABLE and is paused
> by the PM freezer), it is invalid for Free Page Reporting.
> 
> Free Page Reporting (mm/page_reporting.c) schedules its delayed work
> (prdev->work) on the global system_wq. Because system_wq lacks the
> WQ_FREEZABLE flag, the PM freezer (freeze_workqueues_busy()) explicitly
> skips it. Consequently, page_reporting_process() on system_wq remains
> active and unfrozen throughout device suspend.
> 
> If memory is freed into the buddy allocator or a delayed work timer
> expires while the device is being frozen, page_reporting_process() fires
> on system_wq and calls virtballoon_free_page_report(). This function
> passes vb->reporting_vq into virtqueue_add_inbuf() / virtqueue_add_split().
> Because the virtqueues were already destroyed by del_vqs(), this results
> in a Use-After-Free / General Protection Fault:
> 
>     [  250.709271] general protection fault, probably for non-canonical address 0x7f728084daf08d5e: 0000 [#1] SMP PTI
>     [  250.732967] CPU: 2 PID: 38 Comm: kworker/2:1 Not tainted 5.10.0-44-cloud-amd64 #1 Debian 5.10.257-1
>     [  250.751575] Workqueue: events page_reporting_process
>     [  250.756665] RIP: 0010:virtqueue_add_split+0x233/0x4c0 [virtio_ring]
>     ...
>     [  250.867678] virtballoon_free_page_report+0x3a/0xe0 [virtio_balloon]
>     [  250.883446] page_reporting_process+0x225/0x4f0
> 
> (Note: The OOM Notifier and Shrinker/Free Page Hinting features suffer
> from an identical lifecycle flaw and are also vulnerable to UAFs during
> S4 hibernation when memory pressure spikes. This patch focuses on Free
> Page Reporting, which runs periodically, to ensure clean backports to
> stable kernels).
> 
> Fix this by:
> 1. Unregistering page reporting in virtballoon_freeze() prior to calling
>    remove_common(). This clears the RCU pr_dev_info pointer and flushes/
>    cancels prdev->work on system_wq via cancel_delayed_work_sync().
> 2. Re-registering page reporting in virtballoon_restore() after the
>    virtqueues are re-initialized and virtio_device_ready() has been called.
> 3. Unwinding virtqueue initialization via remove_common() in 
>    virtballoon_restore() if page_reporting_register() fails.
> 
> Fixes: 924a663f75e2 ("virtio-balloon: Reporting free page reservations")
> Cc: stable@vger.kernel.org
> Cc: jasowang@redhat.com
> Cc: xuanzhuo@linux.alibaba.com
> Cc: Ammar Faizi <ammarfaizi2@openresty.com>
> Cc: jiaqiyan@google.com
> Cc: ahwilkins@google.com
> Cc: Greg Thelen <gthelen@google.com>
> Cc: Alexander Duyck <alexander.duyck@gmail.com>
> Signed-off-by: Link Lin <linkl@google.com>
> ---
>  drivers/virtio/virtio_balloon.c | 11 +++++++++++
>  1 file changed, 11 insertions(+)
> 
> diff --git a/drivers/virtio/virtio_balloon.c b/drivers/virtio/virtio_balloon.c
> index a1b2c3d4e5f6..45a90fb3abf8 100640
> --- a/drivers/virtio/virtio_balloon.c
> +++ b/drivers/virtio/virtio_balloon.c
> @@ -1055,6 +1055,9 @@ static int virtballoon_freeze(struct virtio_device *vdev)
>  	 * The workqueue is already frozen by the PM core before this
>  	 * function is called.
>  	 */
> +	if (virtio_has_feature(vb->vdev, VIRTIO_BALLOON_F_REPORTING))
> +		page_reporting_unregister(&vb->pr_dev_info);
> +
>  	remove_common(vb);
>  	return 0;
>  }
>  
>  static int virtballoon_restore(struct virtio_device *vdev)
>  {
>  	struct virtio_balloon *vb = vdev->priv;
>  	int ret;
>  
>  	ret = init_vqs(vdev->priv);
>  	if (ret)
>  		return ret;
>  
>  	virtio_device_ready(vdev);
>  
> +	if (virtio_has_feature(vb->vdev, VIRTIO_BALLOON_F_REPORTING)) {
> +		ret = page_reporting_register(&vb->pr_dev_info);
> +		if (ret)
> +			goto out_remove_vqs;
> +	}

Hm, that failure handling is rather nasty.


In virtballoon_freeze() we document:

"The workqueue is already frozen by the PM core before this function is called"

Your report states:

"Workqueue: events page_reporting_process"


I assume that workqueue is not frozen yet because ... it's not freezable :)

So could we queue to system_freezable_wq instead, or define our own freezable
workqueue there? Then a driver doesn't have to worry about that.

-- 
Cheers,

David

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

* Re: [RFC] virtio_balloon: fix Use-After-Free in page reporting during PM freeze
  2026-07-14 13:17 ` David Hildenbrand (Arm)
@ 2026-07-14 13:24   ` Michael S. Tsirkin
  2026-07-14 18:05     ` Link Lin
  2026-07-14 18:21     ` David Rientjes
  0 siblings, 2 replies; 10+ messages in thread
From: Michael S. Tsirkin @ 2026-07-14 13:24 UTC (permalink / raw)
  To: David Hildenbrand (Arm)
  Cc: Link Lin, Andrew Morton, Vlastimil Babka, virtualization,
	linux-mm, linux-kernel, prasin, rientjes, duenwen, jasowang,
	xuanzhuo, Ammar Faizi, jiaqiyan, ahwilkins, Greg Thelen,
	Alexander Duyck, stable

On Tue, Jul 14, 2026 at 03:17:42PM +0200, David Hildenbrand (Arm) wrote:
> On 7/10/26 00:43, Link Lin wrote:
> > During system power management freeze (e.g. ACPI S3 suspend or S4
> > hibernation), virtballoon_freeze() calls remove_common() to reset the
> > virtio device and delete all virtqueues via vdev->config->del_vqs().
> > However, unlike virtballoon_remove(), virtballoon_freeze() fails to call
> > page_reporting_unregister(&vb->pr_dev_info).
> > 
> > The comment in virtballoon_freeze() states:
> >     /*
> >      * The workqueue is already frozen by the PM core before this
> >      * function is called.
> >      */
> > 
> > While this comment was accurate in 2011 for balloon-internal workqueues
> > (such as balloon_wq, which was created with WQ_FREEZABLE and is paused
> > by the PM freezer), it is invalid for Free Page Reporting.
> > 
> > Free Page Reporting (mm/page_reporting.c) schedules its delayed work
> > (prdev->work) on the global system_wq. Because system_wq lacks the
> > WQ_FREEZABLE flag, the PM freezer (freeze_workqueues_busy()) explicitly
> > skips it. Consequently, page_reporting_process() on system_wq remains
> > active and unfrozen throughout device suspend.
> > 
> > If memory is freed into the buddy allocator or a delayed work timer
> > expires while the device is being frozen, page_reporting_process() fires
> > on system_wq and calls virtballoon_free_page_report(). This function
> > passes vb->reporting_vq into virtqueue_add_inbuf() / virtqueue_add_split().
> > Because the virtqueues were already destroyed by del_vqs(), this results
> > in a Use-After-Free / General Protection Fault:
> > 
> >     [  250.709271] general protection fault, probably for non-canonical address 0x7f728084daf08d5e: 0000 [#1] SMP PTI
> >     [  250.732967] CPU: 2 PID: 38 Comm: kworker/2:1 Not tainted 5.10.0-44-cloud-amd64 #1 Debian 5.10.257-1
> >     [  250.751575] Workqueue: events page_reporting_process
> >     [  250.756665] RIP: 0010:virtqueue_add_split+0x233/0x4c0 [virtio_ring]
> >     ...
> >     [  250.867678] virtballoon_free_page_report+0x3a/0xe0 [virtio_balloon]
> >     [  250.883446] page_reporting_process+0x225/0x4f0
> > 
> > (Note: The OOM Notifier and Shrinker/Free Page Hinting features suffer
> > from an identical lifecycle flaw and are also vulnerable to UAFs during
> > S4 hibernation when memory pressure spikes. This patch focuses on Free
> > Page Reporting, which runs periodically, to ensure clean backports to
> > stable kernels).
> > 
> > Fix this by:
> > 1. Unregistering page reporting in virtballoon_freeze() prior to calling
> >    remove_common(). This clears the RCU pr_dev_info pointer and flushes/
> >    cancels prdev->work on system_wq via cancel_delayed_work_sync().
> > 2. Re-registering page reporting in virtballoon_restore() after the
> >    virtqueues are re-initialized and virtio_device_ready() has been called.
> > 3. Unwinding virtqueue initialization via remove_common() in 
> >    virtballoon_restore() if page_reporting_register() fails.
> > 
> > Fixes: 924a663f75e2 ("virtio-balloon: Reporting free page reservations")
> > Cc: stable@vger.kernel.org
> > Cc: jasowang@redhat.com
> > Cc: xuanzhuo@linux.alibaba.com
> > Cc: Ammar Faizi <ammarfaizi2@openresty.com>
> > Cc: jiaqiyan@google.com
> > Cc: ahwilkins@google.com
> > Cc: Greg Thelen <gthelen@google.com>
> > Cc: Alexander Duyck <alexander.duyck@gmail.com>
> > Signed-off-by: Link Lin <linkl@google.com>
> > ---
> >  drivers/virtio/virtio_balloon.c | 11 +++++++++++
> >  1 file changed, 11 insertions(+)
> > 
> > diff --git a/drivers/virtio/virtio_balloon.c b/drivers/virtio/virtio_balloon.c
> > index a1b2c3d4e5f6..45a90fb3abf8 100640
> > --- a/drivers/virtio/virtio_balloon.c
> > +++ b/drivers/virtio/virtio_balloon.c
> > @@ -1055,6 +1055,9 @@ static int virtballoon_freeze(struct virtio_device *vdev)
> >  	 * The workqueue is already frozen by the PM core before this
> >  	 * function is called.
> >  	 */
> > +	if (virtio_has_feature(vb->vdev, VIRTIO_BALLOON_F_REPORTING))
> > +		page_reporting_unregister(&vb->pr_dev_info);
> > +
> >  	remove_common(vb);
> >  	return 0;
> >  }
> >  
> >  static int virtballoon_restore(struct virtio_device *vdev)
> >  {
> >  	struct virtio_balloon *vb = vdev->priv;
> >  	int ret;
> >  
> >  	ret = init_vqs(vdev->priv);
> >  	if (ret)
> >  		return ret;
> >  
> >  	virtio_device_ready(vdev);
> >  
> > +	if (virtio_has_feature(vb->vdev, VIRTIO_BALLOON_F_REPORTING)) {
> > +		ret = page_reporting_register(&vb->pr_dev_info);
> > +		if (ret)
> > +			goto out_remove_vqs;
> > +	}
> 
> Hm, that failure handling is rather nasty.
> 
> 
> In virtballoon_freeze() we document:
> 
> "The workqueue is already frozen by the PM core before this function is called"
> 
> Your report states:
> 
> "Workqueue: events page_reporting_process"
> 
> 
> I assume that workqueue is not frozen yet because ... it's not freezable :)
> 
> So could we queue to system_freezable_wq instead, or define our own freezable
> workqueue there? Then a driver doesn't have to worry about that.
> 
> -- 
> Cheers,
> 
> David

+1.  Just system_freezable_wq will do the trick.

-- 
MST


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

* Re: [RFC] virtio_balloon: fix Use-After-Free in page reporting during PM freeze
  2026-07-14 13:24   ` Michael S. Tsirkin
@ 2026-07-14 18:05     ` Link Lin
  2026-07-14 18:21     ` David Rientjes
  1 sibling, 0 replies; 10+ messages in thread
From: Link Lin @ 2026-07-14 18:05 UTC (permalink / raw)
  To: Michael S. Tsirkin
  Cc: David Hildenbrand (Arm), Andrew Morton, Vlastimil Babka,
	virtualization, linux-mm, linux-kernel, prasin, rientjes, duenwen,
	jasowang, xuanzhuo, Ammar Faizi, jiaqiyan, ahwilkins, Greg Thelen,
	Alexander Duyck, stable

On Mon, Jul 13, 2026 at 6:17 AM David Hildenbrand wrote:
> I assume that workqueue is not frozen yet because ... it's not freezable :)
> So could we queue to system_freezable_wq instead, or define our own freezable
> workqueue there? Then a driver doesn't have to worry about that.

Exactly. As noted in the RFC, the root cause is indeed that system_wq
lacks the WQ_FREEZABLE flag, leaving it active during suspend.

Switching the worker over to system_freezable_wq is a brilliant idea.
It's a much cleaner abstraction that solves the problem at the core,
saving individual drivers from having to micromanage this lifecycle
and handle failure unwinding during freeze/restore.

On Mon, Jul 13, 2026 at 6:26 AM Michael S. Tsirkin wrote:
> +1.  Just system_freezable_wq will do the trick.

Thanks, David and Michael. I will drop the virtio-balloon specific
unregister logic and adopt this approach.

Per the earlier feedback to keep these fixes independent, I'll format
v2 as a 3-part patch series:
  [PATCH v2 1/3] mm/page_reporting: use system_freezable_wq
  [PATCH v2 2/3] virtio_balloon: fix shrinker UAF during PM freeze
  [PATCH v2 3/3] virtio_balloon: fix OOM notifier UAF during PM freeze

I'll send that out shortly.

Thanks,
Link

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

* Re: [RFC] virtio_balloon: fix Use-After-Free in page reporting during PM freeze
  2026-07-14 13:24   ` Michael S. Tsirkin
  2026-07-14 18:05     ` Link Lin
@ 2026-07-14 18:21     ` David Rientjes
  2026-07-14 18:52       ` Michael S. Tsirkin
  1 sibling, 1 reply; 10+ messages in thread
From: David Rientjes @ 2026-07-14 18:21 UTC (permalink / raw)
  To: Michael S. Tsirkin
  Cc: David Hildenbrand (Arm), Link Lin, Andrew Morton, Vlastimil Babka,
	virtualization, linux-mm, linux-kernel, prasin, duenwen, jasowang,
	xuanzhuo, Ammar Faizi, jiaqiyan, ahwilkins, Greg Thelen,
	Alexander Duyck, stable

On Tue, 14 Jul 2026, Michael S. Tsirkin wrote:

> > > diff --git a/drivers/virtio/virtio_balloon.c b/drivers/virtio/virtio_balloon.c
> > > index a1b2c3d4e5f6..45a90fb3abf8 100640
> > > --- a/drivers/virtio/virtio_balloon.c
> > > +++ b/drivers/virtio/virtio_balloon.c
> > > @@ -1055,6 +1055,9 @@ static int virtballoon_freeze(struct virtio_device *vdev)
> > >  	 * The workqueue is already frozen by the PM core before this
> > >  	 * function is called.
> > >  	 */
> > > +	if (virtio_has_feature(vb->vdev, VIRTIO_BALLOON_F_REPORTING))
> > > +		page_reporting_unregister(&vb->pr_dev_info);
> > > +
> > >  	remove_common(vb);
> > >  	return 0;
> > >  }
> > >  
> > >  static int virtballoon_restore(struct virtio_device *vdev)
> > >  {
> > >  	struct virtio_balloon *vb = vdev->priv;
> > >  	int ret;
> > >  
> > >  	ret = init_vqs(vdev->priv);
> > >  	if (ret)
> > >  		return ret;
> > >  
> > >  	virtio_device_ready(vdev);
> > >  
> > > +	if (virtio_has_feature(vb->vdev, VIRTIO_BALLOON_F_REPORTING)) {
> > > +		ret = page_reporting_register(&vb->pr_dev_info);
> > > +		if (ret)
> > > +			goto out_remove_vqs;
> > > +	}
> > 
> > Hm, that failure handling is rather nasty.
> > 
> > 
> > In virtballoon_freeze() we document:
> > 
> > "The workqueue is already frozen by the PM core before this function is called"
> > 
> > Your report states:
> > 
> > "Workqueue: events page_reporting_process"
> > 
> > 
> > I assume that workqueue is not frozen yet because ... it's not freezable :)
> > 
> > So could we queue to system_freezable_wq instead, or define our own freezable
> > workqueue there? Then a driver doesn't have to worry about that.
> > 
> > -- 
> > Cheers,
> > 
> > David
> 
> +1.  Just system_freezable_wq will do the trick.
> 

This makes sense.

I'm curious why this bug hasn't popped up earlier, presumably any VM that 
has gone through suspend while reporting free pages through FPR is 
vulnerable to it and could have panicked as a result.  Which would suggest 
maybe >99% of FPR is done by guests that never suspend?  While under 
pressure this issue seems reproducible.

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

* Re: [RFC] virtio_balloon: fix Use-After-Free in page reporting during PM freeze
  2026-07-14 18:21     ` David Rientjes
@ 2026-07-14 18:52       ` Michael S. Tsirkin
  0 siblings, 0 replies; 10+ messages in thread
From: Michael S. Tsirkin @ 2026-07-14 18:52 UTC (permalink / raw)
  To: David Rientjes
  Cc: David Hildenbrand (Arm), Link Lin, Andrew Morton, Vlastimil Babka,
	virtualization, linux-mm, linux-kernel, prasin, duenwen, jasowang,
	xuanzhuo, Ammar Faizi, jiaqiyan, ahwilkins, Greg Thelen,
	Alexander Duyck, stable

On Tue, Jul 14, 2026 at 11:21:33AM -0700, David Rientjes wrote:
> On Tue, 14 Jul 2026, Michael S. Tsirkin wrote:
> 
> > > > diff --git a/drivers/virtio/virtio_balloon.c b/drivers/virtio/virtio_balloon.c
> > > > index a1b2c3d4e5f6..45a90fb3abf8 100640
> > > > --- a/drivers/virtio/virtio_balloon.c
> > > > +++ b/drivers/virtio/virtio_balloon.c
> > > > @@ -1055,6 +1055,9 @@ static int virtballoon_freeze(struct virtio_device *vdev)
> > > >  	 * The workqueue is already frozen by the PM core before this
> > > >  	 * function is called.
> > > >  	 */
> > > > +	if (virtio_has_feature(vb->vdev, VIRTIO_BALLOON_F_REPORTING))
> > > > +		page_reporting_unregister(&vb->pr_dev_info);
> > > > +
> > > >  	remove_common(vb);
> > > >  	return 0;
> > > >  }
> > > >  
> > > >  static int virtballoon_restore(struct virtio_device *vdev)
> > > >  {
> > > >  	struct virtio_balloon *vb = vdev->priv;
> > > >  	int ret;
> > > >  
> > > >  	ret = init_vqs(vdev->priv);
> > > >  	if (ret)
> > > >  		return ret;
> > > >  
> > > >  	virtio_device_ready(vdev);
> > > >  
> > > > +	if (virtio_has_feature(vb->vdev, VIRTIO_BALLOON_F_REPORTING)) {
> > > > +		ret = page_reporting_register(&vb->pr_dev_info);
> > > > +		if (ret)
> > > > +			goto out_remove_vqs;
> > > > +	}
> > > 
> > > Hm, that failure handling is rather nasty.
> > > 
> > > 
> > > In virtballoon_freeze() we document:
> > > 
> > > "The workqueue is already frozen by the PM core before this function is called"
> > > 
> > > Your report states:
> > > 
> > > "Workqueue: events page_reporting_process"
> > > 
> > > 
> > > I assume that workqueue is not frozen yet because ... it's not freezable :)
> > > 
> > > So could we queue to system_freezable_wq instead, or define our own freezable
> > > workqueue there? Then a driver doesn't have to worry about that.
> > > 
> > > -- 
> > > Cheers,
> > > 
> > > David
> > 
> > +1.  Just system_freezable_wq will do the trick.
> > 
> 
> This makes sense.
> 
> I'm curious why this bug hasn't popped up earlier, presumably any VM that 
> has gone through suspend while reporting free pages through FPR is 
> vulnerable to it and could have panicked as a result.  Which would suggest 
> maybe >99% of FPR is done by guests that never suspend?

Quite possible.

>  While under 
> pressure this issue seems reproducible.


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

end of thread, other threads:[~2026-07-14 18:52 UTC | newest]

Thread overview: 10+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-07-09 22:43 [RFC] virtio_balloon: fix Use-After-Free in page reporting during PM freeze Link Lin
2026-07-09 23:12 ` Andrew Morton
2026-07-10  0:45   ` Link Lin
2026-07-13 19:41     ` David Rientjes
2026-07-13 19:43       ` Michael S. Tsirkin
2026-07-14 13:17 ` David Hildenbrand (Arm)
2026-07-14 13:24   ` Michael S. Tsirkin
2026-07-14 18:05     ` Link Lin
2026-07-14 18:21     ` David Rientjes
2026-07-14 18:52       ` Michael S. Tsirkin

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