From: Álvaro Fernández Rojas Date: Sun, 23 Apr 2017 11:48:05 +0000 (+0200) Subject: kernel: use skb_cow_head() to deal with cloned skbs X-Git-Url: http://git.lede-project.org./?a=commitdiff_plain;h=2db05cd199999d9a3670e5287d067bdab0431f1a;p=openwrt%2Fstaging%2F981213.git kernel: use skb_cow_head() to deal with cloned skbs We need to ensure there is enough headroom to push extra header, but we also need to check if we are allowed to change headers. skb_cow_head() is the proper helper to deal with this. Fixes Ethernet<->WiFi bridge for Raspberry Pi and probably other devices. Signed-off-by: Álvaro Fernández Rojas --- diff --git a/target/linux/generic/patches-4.4/030-1-smsc95xx-Use-skb_cow_head-to-deal-with-cloned-skbs.patch b/target/linux/generic/patches-4.4/030-1-smsc95xx-Use-skb_cow_head-to-deal-with-cloned-skbs.patch new file mode 100644 index 0000000000..36fb936e32 --- /dev/null +++ b/target/linux/generic/patches-4.4/030-1-smsc95xx-Use-skb_cow_head-to-deal-with-cloned-skbs.patch @@ -0,0 +1,40 @@ +From e9156cd26a495a18706e796f02a81fee41ec14f4 Mon Sep 17 00:00:00 2001 +From: James Hughes +Date: Wed, 19 Apr 2017 11:13:40 +0100 +Subject: [PATCH] smsc95xx: Use skb_cow_head to deal with cloned skbs + +The driver was failing to check that the SKB wasn't cloned +before adding checksum data. +Replace existing handling to extend/copy the header buffer +with skb_cow_head. + +Signed-off-by: James Hughes +Acked-by: Eric Dumazet +Acked-by: Woojung Huh +Signed-off-by: David S. Miller +--- + drivers/net/usb/smsc95xx.c | 12 ++++++------ + 1 file changed, 6 insertions(+), 6 deletions(-) + +--- a/drivers/net/usb/smsc95xx.c ++++ b/drivers/net/usb/smsc95xx.c +@@ -1835,13 +1835,13 @@ static struct sk_buff *smsc95xx_tx_fixup + /* We do not advertise SG, so skbs should be already linearized */ + BUG_ON(skb_shinfo(skb)->nr_frags); + +- if (skb_headroom(skb) < overhead) { +- struct sk_buff *skb2 = skb_copy_expand(skb, +- overhead, 0, flags); ++ /* Make writable and expand header space by overhead if required */ ++ if (skb_cow_head(skb, overhead)) { ++ /* Must deallocate here as returning NULL to indicate error ++ * means the skb won't be deallocated in the caller. ++ */ + dev_kfree_skb_any(skb); +- skb = skb2; +- if (!skb) +- return NULL; ++ return NULL; + } + + if (csum) { diff --git a/target/linux/generic/patches-4.4/030-2-smsc75xx-use-skb_cow_head-to-deal-with-cloned-skbs.patch b/target/linux/generic/patches-4.4/030-2-smsc75xx-use-skb_cow_head-to-deal-with-cloned-skbs.patch new file mode 100644 index 0000000000..6312f0f731 --- /dev/null +++ b/target/linux/generic/patches-4.4/030-2-smsc75xx-use-skb_cow_head-to-deal-with-cloned-skbs.patch @@ -0,0 +1,36 @@ +From b7c6d2675899cfff0180412c63fc9cbd5bacdb4d Mon Sep 17 00:00:00 2001 +From: Eric Dumazet +Date: Wed, 19 Apr 2017 09:59:21 -0700 +Subject: [PATCH] smsc75xx: use skb_cow_head() to deal with cloned skbs + +We need to ensure there is enough headroom to push extra header, +but we also need to check if we are allowed to change headers. + +skb_cow_head() is the proper helper to deal with this. + +Fixes: d0cad871703b ("smsc75xx: SMSC LAN75xx USB gigabit ethernet adapter driver") +Signed-off-by: Eric Dumazet +Cc: James Hughes +Signed-off-by: David S. Miller +--- + drivers/net/usb/smsc75xx.c | 8 ++------ + 1 file changed, 2 insertions(+), 6 deletions(-) + +--- a/drivers/net/usb/smsc75xx.c ++++ b/drivers/net/usb/smsc75xx.c +@@ -2193,13 +2193,9 @@ static struct sk_buff *smsc75xx_tx_fixup + { + u32 tx_cmd_a, tx_cmd_b; + +- if (skb_headroom(skb) < SMSC75XX_TX_OVERHEAD) { +- struct sk_buff *skb2 = +- skb_copy_expand(skb, SMSC75XX_TX_OVERHEAD, 0, flags); ++ if (skb_cow_head(skb, SMSC75XX_TX_OVERHEAD)) { + dev_kfree_skb_any(skb); +- skb = skb2; +- if (!skb) +- return NULL; ++ return NULL; + } + + tx_cmd_a = (u32)(skb->len & TX_CMD_A_LEN) | TX_CMD_A_FCS; diff --git a/target/linux/generic/patches-4.4/030-3-cx82310_eth-use-skb_cow_head-to-deal-with-cloned-skb.patch b/target/linux/generic/patches-4.4/030-3-cx82310_eth-use-skb_cow_head-to-deal-with-cloned-skb.patch new file mode 100644 index 0000000000..aee8aa9805 --- /dev/null +++ b/target/linux/generic/patches-4.4/030-3-cx82310_eth-use-skb_cow_head-to-deal-with-cloned-skb.patch @@ -0,0 +1,35 @@ +From a9e840a2081ed28c2b7caa6a9a0041c950b3c37d Mon Sep 17 00:00:00 2001 +From: Eric Dumazet +Date: Wed, 19 Apr 2017 09:59:22 -0700 +Subject: [PATCH] cx82310_eth: use skb_cow_head() to deal with cloned skbs + +We need to ensure there is enough headroom to push extra header, +but we also need to check if we are allowed to change headers. + +skb_cow_head() is the proper helper to deal with this. + +Fixes: cc28a20e77b2 ("introduce cx82310_eth: Conexant CX82310-based ADSL router USB ethernet driver") +Signed-off-by: Eric Dumazet +Cc: James Hughes +Signed-off-by: David S. Miller +--- + drivers/net/usb/cx82310_eth.c | 7 ++----- + 1 file changed, 2 insertions(+), 5 deletions(-) + +--- a/drivers/net/usb/cx82310_eth.c ++++ b/drivers/net/usb/cx82310_eth.c +@@ -293,12 +293,9 @@ static struct sk_buff *cx82310_tx_fixup( + { + int len = skb->len; + +- if (skb_headroom(skb) < 2) { +- struct sk_buff *skb2 = skb_copy_expand(skb, 2, 0, flags); ++ if (skb_cow_head(skb, 2)) { + dev_kfree_skb_any(skb); +- skb = skb2; +- if (!skb) +- return NULL; ++ return NULL; + } + skb_push(skb, 2); + diff --git a/target/linux/generic/patches-4.4/030-4-sr9700-use-skb_cow_head-to-deal-with-cloned-skbs.patch b/target/linux/generic/patches-4.4/030-4-sr9700-use-skb_cow_head-to-deal-with-cloned-skbs.patch new file mode 100644 index 0000000000..4d0fcf6fc2 --- /dev/null +++ b/target/linux/generic/patches-4.4/030-4-sr9700-use-skb_cow_head-to-deal-with-cloned-skbs.patch @@ -0,0 +1,37 @@ +From d532c1082f68176363ed766d09bf187616e282fe Mon Sep 17 00:00:00 2001 +From: Eric Dumazet +Date: Wed, 19 Apr 2017 09:59:23 -0700 +Subject: [PATCH] sr9700: use skb_cow_head() to deal with cloned skbs + +We need to ensure there is enough headroom to push extra header, +but we also need to check if we are allowed to change headers. + +skb_cow_head() is the proper helper to deal with this. + +Fixes: c9b37458e956 ("USB2NET : SR9700 : One chip USB 1.1 USB2NET SR9700Device Driver Support") +Signed-off-by: Eric Dumazet +Cc: James Hughes +Signed-off-by: David S. Miller +--- + drivers/net/usb/sr9700.c | 9 ++------- + 1 file changed, 2 insertions(+), 7 deletions(-) + +--- a/drivers/net/usb/sr9700.c ++++ b/drivers/net/usb/sr9700.c +@@ -456,14 +456,9 @@ static struct sk_buff *sr9700_tx_fixup(s + + len = skb->len; + +- if (skb_headroom(skb) < SR_TX_OVERHEAD) { +- struct sk_buff *skb2; +- +- skb2 = skb_copy_expand(skb, SR_TX_OVERHEAD, 0, flags); ++ if (skb_cow_head(skb, SR_TX_OVERHEAD)) { + dev_kfree_skb_any(skb); +- skb = skb2; +- if (!skb) +- return NULL; ++ return NULL; + } + + __skb_push(skb, SR_TX_OVERHEAD); diff --git a/target/linux/generic/patches-4.4/030-5-lan78xx-use-skb_cow_head-to-deal-with-cloned-skbs.patch b/target/linux/generic/patches-4.4/030-5-lan78xx-use-skb_cow_head-to-deal-with-cloned-skbs.patch new file mode 100644 index 0000000000..4f96041648 --- /dev/null +++ b/target/linux/generic/patches-4.4/030-5-lan78xx-use-skb_cow_head-to-deal-with-cloned-skbs.patch @@ -0,0 +1,38 @@ +From d4ca73591916b760478d2b04334d5dcadc028e9c Mon Sep 17 00:00:00 2001 +From: Eric Dumazet +Date: Wed, 19 Apr 2017 09:59:24 -0700 +Subject: [PATCH] lan78xx: use skb_cow_head() to deal with cloned skbs + +We need to ensure there is enough headroom to push extra header, +but we also need to check if we are allowed to change headers. + +skb_cow_head() is the proper helper to deal with this. + +Fixes: 55d7de9de6c3 ("Microchip's LAN7800 family USB 2/3 to 10/100/1000 Ethernet device driver") +Signed-off-by: Eric Dumazet +Cc: James Hughes +Cc: Woojung Huh +Signed-off-by: David S. Miller +--- + drivers/net/usb/lan78xx.c | 9 ++------- + 1 file changed, 2 insertions(+), 7 deletions(-) + +--- a/drivers/net/usb/lan78xx.c ++++ b/drivers/net/usb/lan78xx.c +@@ -2050,14 +2050,9 @@ static struct sk_buff *lan78xx_tx_prep(s + { + u32 tx_cmd_a, tx_cmd_b; + +- if (skb_headroom(skb) < TX_OVERHEAD) { +- struct sk_buff *skb2; +- +- skb2 = skb_copy_expand(skb, TX_OVERHEAD, 0, flags); ++ if (skb_cow_head(skb, TX_OVERHEAD)) { + dev_kfree_skb_any(skb); +- skb = skb2; +- if (!skb) +- return NULL; ++ return NULL; + } + + if (lan78xx_linearize(skb) < 0) diff --git a/target/linux/generic/patches-4.4/030-6-ch9200-use-skb_cow_head-to-deal-with-cloned-skbs.patch b/target/linux/generic/patches-4.4/030-6-ch9200-use-skb_cow_head-to-deal-with-cloned-skbs.patch new file mode 100644 index 0000000000..2e8bba57e0 --- /dev/null +++ b/target/linux/generic/patches-4.4/030-6-ch9200-use-skb_cow_head-to-deal-with-cloned-skbs.patch @@ -0,0 +1,38 @@ +From 6bc6895bdd6744e0136eaa4a11fbdb20a7db4e40 Mon Sep 17 00:00:00 2001 +From: Eric Dumazet +Date: Wed, 19 Apr 2017 09:59:25 -0700 +Subject: [PATCH] ch9200: use skb_cow_head() to deal with cloned skbs + +We need to ensure there is enough headroom to push extra header, +but we also need to check if we are allowed to change headers. + +skb_cow_head() is the proper helper to deal with this. + +Fixes: 4a476bd6d1d9 ("usbnet: New driver for QinHeng CH9200 devices") +Signed-off-by: Eric Dumazet +Cc: James Hughes +Cc: Matthew Garrett +Signed-off-by: David S. Miller +--- + drivers/net/usb/ch9200.c | 9 ++------- + 1 file changed, 2 insertions(+), 7 deletions(-) + +--- a/drivers/net/usb/ch9200.c ++++ b/drivers/net/usb/ch9200.c +@@ -255,14 +255,9 @@ static struct sk_buff *ch9200_tx_fixup(s + tx_overhead = 0x40; + + len = skb->len; +- if (skb_headroom(skb) < tx_overhead) { +- struct sk_buff *skb2; +- +- skb2 = skb_copy_expand(skb, tx_overhead, 0, flags); ++ if (skb_cow_head(skb, tx_overhead)) { + dev_kfree_skb_any(skb); +- skb = skb2; +- if (!skb) +- return NULL; ++ return NULL; + } + + __skb_push(skb, tx_overhead); diff --git a/target/linux/generic/patches-4.4/030-7-kaweth-use-skb_cow_head-to-deal-with-cloned-skbs.patch b/target/linux/generic/patches-4.4/030-7-kaweth-use-skb_cow_head-to-deal-with-cloned-skbs.patch new file mode 100644 index 0000000000..541c694bec --- /dev/null +++ b/target/linux/generic/patches-4.4/030-7-kaweth-use-skb_cow_head-to-deal-with-cloned-skbs.patch @@ -0,0 +1,43 @@ +From 39fba7835aacda65284a86e611774cbba71dac20 Mon Sep 17 00:00:00 2001 +From: Eric Dumazet +Date: Wed, 19 Apr 2017 09:59:26 -0700 +Subject: [PATCH] kaweth: use skb_cow_head() to deal with cloned skbs + +We can use skb_cow_head() to properly deal with clones, +especially the ones coming from TCP stack that allow their head being +modified. This avoids a copy. + +Signed-off-by: Eric Dumazet +Cc: James Hughes +Signed-off-by: David S. Miller +--- + drivers/net/usb/kaweth.c | 18 ++++++------------ + 1 file changed, 6 insertions(+), 12 deletions(-) + +--- a/drivers/net/usb/kaweth.c ++++ b/drivers/net/usb/kaweth.c +@@ -812,18 +812,12 @@ static netdev_tx_t kaweth_start_xmit(str + } + + /* We now decide whether we can put our special header into the sk_buff */ +- if (skb_cloned(skb) || skb_headroom(skb) < 2) { +- /* no such luck - we make our own */ +- struct sk_buff *copied_skb; +- copied_skb = skb_copy_expand(skb, 2, 0, GFP_ATOMIC); +- dev_kfree_skb_irq(skb); +- skb = copied_skb; +- if (!copied_skb) { +- kaweth->stats.tx_errors++; +- netif_start_queue(net); +- spin_unlock_irq(&kaweth->device_lock); +- return NETDEV_TX_OK; +- } ++ if (skb_cow_head(skb, 2)) { ++ kaweth->stats.tx_errors++; ++ netif_start_queue(net); ++ spin_unlock_irq(&kaweth->device_lock); ++ dev_kfree_skb_any(skb); ++ return NETDEV_TX_OK; + } + + private_header = (__le16 *)__skb_push(skb, 2); diff --git a/target/linux/generic/patches-4.9/023-1-smsc95xx-Use-skb_cow_head-to-deal-with-cloned-skbs.patch b/target/linux/generic/patches-4.9/023-1-smsc95xx-Use-skb_cow_head-to-deal-with-cloned-skbs.patch new file mode 100644 index 0000000000..cfc9abb3b7 --- /dev/null +++ b/target/linux/generic/patches-4.9/023-1-smsc95xx-Use-skb_cow_head-to-deal-with-cloned-skbs.patch @@ -0,0 +1,40 @@ +From e9156cd26a495a18706e796f02a81fee41ec14f4 Mon Sep 17 00:00:00 2001 +From: James Hughes +Date: Wed, 19 Apr 2017 11:13:40 +0100 +Subject: [PATCH] smsc95xx: Use skb_cow_head to deal with cloned skbs + +The driver was failing to check that the SKB wasn't cloned +before adding checksum data. +Replace existing handling to extend/copy the header buffer +with skb_cow_head. + +Signed-off-by: James Hughes +Acked-by: Eric Dumazet +Acked-by: Woojung Huh +Signed-off-by: David S. Miller +--- + drivers/net/usb/smsc95xx.c | 12 ++++++------ + 1 file changed, 6 insertions(+), 6 deletions(-) + +--- a/drivers/net/usb/smsc95xx.c ++++ b/drivers/net/usb/smsc95xx.c +@@ -2001,13 +2001,13 @@ static struct sk_buff *smsc95xx_tx_fixup + /* We do not advertise SG, so skbs should be already linearized */ + BUG_ON(skb_shinfo(skb)->nr_frags); + +- if (skb_headroom(skb) < overhead) { +- struct sk_buff *skb2 = skb_copy_expand(skb, +- overhead, 0, flags); ++ /* Make writable and expand header space by overhead if required */ ++ if (skb_cow_head(skb, overhead)) { ++ /* Must deallocate here as returning NULL to indicate error ++ * means the skb won't be deallocated in the caller. ++ */ + dev_kfree_skb_any(skb); +- skb = skb2; +- if (!skb) +- return NULL; ++ return NULL; + } + + if (csum) { diff --git a/target/linux/generic/patches-4.9/023-2-smsc75xx-use-skb_cow_head-to-deal-with-cloned-skbs.patch b/target/linux/generic/patches-4.9/023-2-smsc75xx-use-skb_cow_head-to-deal-with-cloned-skbs.patch new file mode 100644 index 0000000000..99d98e101c --- /dev/null +++ b/target/linux/generic/patches-4.9/023-2-smsc75xx-use-skb_cow_head-to-deal-with-cloned-skbs.patch @@ -0,0 +1,36 @@ +From b7c6d2675899cfff0180412c63fc9cbd5bacdb4d Mon Sep 17 00:00:00 2001 +From: Eric Dumazet +Date: Wed, 19 Apr 2017 09:59:21 -0700 +Subject: [PATCH] smsc75xx: use skb_cow_head() to deal with cloned skbs + +We need to ensure there is enough headroom to push extra header, +but we also need to check if we are allowed to change headers. + +skb_cow_head() is the proper helper to deal with this. + +Fixes: d0cad871703b ("smsc75xx: SMSC LAN75xx USB gigabit ethernet adapter driver") +Signed-off-by: Eric Dumazet +Cc: James Hughes +Signed-off-by: David S. Miller +--- + drivers/net/usb/smsc75xx.c | 8 ++------ + 1 file changed, 2 insertions(+), 6 deletions(-) + +--- a/drivers/net/usb/smsc75xx.c ++++ b/drivers/net/usb/smsc75xx.c +@@ -2205,13 +2205,9 @@ static struct sk_buff *smsc75xx_tx_fixup + { + u32 tx_cmd_a, tx_cmd_b; + +- if (skb_headroom(skb) < SMSC75XX_TX_OVERHEAD) { +- struct sk_buff *skb2 = +- skb_copy_expand(skb, SMSC75XX_TX_OVERHEAD, 0, flags); ++ if (skb_cow_head(skb, SMSC75XX_TX_OVERHEAD)) { + dev_kfree_skb_any(skb); +- skb = skb2; +- if (!skb) +- return NULL; ++ return NULL; + } + + tx_cmd_a = (u32)(skb->len & TX_CMD_A_LEN) | TX_CMD_A_FCS; diff --git a/target/linux/generic/patches-4.9/023-3-cx82310_eth-use-skb_cow_head-to-deal-with-cloned-skb.patch b/target/linux/generic/patches-4.9/023-3-cx82310_eth-use-skb_cow_head-to-deal-with-cloned-skb.patch new file mode 100644 index 0000000000..aee8aa9805 --- /dev/null +++ b/target/linux/generic/patches-4.9/023-3-cx82310_eth-use-skb_cow_head-to-deal-with-cloned-skb.patch @@ -0,0 +1,35 @@ +From a9e840a2081ed28c2b7caa6a9a0041c950b3c37d Mon Sep 17 00:00:00 2001 +From: Eric Dumazet +Date: Wed, 19 Apr 2017 09:59:22 -0700 +Subject: [PATCH] cx82310_eth: use skb_cow_head() to deal with cloned skbs + +We need to ensure there is enough headroom to push extra header, +but we also need to check if we are allowed to change headers. + +skb_cow_head() is the proper helper to deal with this. + +Fixes: cc28a20e77b2 ("introduce cx82310_eth: Conexant CX82310-based ADSL router USB ethernet driver") +Signed-off-by: Eric Dumazet +Cc: James Hughes +Signed-off-by: David S. Miller +--- + drivers/net/usb/cx82310_eth.c | 7 ++----- + 1 file changed, 2 insertions(+), 5 deletions(-) + +--- a/drivers/net/usb/cx82310_eth.c ++++ b/drivers/net/usb/cx82310_eth.c +@@ -293,12 +293,9 @@ static struct sk_buff *cx82310_tx_fixup( + { + int len = skb->len; + +- if (skb_headroom(skb) < 2) { +- struct sk_buff *skb2 = skb_copy_expand(skb, 2, 0, flags); ++ if (skb_cow_head(skb, 2)) { + dev_kfree_skb_any(skb); +- skb = skb2; +- if (!skb) +- return NULL; ++ return NULL; + } + skb_push(skb, 2); + diff --git a/target/linux/generic/patches-4.9/023-4-sr9700-use-skb_cow_head-to-deal-with-cloned-skbs.patch b/target/linux/generic/patches-4.9/023-4-sr9700-use-skb_cow_head-to-deal-with-cloned-skbs.patch new file mode 100644 index 0000000000..4d0fcf6fc2 --- /dev/null +++ b/target/linux/generic/patches-4.9/023-4-sr9700-use-skb_cow_head-to-deal-with-cloned-skbs.patch @@ -0,0 +1,37 @@ +From d532c1082f68176363ed766d09bf187616e282fe Mon Sep 17 00:00:00 2001 +From: Eric Dumazet +Date: Wed, 19 Apr 2017 09:59:23 -0700 +Subject: [PATCH] sr9700: use skb_cow_head() to deal with cloned skbs + +We need to ensure there is enough headroom to push extra header, +but we also need to check if we are allowed to change headers. + +skb_cow_head() is the proper helper to deal with this. + +Fixes: c9b37458e956 ("USB2NET : SR9700 : One chip USB 1.1 USB2NET SR9700Device Driver Support") +Signed-off-by: Eric Dumazet +Cc: James Hughes +Signed-off-by: David S. Miller +--- + drivers/net/usb/sr9700.c | 9 ++------- + 1 file changed, 2 insertions(+), 7 deletions(-) + +--- a/drivers/net/usb/sr9700.c ++++ b/drivers/net/usb/sr9700.c +@@ -456,14 +456,9 @@ static struct sk_buff *sr9700_tx_fixup(s + + len = skb->len; + +- if (skb_headroom(skb) < SR_TX_OVERHEAD) { +- struct sk_buff *skb2; +- +- skb2 = skb_copy_expand(skb, SR_TX_OVERHEAD, 0, flags); ++ if (skb_cow_head(skb, SR_TX_OVERHEAD)) { + dev_kfree_skb_any(skb); +- skb = skb2; +- if (!skb) +- return NULL; ++ return NULL; + } + + __skb_push(skb, SR_TX_OVERHEAD); diff --git a/target/linux/generic/patches-4.9/023-5-lan78xx-use-skb_cow_head-to-deal-with-cloned-skbs.patch b/target/linux/generic/patches-4.9/023-5-lan78xx-use-skb_cow_head-to-deal-with-cloned-skbs.patch new file mode 100644 index 0000000000..ea8279940b --- /dev/null +++ b/target/linux/generic/patches-4.9/023-5-lan78xx-use-skb_cow_head-to-deal-with-cloned-skbs.patch @@ -0,0 +1,38 @@ +From d4ca73591916b760478d2b04334d5dcadc028e9c Mon Sep 17 00:00:00 2001 +From: Eric Dumazet +Date: Wed, 19 Apr 2017 09:59:24 -0700 +Subject: [PATCH] lan78xx: use skb_cow_head() to deal with cloned skbs + +We need to ensure there is enough headroom to push extra header, +but we also need to check if we are allowed to change headers. + +skb_cow_head() is the proper helper to deal with this. + +Fixes: 55d7de9de6c3 ("Microchip's LAN7800 family USB 2/3 to 10/100/1000 Ethernet device driver") +Signed-off-by: Eric Dumazet +Cc: James Hughes +Cc: Woojung Huh +Signed-off-by: David S. Miller +--- + drivers/net/usb/lan78xx.c | 9 ++------- + 1 file changed, 2 insertions(+), 7 deletions(-) + +--- a/drivers/net/usb/lan78xx.c ++++ b/drivers/net/usb/lan78xx.c +@@ -2419,14 +2419,9 @@ static struct sk_buff *lan78xx_tx_prep(s + { + u32 tx_cmd_a, tx_cmd_b; + +- if (skb_headroom(skb) < TX_OVERHEAD) { +- struct sk_buff *skb2; +- +- skb2 = skb_copy_expand(skb, TX_OVERHEAD, 0, flags); ++ if (skb_cow_head(skb, TX_OVERHEAD)) { + dev_kfree_skb_any(skb); +- skb = skb2; +- if (!skb) +- return NULL; ++ return NULL; + } + + if (lan78xx_linearize(skb) < 0) diff --git a/target/linux/generic/patches-4.9/023-6-ch9200-use-skb_cow_head-to-deal-with-cloned-skbs.patch b/target/linux/generic/patches-4.9/023-6-ch9200-use-skb_cow_head-to-deal-with-cloned-skbs.patch new file mode 100644 index 0000000000..83de38bf8a --- /dev/null +++ b/target/linux/generic/patches-4.9/023-6-ch9200-use-skb_cow_head-to-deal-with-cloned-skbs.patch @@ -0,0 +1,38 @@ +From 6bc6895bdd6744e0136eaa4a11fbdb20a7db4e40 Mon Sep 17 00:00:00 2001 +From: Eric Dumazet +Date: Wed, 19 Apr 2017 09:59:25 -0700 +Subject: [PATCH] ch9200: use skb_cow_head() to deal with cloned skbs + +We need to ensure there is enough headroom to push extra header, +but we also need to check if we are allowed to change headers. + +skb_cow_head() is the proper helper to deal with this. + +Fixes: 4a476bd6d1d9 ("usbnet: New driver for QinHeng CH9200 devices") +Signed-off-by: Eric Dumazet +Cc: James Hughes +Cc: Matthew Garrett +Signed-off-by: David S. Miller +--- + drivers/net/usb/ch9200.c | 9 ++------- + 1 file changed, 2 insertions(+), 7 deletions(-) + +--- a/drivers/net/usb/ch9200.c ++++ b/drivers/net/usb/ch9200.c +@@ -254,14 +254,9 @@ static struct sk_buff *ch9200_tx_fixup(s + tx_overhead = 0x40; + + len = skb->len; +- if (skb_headroom(skb) < tx_overhead) { +- struct sk_buff *skb2; +- +- skb2 = skb_copy_expand(skb, tx_overhead, 0, flags); ++ if (skb_cow_head(skb, tx_overhead)) { + dev_kfree_skb_any(skb); +- skb = skb2; +- if (!skb) +- return NULL; ++ return NULL; + } + + __skb_push(skb, tx_overhead); diff --git a/target/linux/generic/patches-4.9/023-7-kaweth-use-skb_cow_head-to-deal-with-cloned-skbs.patch b/target/linux/generic/patches-4.9/023-7-kaweth-use-skb_cow_head-to-deal-with-cloned-skbs.patch new file mode 100644 index 0000000000..597f25b21d --- /dev/null +++ b/target/linux/generic/patches-4.9/023-7-kaweth-use-skb_cow_head-to-deal-with-cloned-skbs.patch @@ -0,0 +1,43 @@ +From 39fba7835aacda65284a86e611774cbba71dac20 Mon Sep 17 00:00:00 2001 +From: Eric Dumazet +Date: Wed, 19 Apr 2017 09:59:26 -0700 +Subject: [PATCH] kaweth: use skb_cow_head() to deal with cloned skbs + +We can use skb_cow_head() to properly deal with clones, +especially the ones coming from TCP stack that allow their head being +modified. This avoids a copy. + +Signed-off-by: Eric Dumazet +Cc: James Hughes +Signed-off-by: David S. Miller +--- + drivers/net/usb/kaweth.c | 18 ++++++------------ + 1 file changed, 6 insertions(+), 12 deletions(-) + +--- a/drivers/net/usb/kaweth.c ++++ b/drivers/net/usb/kaweth.c +@@ -803,18 +803,12 @@ static netdev_tx_t kaweth_start_xmit(str + } + + /* We now decide whether we can put our special header into the sk_buff */ +- if (skb_cloned(skb) || skb_headroom(skb) < 2) { +- /* no such luck - we make our own */ +- struct sk_buff *copied_skb; +- copied_skb = skb_copy_expand(skb, 2, 0, GFP_ATOMIC); +- dev_kfree_skb_irq(skb); +- skb = copied_skb; +- if (!copied_skb) { +- kaweth->stats.tx_errors++; +- netif_start_queue(net); +- spin_unlock_irq(&kaweth->device_lock); +- return NETDEV_TX_OK; +- } ++ if (skb_cow_head(skb, 2)) { ++ kaweth->stats.tx_errors++; ++ netif_start_queue(net); ++ spin_unlock_irq(&kaweth->device_lock); ++ dev_kfree_skb_any(skb); ++ return NETDEV_TX_OK; + } + + private_header = (__le16 *)__skb_push(skb, 2);