datapath: Avoid assigning a NULL pointer to flow actions.
[sliver-openvswitch.git] / datapath / datapath.c
index f7c3391..71792de 100644 (file)
@@ -811,6 +811,7 @@ static int ovs_flow_cmd_new_or_set(struct sk_buff *skb, struct genl_info *info)
                        goto err_kfree;
                }
        } else if (info->genlhdr->cmd == OVS_FLOW_CMD_NEW) {
+               /* OVS_FLOW_CMD_NEW must have actions. */
                error = -EINVAL;
                goto error;
        }
@@ -850,8 +851,6 @@ static int ovs_flow_cmd_new_or_set(struct sk_buff *skb, struct genl_info *info)
                reply = ovs_flow_cmd_build_info(flow, dp, info, OVS_FLOW_CMD_NEW);
        } else {
                /* We found a matching flow. */
-               struct sw_flow_actions *old_acts;
-
                /* Bail out if we're not allowed to modify an existing flow.
                 * We accept NLM_F_CREATE in place of the intended NLM_F_EXCL
                 * because Generic Netlink treats the latter as a dump
@@ -867,11 +866,14 @@ static int ovs_flow_cmd_new_or_set(struct sk_buff *skb, struct genl_info *info)
                if (!ovs_flow_cmp_unmasked_key(flow, &match))
                        goto err_unlock_ovs;
 
-               /* Update actions. */
-               old_acts = ovsl_dereference(flow->sf_acts);
-               rcu_assign_pointer(flow->sf_acts, acts);
-               ovs_nla_free_flow_actions(old_acts);
+               /* Update actions, if present. */
+               if (acts) {
+                       struct sw_flow_actions *old_acts;
 
+                       old_acts = ovsl_dereference(flow->sf_acts);
+                       rcu_assign_pointer(flow->sf_acts, acts);
+                       ovs_nla_free_flow_actions(old_acts);
+               }
                reply = ovs_flow_cmd_build_info(flow, dp, info, OVS_FLOW_CMD_NEW);
 
                /* Clear stats. */