Skip to content

Commit d091e57

Browse files
nbd168davem330
authored andcommitted
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: 3a1296a ("net: Support GRO/GSO fraglist chaining.") Signed-off-by: Felix Fietkau <[email protected]> Signed-off-by: David S. Miller <[email protected]>
1 parent 59c878c commit d091e57

File tree

1 file changed

+19
-8
lines changed

1 file changed

+19
-8
lines changed

net/core/skbuff.c

Lines changed: 19 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -2123,11 +2123,17 @@ static inline int skb_alloc_rx_flag(const struct sk_buff *skb)
21232123

21242124
struct sk_buff *skb_copy(const struct sk_buff *skb, gfp_t gfp_mask)
21252125
{
2126-
int headerlen = skb_headroom(skb);
2127-
unsigned int size = skb_end_offset(skb) + skb->data_len;
2128-
struct sk_buff *n = __alloc_skb(size, gfp_mask,
2129-
skb_alloc_rx_flag(skb), NUMA_NO_NODE);
2126+
struct sk_buff *n;
2127+
unsigned int size;
2128+
int headerlen;
2129+
2130+
if (WARN_ON_ONCE(skb_shinfo(skb)->gso_type & SKB_GSO_FRAGLIST))
2131+
return NULL;
21302132

2133+
headerlen = skb_headroom(skb);
2134+
size = skb_end_offset(skb) + skb->data_len;
2135+
n = __alloc_skb(size, gfp_mask,
2136+
skb_alloc_rx_flag(skb), NUMA_NO_NODE);
21312137
if (!n)
21322138
return NULL;
21332139

@@ -2455,12 +2461,17 @@ struct sk_buff *skb_copy_expand(const struct sk_buff *skb,
24552461
/*
24562462
* Allocate the copy buffer
24572463
*/
2458-
struct sk_buff *n = __alloc_skb(newheadroom + skb->len + newtailroom,
2459-
gfp_mask, skb_alloc_rx_flag(skb),
2460-
NUMA_NO_NODE);
2461-
int oldheadroom = skb_headroom(skb);
24622464
int head_copy_len, head_copy_off;
2465+
struct sk_buff *n;
2466+
int oldheadroom;
2467+
2468+
if (WARN_ON_ONCE(skb_shinfo(skb)->gso_type & SKB_GSO_FRAGLIST))
2469+
return NULL;
24632470

2471+
oldheadroom = skb_headroom(skb);
2472+
n = __alloc_skb(newheadroom + skb->len + newtailroom,
2473+
gfp_mask, skb_alloc_rx_flag(skb),
2474+
NUMA_NO_NODE);
24642475
if (!n)
24652476
return NULL;
24662477

0 commit comments

Comments
 (0)