Skip to content

Commit be52c9e

Browse files
Jarno RajahalmePravin B Shelar
authored andcommitted
openvswitch: Avoid assigning a NULL pointer to flow actions.
Flow SET can accept an empty set of actions, with the intended semantics of leaving existing actions unmodified. This seems to have been brokin after OVS 1.7, as we have assigned the flow's actions pointer to NULL in this case, but we never check for the NULL pointer later on. This patch restores the intended behavior and documents it in the include/linux/openvswitch.h. Signed-off-by: Jarno Rajahalme <[email protected]> Signed-off-by: Pravin B Shelar <[email protected]>
1 parent 1139e24 commit be52c9e

File tree

2 files changed

+11
-7
lines changed

2 files changed

+11
-7
lines changed

include/uapi/linux/openvswitch.h

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -395,7 +395,9 @@ struct ovs_key_nd {
395395
* @OVS_FLOW_ATTR_ACTIONS: Nested %OVS_ACTION_ATTR_* attributes specifying
396396
* the actions to take for packets that match the key. Always present in
397397
* notifications. Required for %OVS_FLOW_CMD_NEW requests, optional for
398-
* %OVS_FLOW_CMD_SET requests.
398+
* %OVS_FLOW_CMD_SET requests. An %OVS_FLOW_CMD_SET without
399+
* %OVS_FLOW_ATTR_ACTIONS will not modify the actions. To clear the actions,
400+
* an %OVS_FLOW_ATTR_ACTIONS without any nested attributes must be given.
399401
* @OVS_FLOW_ATTR_STATS: &struct ovs_flow_stats giving statistics for this
400402
* flow. Present in notifications if the stats would be nonzero. Ignored in
401403
* requests.

net/openvswitch/datapath.c

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -810,6 +810,7 @@ static int ovs_flow_cmd_new_or_set(struct sk_buff *skb, struct genl_info *info)
810810
goto err_kfree;
811811
}
812812
} else if (info->genlhdr->cmd == OVS_FLOW_CMD_NEW) {
813+
/* OVS_FLOW_CMD_NEW must have actions. */
813814
error = -EINVAL;
814815
goto error;
815816
}
@@ -849,8 +850,6 @@ static int ovs_flow_cmd_new_or_set(struct sk_buff *skb, struct genl_info *info)
849850
reply = ovs_flow_cmd_build_info(flow, dp, info, OVS_FLOW_CMD_NEW);
850851
} else {
851852
/* We found a matching flow. */
852-
struct sw_flow_actions *old_acts;
853-
854853
/* Bail out if we're not allowed to modify an existing flow.
855854
* We accept NLM_F_CREATE in place of the intended NLM_F_EXCL
856855
* because Generic Netlink treats the latter as a dump
@@ -866,11 +865,14 @@ static int ovs_flow_cmd_new_or_set(struct sk_buff *skb, struct genl_info *info)
866865
if (!ovs_flow_cmp_unmasked_key(flow, &match))
867866
goto err_unlock_ovs;
868867

869-
/* Update actions. */
870-
old_acts = ovsl_dereference(flow->sf_acts);
871-
rcu_assign_pointer(flow->sf_acts, acts);
872-
ovs_nla_free_flow_actions(old_acts);
868+
/* Update actions, if present. */
869+
if (acts) {
870+
struct sw_flow_actions *old_acts;
873871

872+
old_acts = ovsl_dereference(flow->sf_acts);
873+
rcu_assign_pointer(flow->sf_acts, acts);
874+
ovs_nla_free_flow_actions(old_acts);
875+
}
874876
reply = ovs_flow_cmd_build_info(flow, dp, info, OVS_FLOW_CMD_NEW);
875877

876878
/* Clear stats. */

0 commit comments

Comments
 (0)