> -----Original Message-----
> From: Intel-wired-lan <[email protected]> On Behalf
> Of Maciej Fijalkowski
> Sent: Wednesday, July 1, 2026 2:45 PM
> To: [email protected]
> Cc: [email protected]; Karlsson, Magnus
> <[email protected]>; [email protected]; [email protected];
> [email protected]; Kitszel, Przemyslaw <[email protected]>;
> Keller, Jacob E <[email protected]>; Fijalkowski, Maciej
> <[email protected]>; Sashiko AI Review <sashiko-
> [email protected]>
> Subject: [Intel-wired-lan] [PATCH v5 net 3/7] i40e: make ring pointers
> unreachable before freeing via rcu
> 
> Sashiko reports:
> ***
> >  err_config:
> > +   i40e_vsi_free_q_vectors(vsi);
> > +err_qvec:
> >     i40e_vsi_clear_rings(vsi);
> This is a pre-existing issue, but can the sequence in
> i40e_vsi_clear_rings() lead to an RCU ordering violation?
> In i40e_vsi_clear_rings(), the rings are freed before the array
> pointers are
> nullified:
>       kfree_rcu(vsi->tx_rings[i], rcu);
>       WRITE_ONCE(vsi->tx_rings[i], NULL);
> Under RCU rules, a pointer must be made unreachable to new readers
> before it is handed off to kfree_rcu(). Could a new RCU reader (like
> i40e_get_netdev_stats_struct_tx()) fetch the pointer after kfree_rcu()
> is invoked, and access freed memory if the grace period expires while
> the reader is still active?
> ***
> 
> Save the Tx ring pointer before clearing the published ring array
> slots and pass the saved pointer to kfree_rcu(). This preserves the
> intended RCU ordering, where new readers can no longer discover the
> ring through
> vsi->tx_rings/rx_rings/xdp_rings before the object is queued for
> deferred freeing, while avoiding a NULL kfree_rcu() argument after the
> slot has already been cleared. Since the Tx pointer is the base of the
> per-queue-pair allocation block, re-reading vsi->tx_rings[i] after
> WRITE_ONCE(..., NULL) would otherwise turn the free into a no-op and
> leak the whole ring block.
> 
> Fixes: 9f65e15b4f98 ("i40e: Move rings from pointer to array to array
> of pointers")
> Reported-by: Sashiko AI Review <[email protected]>
> Signed-off-by: Maciej Fijalkowski <[email protected]>
> ---
>  drivers/net/ethernet/intel/i40e/i40e_main.c | 4 +++-
>  1 file changed, 3 insertions(+), 1 deletion(-)
> 
> diff --git a/drivers/net/ethernet/intel/i40e/i40e_main.c
> b/drivers/net/ethernet/intel/i40e/i40e_main.c
> index 471fa7f7b643..a29a89192a7a 100644
> --- a/drivers/net/ethernet/intel/i40e/i40e_main.c
> +++ b/drivers/net/ethernet/intel/i40e/i40e_main.c
> @@ -11699,11 +11699,13 @@ static void i40e_vsi_clear_rings(struct
> i40e_vsi *vsi)
> 
>       if (vsi->tx_rings && vsi->tx_rings[0]) {
>               for (i = 0; i < vsi->alloc_queue_pairs; i++) {
> -                     kfree_rcu(vsi->tx_rings[i], rcu);
> +                     struct i40e_ring *tx_ring = vsi->tx_rings[i];
> +
>                       WRITE_ONCE(vsi->tx_rings[i], NULL);
>                       WRITE_ONCE(vsi->rx_rings[i], NULL);
>                       if (vsi->xdp_rings)
>                               WRITE_ONCE(vsi->xdp_rings[i], NULL);
> +                     kfree_rcu(tx_ring, rcu);
>               }
>       }
>  }
> --
> 2.43.0

Reviewed-by: Aleksandr Loktionov <[email protected]>

Reply via email to