struct gnet_stats_basic_cpu __percpu *cpu_bstats_hw;
        struct gnet_stats_queue __percpu *cpu_qstats;
        struct tc_cookie        __rcu *act_cookie;
-       struct tcf_chain        *goto_chain;
+       struct tcf_chain        __rcu *goto_chain;
 };
 #define tcf_index      common.tcfa_index
 #define tcf_refcnt     common.tcfa_refcnt
 
 static void tcf_action_goto_chain_exec(const struct tc_action *a,
                                       struct tcf_result *res)
 {
-       const struct tcf_chain *chain = a->goto_chain;
+       const struct tcf_chain *chain = rcu_dereference_bh(a->goto_chain);
 
        res->goto_tp = rcu_dereference_bh(chain->filter_chain);
 }
 EXPORT_SYMBOL(tcf_action_check_ctrlact);
 
 struct tcf_chain *tcf_action_set_ctrlact(struct tc_action *a, int action,
-                                        struct tcf_chain *newchain)
+                                        struct tcf_chain *goto_chain)
 {
-       struct tcf_chain *oldchain = a->goto_chain;
-
        a->tcfa_action = action;
-       a->goto_chain = newchain;
-       return oldchain;
+       rcu_swap_protected(a->goto_chain, goto_chain, 1);
+       return goto_chain;
 }
 EXPORT_SYMBOL(tcf_action_set_ctrlact);
 
  */
 static void free_tcf(struct tc_action *p)
 {
-       struct tcf_chain *chain = p->goto_chain;
+       struct tcf_chain *chain = rcu_dereference_protected(p->goto_chain, 1);
 
        free_percpu(p->cpu_bstats);
        free_percpu(p->cpu_bstats_hw);
                                        return TC_ACT_OK;
                        }
                } else if (TC_ACT_EXT_CMP(ret, TC_ACT_GOTO_CHAIN)) {
+                       if (unlikely(!rcu_access_pointer(a->goto_chain))) {
+                               net_warn_ratelimited("can't go to NULL chain!\n");
+                               return TC_ACT_SHOT;
+                       }
                        tcf_action_goto_chain_exec(a, res);
                }
 
                module_put(a_o->owner);
 
        if (TC_ACT_EXT_CMP(a->tcfa_action, TC_ACT_GOTO_CHAIN) &&
-           !a->goto_chain) {
+           !rcu_access_pointer(a->goto_chain)) {
                tcf_action_destroy_1(a, bind);
                NL_SET_ERR_MSG(extack, "can't use goto chain with NULL chain");
                return ERR_PTR(-EINVAL);