[ovs-dev] [PATCH v4 4/4] datapath: Allow masks for set actions.
Jarno Rajahalme
jrajahalme at nicira.com
Fri Sep 5 21:26:23 UTC 2014
On Sep 5, 2014, at 2:12 PM, Jarno Rajahalme <jrajahalme at 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().
>>
>
More information about the dev
mailing list