Skip to content

Commit 04d55b2

Browse files
Alexander Duyckdavem330
authored andcommitted
udp: Do not copy destructor if one is not present
This patch makes it so that if a destructor is not present we avoid trying to update the skb socket or any reference counting that would be associated with the NULL socket and/or descriptor. By doing this we can support traffic coming from another namespace without any issues. Acked-by: Willem de Bruijn <[email protected]> Signed-off-by: Alexander Duyck <[email protected]> Reviewed-by: Eric Dumazet <[email protected]> Signed-off-by: David S. Miller <[email protected]>
1 parent 6053d0f commit 04d55b2

File tree

1 file changed

+14
-8
lines changed

1 file changed

+14
-8
lines changed

net/ipv4/udp_offload.c

Lines changed: 14 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -195,6 +195,7 @@ struct sk_buff *__udp_gso_segment(struct sk_buff *gso_skb,
195195
struct sk_buff *segs, *seg;
196196
struct udphdr *uh;
197197
unsigned int mss;
198+
bool copy_dtor;
198199
__sum16 check;
199200
__be16 newlen;
200201

@@ -205,12 +206,14 @@ struct sk_buff *__udp_gso_segment(struct sk_buff *gso_skb,
205206
skb_pull(gso_skb, sizeof(*uh));
206207

207208
/* clear destructor to avoid skb_segment assigning it to tail */
208-
WARN_ON_ONCE(gso_skb->destructor != sock_wfree);
209-
gso_skb->destructor = NULL;
209+
copy_dtor = gso_skb->destructor == sock_wfree;
210+
if (copy_dtor)
211+
gso_skb->destructor = NULL;
210212

211213
segs = skb_segment(gso_skb, features);
212214
if (unlikely(IS_ERR_OR_NULL(segs))) {
213-
gso_skb->destructor = sock_wfree;
215+
if (copy_dtor)
216+
gso_skb->destructor = sock_wfree;
214217
return segs;
215218
}
216219

@@ -229,9 +232,11 @@ struct sk_buff *__udp_gso_segment(struct sk_buff *gso_skb,
229232
check = csum16_add(csum16_sub(uh->check, uh->len), newlen);
230233

231234
for (;;) {
232-
seg->destructor = sock_wfree;
233-
seg->sk = sk;
234-
sum_truesize += seg->truesize;
235+
if (copy_dtor) {
236+
seg->destructor = sock_wfree;
237+
seg->sk = sk;
238+
sum_truesize += seg->truesize;
239+
}
235240

236241
if (!seg->next)
237242
break;
@@ -263,8 +268,9 @@ struct sk_buff *__udp_gso_segment(struct sk_buff *gso_skb,
263268
uh->check = gso_make_checksum(seg, ~check) ? : CSUM_MANGLED_0;
264269

265270
/* update refcount for the packet */
266-
refcount_add(sum_truesize - gso_skb->truesize, &sk->sk_wmem_alloc);
267-
271+
if (copy_dtor)
272+
refcount_add(sum_truesize - gso_skb->truesize,
273+
&sk->sk_wmem_alloc);
268274
return segs;
269275
}
270276
EXPORT_SYMBOL_GPL(__udp_gso_segment);

0 commit comments

Comments
 (0)