lists.openwall.net   lists  /  announce  owl-users  owl-dev  john-users  john-dev  passwdqc-users  yescrypt  popa3d-users  /  oss-security  kernel-hardening  musl  sabotage  tlsify  passwords  /  crypt-dev  xvendor  /  Bugtraq  Full-Disclosure  linux-kernel  linux-netdev  linux-ext4  PHC 
Open Source and information security mailing list archives
 
Hash Suite: Windows password security audit tool. GUI, reports in PDF.
[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Date:   Mon, 16 Mar 2020 00:56:25 +0000
From:   Luo bin <luobin9@...wei.com>
To:     <davem@...emloft.net>
CC:     <linux-kernel@...r.kernel.org>, <netdev@...r.kernel.org>,
        <aviad.krawczyk@...wei.com>, <luoxianjun@...wei.com>,
        <cloud.wangxiaoyun@...wei.com>, <yin.yinshi@...wei.com>
Subject: [PATCH net 1/6] hinic: fix process of long length skb without frags

some tool such as pktgen can build an illegal skb with long
length but no fragments, which is unsupported for hw, so
drop it

Signed-off-by: Luo bin <luobin9@...wei.com>
---
 drivers/net/ethernet/huawei/hinic/hinic_ethtool.c |  1 +
 drivers/net/ethernet/huawei/hinic/hinic_main.c    |  1 +
 drivers/net/ethernet/huawei/hinic/hinic_tx.c      | 13 +++++++++----
 drivers/net/ethernet/huawei/hinic/hinic_tx.h      |  2 +-
 4 files changed, 12 insertions(+), 5 deletions(-)

diff --git a/drivers/net/ethernet/huawei/hinic/hinic_ethtool.c b/drivers/net/ethernet/huawei/hinic/hinic_ethtool.c
index 966aea949c0b..dac157bc06a7 100644
--- a/drivers/net/ethernet/huawei/hinic/hinic_ethtool.c
+++ b/drivers/net/ethernet/huawei/hinic/hinic_ethtool.c
@@ -582,6 +582,7 @@ static struct hinic_stats hinic_tx_queue_stats[] = {
 	HINIC_TXQ_STAT(tx_wake),
 	HINIC_TXQ_STAT(tx_dropped),
 	HINIC_TXQ_STAT(big_frags_pkts),
+	HINIC_TXQ_STAT(frag_len_overflow),
 };
 
 #define HINIC_RXQ_STAT(_stat_item) { \
diff --git a/drivers/net/ethernet/huawei/hinic/hinic_main.c b/drivers/net/ethernet/huawei/hinic/hinic_main.c
index 13560975c103..a9bee70bd6c7 100644
--- a/drivers/net/ethernet/huawei/hinic/hinic_main.c
+++ b/drivers/net/ethernet/huawei/hinic/hinic_main.c
@@ -107,6 +107,7 @@ static void update_tx_stats(struct hinic_dev *nic_dev, struct hinic_txq *txq)
 	nic_tx_stats->tx_wake += tx_stats.tx_wake;
 	nic_tx_stats->tx_dropped += tx_stats.tx_dropped;
 	nic_tx_stats->big_frags_pkts += tx_stats.big_frags_pkts;
+	nic_tx_stats->frag_len_overflow += tx_stats.frag_len_overflow;
 	u64_stats_update_end(&nic_tx_stats->syncp);
 
 	hinic_txq_clean_stats(txq);
diff --git a/drivers/net/ethernet/huawei/hinic/hinic_tx.c b/drivers/net/ethernet/huawei/hinic/hinic_tx.c
index 0e13d1c7e474..3c6762086fff 100644
--- a/drivers/net/ethernet/huawei/hinic/hinic_tx.c
+++ b/drivers/net/ethernet/huawei/hinic/hinic_tx.c
@@ -45,9 +45,10 @@
 
 #define HW_CONS_IDX(sq)                 be16_to_cpu(*(u16 *)((sq)->hw_ci_addr))
 
-#define MIN_SKB_LEN                     17
+#define MIN_SKB_LEN			17
+#define HINIC_GSO_MAX_SIZE		65536
 
-#define	MAX_PAYLOAD_OFFSET	        221
+#define	MAX_PAYLOAD_OFFSET		221
 #define TRANSPORT_OFFSET(l4_hdr, skb)	((u32)((l4_hdr) - (skb)->data))
 
 union hinic_l3 {
@@ -84,6 +85,7 @@ void hinic_txq_clean_stats(struct hinic_txq *txq)
 	txq_stats->tx_wake = 0;
 	txq_stats->tx_dropped = 0;
 	txq_stats->big_frags_pkts = 0;
+	txq_stats->frag_len_overflow = 0;
 	u64_stats_update_end(&txq_stats->syncp);
 }
 
@@ -106,6 +108,7 @@ void hinic_txq_get_stats(struct hinic_txq *txq, struct hinic_txq_stats *stats)
 		stats->tx_wake = txq_stats->tx_wake;
 		stats->tx_dropped = txq_stats->tx_dropped;
 		stats->big_frags_pkts = txq_stats->big_frags_pkts;
+		stats->frag_len_overflow = txq_stats->frag_len_overflow;
 	} while (u64_stats_fetch_retry(&txq_stats->syncp, start));
 	u64_stats_update_end(&stats->syncp);
 }
@@ -440,7 +443,6 @@ static int hinic_tx_offload(struct sk_buff *skb, struct hinic_sq_task *task,
 			     vlan_tag >> VLAN_PRIO_SHIFT);
 		offload |= TX_OFFLOAD_VLAN;
 	}
-
 	if (offload)
 		hinic_task_set_l2hdr(task, skb_network_offset(skb));
 
@@ -488,11 +490,14 @@ netdev_tx_t hinic_xmit_frame(struct sk_buff *skb, struct net_device *netdev)
 		txq->txq_stats.big_frags_pkts++;
 		u64_stats_update_end(&txq->txq_stats.syncp);
 	}
-
 	if (nr_sges > txq->max_sges) {
 		netdev_err(netdev, "Too many Tx sges\n");
 		goto skb_error;
 	}
+	if (unlikely(skb->len > HINIC_GSO_MAX_SIZE && nr_sges == 1)) {
+		txq->txq_stats.frag_len_overflow++;
+		goto skb_error;
+	}
 
 	err = tx_map_skb(nic_dev, skb, txq->sges);
 	if (err)
diff --git a/drivers/net/ethernet/huawei/hinic/hinic_tx.h b/drivers/net/ethernet/huawei/hinic/hinic_tx.h
index f158b7db7fb8..ac65b4301c09 100644
--- a/drivers/net/ethernet/huawei/hinic/hinic_tx.h
+++ b/drivers/net/ethernet/huawei/hinic/hinic_tx.h
@@ -22,7 +22,7 @@ struct hinic_txq_stats {
 	u64     tx_wake;
 	u64     tx_dropped;
 	u64	big_frags_pkts;
-
+	u64     frag_len_overflow;
 	struct u64_stats_sync   syncp;
 };
 
-- 
2.17.1

Powered by blists - more mailing lists