Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

linux/dim: Fix overflow in dim calculation

While using net_dim, a dim_sample was used without ever initializing the
comps value. Added use of DIV_ROUND_DOWN_ULL() to prevent potential
overflow, it should not be a problem to save the final result in an int
because after the division by epms the value should not be larger than a
few thousand.

[ 1040.127124] UBSAN: Undefined behaviour in lib/dim/dim.c:78:23
[ 1040.130118] signed integer overflow:
[ 1040.131643] 134718714 * 100 cannot be represented in type 'int'

Fixes: 398c2b05bbee ("linux/dim: Add completions count to dim_sample")
Signed-off-by: Yamin Friedman <yaminf@mellanox.com>
Signed-off-by: Leon Romanovsky <leonro@mellanox.com>
Acked-by: Saeed Mahameed <saeedm@mellanox.com>
Signed-off-by: David S. Miller <davem@davemloft.net>

authored by

Yamin Friedman and committed by
David S. Miller
f06d0ca4 c8ec4632

+7 -7
+1 -1
drivers/net/ethernet/broadcom/bcmsysport.c
··· 992 992 { 993 993 struct bcm_sysport_priv *priv = 994 994 container_of(napi, struct bcm_sysport_priv, napi); 995 - struct dim_sample dim_sample; 995 + struct dim_sample dim_sample = {}; 996 996 unsigned int work_done = 0; 997 997 998 998 work_done = bcm_sysport_desc_rx(priv, budget);
+1 -1
drivers/net/ethernet/broadcom/bnxt/bnxt.c
··· 2136 2136 } 2137 2137 } 2138 2138 if (bp->flags & BNXT_FLAG_DIM) { 2139 - struct dim_sample dim_sample; 2139 + struct dim_sample dim_sample = {}; 2140 2140 2141 2141 dim_update_sample(cpr->event_ctr, 2142 2142 cpr->rx_packets,
+1 -1
drivers/net/ethernet/broadcom/genet/bcmgenet.c
··· 1895 1895 { 1896 1896 struct bcmgenet_rx_ring *ring = container_of(napi, 1897 1897 struct bcmgenet_rx_ring, napi); 1898 - struct dim_sample dim_sample; 1898 + struct dim_sample dim_sample = {}; 1899 1899 unsigned int work_done; 1900 1900 1901 1901 work_done = bcmgenet_desc_rx(ring, budget);
+2 -2
drivers/net/ethernet/mellanox/mlx5/core/en_txrx.c
··· 49 49 static void mlx5e_handle_tx_dim(struct mlx5e_txqsq *sq) 50 50 { 51 51 struct mlx5e_sq_stats *stats = sq->stats; 52 - struct dim_sample dim_sample; 52 + struct dim_sample dim_sample = {}; 53 53 54 54 if (unlikely(!test_bit(MLX5E_SQ_STATE_AM, &sq->state))) 55 55 return; ··· 61 61 static void mlx5e_handle_rx_dim(struct mlx5e_rq *rq) 62 62 { 63 63 struct mlx5e_rq_stats *stats = rq->stats; 64 - struct dim_sample dim_sample; 64 + struct dim_sample dim_sample = {}; 65 65 66 66 if (unlikely(!test_bit(MLX5E_RQ_STATE_AM, &rq->state))) 67 67 return;
+2 -2
lib/dim/dim.c
··· 74 74 delta_us); 75 75 curr_stats->cpms = DIV_ROUND_UP(ncomps * USEC_PER_MSEC, delta_us); 76 76 if (curr_stats->epms != 0) 77 - curr_stats->cpe_ratio = 78 - (curr_stats->cpms * 100) / curr_stats->epms; 77 + curr_stats->cpe_ratio = DIV_ROUND_DOWN_ULL( 78 + curr_stats->cpms * 100, curr_stats->epms); 79 79 else 80 80 curr_stats->cpe_ratio = 0; 81 81