mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
synced 2026-07-16 15:39:42 -04:00
net_sched: act_skbedit: use RCU in tcf_skbedit_dump()
Also storing tcf_action into struct tcf_skbedit_params makes sure there is no discrepancy in tcf_skbedit_act(). Signed-off-by: Eric Dumazet <edumazet@google.com> Link: https://patch.msgid.link/20250709090204.797558-12-edumazet@google.com Signed-off-by: Jakub Kicinski <kuba@kernel.org>
This commit is contained in:
committed by
Jakub Kicinski
parent
cec7a5c6c6
commit
1f376373bd
@@ -12,6 +12,7 @@
|
||||
#include <linux/tc_act/tc_skbedit.h>
|
||||
|
||||
struct tcf_skbedit_params {
|
||||
int action;
|
||||
u32 flags;
|
||||
u32 priority;
|
||||
u32 mark;
|
||||
|
||||
@@ -43,13 +43,11 @@ TC_INDIRECT_SCOPE int tcf_skbedit_act(struct sk_buff *skb,
|
||||
{
|
||||
struct tcf_skbedit *d = to_skbedit(a);
|
||||
struct tcf_skbedit_params *params;
|
||||
int action;
|
||||
|
||||
tcf_lastuse_update(&d->tcf_tm);
|
||||
bstats_update(this_cpu_ptr(d->common.cpu_bstats), skb);
|
||||
|
||||
params = rcu_dereference_bh(d->params);
|
||||
action = READ_ONCE(d->tcf_action);
|
||||
|
||||
if (params->flags & SKBEDIT_F_PRIORITY)
|
||||
skb->priority = params->priority;
|
||||
@@ -85,7 +83,7 @@ TC_INDIRECT_SCOPE int tcf_skbedit_act(struct sk_buff *skb,
|
||||
}
|
||||
if (params->flags & SKBEDIT_F_PTYPE)
|
||||
skb->pkt_type = params->ptype;
|
||||
return action;
|
||||
return params->action;
|
||||
|
||||
err:
|
||||
qstats_drop_inc(this_cpu_ptr(d->common.cpu_qstats));
|
||||
@@ -262,6 +260,7 @@ static int tcf_skbedit_init(struct net *net, struct nlattr *nla,
|
||||
if (flags & SKBEDIT_F_MASK)
|
||||
params_new->mask = *mask;
|
||||
|
||||
params_new->action = parm->action;
|
||||
spin_lock_bh(&d->tcf_lock);
|
||||
goto_ch = tcf_action_set_ctrlact(*a, parm->action, goto_ch);
|
||||
params_new = rcu_replace_pointer(d->params, params_new,
|
||||
@@ -284,9 +283,9 @@ static int tcf_skbedit_init(struct net *net, struct nlattr *nla,
|
||||
static int tcf_skbedit_dump(struct sk_buff *skb, struct tc_action *a,
|
||||
int bind, int ref)
|
||||
{
|
||||
const struct tcf_skbedit *d = to_skbedit(a);
|
||||
unsigned char *b = skb_tail_pointer(skb);
|
||||
struct tcf_skbedit *d = to_skbedit(a);
|
||||
struct tcf_skbedit_params *params;
|
||||
const struct tcf_skbedit_params *params;
|
||||
struct tc_skbedit opt = {
|
||||
.index = d->tcf_index,
|
||||
.refcnt = refcount_read(&d->tcf_refcnt) - ref,
|
||||
@@ -295,10 +294,9 @@ static int tcf_skbedit_dump(struct sk_buff *skb, struct tc_action *a,
|
||||
u64 pure_flags = 0;
|
||||
struct tcf_t t;
|
||||
|
||||
spin_lock_bh(&d->tcf_lock);
|
||||
params = rcu_dereference_protected(d->params,
|
||||
lockdep_is_held(&d->tcf_lock));
|
||||
opt.action = d->tcf_action;
|
||||
rcu_read_lock();
|
||||
params = rcu_dereference(d->params);
|
||||
opt.action = params->action;
|
||||
|
||||
if (nla_put(skb, TCA_SKBEDIT_PARMS, sizeof(opt), &opt))
|
||||
goto nla_put_failure;
|
||||
@@ -333,12 +331,12 @@ static int tcf_skbedit_dump(struct sk_buff *skb, struct tc_action *a,
|
||||
tcf_tm_dump(&t, &d->tcf_tm);
|
||||
if (nla_put_64bit(skb, TCA_SKBEDIT_TM, sizeof(t), &t, TCA_SKBEDIT_PAD))
|
||||
goto nla_put_failure;
|
||||
spin_unlock_bh(&d->tcf_lock);
|
||||
rcu_read_unlock();
|
||||
|
||||
return skb->len;
|
||||
|
||||
nla_put_failure:
|
||||
spin_unlock_bh(&d->tcf_lock);
|
||||
rcu_read_unlock();
|
||||
nlmsg_trim(skb, b);
|
||||
return -1;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user