[PATCH net] vxlan: fix missing options_len update on RX with collect metadata

Subsystems: networking drivers, the rest

STALE3871d

7 messages, 4 authors, 2016-03-04 · open the first message on its own page

[PATCH net] vxlan: fix missing options_len update on RX with collect metadata

From: Daniel Borkmann <daniel@iogearbox.net>
Date: 2016-03-02 01:32:14

When signalling to metadata consumers that the metadata_dst entry
carries additional GBP extension data for vxlan (TUNNEL_VXLAN_OPT),
the dst's vxlan_metadata information is populated, but options_len
is left to zero. F.e. in ovs, ovs_flow_key_extract() checks for
options_len before extracting the data through ip_tunnel_info_opts_get().

Geneve uses ip_tunnel_info_opts_set() helper in receive path, which
sets options_len internally, vxlan however uses ip_tunnel_info_opts(),
so when filling vxlan_metadata, we do need to update options_len.

Fixes: 4c22279848c5 ("ip-tunnel: Use API to access tunnel metadata options.")
Signed-off-by: Daniel Borkmann <daniel@iogearbox.net>
---
 drivers/net/vxlan.c | 4 +++-
 1 file changed, 3 insertions(+), 1 deletion(-)
diff --git a/drivers/net/vxlan.c b/drivers/net/vxlan.c
index b601139..1c32bd1 100644
--- a/drivers/net/vxlan.c
+++ b/drivers/net/vxlan.c
@@ -1308,8 +1308,10 @@ static int vxlan_udp_encap_recv(struct sock *sk, struct sk_buff *skb)
 		gbp = (struct vxlanhdr_gbp *)vxh;
 		md->gbp = ntohs(gbp->policy_id);
 
-		if (tun_dst)
+		if (tun_dst) {
 			tun_dst->u.tun_info.key.tun_flags |= TUNNEL_VXLAN_OPT;
+			tun_dst->u.tun_info.options_len = sizeof(*md);
+		}
 
 		if (gbp->dont_learn)
 			md->gbp |= VXLAN_GBP_DONT_LEARN;
-- 
1.9.3

Re: [PATCH net] vxlan: fix missing options_len update on RX with collect metadata

From: Cong Wang <hidden>
Date: 2016-03-03 01:21:14

On Tue, Mar 1, 2016 at 5:32 PM, Daniel Borkmann [off-list ref] wrote:
quoted hunk
When signalling to metadata consumers that the metadata_dst entry
carries additional GBP extension data for vxlan (TUNNEL_VXLAN_OPT),
the dst's vxlan_metadata information is populated, but options_len
is left to zero. F.e. in ovs, ovs_flow_key_extract() checks for
options_len before extracting the data through ip_tunnel_info_opts_get().

Geneve uses ip_tunnel_info_opts_set() helper in receive path, which
sets options_len internally, vxlan however uses ip_tunnel_info_opts(),
so when filling vxlan_metadata, we do need to update options_len.

Fixes: 4c22279848c5 ("ip-tunnel: Use API to access tunnel metadata options.")
Signed-off-by: Daniel Borkmann <daniel@iogearbox.net>
---
 drivers/net/vxlan.c | 4 +++-
 1 file changed, 3 insertions(+), 1 deletion(-)
diff --git a/drivers/net/vxlan.c b/drivers/net/vxlan.c
index b601139..1c32bd1 100644
--- a/drivers/net/vxlan.c
+++ b/drivers/net/vxlan.c
@@ -1308,8 +1308,10 @@ static int vxlan_udp_encap_recv(struct sock *sk, struct sk_buff *skb)
                gbp = (struct vxlanhdr_gbp *)vxh;
                md->gbp = ntohs(gbp->policy_id);

-               if (tun_dst)
+               if (tun_dst) {
                        tun_dst->u.tun_info.key.tun_flags |= TUNNEL_VXLAN_OPT;
+                       tun_dst->u.tun_info.options_len = sizeof(*md);
+               }
Why not set it in tun_rx_dst() where it is allocated?

Re: [PATCH net] vxlan: fix missing options_len update on RX with collect metadata

From: Daniel Borkmann <daniel@iogearbox.net>
Date: 2016-03-03 08:58:08

On 03/03/2016 02:21 AM, Cong Wang wrote:
On Tue, Mar 1, 2016 at 5:32 PM, Daniel Borkmann [off-list ref] wrote:
quoted
When signalling to metadata consumers that the metadata_dst entry
carries additional GBP extension data for vxlan (TUNNEL_VXLAN_OPT),
the dst's vxlan_metadata information is populated, but options_len
is left to zero. F.e. in ovs, ovs_flow_key_extract() checks for
options_len before extracting the data through ip_tunnel_info_opts_get().

Geneve uses ip_tunnel_info_opts_set() helper in receive path, which
sets options_len internally, vxlan however uses ip_tunnel_info_opts(),
so when filling vxlan_metadata, we do need to update options_len.

Fixes: 4c22279848c5 ("ip-tunnel: Use API to access tunnel metadata options.")
Signed-off-by: Daniel Borkmann <daniel@iogearbox.net>
---
  drivers/net/vxlan.c | 4 +++-
  1 file changed, 3 insertions(+), 1 deletion(-)
diff --git a/drivers/net/vxlan.c b/drivers/net/vxlan.c
index b601139..1c32bd1 100644
--- a/drivers/net/vxlan.c
+++ b/drivers/net/vxlan.c
@@ -1308,8 +1308,10 @@ static int vxlan_udp_encap_recv(struct sock *sk, struct sk_buff *skb)
                 gbp = (struct vxlanhdr_gbp *)vxh;
                 md->gbp = ntohs(gbp->policy_id);

-               if (tun_dst)
+               if (tun_dst) {
                         tun_dst->u.tun_info.key.tun_flags |= TUNNEL_VXLAN_OPT;
+                       tun_dst->u.tun_info.options_len = sizeof(*md);
+               }
Why not set it in tun_rx_dst() where it is allocated?
Nope, current convention is to only fill options_len when an actual
option was detected on RX, f.e. see ip_tunnel_info_opts_set() in
geneve. Consumers like ovs_flow_key_extract() check for options_len
and not TUNNEL_OPTIONS_PRESENT to copy it via ip_tunnel_info_opts_get()
from there.

Re: [PATCH net] vxlan: fix missing options_len update on RX with collect metadata

From: Thomas Graf <tgraf@suug.ch>
Date: 2016-03-03 10:34:00

On 03/02/16 at 02:32am, Daniel Borkmann wrote:
When signalling to metadata consumers that the metadata_dst entry
carries additional GBP extension data for vxlan (TUNNEL_VXLAN_OPT),
the dst's vxlan_metadata information is populated, but options_len
is left to zero. F.e. in ovs, ovs_flow_key_extract() checks for
options_len before extracting the data through ip_tunnel_info_opts_get().

Geneve uses ip_tunnel_info_opts_set() helper in receive path, which
sets options_len internally, vxlan however uses ip_tunnel_info_opts(),
so when filling vxlan_metadata, we do need to update options_len.

Fixes: 4c22279848c5 ("ip-tunnel: Use API to access tunnel metadata options.")
Signed-off-by: Daniel Borkmann <daniel@iogearbox.net>
Acked-by: Thomas Graf <tgraf@suug.ch>

Re: [PATCH net] vxlan: fix missing options_len update on RX with collect metadata

From: David Miller <davem@davemloft.net>
Date: 2016-03-03 22:11:16

From: Daniel Borkmann <daniel@iogearbox.net>
Date: Wed,  2 Mar 2016 02:32:08 +0100
When signalling to metadata consumers that the metadata_dst entry
carries additional GBP extension data for vxlan (TUNNEL_VXLAN_OPT),
the dst's vxlan_metadata information is populated, but options_len
is left to zero. F.e. in ovs, ovs_flow_key_extract() checks for
options_len before extracting the data through ip_tunnel_info_opts_get().

Geneve uses ip_tunnel_info_opts_set() helper in receive path, which
sets options_len internally, vxlan however uses ip_tunnel_info_opts(),
so when filling vxlan_metadata, we do need to update options_len.

Fixes: 4c22279848c5 ("ip-tunnel: Use API to access tunnel metadata options.")
Signed-off-by: Daniel Borkmann <daniel@iogearbox.net>
Applied and queued up for -stable, thanks Daniel.

Re: [PATCH net] vxlan: fix missing options_len update on RX with collect metadata

From: Cong Wang <hidden>
Date: 2016-03-04 00:16:17

On Thu, Mar 3, 2016 at 12:58 AM, Daniel Borkmann [off-list ref] wrote:
On 03/03/2016 02:21 AM, Cong Wang wrote:
quoted
Why not set it in tun_rx_dst() where it is allocated?

Nope, current convention is to only fill options_len when an actual
option was detected on RX, f.e. see ip_tunnel_info_opts_set() in
geneve. Consumers like ovs_flow_key_extract() check for options_len
and not TUNNEL_OPTIONS_PRESENT to copy it via ip_tunnel_info_opts_get()
from there.
But the APIs suck...

You expect to use ip_tunnel_info_opts_{get,set}() to read or write
the tun_info, but actually this is not the case here for vxlan.

Also, ip_tunnel_info_opts_set() could write out of range if the len is
bigger than the allocated length. I know existing callers are fine, but this API
is problematic.

I think this is why we had this bug.

Re: [PATCH net] vxlan: fix missing options_len update on RX with collect metadata

From: Daniel Borkmann <daniel@iogearbox.net>
Date: 2016-03-04 02:23:01

On 03/04/2016 01:16 AM, Cong Wang wrote:
On Thu, Mar 3, 2016 at 12:58 AM, Daniel Borkmann [off-list ref] wrote:
quoted
On 03/03/2016 02:21 AM, Cong Wang wrote:
quoted
Why not set it in tun_rx_dst() where it is allocated?
Nope, current convention is to only fill options_len when an actual
option was detected on RX, f.e. see ip_tunnel_info_opts_set() in
geneve. Consumers like ovs_flow_key_extract() check for options_len
and not TUNNEL_OPTIONS_PRESENT to copy it via ip_tunnel_info_opts_get()
from there.
But the APIs suck...

You expect to use ip_tunnel_info_opts_{get,set}() to read or write
the tun_info, but actually this is not the case here for vxlan.
Yep, since depending on the working mode either skb->mark is populated
or the tunnel opts buffer.
Also, ip_tunnel_info_opts_set() could write out of range if the len is
bigger than the allocated length. I know existing callers are fine, but this API
is problematic.
Current call sites are good agree, API could probably be better, yeah.
I think this is why we had this bug.
Keyboard shortcuts
hback out one level
jnext message in thread
kprevious message in thread
ldrill in
Escclose help / fold thread tree
?toggle this help