mirror of
https://github.com/raspberrypi/linux.git
synced 2025-12-08 10:59:46 +00:00
net: openvswitch: fix TTL decrement action netlink message format
[ Upstream commit69929d4c49] Currently, the openvswitch module is not accepting the correctly formated netlink message for the TTL decrement action. For both setting and getting the dec_ttl action, the actions should be nested in the OVS_DEC_TTL_ATTR_ACTION attribute as mentioned in the openvswitch.h uapi. When the original patch was sent, it was tested with a private OVS userspace implementation. This implementation was unfortunately not upstreamed and reviewed, hence an erroneous version of this patch was sent out. Leaving the patch as-is would cause problems as the kernel module could interpret additional attributes as actions and vice-versa, due to the actions not being encapsulated/nested within the actual attribute, but being concatinated after it. Fixes:744676e777("openvswitch: add TTL decrement action") Signed-off-by: Eelco Chaudron <echaudro@redhat.com> Link: https://lore.kernel.org/r/160622121495.27296.888010441924340582.stgit@wsfd-netdev64.ntdv.lab.eng.bos.redhat.com Signed-off-by: Jakub Kicinski <kuba@kernel.org> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
This commit is contained in:
committed by
Greg Kroah-Hartman
parent
ca18ad48e1
commit
ff764c1b51
@@ -1058,4 +1058,6 @@ enum ovs_dec_ttl_attr {
|
|||||||
__OVS_DEC_TTL_ATTR_MAX
|
__OVS_DEC_TTL_ATTR_MAX
|
||||||
};
|
};
|
||||||
|
|
||||||
|
#define OVS_DEC_TTL_ATTR_MAX (__OVS_DEC_TTL_ATTR_MAX - 1)
|
||||||
|
|
||||||
#endif /* _LINUX_OPENVSWITCH_H */
|
#endif /* _LINUX_OPENVSWITCH_H */
|
||||||
|
|||||||
@@ -970,14 +970,13 @@ static int dec_ttl_exception_handler(struct datapath *dp, struct sk_buff *skb,
|
|||||||
{
|
{
|
||||||
/* The first action is always 'OVS_DEC_TTL_ATTR_ARG'. */
|
/* The first action is always 'OVS_DEC_TTL_ATTR_ARG'. */
|
||||||
struct nlattr *dec_ttl_arg = nla_data(attr);
|
struct nlattr *dec_ttl_arg = nla_data(attr);
|
||||||
int rem = nla_len(attr);
|
|
||||||
|
|
||||||
if (nla_len(dec_ttl_arg)) {
|
if (nla_len(dec_ttl_arg)) {
|
||||||
struct nlattr *actions = nla_next(dec_ttl_arg, &rem);
|
struct nlattr *actions = nla_data(dec_ttl_arg);
|
||||||
|
|
||||||
if (actions)
|
if (actions)
|
||||||
return clone_execute(dp, skb, key, 0, actions, rem,
|
return clone_execute(dp, skb, key, 0, nla_data(actions),
|
||||||
last, false);
|
nla_len(actions), last, false);
|
||||||
}
|
}
|
||||||
consume_skb(skb);
|
consume_skb(skb);
|
||||||
return 0;
|
return 0;
|
||||||
|
|||||||
@@ -2503,28 +2503,42 @@ static int validate_and_copy_dec_ttl(struct net *net,
|
|||||||
__be16 eth_type, __be16 vlan_tci,
|
__be16 eth_type, __be16 vlan_tci,
|
||||||
u32 mpls_label_count, bool log)
|
u32 mpls_label_count, bool log)
|
||||||
{
|
{
|
||||||
int start, err;
|
const struct nlattr *attrs[OVS_DEC_TTL_ATTR_MAX + 1];
|
||||||
u32 nested = true;
|
int start, action_start, err, rem;
|
||||||
|
const struct nlattr *a, *actions;
|
||||||
|
|
||||||
if (!nla_len(attr))
|
memset(attrs, 0, sizeof(attrs));
|
||||||
return ovs_nla_add_action(sfa, OVS_ACTION_ATTR_DEC_TTL,
|
nla_for_each_nested(a, attr, rem) {
|
||||||
NULL, 0, log);
|
int type = nla_type(a);
|
||||||
|
|
||||||
|
/* Ignore unknown attributes to be future proof. */
|
||||||
|
if (type > OVS_DEC_TTL_ATTR_MAX)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (!type || attrs[type])
|
||||||
|
return -EINVAL;
|
||||||
|
|
||||||
|
attrs[type] = a;
|
||||||
|
}
|
||||||
|
|
||||||
|
actions = attrs[OVS_DEC_TTL_ATTR_ACTION];
|
||||||
|
if (rem || !actions || (nla_len(actions) && nla_len(actions) < NLA_HDRLEN))
|
||||||
|
return -EINVAL;
|
||||||
|
|
||||||
start = add_nested_action_start(sfa, OVS_ACTION_ATTR_DEC_TTL, log);
|
start = add_nested_action_start(sfa, OVS_ACTION_ATTR_DEC_TTL, log);
|
||||||
if (start < 0)
|
if (start < 0)
|
||||||
return start;
|
return start;
|
||||||
|
|
||||||
err = ovs_nla_add_action(sfa, OVS_DEC_TTL_ATTR_ACTION, &nested,
|
action_start = add_nested_action_start(sfa, OVS_DEC_TTL_ATTR_ACTION, log);
|
||||||
sizeof(nested), log);
|
if (action_start < 0)
|
||||||
|
return start;
|
||||||
|
|
||||||
if (err)
|
err = __ovs_nla_copy_actions(net, actions, key, sfa, eth_type,
|
||||||
return err;
|
|
||||||
|
|
||||||
err = __ovs_nla_copy_actions(net, attr, key, sfa, eth_type,
|
|
||||||
vlan_tci, mpls_label_count, log);
|
vlan_tci, mpls_label_count, log);
|
||||||
if (err)
|
if (err)
|
||||||
return err;
|
return err;
|
||||||
|
|
||||||
|
add_nested_action_end(*sfa, action_start);
|
||||||
add_nested_action_end(*sfa, start);
|
add_nested_action_end(*sfa, start);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@@ -3487,20 +3501,42 @@ out:
|
|||||||
static int dec_ttl_action_to_attr(const struct nlattr *attr,
|
static int dec_ttl_action_to_attr(const struct nlattr *attr,
|
||||||
struct sk_buff *skb)
|
struct sk_buff *skb)
|
||||||
{
|
{
|
||||||
int err = 0, rem = nla_len(attr);
|
struct nlattr *start, *action_start;
|
||||||
struct nlattr *start;
|
const struct nlattr *a;
|
||||||
|
int err = 0, rem;
|
||||||
|
|
||||||
start = nla_nest_start_noflag(skb, OVS_ACTION_ATTR_DEC_TTL);
|
start = nla_nest_start_noflag(skb, OVS_ACTION_ATTR_DEC_TTL);
|
||||||
|
|
||||||
if (!start)
|
if (!start)
|
||||||
return -EMSGSIZE;
|
return -EMSGSIZE;
|
||||||
|
|
||||||
err = ovs_nla_put_actions(nla_data(attr), rem, skb);
|
nla_for_each_attr(a, nla_data(attr), nla_len(attr), rem) {
|
||||||
if (err)
|
switch (nla_type(a)) {
|
||||||
nla_nest_cancel(skb, start);
|
case OVS_DEC_TTL_ATTR_ACTION:
|
||||||
else
|
|
||||||
nla_nest_end(skb, start);
|
|
||||||
|
|
||||||
|
action_start = nla_nest_start_noflag(skb, OVS_DEC_TTL_ATTR_ACTION);
|
||||||
|
if (!action_start) {
|
||||||
|
err = -EMSGSIZE;
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
|
err = ovs_nla_put_actions(nla_data(a), nla_len(a), skb);
|
||||||
|
if (err)
|
||||||
|
goto out;
|
||||||
|
|
||||||
|
nla_nest_end(skb, action_start);
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
/* Ignore all other option to be future compatible */
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
nla_nest_end(skb, start);
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
out:
|
||||||
|
nla_nest_cancel(skb, start);
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user