Messages in this thread Patch in this message | | | From | Su Yanjun <> | Subject | [PATCH] netfilter: nf_ct_helper: Fix possible panic when nf_conntrack_helper_unregister is used in an unloadable module | Date | Fri, 1 Mar 2019 13:56:06 +0800 |
| |
From: Su Yanjun <suyj.fnst@cn.fujitsu.com>
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@cn.fujitsu.com> --- 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
| |