diff options
author | jhb <jhb@FreeBSD.org> | 2010-03-10 13:23:25 +0000 |
---|---|---|
committer | jhb <jhb@FreeBSD.org> | 2010-03-10 13:23:25 +0000 |
commit | e0724fd324c89b8c46185fe402fd332141ea5bf5 (patch) | |
tree | dae7801acd654dfe736481930016ad68270d7757 /lib/libc/rpc/key_call.c | |
parent | 42dc39ae95f85b0f1bedbdfa406342f9ac3e4fcc (diff) | |
download | FreeBSD-src-e0724fd324c89b8c46185fe402fd332141ea5bf5.zip FreeBSD-src-e0724fd324c89b8c46185fe402fd332141ea5bf5.tar.gz |
Use thr_once() with once_t controls to initialize various thread_key_t
objects used to provide per-thread storage in the RPC code. Almost all
of these used double-checking with a dedicated mutex (tsd_lock) to do this
before. However, that is not always safe with more relaxed memory orders.
There were also other bugs, such as one in __rpc_createrr() that caused a
new key to be allocated each time __rpc_createrr() was invoked.
PR: threads/144558
Reported by: Sam Robb samrobb of averesystems com (key leak)
MFC after: 1 week
Diffstat (limited to 'lib/libc/rpc/key_call.c')
-rw-r--r-- | lib/libc/rpc/key_call.c | 20 |
1 files changed, 13 insertions, 7 deletions
diff --git a/lib/libc/rpc/key_call.c b/lib/libc/rpc/key_call.c index 6cc1139..afb11c8 100644 --- a/lib/libc/rpc/key_call.c +++ b/lib/libc/rpc/key_call.c @@ -279,6 +279,9 @@ struct key_call_private { uid_t uid; /* user-id at last authorization */ }; static struct key_call_private *key_call_private_main = NULL; +static thread_key_t key_call_key; +static once_t key_call_once = ONCE_INITIALIZER; +static int key_call_key_error; static void key_call_destroy(void *vp) @@ -292,6 +295,13 @@ key_call_destroy(void *vp) } } +static void +key_call_init(void) +{ + + key_call_key_error = thr_keycreate(&key_call_key, key_call_destroy); +} + /* * Keep the handle cached. This call may be made quite often. */ @@ -307,7 +317,6 @@ int vers; struct utsname u; int main_thread; int fd; - static thread_key_t key_call_key; #define TOTAL_TIMEOUT 30 /* total timeout talking to keyserver */ #define TOTAL_TRIES 5 /* Number of tries */ @@ -315,12 +324,9 @@ int vers; if ((main_thread = thr_main())) { kcp = key_call_private_main; } else { - if (key_call_key == 0) { - mutex_lock(&tsd_lock); - if (key_call_key == 0) - thr_keycreate(&key_call_key, key_call_destroy); - mutex_unlock(&tsd_lock); - } + if (thr_once(&key_call_once, key_call_init) != 0 || + key_call_key_error != 0) + return ((CLIENT *) NULL); kcp = (struct key_call_private *)thr_getspecific(key_call_key); } if (kcp == (struct key_call_private *)NULL) { |