On Sep 5, 2014, at 2:12 PM, Jarno Rajahalme <jrajaha...@nicira.com> wrote:
>>> 
>>>       case OVS_KEY_ATTR_IPV4:
>> [...]
>>> -               if (ipv4_key->ipv4_frag != flow_key->ip.frag)
>>> -                       return -EINVAL;
>>> +                       /* Non-writeable fields. */
>>> +                       if (mask->ipv4_proto || mask->ipv4_frag)
>>> +                               return -EINVAL;
>>> +               } else {
>>> +                       if (!flow_key->ip.proto)
>>> +                               return -EINVAL;
>> 
>> I believe that this check on ip.proto is being used to verify that the
>> IP header is actually present, so this would mean that we can write
>> off the end of the packet in the masked case.
> 
> But this is at flow set-up time, and the mask could still wildcard the 
> ip.proto field,

I checked this and flow_key is the masked flow key, so it can not be 
wildcarded, sorry for the confusion. However, it is conceivable that a 
userspace app wants to set a flow to match on all IP packets with 
eth_type(0x0800), and then e.g. set(ipv4(tos=0)). So, I’d like to get rid of 
the ip.proto check anyway!

Is the make_writeable() check sufficient?

  Jarno

> so it could be zero or missing in an actual packet. Doesn’t the 
> make_writeable take care of the verification?:
> 
> static int set_ipv4(struct sk_buff *skb, const struct ovs_key_ipv4 *key,
>                   const struct ovs_key_ipv4 *mask)
> {
>       struct iphdr *nh;
>       __be32 new_addr;
>       int err;
> 
>       err = make_writable(skb, skb_network_offset(skb) +
>                                sizeof(struct iphdr));
>       if (unlikely(err))
>               return err;
> 
>       nh = ip_hdr(skb);
> 
> 
>> 
>>>       case OVS_KEY_ATTR_IPV6:
>> [...]
>>> -               if (ipv6_key->ipv6_frag != flow_key->ip.frag)
>>> -                       return -EINVAL;
>>> +                       /* Non-writeable fields. */
>>> +                       if (mask->ipv6_proto || mask->ipv6_frag)
>>> +                               return -EINVAL;
>>> +
>>> +                       /* Invalid bits in the flow label mask? */
>>> +                       if (ntohl(mask->ipv6_label) & 0xFFF00000)
>>> +                               return -EINVAL;
>>> +               } else {
>>> +                       if (!flow_key->ip.proto)
>>> +                               return -EINVAL;
>> 
>> Same issue with header validation here.
>> 
>>> @@ -1605,12 +1649,43 @@ static int validate_set(const struct nlattr *a,
>>> +       /* Convert non-masked set actions to masked set actions.
>>> +        * Tunnel set action returns before getting here. */
>>> +       if (!masked) {
>>> +               int start, len = key_len * 2;
>>> +               struct nlattr *at;
>>> +
>>> +               *skip_copy = true;
>>> +
>>> +               start = add_nested_action_start(sfa,
>>> +                                               OVS_ACTION_ATTR_SET_MASKED);
>>> +               if (start < 0)
>>> +                       return start;
>>> +
>>> +               at = reserve_sfa_size(sfa, nla_attr_size(len));
>>> +               if (IS_ERR(at))
>>> +                       return PTR_ERR(at);
>>> +
>>> +               at->nla_type = key_type;
>>> +               at->nla_len = nla_attr_size(len);
>> 
>> I think this can be simplified by using add_action() or __add_action().
>> 
> 

_______________________________________________
dev mailing list
dev@openvswitch.org
http://openvswitch.org/mailman/listinfo/dev

Reply via email to