netdev.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH net] udp: prevent skbs lingering in tunnel socket queues
@ 2016-05-19 13:58 Hannes Frederic Sowa
  2016-05-19 22:33 ` Cong Wang
  2016-05-20 23:56 ` David Miller
  0 siblings, 2 replies; 6+ messages in thread
From: Hannes Frederic Sowa @ 2016-05-19 13:58 UTC (permalink / raw)
  To: netdev

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>
---
 drivers/net/geneve.c | 10 +++-------
 drivers/net/vxlan.c  |  4 ++--
 net/ipv4/udp.c       |  2 +-
 net/ipv6/udp.c       |  2 +-
 4 files changed, 7 insertions(+), 11 deletions(-)

diff --git a/drivers/net/geneve.c b/drivers/net/geneve.c
index a6dc11ce497f5c..cadefe4fdaa2aa 100644
--- a/drivers/net/geneve.c
+++ b/drivers/net/geneve.c
@@ -335,15 +335,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;
 
 	gs = rcu_dereference_sk_user_data(sk);
 	if (!gs)
@@ -366,10 +366,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,
diff --git a/drivers/net/vxlan.c b/drivers/net/vxlan.c
index 25ab6bf013c4d2..8ff30c3bdfceab 100644
--- a/drivers/net/vxlan.c
+++ b/drivers/net/vxlan.c
@@ -1304,7 +1304,7 @@ static int vxlan_rcv(struct sock *sk, struct sk_buff *skb)
 
 	/* Need UDP and VXLAN header to be present */
 	if (!pskb_may_pull(skb, VXLAN_HLEN))
-		return 1;
+		goto drop;
 
 	unparsed = *vxlan_hdr(skb);
 	/* VNI flag always required to be set */
@@ -1313,7 +1313,7 @@ static int vxlan_rcv(struct sock *sk, struct sk_buff *skb)
 			   ntohl(vxlan_hdr(skb)->vx_flags),
 			   ntohl(vxlan_hdr(skb)->vx_vni));
 		/* Return non vxlan pkt */
-		return 1;
+		goto drop;
 	}
 	unparsed.vx_flags &= ~VXLAN_HF_VNI;
 	unparsed.vx_vni &= ~VXLAN_VNI_MASK;
diff --git a/net/ipv4/udp.c b/net/ipv4/udp.c
index 2e3ebfe5549ef5..d56c0559b477cb 100644
--- a/net/ipv4/udp.c
+++ b/net/ipv4/udp.c
@@ -1565,7 +1565,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 */
diff --git a/net/ipv6/udp.c b/net/ipv6/udp.c
index 2ba6a77a881532..2da1896af93496 100644
--- a/net/ipv6/udp.c
+++ b/net/ipv6/udp.c
@@ -617,7 +617,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 */
-- 
2.5.5

^ permalink raw reply related	[flat|nested] 6+ messages in thread

* Re: [PATCH net] udp: prevent skbs lingering in tunnel socket queues
  2016-05-19 13:58 [PATCH net] udp: prevent skbs lingering in tunnel socket queues Hannes Frederic Sowa
@ 2016-05-19 22:33 ` Cong Wang
  2016-05-19 22:50   ` Hannes Frederic Sowa
  2016-05-20 23:56 ` David Miller
  1 sibling, 1 reply; 6+ messages in thread
From: Cong Wang @ 2016-05-19 22:33 UTC (permalink / raw)
  To: Hannes Frederic Sowa; +Cc: Linux Kernel Network Developers

On Thu, May 19, 2016 at 6:58 AM, Hannes Frederic Sowa
<hannes@stressinduktion.org> wrote:
> diff --git a/net/ipv4/udp.c b/net/ipv4/udp.c
> index 2e3ebfe5549ef5..d56c0559b477cb 100644
> --- a/net/ipv4/udp.c
> +++ b/net/ipv4/udp.c
> @@ -1565,7 +1565,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) {


I don't think you can just remove it here, l2tp_udp_recv_core() still
relies on it:

        /* UDP has verifed checksum */

        /* UDP always verifies the packet length. */
        __skb_pull(skb, sizeof(struct udphdr));

^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: [PATCH net] udp: prevent skbs lingering in tunnel socket queues
  2016-05-19 22:33 ` Cong Wang
@ 2016-05-19 22:50   ` Hannes Frederic Sowa
  2016-05-20  1:56     ` Cong Wang
  0 siblings, 1 reply; 6+ messages in thread
From: Hannes Frederic Sowa @ 2016-05-19 22:50 UTC (permalink / raw)
  To: Cong Wang; +Cc: Linux Kernel Network Developers

Hi Cong,

On Fri, May 20, 2016, at 00:33, Cong Wang wrote:
> On Thu, May 19, 2016 at 6:58 AM, Hannes Frederic Sowa
> <hannes@stressinduktion.org> wrote:
> > diff --git a/net/ipv4/udp.c b/net/ipv4/udp.c
> > index 2e3ebfe5549ef5..d56c0559b477cb 100644
> > --- a/net/ipv4/udp.c
> > +++ b/net/ipv4/udp.c
> > @@ -1565,7 +1565,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) {
> 
> 
> I don't think you can just remove it here, l2tp_udp_recv_core() still
> relies on it:
> 
>         /* UDP has verifed checksum */
> 
>         /* UDP always verifies the packet length. */
>         __skb_pull(skb, sizeof(struct udphdr));

I think this is fine, we check on every entrance to udp that we may pull
(pskb_may_pull) an udphdr but we really never pull the header. At this
point we are guaranteed to have skb->len of at least sizeof(struct
udphdr).

Bye,
Hannes

^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: [PATCH net] udp: prevent skbs lingering in tunnel socket queues
  2016-05-19 22:50   ` Hannes Frederic Sowa
@ 2016-05-20  1:56     ` Cong Wang
  2016-05-20  6:16       ` Hannes Frederic Sowa
  0 siblings, 1 reply; 6+ messages in thread
From: Cong Wang @ 2016-05-20  1:56 UTC (permalink / raw)
  To: Hannes Frederic Sowa; +Cc: Linux Kernel Network Developers

On Thu, May 19, 2016 at 3:50 PM, Hannes Frederic Sowa
<hannes@stressinduktion.org> wrote:
> Hi Cong,
>
> On Fri, May 20, 2016, at 00:33, Cong Wang wrote:
>> On Thu, May 19, 2016 at 6:58 AM, Hannes Frederic Sowa
>> <hannes@stressinduktion.org> wrote:
>> > diff --git a/net/ipv4/udp.c b/net/ipv4/udp.c
>> > index 2e3ebfe5549ef5..d56c0559b477cb 100644
>> > --- a/net/ipv4/udp.c
>> > +++ b/net/ipv4/udp.c
>> > @@ -1565,7 +1565,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) {
>>
>>
>> I don't think you can just remove it here, l2tp_udp_recv_core() still
>> relies on it:
>>
>>         /* UDP has verifed checksum */
>>
>>         /* UDP always verifies the packet length. */
>>         __skb_pull(skb, sizeof(struct udphdr));
>
> I think this is fine, we check on every entrance to udp that we may pull
> (pskb_may_pull) an udphdr but we really never pull the header. At this
> point we are guaranteed to have skb->len of at least sizeof(struct
> udphdr).

Ah, yeah, __udp4_lib_rcv().

BTW, this part (the second half) of your patch is an optimization,
the rest (the first half) is a real bug fix. It makes sense to split
them if you plan to backport it to -stable.

Thanks.

^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: [PATCH net] udp: prevent skbs lingering in tunnel socket queues
  2016-05-20  1:56     ` Cong Wang
@ 2016-05-20  6:16       ` Hannes Frederic Sowa
  0 siblings, 0 replies; 6+ messages in thread
From: Hannes Frederic Sowa @ 2016-05-20  6:16 UTC (permalink / raw)
  To: Cong Wang; +Cc: Linux Kernel Network Developers

On Fri, May 20, 2016, at 03:56, Cong Wang wrote:
> On Thu, May 19, 2016 at 3:50 PM, Hannes Frederic Sowa
> <hannes@stressinduktion.org> wrote:
> > Hi Cong,
> >
> > On Fri, May 20, 2016, at 00:33, Cong Wang wrote:
> >> On Thu, May 19, 2016 at 6:58 AM, Hannes Frederic Sowa
> >> <hannes@stressinduktion.org> wrote:
> >> > diff --git a/net/ipv4/udp.c b/net/ipv4/udp.c
> >> > index 2e3ebfe5549ef5..d56c0559b477cb 100644
> >> > --- a/net/ipv4/udp.c
> >> > +++ b/net/ipv4/udp.c
> >> > @@ -1565,7 +1565,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) {
> >>
> >>
> >> I don't think you can just remove it here, l2tp_udp_recv_core() still
> >> relies on it:
> >>
> >>         /* UDP has verifed checksum */
> >>
> >>         /* UDP always verifies the packet length. */
> >>         __skb_pull(skb, sizeof(struct udphdr));
> >
> > I think this is fine, we check on every entrance to udp that we may pull
> > (pskb_may_pull) an udphdr but we really never pull the header. At this
> > point we are guaranteed to have skb->len of at least sizeof(struct
> > udphdr).
> 
> Ah, yeah, __udp4_lib_rcv().

Yep, or the respective IPv6 part.

> BTW, this part (the second half) of your patch is an optimization,
> the rest (the first half) is a real bug fix. It makes sense to split
> them if you plan to backport it to -stable.

The problem in the second part is that it is a '>' comparison and not a
'>=' check. Thus if you hit the socket with a UDP packet with no payload
after the UDP header it also gets enqueued in the socket queue of vxlan
or geneve.

Bye,
Hannes

^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: [PATCH net] udp: prevent skbs lingering in tunnel socket queues
  2016-05-19 13:58 [PATCH net] udp: prevent skbs lingering in tunnel socket queues Hannes Frederic Sowa
  2016-05-19 22:33 ` Cong Wang
@ 2016-05-20 23:56 ` David Miller
  1 sibling, 0 replies; 6+ messages in thread
From: David Miller @ 2016-05-20 23:56 UTC (permalink / raw)
  To: hannes; +Cc: netdev

From: Hannes Frederic Sowa <hannes@stressinduktion.org>
Date: Thu, 19 May 2016 15:58:33 +0200

> 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>

Looks good, applied and queued up for -stable.

Thanks!

^ permalink raw reply	[flat|nested] 6+ messages in thread

end of thread, other threads:[~2016-05-20 23:56 UTC | newest]

Thread overview: 6+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2016-05-19 13:58 [PATCH net] udp: prevent skbs lingering in tunnel socket queues Hannes Frederic Sowa
2016-05-19 22:33 ` Cong Wang
2016-05-19 22:50   ` Hannes Frederic Sowa
2016-05-20  1:56     ` Cong Wang
2016-05-20  6:16       ` Hannes Frederic Sowa
2016-05-20 23:56 ` David Miller

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).