aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/src/ratelimiter.c
diff options
context:
space:
mode:
authorJason A. Donenfeld <Jason@zx2c4.com>2018-07-31 06:12:57 +0200
committerJason A. Donenfeld <Jason@zx2c4.com>2018-07-31 06:12:57 +0200
commit153c9f601b2d191797e2be76224a9112cdd4d9cb (patch)
tree2178262ab291fee31ba387b6edee5508adb76463 /src/ratelimiter.c
parentmain: add missing chacha20poly1305 header (diff)
downloadwireguard-monolithic-historical-153c9f601b2d191797e2be76224a9112cdd4d9cb.tar.xz
wireguard-monolithic-historical-153c9f601b2d191797e2be76224a9112cdd4d9cb.zip
ratelimiter: prevent init/uninit race
Fixes a classic ABA problem that isn't actually reachable because of rtnl_lock, but it's good to be correct anyway. Reported-by: Jann Horn <jann@thejh.net>
Diffstat (limited to 'src/ratelimiter.c')
-rw-r--r--src/ratelimiter.c10
1 files changed, 6 insertions, 4 deletions
diff --git a/src/ratelimiter.c b/src/ratelimiter.c
index 140d99e..638da2b 100644
--- a/src/ratelimiter.c
+++ b/src/ratelimiter.c
@@ -144,10 +144,10 @@ err_oom:
int ratelimiter_init(void)
{
+ mutex_lock(&init_lock);
if (atomic64_inc_return(&refcnt) != 1)
- return 0;
+ goto out;
- mutex_lock(&init_lock);
entry_cache = KMEM_CACHE(ratelimiter_entry, 0);
if (!entry_cache)
goto err;
@@ -174,6 +174,7 @@ int ratelimiter_init(void)
queue_delayed_work(system_power_efficient_wq, &gc_work, HZ);
get_random_bytes(&key, sizeof(key));
+out:
mutex_unlock(&init_lock);
return 0;
@@ -187,10 +188,10 @@ err:
void ratelimiter_uninit(void)
{
+ mutex_lock(&init_lock);
if (atomic64_dec_if_positive(&refcnt))
- return;
+ goto out;
- mutex_lock(&init_lock);
cancel_delayed_work_sync(&gc_work);
gc_entries(NULL);
rcu_barrier();
@@ -199,6 +200,7 @@ void ratelimiter_uninit(void)
kvfree(table_v6);
#endif
kmem_cache_destroy(entry_cache);
+out:
mutex_unlock(&init_lock);
}