| From a7d34e782c6d125d3fbd670c9125eb20631bbe43 Mon Sep 17 00:00:00 2001 |
| From: Pavel Belous <pbelous@marvell.com> |
| Date: Fri, 14 Feb 2020 18:44:55 +0300 |
| Subject: [PATCH] net: atlantic: fix use after free kasan warn |
| |
| commit a4980919ad6a7be548d499bc5338015e1a9191c6 upstream. |
| |
| skb->len is used to calculate statistics after xmit invocation. |
| |
| Under a stress load it may happen that skb will be xmited, |
| rx interrupt will come and skb will be freed, all before xmit function |
| is even returned. |
| |
| Eventually, skb->len will access unallocated area. |
| |
| Moving stats calculation into tx_clean routine. |
| |
| Fixes: 018423e90bee ("net: ethernet: aquantia: Add ring support code") |
| Reported-by: Christophe Vu-Brugier <cvubrugier@fastmail.fm> |
| Signed-off-by: Igor Russkikh <irusskikh@marvell.com> |
| Signed-off-by: Pavel Belous <pbelous@marvell.com> |
| Signed-off-by: Dmitry Bogdanov <dbogdanov@marvell.com> |
| Signed-off-by: David S. Miller <davem@davemloft.net> |
| Signed-off-by: Paul Gortmaker <paul.gortmaker@windriver.com> |
| |
| diff --git a/drivers/net/ethernet/aquantia/atlantic/aq_nic.c b/drivers/net/ethernet/aquantia/atlantic/aq_nic.c |
| index 557e9a7bfd28..006d92ca7f84 100644 |
| --- a/drivers/net/ethernet/aquantia/atlantic/aq_nic.c |
| +++ b/drivers/net/ethernet/aquantia/atlantic/aq_nic.c |
| @@ -584,10 +584,6 @@ int aq_nic_xmit(struct aq_nic_s *self, struct sk_buff *skb) |
| if (likely(frags)) { |
| err = self->aq_hw_ops->hw_ring_tx_xmit(self->aq_hw, |
| ring, frags); |
| - if (err >= 0) { |
| - ++ring->stats.tx.packets; |
| - ring->stats.tx.bytes += skb->len; |
| - } |
| } else { |
| err = NETDEV_TX_BUSY; |
| } |
| diff --git a/drivers/net/ethernet/aquantia/atlantic/aq_ring.c b/drivers/net/ethernet/aquantia/atlantic/aq_ring.c |
| index e0f24580f50e..6282f89868dc 100644 |
| --- a/drivers/net/ethernet/aquantia/atlantic/aq_ring.c |
| +++ b/drivers/net/ethernet/aquantia/atlantic/aq_ring.c |
| @@ -243,9 +243,12 @@ bool aq_ring_tx_clean(struct aq_ring_s *self) |
| } |
| } |
| |
| - if (unlikely(buff->is_eop)) |
| - dev_kfree_skb_any(buff->skb); |
| + if (unlikely(buff->is_eop)) { |
| + ++self->stats.rx.packets; |
| + self->stats.tx.bytes += buff->skb->len; |
| |
| + dev_kfree_skb_any(buff->skb); |
| + } |
| buff->pa = 0U; |
| buff->eop_index = 0xffffU; |
| self->sw_head = aq_ring_next_dx(self, self->sw_head); |
| -- |
| 2.7.4 |
| |