|
|
@@ -0,0 +1,59 @@
|
|
|
+From: Felix Fietkau <[email protected]>
|
|
|
+Date: Sat, 27 Apr 2024 19:29:45 +0200
|
|
|
+Subject: [PATCH] net: core: reject skb_copy(_expand) for fraglist GSO skbs
|
|
|
+
|
|
|
+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 <[email protected]>
|
|
|
+---
|
|
|
+
|
|
|
+--- a/net/core/skbuff.c
|
|
|
++++ b/net/core/skbuff.c
|
|
|
+@@ -1720,11 +1720,17 @@ static inline int skb_alloc_rx_flag(cons
|
|
|
+
|
|
|
+ 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;
|
|
|
+
|
|
|
+@@ -2037,12 +2043,17 @@ struct sk_buff *skb_copy_expand(const st
|
|
|
+ /*
|
|
|
+ * 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;
|
|
|
+
|