History

udp: prevent skbs lingering in tunnel socket queues

In case we find a socket with encapsulation enabled we should call the encap_recv function even if just a udp header without payload is available. The callbacks are responsible for correctly verifying and dropping the packets. Also, in case the header validation fails for geneve and vxlan we shouldn't put the skb back into the socket queue, no one will pick them up there. Instead we can simply discard them in the respective encap_recv functions.

Hannes Frederic Sowa committed 10 years ago

Commit e5aed001 parent cb543e84 files · +7 −11Browse files

Unified · Split

4 files
  1. drivers/net/geneve.c +3 −7
  2. drivers/net/vxlan.c +2 −2
  3. net/ipv4/udp.c +1 −1
  4. net/ipv6/udp.c +1 −1
drivers/net/geneve.c+3−7
@@ -335,15 +335,15 @@ static int geneve_udp_encap_recv(struct sock *sk, struct sk_buff *skb) · 334 unmodified lines
335 335
336 /* Need Geneve and inner Ethernet header to be present */336 /* Need Geneve and inner Ethernet header to be present */
337 if (unlikely(!pskb_may_pull(skb, GENEVE_BASE_HLEN)))337 if (unlikely(!pskb_may_pull(skb, GENEVE_BASE_HLEN)))
338 goto error;338 goto drop;
339 339
340 /* Return packets with reserved bits set */340 /* Return packets with reserved bits set */
341 geneveh = geneve_hdr(skb);341 geneveh = geneve_hdr(skb);
342 if (unlikely(geneveh->ver != GENEVE_VER))342 if (unlikely(geneveh->ver != GENEVE_VER))
343 goto error;343 goto drop;
344 344
345 if (unlikely(geneveh->proto_type != htons(ETH_P_TEB)))345 if (unlikely(geneveh->proto_type != htons(ETH_P_TEB)))
346 goto error;346 goto drop;
347 347
348 gs = rcu_dereference_sk_user_data(sk);348 gs = rcu_dereference_sk_user_data(sk);
349 if (!gs)349 if (!gs)
@@ -366,10 +366,6 @@ drop: · 16 unmodified lines
366 /* Consume bad packet */366 /* Consume bad packet */
367 kfree_skb(skb);367 kfree_skb(skb);
368 return 0;368 return 0;
369
370error:
371 /* Let the UDP layer deal with the skb */
372 return 1;
373}369}
374 370
375static struct socket *geneve_create_sock(struct net *net, bool ipv6,371static struct socket *geneve_create_sock(struct net *net, bool ipv6,
drivers/net/vxlan.c+2−2
@@ -1304,7 +1304,7 @@ static int vxlan_rcv(struct sock *sk, struct sk_buff *skb) · 1303 unmodified lines
1304 1304
1305 /* Need UDP and VXLAN header to be present */1305 /* Need UDP and VXLAN header to be present */
1306 if (!pskb_may_pull(skb, VXLAN_HLEN))1306 if (!pskb_may_pull(skb, VXLAN_HLEN))
1307 return 1;1307 goto drop;
1308 1308
1309 unparsed = *vxlan_hdr(skb);1309 unparsed = *vxlan_hdr(skb);
1310 /* VNI flag always required to be set */1310 /* VNI flag always required to be set */
@@ -1313,7 +1313,7 @@ static int vxlan_rcv(struct sock *sk, struct sk_buff *skb) · 2 unmodified lines
1313 ntohl(vxlan_hdr(skb)->vx_flags),1313 ntohl(vxlan_hdr(skb)->vx_flags),
1314 ntohl(vxlan_hdr(skb)->vx_vni));1314 ntohl(vxlan_hdr(skb)->vx_vni));
1315 /* Return non vxlan pkt */1315 /* Return non vxlan pkt */
1316 return 1;1316 goto drop;
1317 }1317 }
1318 unparsed.vx_flags &= ~VXLAN_HF_VNI;1318 unparsed.vx_flags &= ~VXLAN_HF_VNI;
1319 unparsed.vx_vni &= ~VXLAN_VNI_MASK;1319 unparsed.vx_vni &= ~VXLAN_VNI_MASK;
net/ipv4/udp.c+1−1
@@ -1565,7 +1565,7 @@ int udp_queue_rcv_skb(struct sock *sk, struct sk_buff *skb) · 1564 unmodified lines
1565 1565
1566 /* if we're overly short, let UDP handle it */1566 /* if we're overly short, let UDP handle it */
1567 encap_rcv = ACCESS_ONCE(up->encap_rcv);1567 encap_rcv = ACCESS_ONCE(up->encap_rcv);
1568 if (skb->len > sizeof(struct udphdr) && encap_rcv) {1568 if (encap_rcv) {
1569 int ret;1569 int ret;
1570 1570
1571 /* Verify checksum before giving to encap */1571 /* Verify checksum before giving to encap */
net/ipv6/udp.c+1−1
@@ -617,7 +617,7 @@ int udpv6_queue_rcv_skb(struct sock *sk, struct sk_buff *skb) · 616 unmodified lines
617 617
618 /* if we're overly short, let UDP handle it */618 /* if we're overly short, let UDP handle it */
619 encap_rcv = ACCESS_ONCE(up->encap_rcv);619 encap_rcv = ACCESS_ONCE(up->encap_rcv);
620 if (skb->len > sizeof(struct udphdr) && encap_rcv) {620 if (encap_rcv) {
621 int ret;621 int ret;
622 622
623 /* Verify checksum before giving to encap */623 /* Verify checksum before giving to encap */