From 8271d9b99a3b98c662ee9a6257a144284b7e1728 Mon Sep 17 00:00:00 2001 From: Konstantin Belousov Date: Tue, 20 Feb 2024 16:45:29 +0200 Subject: [PATCH] libsys: remove usage of pthread_once and _once_stub that existed in auxv.c, use simple bool gate instead. This leaves a small window if two threads try to call _elf_aux_info(3) simultaneously. The situation is safe because auxv parsing is really idempotent. The parsed data is the same, and we store atomic types (int/long/ptr) so double-init does not matter. Reviewed by: brooks, imp Sponsored by: The FreeBSD Foundation Differential revision: https://reviews.freebsd.org/D43985 --- lib/libc/gen/Makefile.inc | 1 + lib/{libsys => libc/gen}/_once_stub.c | 0 lib/libsys/Makefile.sys | 1 - lib/libsys/auxv.c | 20 ++++++++++++++++++-- 4 files changed, 19 insertions(+), 3 deletions(-) rename lib/{libsys => libc/gen}/_once_stub.c (100%) diff --git a/lib/libc/gen/Makefile.inc b/lib/libc/gen/Makefile.inc index 8d30e06cfed9..ce7a34d0e58e 100644 --- a/lib/libc/gen/Makefile.inc +++ b/lib/libc/gen/Makefile.inc @@ -9,6 +9,7 @@ CONFSPACKAGE= runtime SRCS+= \ __pthread_mutex_init_calloc_cb_stub.c \ __xuname.c \ + _once_stub.c \ _pthread_stubs.c \ _rand48.c \ _spinlock_stub.c \ diff --git a/lib/libsys/_once_stub.c b/lib/libc/gen/_once_stub.c similarity index 100% rename from lib/libsys/_once_stub.c rename to lib/libc/gen/_once_stub.c diff --git a/lib/libsys/Makefile.sys b/lib/libsys/Makefile.sys index cb9ca1749ba8..e33a11bacb57 100644 --- a/lib/libsys/Makefile.sys +++ b/lib/libsys/Makefile.sys @@ -33,7 +33,6 @@ PSEUDO+= _clock_gettime.o _gettimeofday.o SRCS+= \ __error.c \ __getosreldate.c \ - _once_stub.c \ getpagesize.c \ getpagesizes.c \ interposing_table.c diff --git a/lib/libsys/auxv.c b/lib/libsys/auxv.c index b0b3a8ed708b..88f49ef53be1 100644 --- a/lib/libsys/auxv.c +++ b/lib/libsys/auxv.c @@ -31,6 +31,7 @@ #include #include #include +#include #include #include #include "un-namespace.h" @@ -40,6 +41,8 @@ extern int _DYNAMIC; #pragma weak _DYNAMIC void *__elf_aux_vector; + +#ifndef PIC static pthread_once_t aux_vector_once = PTHREAD_ONCE_INIT; static void @@ -61,8 +64,9 @@ __init_elf_aux_vector(void) return; _once(&aux_vector_once, init_aux_vector_once); } +#endif -static pthread_once_t aux_once = PTHREAD_ONCE_INIT; +static bool aux_once = false; static int pagesize, osreldate, canary_len, ncpus, pagesizes_len, bsdflags; static int hwcap_present, hwcap2_present; static char *canary, *pagesizes, *execpath; @@ -77,11 +81,19 @@ static void _init_aux_powerpc_fixup(void); int _powerpc_elf_aux_info(int, void *, int); #endif +/* + * This function might be called and actual body executed more than + * once in multithreading environment. Due to this, it is and must + * continue to be idempotent. All stores are atomic (no store + * tearing), because we only assign to int/long/ptr. + */ static void init_aux(void) { Elf_Auxinfo *aux; + if (aux_once) + return; for (aux = __elf_aux_vector; aux->a_type != AT_NULL; aux++) { switch (aux->a_type) { case AT_BSDFLAGS: @@ -166,6 +178,8 @@ init_aux(void) if (!powerpc_new_auxv_format) _init_aux_powerpc_fixup(); #endif + + aux_once = true; } #ifdef __powerpc__ @@ -256,10 +270,12 @@ _elf_aux_info(int aux, void *buf, int buflen) { int res; +#ifndef PIC __init_elf_aux_vector(); +#endif if (__elf_aux_vector == NULL) return (ENOSYS); - _once(&aux_once, init_aux); + init_aux(); /* idempotent */ if (buflen < 0) return (EINVAL);