diff options
author | Lennart Poettering <lennart@poettering.net> | 2020-09-12 00:09:07 +0200 |
---|---|---|
committer | Zbigniew Jędrzejewski-Szmek <zbyszek@in.waw.pl> | 2020-09-20 11:56:30 +0200 |
commit | 1557cfcf7ce1f2b9f2dbd28e1f9ee9fad606dec0 (patch) | |
tree | b88d8e38266d2f5e7d05de40102bce599c9f263f | |
parent | 0db378d852c03667360a94e2b2d6c5c0ab09b931 (diff) | |
download | systemd-1557cfcf7ce1f2b9f2dbd28e1f9ee9fad606dec0.tar.gz |
hashmap: make sure to initialize shared hash key atomically
if we allocate a bunch of hash tables all at the same time, with none
earlier than the other, there's a good chance we'll initialize the
shared hash key multiple times, so that some threads will see a
different shared hash key than others.
Let's fix that, and make sure really everyone sees the same hash key.
Fixes: #17007
(cherry picked from commit ae0b700a856c0ae460d271bb50dccfaae84dbcab)
(cherry picked from commit e662cf6d515daad19e70c3d85e244b213ac48997)
-rw-r--r-- | src/basic/hashmap.c | 13 |
1 files changed, 7 insertions, 6 deletions
diff --git a/src/basic/hashmap.c b/src/basic/hashmap.c index 4853514c96..beac195d05 100644 --- a/src/basic/hashmap.c +++ b/src/basic/hashmap.c @@ -1,6 +1,7 @@ /* SPDX-License-Identifier: LGPL-2.1+ */ #include <errno.h> +#include <pthread.h> #include <stdint.h> #include <stdlib.h> @@ -19,7 +20,6 @@ #include "strv.h" #if ENABLE_DEBUG_HASHMAP -#include <pthread.h> #include "list.h" #endif @@ -194,7 +194,6 @@ assert_cc(DIRECT_BUCKETS(struct set_entry) < (1 << 3)); * a handful of directly stored entries in a hashmap. When a hashmap * outgrows direct storage, it gets its own key for indirect storage. */ static uint8_t shared_hash_key[HASH_KEY_SIZE]; -static bool shared_hash_key_initialized; /* Fields that all hashmap/set types must have */ struct HashmapBase { @@ -770,6 +769,10 @@ static void reset_direct_storage(HashmapBase *h) { memset(p, DIB_RAW_INIT, sizeof(dib_raw_t) * hi->n_direct_buckets); } +static void shared_hash_key_initialize(void) { + random_bytes(shared_hash_key, sizeof(shared_hash_key)); +} + static struct HashmapBase *hashmap_base_new(const struct hash_ops *hash_ops, enum HashmapType type HASHMAP_DEBUG_PARAMS) { HashmapBase *h; const struct hashmap_type_info *hi = &hashmap_type_info[type]; @@ -792,10 +795,8 @@ static struct HashmapBase *hashmap_base_new(const struct hash_ops *hash_ops, enu reset_direct_storage(h); - if (!shared_hash_key_initialized) { - random_bytes(shared_hash_key, sizeof(shared_hash_key)); - shared_hash_key_initialized= true; - } + static pthread_once_t once = PTHREAD_ONCE_INIT; + assert_se(pthread_once(&once, shared_hash_key_initialize) == 0); #if ENABLE_DEBUG_HASHMAP h->debug.func = func; |