bnxt_en: Improve RX consumer index validity check.
authorMichael Chan <michael.chan@broadcom.com>
Mon, 8 Apr 2019 21:39:54 +0000 (17:39 -0400)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Wed, 17 Apr 2019 06:37:49 +0000 (08:37 +0200)
[ Upstream commit a1b0e4e684e9c300b9e759b46cb7a0147e61ddff ]

There is logic to check that the RX/TPA consumer index is the expected
index to work around a hardware problem.  However, the potentially bad
consumer index is first used to index into an array to reference an entry.
This can potentially crash if the bad consumer index is beyond legal
range.  Improve the logic to use the consumer index for dereferencing
after the validity check and log an error message.

Fixes: fa7e28127a5a ("bnxt_en: Add workaround to detect bad opaque in rx completion (part 2)")
Signed-off-by: Michael Chan <michael.chan@broadcom.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
drivers/net/ethernet/broadcom/bnxt/bnxt.c

index 15ad247955f7892383ac14c769c9f20341933a3c..1e5498431618d1d81533e5c317655cad196501fa 100644 (file)
@@ -1076,6 +1076,8 @@ static void bnxt_tpa_start(struct bnxt *bp, struct bnxt_rx_ring_info *rxr,
        tpa_info = &rxr->rx_tpa[agg_id];
 
        if (unlikely(cons != rxr->rx_next_cons)) {
+               netdev_warn(bp->dev, "TPA cons %x != expected cons %x\n",
+                           cons, rxr->rx_next_cons);
                bnxt_sched_reset(bp, rxr);
                return;
        }
@@ -1528,15 +1530,17 @@ static int bnxt_rx_pkt(struct bnxt *bp, struct bnxt_napi *bnapi, u32 *raw_cons,
        }
 
        cons = rxcmp->rx_cmp_opaque;
-       rx_buf = &rxr->rx_buf_ring[cons];
-       data = rx_buf->data;
-       data_ptr = rx_buf->data_ptr;
        if (unlikely(cons != rxr->rx_next_cons)) {
                int rc1 = bnxt_discard_rx(bp, bnapi, raw_cons, rxcmp);
 
+               netdev_warn(bp->dev, "RX cons %x != expected cons %x\n",
+                           cons, rxr->rx_next_cons);
                bnxt_sched_reset(bp, rxr);
                return rc1;
        }
+       rx_buf = &rxr->rx_buf_ring[cons];
+       data = rx_buf->data;
+       data_ptr = rx_buf->data_ptr;
        prefetch(data_ptr);
 
        misc = le32_to_cpu(rxcmp->rx_cmp_misc_v1);