Skip to content

Commit d1a37de

Browse files
Yunsheng Lindavem330
authored andcommitted
net: hns3: fix a use after free problem in hns3_nic_maybe_stop_tx()
Currently, hns3_nic_maybe_stop_tx() uses skb_copy() to linearize a SKB if the BD num required by the SKB does not meet the hardware limitation, and it linearizes the SKB by allocating a new linearized SKB and freeing the old SKB, if hns3_nic_maybe_stop_tx() returns -EBUSY because there are no enough space in the ring to send the linearized skb to hardware, the sch_direct_xmit() still hold reference to old SKB and try to retransmit the old SKB when dev_hard_start_xmit() return TX_BUSY, which may cause use after freed problem. This patch fixes it by using __skb_linearize() to linearize the SKB in hns3_nic_maybe_stop_tx(). Fixes: 51e8439 ("net: hns3: add 8 BD limit for tx flow") Signed-off-by: Yunsheng Lin <[email protected]> Signed-off-by: Huazhong Tan <[email protected]> Signed-off-by: David S. Miller <[email protected]>
1 parent 2a597ef commit d1a37de

File tree

1 file changed

+6
-13
lines changed

1 file changed

+6
-13
lines changed

drivers/net/ethernet/hisilicon/hns3/hns3_enet.c

Lines changed: 6 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1288,31 +1288,24 @@ static bool hns3_skb_need_linearized(struct sk_buff *skb, unsigned int *bd_size,
12881288

12891289
static int hns3_nic_maybe_stop_tx(struct hns3_enet_ring *ring,
12901290
struct net_device *netdev,
1291-
struct sk_buff **out_skb)
1291+
struct sk_buff *skb)
12921292
{
12931293
struct hns3_nic_priv *priv = netdev_priv(netdev);
12941294
unsigned int bd_size[HNS3_MAX_TSO_BD_NUM + 1U];
1295-
struct sk_buff *skb = *out_skb;
12961295
unsigned int bd_num;
12971296

12981297
bd_num = hns3_tx_bd_num(skb, bd_size);
12991298
if (unlikely(bd_num > HNS3_MAX_NON_TSO_BD_NUM)) {
1300-
struct sk_buff *new_skb;
1301-
13021299
if (bd_num <= HNS3_MAX_TSO_BD_NUM && skb_is_gso(skb) &&
13031300
!hns3_skb_need_linearized(skb, bd_size, bd_num))
13041301
goto out;
13051302

1306-
/* manual split the send packet */
1307-
new_skb = skb_copy(skb, GFP_ATOMIC);
1308-
if (!new_skb)
1303+
if (__skb_linearize(skb))
13091304
return -ENOMEM;
1310-
dev_kfree_skb_any(skb);
1311-
*out_skb = new_skb;
13121305

1313-
bd_num = hns3_tx_bd_count(new_skb->len);
1314-
if ((skb_is_gso(new_skb) && bd_num > HNS3_MAX_TSO_BD_NUM) ||
1315-
(!skb_is_gso(new_skb) &&
1306+
bd_num = hns3_tx_bd_count(skb->len);
1307+
if ((skb_is_gso(skb) && bd_num > HNS3_MAX_TSO_BD_NUM) ||
1308+
(!skb_is_gso(skb) &&
13161309
bd_num > HNS3_MAX_NON_TSO_BD_NUM))
13171310
return -ENOMEM;
13181311

@@ -1415,7 +1408,7 @@ netdev_tx_t hns3_nic_net_xmit(struct sk_buff *skb, struct net_device *netdev)
14151408
/* Prefetch the data used later */
14161409
prefetch(skb->data);
14171410

1418-
ret = hns3_nic_maybe_stop_tx(ring, netdev, &skb);
1411+
ret = hns3_nic_maybe_stop_tx(ring, netdev, skb);
14191412
if (unlikely(ret <= 0)) {
14201413
if (ret == -EBUSY) {
14211414
u64_stats_update_begin(&ring->syncp);

0 commit comments

Comments
 (0)