]> git.ipfire.org Git - thirdparty/linux.git/commitdiff
net_sched: act_ct: use RCU in tcf_ct_dump()
authorEric Dumazet <edumazet@google.com>
Wed, 9 Jul 2025 09:01:56 +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_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>
include/net/tc_act/tc_ct.h
net/sched/act_ct.c

index e6b45cb27ebf43d6c937fd823767ac1cc9797524..8b90c86c0b0ddd63a3eab7d59328404deb148b10 100644 (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;
 
index c02f39efc6efead9e18908bdb307872445c6b8fd..6749a4a9a9cd0a43897fcd20d228721ce057cb88 100644 (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;
 }