All of lore.kernel.org
 help / color / mirror / Atom feed
From: sashiko-bot@kernel.org
To: "Haishuang Yan" <yanhaishuang@cmss.chinamobile.com>
Cc: virtualization@lists.linux.dev, bpf@vger.kernel.org,
	"Michael S. Tsirkin" <mst@redhat.com>,
	"Eugenio Perez" <eperezma@redhat.com>
Subject: Re: [PATCH net v2 3/3] virtio_net: Keep AF_XDP zero-copy pools bound across suspend
Date: Mon, 09 Nov 2026 11:39:33 +0000	[thread overview]
Message-ID: <sashiko-outbox-204885@kernel.org> (raw)
In-Reply-To: <20261108193845.73621-4-yanhaishuang@cmss.chinamobile.com>

Thank you for your contribution! Sashiko AI review found 4 potential
issues to consider:
- [High] virtio_net: virtnet_xsk_pools_attach() attaches unmapped AF_XDP
  pool
- [Medium] virtio_net: UAF on vi->rq in virtnet_xsk_pool_disable() after
  failed restore
- [Medium] virtio_net: DMA map leak in virtnet_xsk_pool_disable() after
  XDP detach
- [Medium] virtio_net: missing rtnl_lock() around xsk_pool_dma_unmap()
  on freeze
--

commit f8bbdffa48d34460262d93d81019cacaef0e299f
Author: Haishuang Yan <yanhaishuang@cmss.chinamobile.com>

virtio_net: Keep AF_XDP zero-copy pools bound across suspend

This commit preserves AF_XDP zero-copy pools across suspend and resume by
releasing only the per-queue driver state on freeze while keeping the pools
DMA-mapped, then re-attaching them to the newly allocated queues on
restore.

> diff --git a/drivers/net/virtio_net.c b/drivers/net/virtio_net.c
> index f9d227060375c..d9c920f421268 100644
> --- a/drivers/net/virtio_net.c
> +++ b/drivers/net/virtio_net.c

[ ... ]

> @@ -5808,6 +5810,7 @@ static int virtnet_restore_up(struct virtio_device *vdev)
>  err_destroy_pools:
>  	virtio_reset_device(vdev);
>  	free_unused_bufs(vi);
> +	virtnet_xsk_pools_release(vi);
>  	virtnet_destroy_page_pools(vi);
>  	virtnet_del_vqs(vi);
>  	return err;
> @@ -6038,6 +6041,13 @@ static int virtnet_xsk_pool_disable(struct net_device *dev, u16 qid)
>  	rq = &vi->rq[qid];
>  
>  	pool = rq->xsk_pool;
> +	if (!pool) {
> +		/* Binding it again on restore failed, only the DMA map is left */
> +		pool = xsk_get_pool_from_qid(dev, qid);
> +		if (pool)
> +			xsk_pool_dma_unmap(pool, 0);
> +		return 0;
> +	}

[Severity: Medium]
Can virtnet_xsk_pool_disable() dereference a freed or NULL vi->rq after a
failed restore?

If virtnet_restore_up() fails (for example at err_destroy_pools, or
earlier in init_vqs()), virtnet_del_vqs() -> virtnet_free_queues() frees
vi->rq and vi->sq while the net_device and bound AF_XDP pools remain
registered.  When the socket is later closed, virtnet_xsk_pool_disable()
reads vi->rq[qid].xsk_pool from the dangling vi->rq pointer.

[Severity: Medium]
Can this fallback also leak the pool's DMA mappings if XDP is detached
before the socket is closed?

When virtnet_xsk_pool_attach() fails on restore for a pool bound to an XDP
queue (qid >= curr_qp), rq->xsk_pool is left NULL while the pool stays
DMA-mapped.  If the XDP program is then removed via virtnet_xdp_set(),
netif_set_real_num_rx_queues() lowers dev->real_num_rx_queues to
curr_qp <= qid (and dev->real_num_tx_queues is also curr_qp).  When the
socket is subsequently closed, xsk_get_pool_from_qid(dev, qid) returns
NULL because qid is no longer below real_num_rx_queues or
real_num_tx_queues, skipping xsk_pool_dma_unmap().

Unmapping the pool directly in virtnet_xsk_pools_attach() when
virtnet_xsk_pool_attach() fails would avoid leaving a half-bound DMA map
behind.

> @@ -6053,6 +6063,133 @@ static int virtnet_xsk_pool_disable(struct net_device *dev, u16 qid)
>  	return err;
>  }
>  
> +/*
> + * Freeze frees the receive and send queues, but the AF_XDP sockets stay
> + * bound and the xsk core keeps their pools. Release only the driver state
> + * of the zero-copy pools here, once the device is reset and the buffers
> + * posted to it are back in the pools. The pools stay DMA mapped, since the
> + * DMA device is still the same after restore and the buffers on their free
> + * lists keep their DMA addresses.
> + *
> + * A pool left above curr_queue_pairs by removing XDP is not bound again
> + * on restore, so unmap it as well.
> + */
> +static void virtnet_xsk_pools_release(struct virtnet_info *vi)
> +{
> +	int i;
> +
> +	for (i = 0; i < vi->max_queue_pairs; i++) {
> +		struct receive_queue *rq = &vi->rq[i];
> +		struct send_queue *sq = &vi->sq[i];
> +
> +		if (rq->xsk_pool) {
> +			if (i >= vi->curr_queue_pairs)
> +				xsk_pool_dma_unmap(rq->xsk_pool, 0);

[Severity: Medium]
Does calling xsk_pool_dma_unmap() here without holding rtnl_lock() race on
pool->umem->xsk_dma_list?

remove_vq_common() calls virtnet_xsk_pools_release() outside rtnl_lock()
during virtnet_freeze().  xp_dma_unmap() walks and deletes entries from
pool->umem->xsk_dma_list, which is protected by rtnl_lock.  If an xdp_umem
is shared across multiple devices via XDP_SHARED_UMEM, concurrent async
suspends can corrupt xsk_dma_list.

[ ... ]

> +/*
> + * On restore, set the zero-copy pools up again on the new queues before
> + * they are filled and their NAPI is enabled.
> + */
> +static void virtnet_xsk_pools_attach(struct virtnet_info *vi)
> +{
> +	struct xsk_buff_pool *pool;
> +	int i, err;
> +
> +	ASSERT_RTNL();
> +
> +	for (i = 0; i < vi->curr_queue_pairs; i++) {
> +		pool = xsk_get_pool_from_qid(vi->dev, i);
> +		if (!pool || !pool->umem->zc)
> +			continue;
> +
> +		/* The pool stays DMA mapped until it is disabled */
> +		err = virtnet_xsk_pool_attach(vi, i, pool);

[Severity: High]
Can virtnet_xsk_pools_attach() re-attach a pool that was already
DMA-unmapped by virtnet_xsk_pools_release()?

If a pool is bound to an XDP queue qid, detaching XDP lowers
vi->curr_queue_pairs below qid, and the next freeze unmaps the pool in
virtnet_xsk_pools_release() via xsk_pool_dma_unmap().  xp_dma_unmap() sets
pool->dma_pages = NULL and pool->dev = NULL, but pool->umem->zc and
dev->_rx[qid].pool remain set.  If XDP is re-attached after resume (raising
vi->curr_queue_pairs above qid again) and the system suspends a second
time, virtnet_xsk_pools_attach() sees pool->umem->zc == true and attaches
the unmapped pool to the queue, leading to a NULL pointer dereference on
pool->dma_pages or pool->dev during RX/TX.

Should this check pool->dma_pages instead of pool->umem->zc, or re-map the
pool when pool->dma_pages is NULL?

-- 
Sashiko AI review · https://sashiko.dev/#/patchset/20261108193845.73621-1-yanhaishuang@cmss.chinamobile.com?part=3

  reply	other threads:[~2026-11-09 11:39 UTC|newest]

Thread overview: 11+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-11-08 19:38 [PATCH net v2 0/3] virtio_net: AF_XDP zero-copy fixes for arm64 and suspend Haishuang Yan
2026-11-08 19:38 ` [PATCH net v2 1/3] virtio_net: Don't DMA map the kernel image for the AF_XDP TX header Haishuang Yan
2026-11-09 11:39   ` sashiko-bot
2026-11-08 19:38 ` [PATCH net v2 2/3] virtio_net: Disable AF_XDP pools on queues above curr_queue_pairs Haishuang Yan
2026-11-09 11:39   ` sashiko-bot
2026-11-09 12:34   ` netdev-bot+sashiko
2026-11-10 11:20     ` Haishuang Yan
2026-11-08 19:38 ` [PATCH net v2 3/3] virtio_net: Keep AF_XDP zero-copy pools bound across suspend Haishuang Yan
2026-11-09 11:39   ` sashiko-bot [this message]
2026-11-09 12:34   ` netdev-bot+sashiko
2026-11-10 11:21     ` Haishuang Yan

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=sashiko-outbox-204885@kernel.org \
    --to=sashiko-bot@kernel.org \
    --cc=bpf@vger.kernel.org \
    --cc=eperezma@redhat.com \
    --cc=mst@redhat.com \
    --cc=sashiko-reviews@lists.linux.dev \
    --cc=virtualization@lists.linux.dev \
    --cc=yanhaishuang@cmss.chinamobile.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.