aboutsummaryrefslogtreecommitdiffstats
path: root/net
diff options
context:
space:
mode:
authorGao Feng <fgao@ikuai8.com>2017-03-29 07:11:27 -0400
committerPablo Neira Ayuso <pablo@netfilter.org>2017-04-08 17:52:15 -0400
commit8b5995d0633b04f9a0d321a7cc77e386440730cf (patch)
treed495422d1ce9a6b03ba312921d2b4b9ad90779d8 /net
parent97aae0df1de4d7dd80905fb067e28b032a132995 (diff)
netfilter: helper: Add the rcu lock when call __nf_conntrack_helper_find
When invoke __nf_conntrack_helper_find, it needs the rcu lock to protect the helper module which would not be unloaded. Now there are two caller nf_conntrack_helper_try_module_get and ctnetlink_create_expect which don't hold rcu lock. And the other callers left like ctnetlink_change_helper, ctnetlink_create_conntrack, and ctnetlink_glue_attach_expect, they already hold the rcu lock or spin_lock_bh. Remove the rcu lock in functions nf_ct_helper_expectfn_find_by_name and nf_ct_helper_expectfn_find_by_symbol. Because they return one pointer which needs rcu lock, so their caller should hold the rcu lock, not in these two functions. Signed-off-by: Gao Feng <fgao@ikuai8.com> Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
Diffstat (limited to 'net')
-rw-r--r--net/netfilter/nf_conntrack_helper.c17
-rw-r--r--net/netfilter/nf_conntrack_netlink.c10
2 files changed, 20 insertions, 7 deletions
diff --git a/net/netfilter/nf_conntrack_helper.c b/net/netfilter/nf_conntrack_helper.c
index 6dc44d9b4190..4eeb3418366a 100644
--- a/net/netfilter/nf_conntrack_helper.c
+++ b/net/netfilter/nf_conntrack_helper.c
@@ -158,16 +158,25 @@ nf_conntrack_helper_try_module_get(const char *name, u16 l3num, u8 protonum)
158{ 158{
159 struct nf_conntrack_helper *h; 159 struct nf_conntrack_helper *h;
160 160
161 rcu_read_lock();
162
161 h = __nf_conntrack_helper_find(name, l3num, protonum); 163 h = __nf_conntrack_helper_find(name, l3num, protonum);
162#ifdef CONFIG_MODULES 164#ifdef CONFIG_MODULES
163 if (h == NULL) { 165 if (h == NULL) {
164 if (request_module("nfct-helper-%s", name) == 0) 166 rcu_read_unlock();
167 if (request_module("nfct-helper-%s", name) == 0) {
168 rcu_read_lock();
165 h = __nf_conntrack_helper_find(name, l3num, protonum); 169 h = __nf_conntrack_helper_find(name, l3num, protonum);
170 } else {
171 return h;
172 }
166 } 173 }
167#endif 174#endif
168 if (h != NULL && !try_module_get(h->me)) 175 if (h != NULL && !try_module_get(h->me))
169 h = NULL; 176 h = NULL;
170 177
178 rcu_read_unlock();
179
171 return h; 180 return h;
172} 181}
173EXPORT_SYMBOL_GPL(nf_conntrack_helper_try_module_get); 182EXPORT_SYMBOL_GPL(nf_conntrack_helper_try_module_get);
@@ -311,38 +320,36 @@ void nf_ct_helper_expectfn_unregister(struct nf_ct_helper_expectfn *n)
311} 320}
312EXPORT_SYMBOL_GPL(nf_ct_helper_expectfn_unregister); 321EXPORT_SYMBOL_GPL(nf_ct_helper_expectfn_unregister);
313 322
323/* Caller should hold the rcu lock */
314struct nf_ct_helper_expectfn * 324struct nf_ct_helper_expectfn *
315nf_ct_helper_expectfn_find_by_name(const char *name) 325nf_ct_helper_expectfn_find_by_name(const char *name)
316{ 326{
317 struct nf_ct_helper_expectfn *cur; 327 struct nf_ct_helper_expectfn *cur;
318 bool found = false; 328 bool found = false;
319 329
320 rcu_read_lock();
321 list_for_each_entry_rcu(cur, &nf_ct_helper_expectfn_list, head) { 330 list_for_each_entry_rcu(cur, &nf_ct_helper_expectfn_list, head) {
322 if (!strcmp(cur->name, name)) { 331 if (!strcmp(cur->name, name)) {
323 found = true; 332 found = true;
324 break; 333 break;
325 } 334 }
326 } 335 }
327 rcu_read_unlock();
328 return found ? cur : NULL; 336 return found ? cur : NULL;
329} 337}
330EXPORT_SYMBOL_GPL(nf_ct_helper_expectfn_find_by_name); 338EXPORT_SYMBOL_GPL(nf_ct_helper_expectfn_find_by_name);
331 339
340/* Caller should hold the rcu lock */
332struct nf_ct_helper_expectfn * 341struct nf_ct_helper_expectfn *
333nf_ct_helper_expectfn_find_by_symbol(const void *symbol) 342nf_ct_helper_expectfn_find_by_symbol(const void *symbol)
334{ 343{
335 struct nf_ct_helper_expectfn *cur; 344 struct nf_ct_helper_expectfn *cur;
336 bool found = false; 345 bool found = false;
337 346
338 rcu_read_lock();
339 list_for_each_entry_rcu(cur, &nf_ct_helper_expectfn_list, head) { 347 list_for_each_entry_rcu(cur, &nf_ct_helper_expectfn_list, head) {
340 if (cur->expectfn == symbol) { 348 if (cur->expectfn == symbol) {
341 found = true; 349 found = true;
342 break; 350 break;
343 } 351 }
344 } 352 }
345 rcu_read_unlock();
346 return found ? cur : NULL; 353 return found ? cur : NULL;
347} 354}
348EXPORT_SYMBOL_GPL(nf_ct_helper_expectfn_find_by_symbol); 355EXPORT_SYMBOL_GPL(nf_ct_helper_expectfn_find_by_symbol);
diff --git a/net/netfilter/nf_conntrack_netlink.c b/net/netfilter/nf_conntrack_netlink.c
index 59ee27deb9a0..06d28ac663df 100644
--- a/net/netfilter/nf_conntrack_netlink.c
+++ b/net/netfilter/nf_conntrack_netlink.c
@@ -3133,23 +3133,27 @@ ctnetlink_create_expect(struct net *net,
3133 return -ENOENT; 3133 return -ENOENT;
3134 ct = nf_ct_tuplehash_to_ctrack(h); 3134 ct = nf_ct_tuplehash_to_ctrack(h);
3135 3135
3136 rcu_read_lock();
3136 if (cda[CTA_EXPECT_HELP_NAME]) { 3137 if (cda[CTA_EXPECT_HELP_NAME]) {
3137 const char *helpname = nla_data(cda[CTA_EXPECT_HELP_NAME]); 3138 const char *helpname = nla_data(cda[CTA_EXPECT_HELP_NAME]);
3138 3139
3139 helper = __nf_conntrack_helper_find(helpname, u3, 3140 helper = __nf_conntrack_helper_find(helpname, u3,
3140 nf_ct_protonum(ct)); 3141 nf_ct_protonum(ct));
3141 if (helper == NULL) { 3142 if (helper == NULL) {
3143 rcu_read_unlock();
3142#ifdef CONFIG_MODULES 3144#ifdef CONFIG_MODULES
3143 if (request_module("nfct-helper-%s", helpname) < 0) { 3145 if (request_module("nfct-helper-%s", helpname) < 0) {
3144 err = -EOPNOTSUPP; 3146 err = -EOPNOTSUPP;
3145 goto err_ct; 3147 goto err_ct;
3146 } 3148 }
3149 rcu_read_lock();
3147 helper = __nf_conntrack_helper_find(helpname, u3, 3150 helper = __nf_conntrack_helper_find(helpname, u3,
3148 nf_ct_protonum(ct)); 3151 nf_ct_protonum(ct));
3149 if (helper) { 3152 if (helper) {
3150 err = -EAGAIN; 3153 err = -EAGAIN;
3151 goto err_ct; 3154 goto err_rcu;
3152 } 3155 }
3156 rcu_read_unlock();
3153#endif 3157#endif
3154 err = -EOPNOTSUPP; 3158 err = -EOPNOTSUPP;
3155 goto err_ct; 3159 goto err_ct;
@@ -3159,11 +3163,13 @@ ctnetlink_create_expect(struct net *net,
3159 exp = ctnetlink_alloc_expect(cda, ct, helper, &tuple, &mask); 3163 exp = ctnetlink_alloc_expect(cda, ct, helper, &tuple, &mask);
3160 if (IS_ERR(exp)) { 3164 if (IS_ERR(exp)) {
3161 err = PTR_ERR(exp); 3165 err = PTR_ERR(exp);
3162 goto err_ct; 3166 goto err_rcu;
3163 } 3167 }
3164 3168
3165 err = nf_ct_expect_related_report(exp, portid, report); 3169 err = nf_ct_expect_related_report(exp, portid, report);
3166 nf_ct_expect_put(exp); 3170 nf_ct_expect_put(exp);
3171err_rcu:
3172 rcu_read_unlock();
3167err_ct: 3173err_ct:
3168 nf_ct_put(ct); 3174 nf_ct_put(ct);
3169 return err; 3175 return err;