From ccb2390d4fa59d6880d8e3948b10ce05579ce355 Mon Sep 17 00:00:00 2001 From: Felix Fietkau Date: Sun, 5 May 2024 20:48:23 +0200 Subject: [PATCH] kernel: fix corrupted ethernet header on bridge multicast-to-unicast Fixes: 45a8e962a591 ("kernel: fix crash with multicast-to-unicast and fraglist GRO") Signed-off-by: Felix Fietkau --- ...orrupted-ethernet-header-on-multicas.patch | 42 +++++++++++++++++++ ...orrupted-ethernet-header-on-multicas.patch | 42 +++++++++++++++++++ 2 files changed, 84 insertions(+) create mode 100644 target/linux/generic/pending-6.1/684-net-bridge-fix-corrupted-ethernet-header-on-multicas.patch create mode 100644 target/linux/generic/pending-6.6/684-net-bridge-fix-corrupted-ethernet-header-on-multicas.patch diff --git a/target/linux/generic/pending-6.1/684-net-bridge-fix-corrupted-ethernet-header-on-multicas.patch b/target/linux/generic/pending-6.1/684-net-bridge-fix-corrupted-ethernet-header-on-multicas.patch new file mode 100644 index 0000000000..c315790082 --- /dev/null +++ b/target/linux/generic/pending-6.1/684-net-bridge-fix-corrupted-ethernet-header-on-multicas.patch @@ -0,0 +1,42 @@ +From: Felix Fietkau +Date: Sun, 5 May 2024 20:36:56 +0200 +Subject: [PATCH] net: bridge: fix corrupted ethernet header on + multicast-to-unicast + +The change from skb_copy to pskb_copy unfortunately changed the data +copying to omit the ethernet header, since it was pulled before reaching +this point. Fix this by calling __skb_push/pull around pskb_copy. + +Fixes: 59c878cbcdd8 ("net: bridge: fix multicast-to-unicast with fraglist GSO") +Signed-off-by: Felix Fietkau +--- + +--- a/net/bridge/br_forward.c ++++ b/net/bridge/br_forward.c +@@ -253,6 +253,7 @@ static void maybe_deliver_addr(struct ne + { + struct net_device *dev = BR_INPUT_SKB_CB(skb)->brdev; + const unsigned char *src = eth_hdr(skb)->h_source; ++ struct sk_buff *nskb; + + if (!should_deliver(p, skb)) + return; +@@ -261,12 +262,16 @@ static void maybe_deliver_addr(struct ne + if (skb->dev == p->dev && ether_addr_equal(src, addr)) + return; + +- skb = pskb_copy(skb, GFP_ATOMIC); +- if (!skb) { ++ __skb_push(skb, ETH_HLEN); ++ nskb = pskb_copy(skb, GFP_ATOMIC); ++ __skb_pull(skb, ETH_HLEN); ++ if (!nskb) { + DEV_STATS_INC(dev, tx_dropped); + return; + } + ++ skb = nskb; ++ __skb_pull(skb, ETH_HLEN); + if (!is_broadcast_ether_addr(addr)) + memcpy(eth_hdr(skb)->h_dest, addr, ETH_ALEN); + diff --git a/target/linux/generic/pending-6.6/684-net-bridge-fix-corrupted-ethernet-header-on-multicas.patch b/target/linux/generic/pending-6.6/684-net-bridge-fix-corrupted-ethernet-header-on-multicas.patch new file mode 100644 index 0000000000..fb2fab24e3 --- /dev/null +++ b/target/linux/generic/pending-6.6/684-net-bridge-fix-corrupted-ethernet-header-on-multicas.patch @@ -0,0 +1,42 @@ +From: Felix Fietkau +Date: Sun, 5 May 2024 20:36:56 +0200 +Subject: [PATCH] net: bridge: fix corrupted ethernet header on + multicast-to-unicast + +The change from skb_copy to pskb_copy unfortunately changed the data +copying to omit the ethernet header, since it was pulled before reaching +this point. Fix this by calling __skb_push/pull around pskb_copy. + +Fixes: 59c878cbcdd8 ("net: bridge: fix multicast-to-unicast with fraglist GSO") +Signed-off-by: Felix Fietkau +--- + +--- a/net/bridge/br_forward.c ++++ b/net/bridge/br_forward.c +@@ -258,6 +258,7 @@ static void maybe_deliver_addr(struct ne + { + struct net_device *dev = BR_INPUT_SKB_CB(skb)->brdev; + const unsigned char *src = eth_hdr(skb)->h_source; ++ struct sk_buff *nskb; + + if (!should_deliver(p, skb)) + return; +@@ -266,12 +267,16 @@ static void maybe_deliver_addr(struct ne + if (skb->dev == p->dev && ether_addr_equal(src, addr)) + return; + +- skb = pskb_copy(skb, GFP_ATOMIC); +- if (!skb) { ++ __skb_push(skb, ETH_HLEN); ++ nskb = pskb_copy(skb, GFP_ATOMIC); ++ __skb_pull(skb, ETH_HLEN); ++ if (!nskb) { + DEV_STATS_INC(dev, tx_dropped); + return; + } + ++ skb = nskb; ++ __skb_pull(skb, ETH_HLEN); + if (!is_broadcast_ether_addr(addr)) + memcpy(eth_hdr(skb)->h_dest, addr, ETH_ALEN); + -- 2.30.2