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

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

index a04bcac7adf4b61b73181d5dbd2ff9eee3cf5e97..7fe01ab236da4eaa0624db08d0a9599e36820bee 100644 (file)
@@ -7,6 +7,7 @@
 struct tcf_ctinfo_params {
        struct rcu_head rcu;
        struct net *net;
+       int action;
        u32 dscpmask;
        u32 dscpstatemask;
        u32 cpmarkmask;
index 93ab3bcd6d3106a1561f043e078d0be5997ea277..71efe04d00b5c6195e43f1ea6dab1548f6f97293 100644 (file)
@@ -88,13 +88,11 @@ TC_INDIRECT_SCOPE int tcf_ctinfo_act(struct sk_buff *skb,
        struct tcf_ctinfo_params *cp;
        struct nf_conn *ct;
        int proto, wlen;
-       int action;
 
        cp = rcu_dereference_bh(ca->params);
 
        tcf_lastuse_update(&ca->tcf_tm);
        tcf_action_update_bstats(&ca->common, skb);
-       action = READ_ONCE(ca->tcf_action);
 
        wlen = skb_network_offset(skb);
        switch (skb_protocol(skb, true)) {
@@ -141,7 +139,7 @@ TC_INDIRECT_SCOPE int tcf_ctinfo_act(struct sk_buff *skb,
        if (thash)
                nf_ct_put(ct);
 out:
-       return action;
+       return cp->action;
 }
 
 static const struct nla_policy ctinfo_policy[TCA_CTINFO_MAX + 1] = {
@@ -258,6 +256,8 @@ static int tcf_ctinfo_init(struct net *net, struct nlattr *nla,
                cp_new->mode |= CTINFO_MODE_CPMARK;
        }
 
+       cp_new->action = actparm->action;
+
        spin_lock_bh(&ci->tcf_lock);
        goto_ch = tcf_action_set_ctrlact(*a, actparm->action, goto_ch);
        cp_new = rcu_replace_pointer(ci->params, cp_new,
@@ -282,25 +282,24 @@ release_idr:
 static int tcf_ctinfo_dump(struct sk_buff *skb, struct tc_action *a,
                           int bind, int ref)
 {
-       struct tcf_ctinfo *ci = to_ctinfo(a);
+       const struct tcf_ctinfo *ci = to_ctinfo(a);
+       unsigned char *b = skb_tail_pointer(skb);
+       const struct tcf_ctinfo_params *cp;
        struct tc_ctinfo opt = {
                .index   = ci->tcf_index,
                .refcnt  = refcount_read(&ci->tcf_refcnt) - ref,
                .bindcnt = atomic_read(&ci->tcf_bindcnt) - bind,
        };
-       unsigned char *b = skb_tail_pointer(skb);
-       struct tcf_ctinfo_params *cp;
        struct tcf_t t;
 
-       spin_lock_bh(&ci->tcf_lock);
-       cp = rcu_dereference_protected(ci->params,
-                                      lockdep_is_held(&ci->tcf_lock));
+       rcu_read_lock();
+       cp = rcu_dereference(ci->params);
 
        tcf_tm_dump(&t, &ci->tcf_tm);
        if (nla_put_64bit(skb, TCA_CTINFO_TM, sizeof(t), &t, TCA_CTINFO_PAD))
                goto nla_put_failure;
 
-       opt.action = ci->tcf_action;
+       opt.action = cp->action;
        if (nla_put(skb, TCA_CTINFO_ACT, sizeof(opt), &opt))
                goto nla_put_failure;
 
@@ -337,11 +336,11 @@ static int tcf_ctinfo_dump(struct sk_buff *skb, struct tc_action *a,
                              TCA_CTINFO_PAD))
                goto nla_put_failure;
 
-       spin_unlock_bh(&ci->tcf_lock);
+       rcu_read_unlock();
        return skb->len;
 
 nla_put_failure:
-       spin_unlock_bh(&ci->tcf_lock);
+       rcu_read_unlock();
        nlmsg_trim(skb, b);
        return -1;
 }