diff options
author | Pavel Emelyanov <xemul@openvz.org> | 2008-07-31 03:38:31 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2008-07-31 03:38:31 -0400 |
commit | a8ddc9163c6a16cd62531dba1ec5020484e33b02 (patch) | |
tree | 316873162ae914edd6a4f250693017486dede52a /net | |
parent | ae375044d31075a31de5a839e07ded7f67b660aa (diff) |
netfilter: ipt_recent: fix race between recent_mt_destroy and proc manipulations
The thing is that recent_mt_destroy first flushes the entries
from table with the recent_table_flush and only *after* this
removes the proc file, corresponding to that table.
Thus, if we manage to write to this file the '+XXX' command we
will leak some entries. If we manage to write there a 'clean'
command we'll race in two recent_table_flush flows, since the
recent_mt_destroy calls this outside the recent_lock.
The proper solution as I see it is to remove the proc file first
and then go on with flushing the table. This flushing becomes
safe w/o the lock, since the table is already inaccessible from
the outside.
Signed-off-by: Pavel Emelyanov <xemul@openvz.org>
Signed-off-by: Patrick McHardy <kaber@trash.net>
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net')
-rw-r--r-- | net/ipv4/netfilter/ipt_recent.c | 2 |
1 files changed, 1 insertions, 1 deletions
diff --git a/net/ipv4/netfilter/ipt_recent.c b/net/ipv4/netfilter/ipt_recent.c index 21cb053f5d7..3974d7cae5c 100644 --- a/net/ipv4/netfilter/ipt_recent.c +++ b/net/ipv4/netfilter/ipt_recent.c | |||
@@ -305,10 +305,10 @@ static void recent_mt_destroy(const struct xt_match *match, void *matchinfo) | |||
305 | spin_lock_bh(&recent_lock); | 305 | spin_lock_bh(&recent_lock); |
306 | list_del(&t->list); | 306 | list_del(&t->list); |
307 | spin_unlock_bh(&recent_lock); | 307 | spin_unlock_bh(&recent_lock); |
308 | recent_table_flush(t); | ||
309 | #ifdef CONFIG_PROC_FS | 308 | #ifdef CONFIG_PROC_FS |
310 | remove_proc_entry(t->name, proc_dir); | 309 | remove_proc_entry(t->name, proc_dir); |
311 | #endif | 310 | #endif |
311 | recent_table_flush(t); | ||
312 | kfree(t); | 312 | kfree(t); |
313 | } | 313 | } |
314 | mutex_unlock(&recent_mutex); | 314 | mutex_unlock(&recent_mutex); |