aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJarno Rajahalme <jrajahalme@nicira.com>2014-05-05 12:59:40 -0400
committerPravin B Shelar <pshelar@nicira.com>2014-05-22 19:27:34 -0400
commitbe52c9e96a6657d117bb0ec6e11438fb246af5c7 (patch)
tree92764c69b9c3cda7a6263dd5163caeea57a6e815
parent1139e241ec436b9e9610c7a33ac5c6657f87fda1 (diff)
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 <jrajahalme@nicira.com> Signed-off-by: Pravin B Shelar <pshelar@nicira.com>
-rw-r--r--include/uapi/linux/openvswitch.h4
-rw-r--r--net/openvswitch/datapath.c14
2 files changed, 11 insertions, 7 deletions
diff --git a/include/uapi/linux/openvswitch.h b/include/uapi/linux/openvswitch.h
index 970553cbbc8e..0b979ee4bfc0 100644
--- a/include/uapi/linux/openvswitch.h
+++ b/include/uapi/linux/openvswitch.h
@@ -395,7 +395,9 @@ struct ovs_key_nd {
395 * @OVS_FLOW_ATTR_ACTIONS: Nested %OVS_ACTION_ATTR_* attributes specifying 395 * @OVS_FLOW_ATTR_ACTIONS: Nested %OVS_ACTION_ATTR_* attributes specifying
396 * the actions to take for packets that match the key. Always present in 396 * the actions to take for packets that match the key. Always present in
397 * notifications. Required for %OVS_FLOW_CMD_NEW requests, optional for 397 * 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.
399 * @OVS_FLOW_ATTR_STATS: &struct ovs_flow_stats giving statistics for this 401 * @OVS_FLOW_ATTR_STATS: &struct ovs_flow_stats giving statistics for this
400 * flow. Present in notifications if the stats would be nonzero. Ignored in 402 * flow. Present in notifications if the stats would be nonzero. Ignored in
401 * requests. 403 * requests.
diff --git a/net/openvswitch/datapath.c b/net/openvswitch/datapath.c
index 8867d7e2d65b..90a1e5e66287 100644
--- a/net/openvswitch/datapath.c
+++ b/net/openvswitch/datapath.c
@@ -810,6 +810,7 @@ static int ovs_flow_cmd_new_or_set(struct sk_buff *skb, struct genl_info *info)
810 goto err_kfree; 810 goto err_kfree;
811 } 811 }
812 } else if (info->genlhdr->cmd == OVS_FLOW_CMD_NEW) { 812 } else if (info->genlhdr->cmd == OVS_FLOW_CMD_NEW) {
813 /* OVS_FLOW_CMD_NEW must have actions. */
813 error = -EINVAL; 814 error = -EINVAL;
814 goto error; 815 goto error;
815 } 816 }
@@ -849,8 +850,6 @@ static int ovs_flow_cmd_new_or_set(struct sk_buff *skb, struct genl_info *info)
849 reply = ovs_flow_cmd_build_info(flow, dp, info, OVS_FLOW_CMD_NEW); 850 reply = ovs_flow_cmd_build_info(flow, dp, info, OVS_FLOW_CMD_NEW);
850 } else { 851 } else {
851 /* We found a matching flow. */ 852 /* We found a matching flow. */
852 struct sw_flow_actions *old_acts;
853
854 /* Bail out if we're not allowed to modify an existing flow. 853 /* Bail out if we're not allowed to modify an existing flow.
855 * We accept NLM_F_CREATE in place of the intended NLM_F_EXCL 854 * We accept NLM_F_CREATE in place of the intended NLM_F_EXCL
856 * because Generic Netlink treats the latter as a dump 855 * 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)
866 if (!ovs_flow_cmp_unmasked_key(flow, &match)) 865 if (!ovs_flow_cmp_unmasked_key(flow, &match))
867 goto err_unlock_ovs; 866 goto err_unlock_ovs;
868 867
869 /* Update actions. */ 868 /* Update actions, if present. */
870 old_acts = ovsl_dereference(flow->sf_acts); 869 if (acts) {
871 rcu_assign_pointer(flow->sf_acts, acts); 870 struct sw_flow_actions *old_acts;
872 ovs_nla_free_flow_actions(old_acts);
873 871
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 }
874 reply = ovs_flow_cmd_build_info(flow, dp, info, OVS_FLOW_CMD_NEW); 876 reply = ovs_flow_cmd_build_info(flow, dp, info, OVS_FLOW_CMD_NEW);
875 877
876 /* Clear stats. */ 878 /* Clear stats. */