diff options
| author | Harald Welte <laforge@netfilter.org> | 2005-02-23 03:50:04 -0800 |
|---|---|---|
| committer | David S. Miller <davem@nuts.davemloft.net> | 2005-02-23 03:50:04 -0800 |
| commit | dd9e577353e5eb7f66c45913cdb5a5c7c09cbdd3 (patch) | |
| tree | 9bf0fcad30927e2d173f3f07f7afbb0fe9baffd7 | |
| parent | 320d00c5d760ea1809d1861b347b1858afedb254 (diff) | |
[NETFILTER]: ipt_hashlimit rule load time race condition
This is the best we've got: We cannot release and re-grab lock,
since checkentry() is called before ip_tables.c grabs ipt_mutex.
We also cannot grab the hashtable spinlock, since htable_create will
call vmalloc, and that can sleep. And we cannot just re-search
the list of htable's in htable_create(), since then we would
create duplicate proc files.
Signed-off-by: Harald Welte <laforge@netfilter.org>
Signed-off-by: David S. Miller <davem@davemloft.net>
| -rw-r--r-- | net/ipv4/netfilter/ipt_hashlimit.c | 10 |
1 files changed, 10 insertions, 0 deletions
diff --git a/net/ipv4/netfilter/ipt_hashlimit.c b/net/ipv4/netfilter/ipt_hashlimit.c index 9d80cac77089..6e4d8e0e65d5 100644 --- a/net/ipv4/netfilter/ipt_hashlimit.c +++ b/net/ipv4/netfilter/ipt_hashlimit.c @@ -98,6 +98,7 @@ struct ipt_hashlimit_htable { }; static DECLARE_RWLOCK(hashlimit_lock); /* protects htables list */ +static DECLARE_MUTEX(hlimit_mutex); /* additional checkentry protection */ static LIST_HEAD(hashlimit_htables); static kmem_cache_t *hashlimit_cachep; @@ -531,10 +532,19 @@ hashlimit_checkentry(const char *tablename, if (!r->cfg.expire) return 0; + /* This is the best we've got: We cannot release and re-grab lock, + * since checkentry() is called before ip_tables.c grabs ipt_mutex. + * We also cannot grab the hashtable spinlock, since htable_create will + * call vmalloc, and that can sleep. And we cannot just re-search + * the list of htable's in htable_create(), since then we would + * create duplicate proc files. -HW */ + down(&hlimit_mutex); r->hinfo = htable_find_get(r->name); if (!r->hinfo && (htable_create(r) != 0)) { + up(&hlimit_mutex); return 0; } + up(&hlimit_mutex); /* Ugly hack: For SMP, we only want to use one set */ r->u.master = r; |
