]> git.ipfire.org Git - thirdparty/linux.git/commitdiff
net_sched: act_pedit: use RCU in tcf_pedit_dump()
authorEric Dumazet <edumazet@google.com>
Wed, 9 Jul 2025 09:02:01 +0000 (09:02 +0000)
committerJakub Kicinski <kuba@kernel.org>
Fri, 11 Jul 2025 23:01:17 +0000 (16:01 -0700)
Also storing tcf_action into struct tcf_pedit_params
makes sure there is no discrepancy in tcf_pedit_act().

Signed-off-by: Eric Dumazet <edumazet@google.com>
Link: https://patch.msgid.link/20250709090204.797558-10-edumazet@google.com
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
include/net/tc_act/tc_pedit.h
net/sched/act_pedit.c

index 83fe3993178180a92d4493ad864b7bada16b1417..f58ee15cd858cf0291565c92a73e35c1f590431b 100644 (file)
@@ -14,6 +14,7 @@ struct tcf_pedit_key_ex {
 struct tcf_pedit_parms {
        struct tc_pedit_key     *tcfp_keys;
        struct tcf_pedit_key_ex *tcfp_keys_ex;
+       int action;
        u32 tcfp_off_max_hint;
        unsigned char tcfp_nkeys;
        unsigned char tcfp_flags;
index fc0a35a7b62ac7a550f8f03d4a424f7b5ce5b51c..4b65901397a88864014f74c53d0fa00b40ac6613 100644 (file)
@@ -279,7 +279,7 @@ static int tcf_pedit_init(struct net *net, struct nlattr *nla,
        }
 
        p = to_pedit(*a);
-
+       nparms->action = parm->action;
        spin_lock_bh(&p->tcf_lock);
        goto_ch = tcf_action_set_ctrlact(*a, parm->action, goto_ch);
        oparms = rcu_replace_pointer(p->parms, nparms, 1);
@@ -483,7 +483,7 @@ TC_INDIRECT_SCOPE int tcf_pedit_act(struct sk_buff *skb,
 bad:
        tcf_action_inc_overlimit_qstats(&p->common);
 done:
-       return p->tcf_action;
+       return parms->action;
 }
 
 static void tcf_pedit_stats_update(struct tc_action *a, u64 bytes, u64 packets,
@@ -500,19 +500,19 @@ static int tcf_pedit_dump(struct sk_buff *skb, struct tc_action *a,
                          int bind, int ref)
 {
        unsigned char *b = skb_tail_pointer(skb);
-       struct tcf_pedit *p = to_pedit(a);
-       struct tcf_pedit_parms *parms;
+       const struct tcf_pedit *p = to_pedit(a);
+       const struct tcf_pedit_parms *parms;
        struct tc_pedit *opt;
        struct tcf_t t;
        int s;
 
-       spin_lock_bh(&p->tcf_lock);
-       parms = rcu_dereference_protected(p->parms, 1);
+       rcu_read_lock();
+       parms = rcu_dereference(p->parms);
        s = struct_size(opt, keys, parms->tcfp_nkeys);
 
        opt = kzalloc(s, GFP_ATOMIC);
        if (unlikely(!opt)) {
-               spin_unlock_bh(&p->tcf_lock);
+               rcu_read_unlock();
                return -ENOBUFS;
        }
        opt->nkeys = parms->tcfp_nkeys;
@@ -521,7 +521,7 @@ static int tcf_pedit_dump(struct sk_buff *skb, struct tc_action *a,
               flex_array_size(opt, keys, parms->tcfp_nkeys));
        opt->index = p->tcf_index;
        opt->flags = parms->tcfp_flags;
-       opt->action = p->tcf_action;
+       opt->action = parms->action;
        opt->refcnt = refcount_read(&p->tcf_refcnt) - ref;
        opt->bindcnt = atomic_read(&p->tcf_bindcnt) - bind;
 
@@ -540,13 +540,13 @@ static int tcf_pedit_dump(struct sk_buff *skb, struct tc_action *a,
        tcf_tm_dump(&t, &p->tcf_tm);
        if (nla_put_64bit(skb, TCA_PEDIT_TM, sizeof(t), &t, TCA_PEDIT_PAD))
                goto nla_put_failure;
-       spin_unlock_bh(&p->tcf_lock);
+       rcu_read_unlock();
 
        kfree(opt);
        return skb->len;
 
 nla_put_failure:
-       spin_unlock_bh(&p->tcf_lock);
+       rcu_read_unlock();
        nlmsg_trim(skb, b);
        kfree(opt);
        return -1;