OSDN Git Service

linux/dim: Fix overflow in dim calculation
authorYamin Friedman <yaminf@mellanox.com>
Tue, 23 Jul 2019 07:22:47 +0000 (10:22 +0300)
committerDavid S. Miller <davem@davemloft.net>
Thu, 25 Jul 2019 18:34:39 +0000 (11:34 -0700)
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>
drivers/net/ethernet/broadcom/bcmsysport.c
drivers/net/ethernet/broadcom/bnxt/bnxt.c
drivers/net/ethernet/broadcom/genet/bcmgenet.c
drivers/net/ethernet/mellanox/mlx5/core/en_txrx.c
lib/dim/dim.c

index b9c5cea..9483553 100644 (file)
@@ -992,7 +992,7 @@ static int bcm_sysport_poll(struct napi_struct *napi, int budget)
 {
        struct bcm_sysport_priv *priv =
                container_of(napi, struct bcm_sysport_priv, napi);
-       struct dim_sample dim_sample;
+       struct dim_sample dim_sample = {};
        unsigned int work_done = 0;
 
        work_done = bcm_sysport_desc_rx(priv, budget);
index 7134d2c..7070349 100644 (file)
@@ -2136,7 +2136,7 @@ static int bnxt_poll(struct napi_struct *napi, int budget)
                }
        }
        if (bp->flags & BNXT_FLAG_DIM) {
-               struct dim_sample dim_sample;
+               struct dim_sample dim_sample = {};
 
                dim_update_sample(cpr->event_ctr,
                                  cpr->rx_packets,
index a2b5780..d3a0b61 100644 (file)
@@ -1895,7 +1895,7 @@ static int bcmgenet_rx_poll(struct napi_struct *napi, int budget)
 {
        struct bcmgenet_rx_ring *ring = container_of(napi,
                        struct bcmgenet_rx_ring, napi);
-       struct dim_sample dim_sample;
+       struct dim_sample dim_sample = {};
        unsigned int work_done;
 
        work_done = bcmgenet_desc_rx(ring, budget);
index c50b6f0..49b06b2 100644 (file)
@@ -49,7 +49,7 @@ static inline bool mlx5e_channel_no_affinity_change(struct mlx5e_channel *c)
 static void mlx5e_handle_tx_dim(struct mlx5e_txqsq *sq)
 {
        struct mlx5e_sq_stats *stats = sq->stats;
-       struct dim_sample dim_sample;
+       struct dim_sample dim_sample = {};
 
        if (unlikely(!test_bit(MLX5E_SQ_STATE_AM, &sq->state)))
                return;
@@ -61,7 +61,7 @@ static void mlx5e_handle_tx_dim(struct mlx5e_txqsq *sq)
 static void mlx5e_handle_rx_dim(struct mlx5e_rq *rq)
 {
        struct mlx5e_rq_stats *stats = rq->stats;
-       struct dim_sample dim_sample;
+       struct dim_sample dim_sample = {};
 
        if (unlikely(!test_bit(MLX5E_RQ_STATE_AM, &rq->state)))
                return;
index 439d641..38045d6 100644 (file)
@@ -74,8 +74,8 @@ void dim_calc_stats(struct dim_sample *start, struct dim_sample *end,
                                        delta_us);
        curr_stats->cpms = DIV_ROUND_UP(ncomps * USEC_PER_MSEC, delta_us);
        if (curr_stats->epms != 0)
-               curr_stats->cpe_ratio =
-                               (curr_stats->cpms * 100) / curr_stats->epms;
+               curr_stats->cpe_ratio = DIV_ROUND_DOWN_ULL(
+                       curr_stats->cpms * 100, curr_stats->epms);
        else
                curr_stats->cpe_ratio = 0;