On 01.07.2026 12:41, Przemek Kitszel wrote:
> Integrate ice_vsi_alloc_stat_arrays() with realloc variant.
>
> Instead of keeping two functions for stat arrays allocation, change the
> ice_vsi_realloc_stat_arrays() to handle initial condition (no vsi_stat
> entry) and replace ice_vsi_alloc_stat_arrays() by the more generic
> ice_vsi_realloc_stat_arrays().
>
> Note that VSIs of ICE_VSI_CHNL type are ignored in realloc variant as they
> were in the replaced ice_vsi_alloc_stat_arrays().
>
> This is a fix for stats array overflow that occurs when VF is given more
> queues (an operation that will be more frequent, and by bigger increase,
> when we will merge my "XLVF" series).
>
> Splat for increasing number of queues thanks to Michal Schmidt:
> KASAN detects the bug:
> ==================================================================
> BUG: KASAN: slab-out-of-bounds in ice_vsi_alloc_ring_stats+0x385/0x4a0 [ice]
> Read of size 8 at addr ffff88810affea60 by task kworker/u131:7/221
>
> CPU: 24 UID: 0 PID: 221 Comm: kworker/u131:7 Not tainted 7.1.0-rc1+ #1
> PREEMPT(lazy)
> ...
> Workqueue: ice ice_service_task [ice]
> Call Trace:
> <TASK>
> ...
> kasan_report+0xd7/0x120
> ice_vsi_alloc_ring_stats+0x385/0x4a0 [ice]
> ice_vsi_cfg_def+0x12e2/0x2060 [ice]
> ice_vsi_cfg+0xb5/0x3c0 [ice]
> ice_reset_vf+0x858/0xf80 [ice]
> ice_vc_request_qs_msg+0x1da/0x290 [ice]
> ice_vc_process_vf_msg+0xb15/0x1430 [ice]
> __ice_clean_ctrlq+0x70d/0x9d0 [ice]
> ice_service_task+0x840/0xf20 [ice]
> process_one_work+0x690/0xff0
> worker_thread+0x4d9/0xd20
> kthread+0x322/0x410
> ret_from_fork+0x332/0x660
> ret_from_fork_asm+0x1a/0x30
> </TASK>
>
> Allocated by task 2439:
> kasan_save_stack+0x1c/0x40
> kasan_save_track+0x10/0x30
> __kasan_kmalloc+0x96/0xb0
> __kmalloc_noprof+0x1d8/0x580
> ice_vsi_cfg_def+0x115c/0x2060 [ice]
> ice_vsi_cfg+0xb5/0x3c0 [ice]
> ice_vsi_setup+0x180/0x320 [ice]
> ice_start_vfs+0x1f3/0x590 [ice]
> ice_ena_vfs+0x66d/0x798 [ice]
> ice_sriov_configure.cold+0xe4/0x121 [ice]
> sriov_numvfs_store+0x279/0x480
> kernfs_fop_write_iter+0x331/0x4f0
> vfs_write+0x4c4/0xe40
> ksys_write+0x10c/0x240
> do_syscall_64+0xd9/0x650
> entry_SYSCALL_64_after_hwframe+0x76/0x7e
>
> The buggy address belongs to the object at ffff88810affea40
> which belongs to the cache kmalloc-32 of size 32
> The buggy address is located 0 bytes to the right of
> allocated 32-byte region [ffff88810affea40, ffff88810affea60)
>
> Fixes: 2a2cb4c6c181 ("ice: replace ice_vf_recreate_vsi() with
> ice_vf_reconfig_vsi()")
> Closes: https://redhat.atlassian.net/browse/RHEL-164321
Is there a simpler reproducer than the script attached in the ticket?
> Signed-off-by: Przemek Kitszel <[email protected]>
Reviewed-by: Marcin Szycik <[email protected]>
> ---
> This is an alternative to the fix [1] by Michal Schmidt, which were
> blocked due to AI feedback. My fix was already developed before Michal's,
> just not public back then. We have agreed to go on with my version.
>
> [1]
> https://lore.kernel.org/netdev/[email protected]
> ---
> drivers/net/ethernet/intel/ice/ice_lib.c | 57 +++++-------------------
> 1 file changed, 11 insertions(+), 46 deletions(-)
>
> diff --git a/drivers/net/ethernet/intel/ice/ice_lib.c
> b/drivers/net/ethernet/intel/ice/ice_lib.c
> index e48ee5940f17..ae167b42c558 100644
> --- a/drivers/net/ethernet/intel/ice/ice_lib.c
> +++ b/drivers/net/ethernet/intel/ice/ice_lib.c
> @@ -513,51 +513,6 @@ static irqreturn_t ice_msix_clean_rings(int
> __always_unused irq, void *data)
> return IRQ_HANDLED;
> }
>
> -/**
> - * ice_vsi_alloc_stat_arrays - Allocate statistics arrays
> - * @vsi: VSI pointer
> - */
> -static int ice_vsi_alloc_stat_arrays(struct ice_vsi *vsi)
> -{
> - struct ice_vsi_stats *vsi_stat;
> - struct ice_pf *pf = vsi->back;
> -
> - if (vsi->type == ICE_VSI_CHNL)
> - return 0;
> - if (!pf->vsi_stats)
> - return -ENOENT;
> -
> - if (pf->vsi_stats[vsi->idx])
> - /* realloc will happen in rebuild path */
> - return 0;
> -
> - vsi_stat = kzalloc_obj(*vsi_stat);
> - if (!vsi_stat)
> - return -ENOMEM;
> -
> - vsi_stat->tx_ring_stats =
> - kzalloc_objs(*vsi_stat->tx_ring_stats, vsi->alloc_txq);
> - if (!vsi_stat->tx_ring_stats)
> - goto err_alloc_tx;
> -
> - vsi_stat->rx_ring_stats =
> - kzalloc_objs(*vsi_stat->rx_ring_stats, vsi->alloc_rxq);
> - if (!vsi_stat->rx_ring_stats)
> - goto err_alloc_rx;
> -
> - pf->vsi_stats[vsi->idx] = vsi_stat;
> -
> - return 0;
> -
> -err_alloc_rx:
> - kfree(vsi_stat->rx_ring_stats);
> -err_alloc_tx:
> - kfree(vsi_stat->tx_ring_stats);
> - kfree(vsi_stat);
> - pf->vsi_stats[vsi->idx] = NULL;
> - return -ENOMEM;
> -}
> -
> /**
> * ice_vsi_alloc_def - set default values for already allocated VSI
> * @vsi: ptr to VSI
> @@ -2319,7 +2274,17 @@ static int ice_vsi_realloc_stat_arrays(struct ice_vsi
> *vsi)
> u16 prev_txq = vsi->alloc_txq;
> u16 prev_rxq = vsi->alloc_rxq;
>
> + if (vsi->type == ICE_VSI_CHNL)
> + return 0;
> +
> vsi_stat = pf->vsi_stats[vsi->idx];
> + if (!vsi_stat) {
> + vsi_stat = kzalloc_obj(*vsi_stat);
> + if (!vsi_stat)
> + return -ENOMEM;
> +
> + pf->vsi_stats[vsi->idx] = vsi_stat;
> + }
>
> if (req_txq < prev_txq) {
> for (int i = req_txq; i < prev_txq; i++) {
> @@ -2379,7 +2344,7 @@ static int ice_vsi_cfg_def(struct ice_vsi *vsi)
> return ret;
>
> /* allocate memory for Tx/Rx ring stat pointers */
> - ret = ice_vsi_alloc_stat_arrays(vsi);
> + ret = ice_vsi_realloc_stat_arrays(vsi);
> if (ret)
> goto unroll_vsi_alloc;
>