]> git.kernelconcepts.de Git - karo-tx-linux.git/commitdiff
udp: prevent skbs lingering in tunnel socket queues
authorHannes Frederic Sowa <hannes@stressinduktion.org>
Thu, 19 May 2016 13:58:33 +0000 (15:58 +0200)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Fri, 24 Jun 2016 17:18:16 +0000 (10:18 -0700)
[ Upstream commit e5aed006be918af163eb397e45aa5ea6cefd5e01 ]

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.

Signed-off-by: Hannes Frederic Sowa <hannes@stressinduktion.org>
Signed-off-by: David S. Miller <davem@davemloft.net>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
drivers/net/geneve.c
drivers/net/vxlan.c
net/ipv4/udp.c
net/ipv6/udp.c

index 58efdec12f300dec69f6790c19f7cd56b10a4b22..e3f939fef6968a11179b1a5be2edf65037a07950 100644 (file)
@@ -310,15 +310,15 @@ static int geneve_udp_encap_recv(struct sock *sk, struct sk_buff *skb)
 
        /* Need Geneve and inner Ethernet header to be present */
        if (unlikely(!pskb_may_pull(skb, GENEVE_BASE_HLEN)))
-               goto error;
+               goto drop;
 
        /* Return packets with reserved bits set */
        geneveh = geneve_hdr(skb);
        if (unlikely(geneveh->ver != GENEVE_VER))
-               goto error;
+               goto drop;
 
        if (unlikely(geneveh->proto_type != htons(ETH_P_TEB)))
-               goto error;
+               goto drop;
 
        opts_len = geneveh->opt_len * 4;
        if (iptunnel_pull_header(skb, GENEVE_BASE_HLEN + opts_len,
@@ -336,10 +336,6 @@ drop:
        /* Consume bad packet */
        kfree_skb(skb);
        return 0;
-
-error:
-       /* Let the UDP layer deal with the skb */
-       return 1;
 }
 
 static struct socket *geneve_create_sock(struct net *net, bool ipv6,
index 3c0df70e2f53aa0020b79e93f3adf92b43fee0b3..0496f1a8a57d755a5411439a2a8a38e991bde359 100644 (file)
@@ -1254,7 +1254,7 @@ static int vxlan_udp_encap_recv(struct sock *sk, struct sk_buff *skb)
 
        /* Need Vxlan and inner Ethernet header to be present */
        if (!pskb_may_pull(skb, VXLAN_HLEN))
-               goto error;
+               goto drop;
 
        vxh = (struct vxlanhdr *)(udp_hdr(skb) + 1);
        flags = ntohl(vxh->vx_flags);
@@ -1344,13 +1344,7 @@ drop:
 bad_flags:
        netdev_dbg(skb->dev, "invalid vxlan flags=%#x vni=%#x\n",
                   ntohl(vxh->vx_flags), ntohl(vxh->vx_vni));
-
-error:
-       if (tun_dst)
-               dst_release((struct dst_entry *)tun_dst);
-
-       /* Return non vxlan pkt */
-       return 1;
+       goto drop;
 }
 
 static int arp_reduce(struct net_device *dev, struct sk_buff *skb)
index 21fbb54f11d0db4e58743ddef8bbfe8bb01bfc8e..44e1632370dd267d4487136ee6e8a7ed202db3d6 100644 (file)
@@ -1531,7 +1531,7 @@ int udp_queue_rcv_skb(struct sock *sk, struct sk_buff *skb)
 
                /* if we're overly short, let UDP handle it */
                encap_rcv = ACCESS_ONCE(up->encap_rcv);
-               if (skb->len > sizeof(struct udphdr) && encap_rcv) {
+               if (encap_rcv) {
                        int ret;
 
                        /* Verify checksum before giving to encap */
index 6665e1a0bfe1e585affc5726b715ea561a2ce563..275af43306f929e3eaf816e2fd97e606d2d908e1 100644 (file)
@@ -647,7 +647,7 @@ int udpv6_queue_rcv_skb(struct sock *sk, struct sk_buff *skb)
 
                /* if we're overly short, let UDP handle it */
                encap_rcv = ACCESS_ONCE(up->encap_rcv);
-               if (skb->len > sizeof(struct udphdr) && encap_rcv) {
+               if (encap_rcv) {
                        int ret;
 
                        /* Verify checksum before giving to encap */