From: Su Yanjun <suyj.fnst@xxxxxxxxxxxxxx> Because nf_conntrack_helper_unregister maybe used in an unloadable module, it uses 'synchronize_rcu' which may cause kernel panic. According to the artical: RCU and Unloadable Modules https://lwn.net/Articles/217484/ When we have a heavy rcu callback load, then some of the callbacks might be deferred in order to allow other processing to proceed. sychnorize_rcu does not wait rcu callback complete and module may be unloaded before callback done. This patch uses rcu_barrier instead of synchronize_rcu will prevent this situation. Signed-off-by: Su Yanjun <suyj.fnst@xxxxxxxxxxxxxx> --- net/netfilter/nf_conntrack_helper.c | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/net/netfilter/nf_conntrack_helper.c b/net/netfilter/nf_conntrack_helper.c index 274baf1..0ee9378 100644 --- a/net/netfilter/nf_conntrack_helper.c +++ b/net/netfilter/nf_conntrack_helper.c @@ -397,8 +397,15 @@ void nf_conntrack_helper_unregister(struct nf_conntrack_helper *me) /* Make sure every nothing is still using the helper unless its a * connection in the hash. + * + * 'synchronize_rcu' may have problem when rcu callback function + * is used in unloadable modules. Use rcu_barrier instead, so that + * it will wait until rcu callback completes before modules are + * unloaded. + * More detail about rcu_barrier please see: + * https://lwn.net/Articles/217484/ */ - synchronize_rcu(); + rcu_barrier(); nf_ct_expect_iterate_destroy(expect_iter_me, NULL); nf_ct_iterate_destroy(unhelp, me); @@ -406,7 +413,7 @@ void nf_conntrack_helper_unregister(struct nf_conntrack_helper *me) /* Maybe someone has gotten the helper already when unhelp above. * So need to wait it. */ - synchronize_rcu(); + rcu_barrier(); } EXPORT_SYMBOL_GPL(nf_conntrack_helper_unregister); -- 2.7.4