From: Ben Pfaff Date: Wed, 16 Nov 2011 00:02:39 +0000 (-0800) Subject: datapath: Properly validate length of OVS_KEY_ATTR_ENCAP attributes. X-Git-Tag: v1.4.0~151 X-Git-Url: http://git.onelab.eu/?a=commitdiff_plain;h=4094406ffde8233443bf0ecffe1b18b8bb24e8d3;p=sliver-openvswitch.git datapath: Properly validate length of OVS_KEY_ATTR_ENCAP attributes. Without this, every VLAN packet goes to userspace because VLAN flows cannot be set up. Signed-off-by: Ben Pfaff Acked-by: Jesse Gross --- diff --git a/datapath/flow.c b/datapath/flow.c index 7a1362489..44813195a 100644 --- a/datapath/flow.c +++ b/datapath/flow.c @@ -846,8 +846,8 @@ void flow_tbl_remove(struct flow_table *table, struct sw_flow *flow) } /* The size of the argument for each %OVS_KEY_ATTR_* Netlink attribute. */ -const u32 ovs_key_lens[OVS_KEY_ATTR_MAX + 1] = { - [OVS_KEY_ATTR_ENCAP] = 0, +const int ovs_key_lens[OVS_KEY_ATTR_MAX + 1] = { + [OVS_KEY_ATTR_ENCAP] = -1, [OVS_KEY_ATTR_PRIORITY] = sizeof(u32), [OVS_KEY_ATTR_IN_PORT] = sizeof(u32), [OVS_KEY_ATTR_ETHERNET] = sizeof(struct ovs_key_ethernet), @@ -982,10 +982,15 @@ static int parse_flow_nlattrs(const struct nlattr *attr, attrs = 0; nla_for_each_nested(nla, attr, rem) { u16 type = nla_type(nla); + int expected_len; - if (type > OVS_KEY_ATTR_MAX || attrs & (1ULL << type) || - nla_len(nla) != ovs_key_lens[type]) + if (type > OVS_KEY_ATTR_MAX || attrs & (1ULL << type)) return -EINVAL; + + expected_len = ovs_key_lens[type]; + if (nla_len(nla) != expected_len && expected_len != -1) + return -EINVAL; + attrs |= 1ULL << type; a[type] = nla; } @@ -1187,7 +1192,7 @@ int flow_metadata_from_nlattrs(u32 *priority, u16 *in_port, __be64 *tun_id, nla_for_each_nested(nla, attr, rem) { int type = nla_type(nla); - if (type <= OVS_KEY_ATTR_MAX && ovs_key_lens[type] != 0) { + if (type <= OVS_KEY_ATTR_MAX && ovs_key_lens[type] > 0) { if (nla_len(nla) != ovs_key_lens[type]) return -EINVAL; diff --git a/datapath/flow.h b/datapath/flow.h index 43360cc6e..40b1883ab 100644 --- a/datapath/flow.h +++ b/datapath/flow.h @@ -187,6 +187,6 @@ void flow_tbl_remove(struct flow_table *table, struct sw_flow *flow); u32 flow_hash(const struct sw_flow_key *key, int key_len); struct sw_flow *flow_tbl_next(struct flow_table *table, u32 *bucket, u32 *idx); -extern const u32 ovs_key_lens[OVS_KEY_ATTR_MAX + 1]; +extern const int ovs_key_lens[OVS_KEY_ATTR_MAX + 1]; #endif /* flow.h */