+++ /dev/null
-From f99dc00b5934c90c2b22d275254ca777025d3e44 Mon Sep 17 00:00:00 2001
-From: Sasha Levin <sashal@kernel.org>
-Date: Sat, 27 Apr 2024 20:24:19 +0200
-Subject: net: core: reject skb_copy(_expand) for fraglist GSO skbs
-
-From: Felix Fietkau <nbd@nbd.name>
-
-[ Upstream commit d091e579b864fa790dd6a0cd537a22c383126681 ]
-
-SKB_GSO_FRAGLIST skbs must not be linearized, otherwise they become
-invalid. Return NULL if such an skb is passed to skb_copy or
-skb_copy_expand, in order to prevent a crash on a potential later
-call to skb_gso_segment.
-
-Fixes: 3a1296a38d0c ("net: Support GRO/GSO fraglist chaining.")
-Signed-off-by: Felix Fietkau <nbd@nbd.name>
-Signed-off-by: David S. Miller <davem@davemloft.net>
-Signed-off-by: Sasha Levin <sashal@kernel.org>
----
- net/core/skbuff.c | 27 +++++++++++++++++++--------
- 1 file changed, 19 insertions(+), 8 deletions(-)
-
-diff --git a/net/core/skbuff.c b/net/core/skbuff.c
-index 50261f3aec82b..fd53b66f2ca1d 100644
---- a/net/core/skbuff.c
-+++ b/net/core/skbuff.c
-@@ -1516,11 +1516,17 @@ static inline int skb_alloc_rx_flag(const struct sk_buff *skb)
-
- struct sk_buff *skb_copy(const struct sk_buff *skb, gfp_t gfp_mask)
- {
-- int headerlen = skb_headroom(skb);
-- unsigned int size = skb_end_offset(skb) + skb->data_len;
-- struct sk_buff *n = __alloc_skb(size, gfp_mask,
-- skb_alloc_rx_flag(skb), NUMA_NO_NODE);
-+ struct sk_buff *n;
-+ unsigned int size;
-+ int headerlen;
-+
-+ if (WARN_ON_ONCE(skb_shinfo(skb)->gso_type & SKB_GSO_FRAGLIST))
-+ return NULL;
-
-+ headerlen = skb_headroom(skb);
-+ size = skb_end_offset(skb) + skb->data_len;
-+ n = __alloc_skb(size, gfp_mask,
-+ skb_alloc_rx_flag(skb), NUMA_NO_NODE);
- if (!n)
- return NULL;
-
-@@ -1750,12 +1756,17 @@ struct sk_buff *skb_copy_expand(const struct sk_buff *skb,
- /*
- * Allocate the copy buffer
- */
-- struct sk_buff *n = __alloc_skb(newheadroom + skb->len + newtailroom,
-- gfp_mask, skb_alloc_rx_flag(skb),
-- NUMA_NO_NODE);
-- int oldheadroom = skb_headroom(skb);
- int head_copy_len, head_copy_off;
-+ struct sk_buff *n;
-+ int oldheadroom;
-+
-+ if (WARN_ON_ONCE(skb_shinfo(skb)->gso_type & SKB_GSO_FRAGLIST))
-+ return NULL;
-
-+ oldheadroom = skb_headroom(skb);
-+ n = __alloc_skb(newheadroom + skb->len + newtailroom,
-+ gfp_mask, skb_alloc_rx_flag(skb),
-+ NUMA_NO_NODE);
- if (!n)
- return NULL;
-
---
-2.43.0
-