net_sched: act_ct: use RCU in tcf_ct_dump()

Also storing tcf_action into struct tcf_ct_params
makes sure there is no discrepancy in tcf_ct_act().

Signed-off-by: Eric Dumazet <edumazet@google.com>
Link: https://patch.msgid.link/20250709090204.797558-5-edumazet@google.com
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
This commit is contained in:
Eric Dumazet 2025-07-09 09:01:56 +00:00 committed by Jakub Kicinski
parent ba9dc9c140
commit 554e66bad8
2 changed files with 16 additions and 16 deletions

View file

@ -13,7 +13,7 @@ struct tcf_ct_params {
struct nf_conntrack_helper *helper;
struct nf_conn *tmpl;
u16 zone;
int action;
u32 mark;
u32 mark_mask;

View file

@ -977,7 +977,7 @@ TC_INDIRECT_SCOPE int tcf_ct_act(struct sk_buff *skb, const struct tc_action *a,
p = rcu_dereference_bh(c->params);
retval = READ_ONCE(c->tcf_action);
retval = p->action;
commit = p->ct_action & TCA_CT_ACT_COMMIT;
clear = p->ct_action & TCA_CT_ACT_CLEAR;
tmpl = p->tmpl;
@ -1409,6 +1409,7 @@ static int tcf_ct_init(struct net *net, struct nlattr *nla,
if (err)
goto cleanup;
params->action = parm->action;
spin_lock_bh(&c->tcf_lock);
goto_ch = tcf_action_set_ctrlact(*a, parm->action, goto_ch);
params = rcu_replace_pointer(c->params, params,
@ -1442,8 +1443,8 @@ static void tcf_ct_cleanup(struct tc_action *a)
}
static int tcf_ct_dump_key_val(struct sk_buff *skb,
void *val, int val_type,
void *mask, int mask_type,
const void *val, int val_type,
const void *mask, int mask_type,
int len)
{
int err;
@ -1464,9 +1465,9 @@ static int tcf_ct_dump_key_val(struct sk_buff *skb,
return 0;
}
static int tcf_ct_dump_nat(struct sk_buff *skb, struct tcf_ct_params *p)
static int tcf_ct_dump_nat(struct sk_buff *skb, const struct tcf_ct_params *p)
{
struct nf_nat_range2 *range = &p->range;
const struct nf_nat_range2 *range = &p->range;
if (!(p->ct_action & TCA_CT_ACT_NAT))
return 0;
@ -1504,7 +1505,8 @@ static int tcf_ct_dump_nat(struct sk_buff *skb, struct tcf_ct_params *p)
return 0;
}
static int tcf_ct_dump_helper(struct sk_buff *skb, struct nf_conntrack_helper *helper)
static int tcf_ct_dump_helper(struct sk_buff *skb,
const struct nf_conntrack_helper *helper)
{
if (!helper)
return 0;
@ -1521,9 +1523,8 @@ static inline int tcf_ct_dump(struct sk_buff *skb, struct tc_action *a,
int bind, int ref)
{
unsigned char *b = skb_tail_pointer(skb);
struct tcf_ct *c = to_ct(a);
struct tcf_ct_params *p;
const struct tcf_ct *c = to_ct(a);
const struct tcf_ct_params *p;
struct tc_ct opt = {
.index = c->tcf_index,
.refcnt = refcount_read(&c->tcf_refcnt) - ref,
@ -1531,10 +1532,9 @@ static inline int tcf_ct_dump(struct sk_buff *skb, struct tc_action *a,
};
struct tcf_t t;
spin_lock_bh(&c->tcf_lock);
p = rcu_dereference_protected(c->params,
lockdep_is_held(&c->tcf_lock));
opt.action = c->tcf_action;
rcu_read_lock();
p = rcu_dereference(c->params);
opt.action = p->action;
if (tcf_ct_dump_key_val(skb,
&p->ct_action, TCA_CT_ACTION,
@ -1579,11 +1579,11 @@ skip_dump:
tcf_tm_dump(&t, &c->tcf_tm);
if (nla_put_64bit(skb, TCA_CT_TM, sizeof(t), &t, TCA_CT_PAD))
goto nla_put_failure;
spin_unlock_bh(&c->tcf_lock);
rcu_read_unlock();
return skb->len;
nla_put_failure:
spin_unlock_bh(&c->tcf_lock);
rcu_read_unlock();
nlmsg_trim(skb, b);
return -1;
}