nsswitch: avoid calling pthread_getspecific() on an uninitialized key
authorRalph Boehme <slow@samba.org>
Thu, 5 Jan 2023 15:25:11 +0000 (16:25 +0100)
committerStefan Metzmacher <metze@samba.org>
Fri, 6 Jan 2023 15:04:46 +0000 (15:04 +0000)
Found by ASAN:

$ bin/stress-nss-libwbclient
...
==1639426==ERROR: AddressSanitizer: unknown-crash on address 0x7f3907d85000 at pc 0x7f3907d649fb bp 0x7ffc6545f5b0 sp 0x7ffc6545f5a8
READ of size 4 at 0x7f3907d85000 thread T0
    #0 0x7f3907d649fa in winbind_close_sock ../../nsswitch/wb_common.c:220
    #1 0x7f3907d65866 in winbind_destructor ../../nsswitch/wb_common.c:246
    #2 0x7f3907da5d3d in _dl_fini /usr/src/debug/glibc-2.35-20.fc36.x86_64/elf/dl-fini.c:142
    #3 0x7f3907241044 in __run_exit_handlers (/lib64/libc.so.6+0x41044)
    #4 0x7f39072411bf in exit (/lib64/libc.so.6+0x411bf)
    #5 0x7f3907229516 in __libc_start_call_main (/lib64/libc.so.6+0x29516)
    #6 0x7f39072295c8 in __libc_start_main_impl (/lib64/libc.so.6+0x295c8)
    #7 0x56236a2042b4 in _start (/data/git/samba/scratch3/bin/default/nsswitch/stress-nss-libwbclient+0x22b4)

Address 0x7f3907d85000 is a wild pointer inside of access range of size 0x000000000004.
SUMMARY: AddressSanitizer: unknown-crash ../../nsswitch/wb_common.c:220 in winbind_close_sock

The pthread key in wb_global_ctx.key is only initialized if
wb_thread_ctx_initialize() is called via get_wb_global_ctx() -> get_wb_thread_ctx().

Signed-off-by: Ralph Boehme <slow@samba.org>
Reviewed-by: Stefan Metzmacher <metze@samba.org>
Autobuild-User(master): Stefan Metzmacher <metze@samba.org>
Autobuild-Date(master): Fri Jan  6 15:04:46 UTC 2023 on sn-devel-184

nsswitch/wb_common.c

index 7ae3a11162dce76cac319d0b57d756f453601978..d569e761ebe4a0193124e49446042a7f793d1952 100644 (file)
@@ -43,6 +43,7 @@ struct winbindd_context {
 };
 
 static struct wb_global_ctx {
+       bool initialized;
 #ifdef HAVE_PTHREAD
        pthread_once_t control;
        pthread_key_t key;
@@ -141,16 +142,23 @@ static struct winbindd_context *get_wb_thread_ctx(void)
 
 static struct winbindd_context *get_wb_global_ctx(void)
 {
-#ifdef HAVE_PTHREAD
-       return get_wb_thread_ctx();
-#else
-       static struct winbindd_context ctx = {
+       struct winbindd_context *ctx = NULL;
+#ifndef HAVE_PTHREAD
+       static struct winbindd_context _ctx = {
                .winbindd_fd = -1,
                .is_privileged = false,
                .our_pid = 0
        };
-       return &ctx;
 #endif
+
+#ifdef HAVE_PTHREAD
+       ctx = get_wb_thread_ctx();
+#else
+       ctx = &_ctx;
+#endif
+
+       wb_global_ctx.initialized = true;
+       return ctx;
 }
 
 void winbind_set_client_name(const char *name)
@@ -234,6 +242,10 @@ static void winbind_destructor(void)
 {
        struct winbindd_context *ctx;
 
+       if (!wb_global_ctx.initialized) {
+               return;
+       }
+
 #ifdef HAVE_PTHREAD_H
        ctx = (struct winbindd_context *)pthread_getspecific(wb_global_ctx.key);
        if (ctx == NULL) {