net: sched: call tcf_ct_params_free to free params in tcf_ct_init
This patch is to make the err path simple by calling tcf_ct_params_free(), so that it won't cause problems when more members are added into param and need freeing on the err path. Acked-by: Marcelo Ricardo Leitner <marcelo.leitner@gmail.com> Signed-off-by: Xin Long <lucien.xin@gmail.com> Signed-off-by: Paolo Abeni <pabeni@redhat.com>
This commit is contained in:
+18
-17
@@ -345,11 +345,9 @@ static void tcf_ct_flow_table_cleanup_work(struct work_struct *work)
|
|||||||
module_put(THIS_MODULE);
|
module_put(THIS_MODULE);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void tcf_ct_flow_table_put(struct tcf_ct_params *params)
|
static void tcf_ct_flow_table_put(struct tcf_ct_flow_table *ct_ft)
|
||||||
{
|
{
|
||||||
struct tcf_ct_flow_table *ct_ft = params->ct_ft;
|
if (refcount_dec_and_test(&ct_ft->ref)) {
|
||||||
|
|
||||||
if (refcount_dec_and_test(¶ms->ct_ft->ref)) {
|
|
||||||
rhashtable_remove_fast(&zones_ht, &ct_ft->node, zones_params);
|
rhashtable_remove_fast(&zones_ht, &ct_ft->node, zones_params);
|
||||||
INIT_RCU_WORK(&ct_ft->rwork, tcf_ct_flow_table_cleanup_work);
|
INIT_RCU_WORK(&ct_ft->rwork, tcf_ct_flow_table_cleanup_work);
|
||||||
queue_rcu_work(act_ct_wq, &ct_ft->rwork);
|
queue_rcu_work(act_ct_wq, &ct_ft->rwork);
|
||||||
@@ -832,18 +830,23 @@ out_free:
|
|||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void tcf_ct_params_free(struct rcu_head *head)
|
static void tcf_ct_params_free(struct tcf_ct_params *params)
|
||||||
{
|
{
|
||||||
struct tcf_ct_params *params = container_of(head,
|
if (params->ct_ft)
|
||||||
struct tcf_ct_params, rcu);
|
tcf_ct_flow_table_put(params->ct_ft);
|
||||||
|
|
||||||
tcf_ct_flow_table_put(params);
|
|
||||||
|
|
||||||
if (params->tmpl)
|
if (params->tmpl)
|
||||||
nf_ct_put(params->tmpl);
|
nf_ct_put(params->tmpl);
|
||||||
kfree(params);
|
kfree(params);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void tcf_ct_params_free_rcu(struct rcu_head *head)
|
||||||
|
{
|
||||||
|
struct tcf_ct_params *params;
|
||||||
|
|
||||||
|
params = container_of(head, struct tcf_ct_params, rcu);
|
||||||
|
tcf_ct_params_free(params);
|
||||||
|
}
|
||||||
|
|
||||||
#if IS_ENABLED(CONFIG_NF_NAT)
|
#if IS_ENABLED(CONFIG_NF_NAT)
|
||||||
/* Modelled after nf_nat_ipv[46]_fn().
|
/* Modelled after nf_nat_ipv[46]_fn().
|
||||||
* range is only used for new, uninitialized NAT state.
|
* range is only used for new, uninitialized NAT state.
|
||||||
@@ -1390,7 +1393,7 @@ static int tcf_ct_init(struct net *net, struct nlattr *nla,
|
|||||||
|
|
||||||
err = tcf_ct_flow_table_get(net, params);
|
err = tcf_ct_flow_table_get(net, params);
|
||||||
if (err)
|
if (err)
|
||||||
goto cleanup_params;
|
goto cleanup;
|
||||||
|
|
||||||
spin_lock_bh(&c->tcf_lock);
|
spin_lock_bh(&c->tcf_lock);
|
||||||
goto_ch = tcf_action_set_ctrlact(*a, parm->action, goto_ch);
|
goto_ch = tcf_action_set_ctrlact(*a, parm->action, goto_ch);
|
||||||
@@ -1401,17 +1404,15 @@ static int tcf_ct_init(struct net *net, struct nlattr *nla,
|
|||||||
if (goto_ch)
|
if (goto_ch)
|
||||||
tcf_chain_put_by_act(goto_ch);
|
tcf_chain_put_by_act(goto_ch);
|
||||||
if (params)
|
if (params)
|
||||||
call_rcu(¶ms->rcu, tcf_ct_params_free);
|
call_rcu(¶ms->rcu, tcf_ct_params_free_rcu);
|
||||||
|
|
||||||
return res;
|
return res;
|
||||||
|
|
||||||
cleanup_params:
|
|
||||||
if (params->tmpl)
|
|
||||||
nf_ct_put(params->tmpl);
|
|
||||||
cleanup:
|
cleanup:
|
||||||
if (goto_ch)
|
if (goto_ch)
|
||||||
tcf_chain_put_by_act(goto_ch);
|
tcf_chain_put_by_act(goto_ch);
|
||||||
kfree(params);
|
if (params)
|
||||||
|
tcf_ct_params_free(params);
|
||||||
tcf_idr_release(*a, bind);
|
tcf_idr_release(*a, bind);
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
@@ -1423,7 +1424,7 @@ static void tcf_ct_cleanup(struct tc_action *a)
|
|||||||
|
|
||||||
params = rcu_dereference_protected(c->params, 1);
|
params = rcu_dereference_protected(c->params, 1);
|
||||||
if (params)
|
if (params)
|
||||||
call_rcu(¶ms->rcu, tcf_ct_params_free);
|
call_rcu(¶ms->rcu, tcf_ct_params_free_rcu);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int tcf_ct_dump_key_val(struct sk_buff *skb,
|
static int tcf_ct_dump_key_val(struct sk_buff *skb,
|
||||||
|
|||||||
Reference in New Issue
Block a user