Commit 3b7dabf029478bb80507a6c4500ca94132a2bc0b

Authored by Liping Zhang
Committed by Pablo Neira Ayuso
1 parent f83bf8da11

netfilter: invoke synchronize_rcu after set the _hook_ to NULL

Otherwise, another CPU may access the invalid pointer. For example:
    CPU0                CPU1
     -              rcu_read_lock();
     -              pfunc = _hook_;
  _hook_ = NULL;          -
  mod unload              -
     -                 pfunc(); // invalid, panic
     -             rcu_read_unlock();

So we must call synchronize_rcu() to wait the rcu reader to finish.

Also note, in nf_nat_snmp_basic_fini, synchronize_rcu() will be invoked
by later nf_conntrack_helper_unregister, but I'm inclined to add a
explicit synchronize_rcu after set the nf_nat_snmp_hook to NULL. Depend
on such obscure assumptions is not a good idea.

Last, in nfnetlink_cttimeout, we use kfree_rcu to free the time object,
so in cttimeout_exit, invoking rcu_barrier() is not necessary at all,
remove it too.

Signed-off-by: Liping Zhang <zlpnobody@gmail.com>
Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>

Showing 5 changed files with 7 additions and 1 deletions Side-by-side Diff

net/ipv4/netfilter/nf_nat_snmp_basic.c
... ... @@ -1304,6 +1304,7 @@
1304 1304 static void __exit nf_nat_snmp_basic_fini(void)
1305 1305 {
1306 1306 RCU_INIT_POINTER(nf_nat_snmp_hook, NULL);
  1307 + synchronize_rcu();
1307 1308 nf_conntrack_helper_unregister(&snmp_trap_helper);
1308 1309 }
1309 1310  
net/netfilter/nf_conntrack_ecache.c
... ... @@ -290,6 +290,7 @@
290 290 BUG_ON(notify != new);
291 291 RCU_INIT_POINTER(net->ct.nf_conntrack_event_cb, NULL);
292 292 mutex_unlock(&nf_ct_ecache_mutex);
  293 + /* synchronize_rcu() is called from ctnetlink_exit. */
293 294 }
294 295 EXPORT_SYMBOL_GPL(nf_conntrack_unregister_notifier);
295 296  
... ... @@ -326,6 +327,7 @@
326 327 BUG_ON(notify != new);
327 328 RCU_INIT_POINTER(net->ct.nf_expect_event_cb, NULL);
328 329 mutex_unlock(&nf_ct_ecache_mutex);
  330 + /* synchronize_rcu() is called from ctnetlink_exit. */
329 331 }
330 332 EXPORT_SYMBOL_GPL(nf_ct_expect_unregister_notifier);
331 333  
net/netfilter/nf_conntrack_netlink.c
... ... @@ -3442,6 +3442,7 @@
3442 3442 #ifdef CONFIG_NETFILTER_NETLINK_GLUE_CT
3443 3443 RCU_INIT_POINTER(nfnl_ct_hook, NULL);
3444 3444 #endif
  3445 + synchronize_rcu();
3445 3446 }
3446 3447  
3447 3448 module_init(ctnetlink_init);
net/netfilter/nf_nat_core.c
... ... @@ -903,6 +903,8 @@
903 903 #ifdef CONFIG_XFRM
904 904 RCU_INIT_POINTER(nf_nat_decode_session_hook, NULL);
905 905 #endif
  906 + synchronize_rcu();
  907 +
906 908 for (i = 0; i < NFPROTO_NUMPROTO; i++)
907 909 kfree(nf_nat_l4protos[i]);
908 910  
net/netfilter/nfnetlink_cttimeout.c
... ... @@ -646,8 +646,8 @@
646 646 #ifdef CONFIG_NF_CONNTRACK_TIMEOUT
647 647 RCU_INIT_POINTER(nf_ct_timeout_find_get_hook, NULL);
648 648 RCU_INIT_POINTER(nf_ct_timeout_put_hook, NULL);
  649 + synchronize_rcu();
649 650 #endif /* CONFIG_NF_CONNTRACK_TIMEOUT */
650   - rcu_barrier();
651 651 }
652 652  
653 653 module_init(cttimeout_init);