60 lines
1.8 KiB
Diff
60 lines
1.8 KiB
Diff
From: Felix Fietkau <nbd@nbd.name>
|
|
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 <nbd@nbd.name>
|
|
---
|
|
|
|
--- a/net/core/skbuff.c
|
|
+++ b/net/core/skbuff.c
|
|
@@ -1971,11 +1971,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;
|
|
|
|
@@ -2303,12 +2309,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;
|
|
|