]> git.ipfire.org Git - thirdparty/kernel/stable.git/commitdiff
net_sched: act_tunnel_key: use RCU in tunnel_key_dump()
authorEric Dumazet <edumazet@google.com>
Wed, 27 Aug 2025 12:53:48 +0000 (12:53 +0000)
committerJakub Kicinski <kuba@kernel.org>
Thu, 28 Aug 2025 23:46:23 +0000 (16:46 -0700)
Also storing tcf_action into struct tcf_tunnel_key_params
makes sure there is no discrepancy in tunnel_key_act().

No longer block BH in tunnel_key_init() when acquiring tcf_lock.

Signed-off-by: Eric Dumazet <edumazet@google.com>
Reviewed-by: Simon Horman <horms@kernel.org>
Link: https://patch.msgid.link/20250827125349.3505302-4-edumazet@google.com
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
include/net/tc_act/tc_tunnel_key.h
net/sched/act_tunnel_key.c

index 879fe8cff581951c759076b159d3ee16f9db34c1..0f1925f97520209b3a9f110d3c7e9bb3c5ef2968 100644 (file)
@@ -14,6 +14,7 @@
 struct tcf_tunnel_key_params {
        struct rcu_head         rcu;
        int                     tcft_action;
+       int                     action;
        struct metadata_dst     *tcft_enc_metadata;
 };
 
index 2cef4b08befbecf498ea836d45abdef1ee4e06b5..e1c8b48c217c339d5e806d031ba287df2a57b1aa 100644 (file)
@@ -29,13 +29,11 @@ TC_INDIRECT_SCOPE int tunnel_key_act(struct sk_buff *skb,
 {
        struct tcf_tunnel_key *t = to_tunnel_key(a);
        struct tcf_tunnel_key_params *params;
-       int action;
 
        params = rcu_dereference_bh(t->params);
 
        tcf_lastuse_update(&t->tcf_tm);
        tcf_action_update_bstats(&t->common, skb);
-       action = READ_ONCE(t->tcf_action);
 
        switch (params->tcft_action) {
        case TCA_TUNNEL_KEY_ACT_RELEASE:
@@ -51,7 +49,7 @@ TC_INDIRECT_SCOPE int tunnel_key_act(struct sk_buff *skb,
                break;
        }
 
-       return action;
+       return params->action;
 }
 
 static const struct nla_policy
@@ -532,11 +530,12 @@ static int tunnel_key_init(struct net *net, struct nlattr *nla,
        params_new->tcft_action = parm->t_action;
        params_new->tcft_enc_metadata = metadata;
 
-       spin_lock_bh(&t->tcf_lock);
+       params_new->action = parm->action;
+       spin_lock(&t->tcf_lock);
        goto_ch = tcf_action_set_ctrlact(*a, parm->action, goto_ch);
        params_new = rcu_replace_pointer(t->params, params_new,
                                         lockdep_is_held(&t->tcf_lock));
-       spin_unlock_bh(&t->tcf_lock);
+       spin_unlock(&t->tcf_lock);
        tunnel_key_release_params(params_new);
        if (goto_ch)
                tcf_chain_put_by_act(goto_ch);
@@ -726,10 +725,9 @@ static int tunnel_key_dump(struct sk_buff *skb, struct tc_action *a,
        };
        struct tcf_t tm;
 
-       spin_lock_bh(&t->tcf_lock);
-       params = rcu_dereference_protected(t->params,
-                                          lockdep_is_held(&t->tcf_lock));
-       opt.action   = t->tcf_action;
+       rcu_read_lock();
+       params = rcu_dereference(t->params);
+       opt.action   = params->action;
        opt.t_action = params->tcft_action;
 
        if (nla_put(skb, TCA_TUNNEL_KEY_PARMS, sizeof(opt), &opt))
@@ -766,12 +764,12 @@ static int tunnel_key_dump(struct sk_buff *skb, struct tc_action *a,
        if (nla_put_64bit(skb, TCA_TUNNEL_KEY_TM, sizeof(tm),
                          &tm, TCA_TUNNEL_KEY_PAD))
                goto nla_put_failure;
-       spin_unlock_bh(&t->tcf_lock);
+       rcu_read_unlock();
 
        return skb->len;
 
 nla_put_failure:
-       spin_unlock_bh(&t->tcf_lock);
+       rcu_read_unlock();
        nlmsg_trim(skb, b);
        return -1;
 }