mirror of
https://github.com/torvalds/linux.git
synced 2026-09-22 20:54:03 +02:00
hinic3: Fix skb linearization mismatch and drop skb when skb_checksum_help() failed
Previously, hinic3_send_one_skb() cached the skb fragment count before
calling hinic3_tx_offload(). If hinic3_tx_csum() falls back to
skb_checksum_help() for unsupported tunnel packets, the skb may be
linearized. Continuing to build the TX descriptor with the stale
fragment count leads to a descriptor mismatch, which can trigger
out-of-bounds DMA reads or IOMMU faults.
Furthermore, the old code ignored the return value of skb_checksum_help(),
transmitting corrupted packets with incomplete checksums upon failure.
Fix this by:
1. Moving the hinic3_tx_offload() call before calculating 'num_sge' to
ensure the correct fragment count is used if the SKB is linearized.
2. Propagating skb_checksum_help() errors and returning
HINIC3_TX_OFFLOAD_INVALID to properly drop the skb.
Fixes: 17fcb3dc12 ("hinic3: module initialization and tx/rx logic")
Co-developed-by: Teng Peisen <tengpeisen@huawei.com>
Signed-off-by: Teng Peisen <tengpeisen@huawei.com>
Co-developed-by: Wu Di <wudi234@huawei.com>
Signed-off-by: Wu Di <wudi234@huawei.com>
Signed-off-by: Fan Gong <gongfan1@huawei.com>
Reviewed-by: Simon Horman <horms@kernel.org>
Link: https://patch.msgid.link/78d8c61cab588240948eaddcb437d59add9f77ae.1786448013.git.tengpeisen@huawei.com
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
This commit is contained in:
parent
603fa1f50a
commit
d0c2bed692
|
|
@ -261,8 +261,7 @@ static int hinic3_tx_csum(struct hinic3_txq *txq, struct hinic3_sq_task *task,
|
|||
((struct udphdr *)skb_transport_header(skb))->dest !=
|
||||
VXLAN_OFFLOAD_PORT_LE) {
|
||||
/* Unsupported tunnel packet, disable csum offload */
|
||||
skb_checksum_help(skb);
|
||||
return 0;
|
||||
return skb_checksum_help(skb);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -412,6 +411,10 @@ static u32 hinic3_tx_offload(struct sk_buff *skb, struct hinic3_sq_task *task,
|
|||
offload |= HINIC3_TX_OFFLOAD_TSO;
|
||||
} else {
|
||||
tso_cs_en = hinic3_tx_csum(txq, task, skb);
|
||||
if (tso_cs_en < 0) {
|
||||
offload = HINIC3_TX_OFFLOAD_INVALID;
|
||||
return offload;
|
||||
}
|
||||
if (tso_cs_en)
|
||||
offload |= HINIC3_TX_OFFLOAD_CSUM;
|
||||
}
|
||||
|
|
@ -545,6 +548,7 @@ static netdev_tx_t hinic3_send_one_skb(struct sk_buff *skb,
|
|||
skb->len = MIN_SKB_LEN;
|
||||
}
|
||||
|
||||
offload = hinic3_tx_offload(skb, &task, &queue_info, txq);
|
||||
num_sge = skb_shinfo(skb)->nr_frags + 1;
|
||||
/* assume normal wqe format + 1 wqebb for task info */
|
||||
wqebb_cnt = num_sge + 1;
|
||||
|
|
@ -560,7 +564,6 @@ static netdev_tx_t hinic3_send_one_skb(struct sk_buff *skb,
|
|||
return NETDEV_TX_BUSY;
|
||||
}
|
||||
|
||||
offload = hinic3_tx_offload(skb, &task, &queue_info, txq);
|
||||
if (unlikely(offload == HINIC3_TX_OFFLOAD_INVALID)) {
|
||||
goto err_drop_pkt;
|
||||
} else if (!offload) {
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user