Never mind. It is also covered.
On Tue, Jul 16, 2013 at 3:07 PM, Andy Zhou <az...@nicira.com> wrote: > What if the IP protocol field is partially masked? > > > On Tue, Jul 16, 2013 at 1:54 PM, Jesse Gross <je...@nicira.com> wrote: > >> I think it actually is safe even in the presence of partial masks >> because of the way that we are enforcing the checks. For example, if >> we have a set TCP action then it isn't safe to just look at the IP >> protocol because that could correspond to a packet that is truncated >> after the IP header. Instead, we need to verify that the TCP header >> actually exists, which we do by looking at some fields in the >> appropriate header (in the case of TCP one of the two port numbers >> must be non-zero). Given this, I think our existing prerequisite >> checks in the flow setup can handle the rest. >> >> On Tue, Jul 16, 2013 at 12:11 PM, Andy Zhou <az...@nicira.com> wrote: >> > Using masked key for validate_and_copy_actions() won't be safe against >> > partially masked fields. >> > It may not be a problem in practice, but it is technically possible >> with the >> > netlink messages. >> > >> > Would you please add a error log before returning EINVAL. >> > >> > I like the API clean ups. It makes the code easier to follow. >> > >> > Thanks, >> > >> > --andy >> > >> > >> > On Mon, Jul 15, 2013 at 10:51 PM, Jesse Gross <je...@nicira.com> wrote: >> >> >> >> It is important to validate flow actions to ensure that they do >> >> not try to write off the end of a packet. The mechanism to do this >> >> is to ensure that a flow is precise enough to describe valid vs. >> >> invalid packets and only allowing actions on valid flows. >> >> >> >> The introduction of megaflows broke this by using a narrow base >> >> flow but a potentially wide match. This meant that while the >> >> original flow was properly validated, later packets might not >> >> conform to that flow and could be truncated. This switches to >> >> using the masked flow instead, effectively requiring that all >> >> possible matching packets be valid in order for a flow's actions >> >> to be accepted. >> >> >> >> This change only affects the flow setup path - executed packets >> >> have always used the flow extracted from the packet and therefore >> >> were properly validated. >> >> >> >> Signed-off-by: Jesse Gross <je...@nicira.com> >> >> --- >> >> datapath/datapath.c | 11 ++++++++--- >> >> datapath/flow.c | 12 ++++-------- >> >> datapath/flow.h | 5 +++-- >> >> 3 files changed, 15 insertions(+), 13 deletions(-) >> >> >> >> diff --git a/datapath/datapath.c b/datapath/datapath.c >> >> index eb07a89..8c9b7f7 100644 >> >> --- a/datapath/datapath.c >> >> +++ b/datapath/datapath.c >> >> @@ -1251,7 +1251,7 @@ static int ovs_flow_cmd_new_or_set(struct sk_buff >> >> *skb, struct genl_info *info) >> >> { >> >> struct nlattr **a = info->attrs; >> >> struct ovs_header *ovs_header = info->userhdr; >> >> - struct sw_flow_key key; >> >> + struct sw_flow_key key, masked_key; >> >> struct sw_flow *flow = NULL; >> >> struct sw_flow_mask mask; >> >> struct sk_buff *reply; >> >> @@ -1279,7 +1279,9 @@ static int ovs_flow_cmd_new_or_set(struct sk_buff >> >> *skb, struct genl_info *info) >> >> if (IS_ERR(acts)) >> >> goto error; >> >> >> >> - error = >> >> validate_and_copy_actions(a[OVS_FLOW_ATTR_ACTIONS], &key, 0, &acts); >> >> + ovs_flow_key_mask(&masked_key, &key, &mask); >> >> + error = >> >> validate_and_copy_actions(a[OVS_FLOW_ATTR_ACTIONS], >> >> + &masked_key, 0, >> &acts); >> >> if (error) >> >> goto err_kfree; >> >> } else if (info->genlhdr->cmd == OVS_FLOW_CMD_NEW) { >> >> @@ -1324,6 +1326,9 @@ static int ovs_flow_cmd_new_or_set(struct sk_buff >> >> *skb, struct genl_info *info) >> >> } >> >> clear_stats(flow); >> >> >> >> + flow->key = masked_key; >> >> + flow->unmasked_key = key; >> >> + >> >> /* Make sure mask is unique in the system */ >> >> mask_p = ovs_sw_flow_mask_find(table, &mask); >> >> if (!mask_p) { >> >> @@ -1341,7 +1346,7 @@ static int ovs_flow_cmd_new_or_set(struct sk_buff >> >> *skb, struct genl_info *info) >> >> rcu_assign_pointer(flow->sf_acts, acts); >> >> >> >> /* Put flow in bucket. */ >> >> - ovs_flow_insert(table, flow, &key, match.range.end); >> >> + ovs_flow_insert(table, flow); >> >> >> >> reply = ovs_flow_cmd_build_info(flow, dp, >> >> info->snd_portid, >> >> info->snd_seq, >> >> OVS_FLOW_CMD_NEW); >> >> diff --git a/datapath/flow.c b/datapath/flow.c >> >> index be69186..752c8d6 100644 >> >> --- a/datapath/flow.c >> >> +++ b/datapath/flow.c >> >> @@ -349,9 +349,8 @@ static bool icmp6hdr_ok(struct sk_buff *skb) >> >> sizeof(struct icmp6hdr)); >> >> } >> >> >> >> -static void flow_key_mask(struct sw_flow_key *dst, >> >> - const struct sw_flow_key *src, >> >> - const struct sw_flow_mask *mask) >> >> +void ovs_flow_key_mask(struct sw_flow_key *dst, const struct >> sw_flow_key >> >> *src, >> >> + const struct sw_flow_mask *mask) >> >> { >> >> u8 *m = (u8 *)&mask->key + mask->range.start; >> >> u8 *s = (u8 *)src + mask->range.start; >> >> @@ -1045,7 +1044,7 @@ static struct sw_flow >> *ovs_masked_flow_lookup(struct >> >> flow_table *table, >> >> u32 hash; >> >> struct sw_flow_key masked_key; >> >> >> >> - flow_key_mask(&masked_key, flow_key, mask); >> >> + ovs_flow_key_mask(&masked_key, flow_key, mask); >> >> hash = ovs_flow_hash(&masked_key, key_start, key_len); >> >> head = find_bucket(table, hash); >> >> hlist_for_each_entry_rcu(flow, head, >> hash_node[table->node_ver]) { >> >> @@ -1071,11 +1070,8 @@ struct sw_flow *ovs_flow_lookup(struct >> flow_table >> >> *tbl, >> >> } >> >> >> >> >> >> -void ovs_flow_insert(struct flow_table *table, struct sw_flow *flow, >> >> - const struct sw_flow_key *key, int key_len) >> >> +void ovs_flow_insert(struct flow_table *table, struct sw_flow *flow) >> >> { >> >> - flow->unmasked_key = *key; >> >> - flow_key_mask(&flow->key, &flow->unmasked_key, >> >> ovsl_dereference(flow->mask)); >> >> flow->hash = ovs_flow_hash(&flow->key, >> >> ovsl_dereference(flow->mask)->range.start, >> >> ovsl_dereference(flow->mask)->range.end); >> >> diff --git a/datapath/flow.h b/datapath/flow.h >> >> index a31dab0..1a3764e 100644 >> >> --- a/datapath/flow.h >> >> +++ b/datapath/flow.h >> >> @@ -216,9 +216,8 @@ void ovs_flow_tbl_destroy(struct flow_table *table, >> >> bool deferred); >> >> struct flow_table *ovs_flow_tbl_alloc(int new_size); >> >> struct flow_table *ovs_flow_tbl_expand(struct flow_table *table); >> >> struct flow_table *ovs_flow_tbl_rehash(struct flow_table *table); >> >> -void ovs_flow_insert(struct flow_table *table, struct sw_flow *flow, >> >> - const struct sw_flow_key *key, int key_len); >> >> >> >> +void ovs_flow_insert(struct flow_table *table, struct sw_flow *flow); >> >> void ovs_flow_remove(struct flow_table *table, struct sw_flow *flow); >> >> >> >> struct sw_flow *ovs_flow_dump_next(struct flow_table *table, u32 >> *bucket, >> >> u32 *idx); >> >> @@ -258,4 +257,6 @@ void ovs_sw_flow_mask_del_ref(struct sw_flow_mask >> *, >> >> bool deferred); >> >> void ovs_sw_flow_mask_insert(struct flow_table *, struct sw_flow_mask >> *); >> >> struct sw_flow_mask *ovs_sw_flow_mask_find(const struct flow_table *, >> >> const struct sw_flow_mask *); >> >> +void ovs_flow_key_mask(struct sw_flow_key *dst, const struct >> sw_flow_key >> >> *src, >> >> + const struct sw_flow_mask *mask); >> >> #endif /* flow.h */ >> >> -- >> >> 1.8.1.2 >> >> >> >> _______________________________________________ >> >> dev mailing list >> >> dev@openvswitch.org >> >> http://openvswitch.org/mailman/listinfo/dev >> > >> > >> > >
_______________________________________________ dev mailing list dev@openvswitch.org http://openvswitch.org/mailman/listinfo/dev