diff options
Diffstat (limited to 'net')
-rw-r--r-- | net/ipv4/netfilter/ipt_recent.c | 15 |
1 files changed, 10 insertions, 5 deletions
diff --git a/net/ipv4/netfilter/ipt_recent.c b/net/ipv4/netfilter/ipt_recent.c index 9686c4d2057d..9b09e481957d 100644 --- a/net/ipv4/netfilter/ipt_recent.c +++ b/net/ipv4/netfilter/ipt_recent.c | |||
@@ -69,6 +69,7 @@ struct recent_table { | |||
69 | 69 | ||
70 | static LIST_HEAD(tables); | 70 | static LIST_HEAD(tables); |
71 | static DEFINE_SPINLOCK(recent_lock); | 71 | static DEFINE_SPINLOCK(recent_lock); |
72 | static DEFINE_MUTEX(recent_mutex); | ||
72 | 73 | ||
73 | #ifdef CONFIG_PROC_FS | 74 | #ifdef CONFIG_PROC_FS |
74 | static struct proc_dir_entry *proc_dir; | 75 | static struct proc_dir_entry *proc_dir; |
@@ -249,7 +250,7 @@ ipt_recent_checkentry(const char *tablename, const void *ip, | |||
249 | strnlen(info->name, IPT_RECENT_NAME_LEN) == IPT_RECENT_NAME_LEN) | 250 | strnlen(info->name, IPT_RECENT_NAME_LEN) == IPT_RECENT_NAME_LEN) |
250 | return 0; | 251 | return 0; |
251 | 252 | ||
252 | spin_lock_bh(&recent_lock); | 253 | mutex_lock(&recent_mutex); |
253 | t = recent_table_lookup(info->name); | 254 | t = recent_table_lookup(info->name); |
254 | if (t != NULL) { | 255 | if (t != NULL) { |
255 | t->refcnt++; | 256 | t->refcnt++; |
@@ -258,7 +259,7 @@ ipt_recent_checkentry(const char *tablename, const void *ip, | |||
258 | } | 259 | } |
259 | 260 | ||
260 | t = kzalloc(sizeof(*t) + sizeof(t->iphash[0]) * ip_list_hash_size, | 261 | t = kzalloc(sizeof(*t) + sizeof(t->iphash[0]) * ip_list_hash_size, |
261 | GFP_ATOMIC); | 262 | GFP_KERNEL); |
262 | if (t == NULL) | 263 | if (t == NULL) |
263 | goto out; | 264 | goto out; |
264 | strcpy(t->name, info->name); | 265 | strcpy(t->name, info->name); |
@@ -274,10 +275,12 @@ ipt_recent_checkentry(const char *tablename, const void *ip, | |||
274 | t->proc->proc_fops = &recent_fops; | 275 | t->proc->proc_fops = &recent_fops; |
275 | t->proc->data = t; | 276 | t->proc->data = t; |
276 | #endif | 277 | #endif |
278 | spin_lock_bh(&recent_lock); | ||
277 | list_add_tail(&t->list, &tables); | 279 | list_add_tail(&t->list, &tables); |
280 | spin_unlock_bh(&recent_lock); | ||
278 | ret = 1; | 281 | ret = 1; |
279 | out: | 282 | out: |
280 | spin_unlock_bh(&recent_lock); | 283 | mutex_unlock(&recent_mutex); |
281 | return ret; | 284 | return ret; |
282 | } | 285 | } |
283 | 286 | ||
@@ -288,17 +291,19 @@ ipt_recent_destroy(const struct xt_match *match, void *matchinfo, | |||
288 | const struct ipt_recent_info *info = matchinfo; | 291 | const struct ipt_recent_info *info = matchinfo; |
289 | struct recent_table *t; | 292 | struct recent_table *t; |
290 | 293 | ||
291 | spin_lock_bh(&recent_lock); | 294 | mutex_lock(&recent_mutex); |
292 | t = recent_table_lookup(info->name); | 295 | t = recent_table_lookup(info->name); |
293 | if (--t->refcnt == 0) { | 296 | if (--t->refcnt == 0) { |
297 | spin_lock_bh(&recent_lock); | ||
294 | list_del(&t->list); | 298 | list_del(&t->list); |
299 | spin_unlock_bh(&recent_lock); | ||
295 | recent_table_flush(t); | 300 | recent_table_flush(t); |
296 | #ifdef CONFIG_PROC_FS | 301 | #ifdef CONFIG_PROC_FS |
297 | remove_proc_entry(t->name, proc_dir); | 302 | remove_proc_entry(t->name, proc_dir); |
298 | #endif | 303 | #endif |
299 | kfree(t); | 304 | kfree(t); |
300 | } | 305 | } |
301 | spin_unlock_bh(&recent_lock); | 306 | mutex_unlock(&recent_mutex); |
302 | } | 307 | } |
303 | 308 | ||
304 | #ifdef CONFIG_PROC_FS | 309 | #ifdef CONFIG_PROC_FS |