From bb1371816442eb08c0646b91de84a398e2f733b8 Mon Sep 17 00:00:00 2001 From: Bruno Faccini Date: Fri, 26 May 2023 12:52:36 +0200 Subject: [PATCH 01/11] DAOS-13194 gurt: environment APIs hook In order to prevent known race to occur due to lack of locking in Glibc environment APIs (getenv()/[uns]setenv()/ putenv()/clearenv()), they have been overloaded and strengthened in Gurt with hooks now all using a common lock/mutex. Libgurt is the preferred place for this as it is the lowest layer in DAOS, so it will be the earliest to be loaded and will ensure the hook to be installed as early as possible and could prevent usage of LD_PRELOAD. This will address the main lack of multi-thread protection in the Glibc APIs but do not handle all unsafe use-cases (like the change/removal of an env var when its value address has already been grabbed by a previous getenv(), ...). Required-githooks: true Signed-off-by: Bruno Faccini --- src/gurt/SConscript | 2 +- src/gurt/misc.c | 107 ++++++++++++++++++++++++++ src/gurt/tests/SConscript | 2 +- src/tests/ftest/cart/utest/SConscript | 2 +- 4 files changed, 110 insertions(+), 3 deletions(-) diff --git a/src/gurt/SConscript b/src/gurt/SConscript index 5970a8ce53b..5397848bace 100644 --- a/src/gurt/SConscript +++ b/src/gurt/SConscript @@ -19,7 +19,7 @@ def scons(): denv = env.Clone() - denv.AppendUnique(LIBS=['pthread', 'yaml', 'm']) + denv.AppendUnique(LIBS=['pthread', 'yaml', 'm', 'dl']) denv.require('uuid') gurt_targets = denv.SharedObject(SRC) diff --git a/src/gurt/misc.c b/src/gurt/misc.c index e835b91d506..b4c2be30405 100644 --- a/src/gurt/misc.c +++ b/src/gurt/misc.c @@ -12,7 +12,13 @@ #include #include #include +#include +#include +#include +#include + #include +#include /* state buffer for DAOS rand and srand calls, NOT thread safe */ static struct drand48_data randBuffer = {0}; @@ -1192,3 +1198,104 @@ d_vec_pointers_append(struct d_vec_pointers *pointers, void *pointer) pointers->p_len++; return 0; } + +/** + * Overloads to hook the unsafe getenv()/[un]setenv()/putenv()/clearenv() + * functions from glibc. + * Libgurt is the preferred place for this as it is the lowest layer in DAOS, + * so it will be the earliest to be loaded and will ensure the hook to be + * installed as early as possible and could prevent usage of LD_PRELOAD. + * The idea is to strengthen all the environment APIs by using a common lock. + * + * XXX this will address the main lack of multi-thread protection in the Glibc + * APIs but do not handle all unsafe use-cases (like the change/removal of an + * env var when its value address has already been grabbed by a previous + * getenv(), ...). + */ + +static pthread_mutex_t hook_env_lock = PTHREAD_MUTEX_INITIALIZER; +static char *(*real_getenv)(const char *) = NULL; +static int (*real_putenv)(char *) = NULL; +static int (*real_setenv)(const char *, const char *, int) = NULL; +static int (*real_unsetenv)(const char *) = NULL; +static int (*real_clearenv)(void) = NULL; + +char *getenv(const char *name) { + char *p; + + D_MUTEX_LOCK(&hook_env_lock); + if (real_getenv == NULL) { + real_getenv = (char * (*)(const char *))dlsym(RTLD_NEXT, "getenv"); + D_ASSERT(real_getenv != NULL); + } + + p = real_getenv(name); + D_MUTEX_UNLOCK(&hook_env_lock); + fprintf(stderr, "getenv(%s) has been hooked\n", name); + + return p; +} + +int putenv(char *name) { + int rc; + + D_MUTEX_LOCK(&hook_env_lock); + if (real_putenv == NULL) { + real_putenv = (int (*)(char *))dlsym(RTLD_NEXT, "putenv"); + D_ASSERT(real_putenv != NULL); + } + + rc = real_putenv(name); + D_MUTEX_UNLOCK(&hook_env_lock); + fprintf(stderr, "unsetenv(%s) has been hooked\n", name); + + return rc; +} + +int setenv(const char *name, const char *value, int overwrite) { + int rc; + + D_MUTEX_LOCK(&hook_env_lock); + if (real_setenv == NULL) { + real_setenv = (int (*)(const char *, const char *, int))dlsym(RTLD_NEXT, "setenv"); + D_ASSERT(real_setenv != NULL); + } + + rc = real_setenv(name, value, overwrite); + D_MUTEX_UNLOCK(&hook_env_lock); + fprintf(stderr, "setenv(%s, %s, %d) has been hooked\n", name, value, overwrite); + + return rc; +} + +int unsetenv(const char *name) { + int rc; + + D_MUTEX_LOCK(&hook_env_lock); + if (real_unsetenv == NULL) { + real_unsetenv = (int (*)(const char *))dlsym(RTLD_NEXT, "unsetenv"); + D_ASSERT(real_unsetenv != NULL); + } + + rc = real_unsetenv(name); + D_MUTEX_UNLOCK(&hook_env_lock); + fprintf(stderr, "unsetenv(%s) has been hooked\n", name); + + return rc; +} + +int clearenv(void) { + int rc; + + D_MUTEX_LOCK(&hook_env_lock); + if (real_clearenv == NULL) { + real_clearenv = (int (*)(void))dlsym(RTLD_NEXT, "clearenv"); + D_ASSERT(real_clearenv != NULL); + } + + rc = real_clearenv(); + D_MUTEX_UNLOCK(&hook_env_lock); + fprintf(stderr, "clearenv() has been hooked\n"); + + return rc; +} diff --git a/src/gurt/tests/SConscript b/src/gurt/tests/SConscript index fbe8d52cb03..6ba63fe61df 100644 --- a/src/gurt/tests/SConscript +++ b/src/gurt/tests/SConscript @@ -18,7 +18,7 @@ def scons(): test_env = env.Clone() test_env.require('mercury', 'uuid') - test_env.AppendUnique(LIBS=['pthread', 'cmocka', 'm']) + test_env.AppendUnique(LIBS=['pthread', 'cmocka', 'm', 'dl']) test_env.AppendUnique(CXXFLAGS=['-std=c++0x']) tests = [] diff --git a/src/tests/ftest/cart/utest/SConscript b/src/tests/ftest/cart/utest/SConscript index 1a950de86a9..6347bacfc9e 100644 --- a/src/tests/ftest/cart/utest/SConscript +++ b/src/tests/ftest/cart/utest/SConscript @@ -19,7 +19,7 @@ def scons(): test_env = env.Clone() test_env.require('mercury', 'uuid', 'cmocka') - test_env.AppendUnique(LIBS=['pthread', 'm']) + test_env.AppendUnique(LIBS=['pthread', 'm', 'dl']) test_env.AppendUnique(CXXFLAGS=['-std=c++0x']) test_env.AppendUnique(LIBPATH=LIBPATH) test_env.AppendUnique(RPATH_FULL=LIBPATH) From 51f5789b0188865453cd07c5bea730e878c67fa9 Mon Sep 17 00:00:00 2001 From: Bruno Faccini Date: Fri, 26 May 2023 13:32:00 +0200 Subject: [PATCH 02/11] DAOS-13194 gurt: remove debug prints and some cosmetics I had forgotten to remove debug fprintf()s to stderr, and there was some cosmetic fixes requested by our set of code beautifiers... Required-githooks: true Signed-off-by: Bruno Faccini --- src/gurt/misc.c | 31 +++++++++++++++---------------- 1 file changed, 15 insertions(+), 16 deletions(-) diff --git a/src/gurt/misc.c b/src/gurt/misc.c index b4c2be30405..3eb9a3e6af0 100644 --- a/src/gurt/misc.c +++ b/src/gurt/misc.c @@ -18,7 +18,6 @@ #include #include -#include /* state buffer for DAOS rand and srand calls, NOT thread safe */ static struct drand48_data randBuffer = {0}; @@ -1214,13 +1213,14 @@ d_vec_pointers_append(struct d_vec_pointers *pointers, void *pointer) */ static pthread_mutex_t hook_env_lock = PTHREAD_MUTEX_INITIALIZER; -static char *(*real_getenv)(const char *) = NULL; -static int (*real_putenv)(char *) = NULL; -static int (*real_setenv)(const char *, const char *, int) = NULL; -static int (*real_unsetenv)(const char *) = NULL; -static int (*real_clearenv)(void) = NULL; +static char *(*real_getenv)(const char *); +static int (*real_putenv)(char *); +static int (*real_setenv)(const char *, const char *, int); +static int (*real_unsetenv)(const char *); +static int (*real_clearenv)(void); -char *getenv(const char *name) { +char *getenv(const char *name) +{ char *p; D_MUTEX_LOCK(&hook_env_lock); @@ -1231,12 +1231,12 @@ char *getenv(const char *name) { p = real_getenv(name); D_MUTEX_UNLOCK(&hook_env_lock); - fprintf(stderr, "getenv(%s) has been hooked\n", name); return p; } -int putenv(char *name) { +int putenv(char *name) +{ int rc; D_MUTEX_LOCK(&hook_env_lock); @@ -1247,12 +1247,12 @@ int putenv(char *name) { rc = real_putenv(name); D_MUTEX_UNLOCK(&hook_env_lock); - fprintf(stderr, "unsetenv(%s) has been hooked\n", name); return rc; } -int setenv(const char *name, const char *value, int overwrite) { +int setenv(const char *name, const char *value, int overwrite) +{ int rc; D_MUTEX_LOCK(&hook_env_lock); @@ -1263,12 +1263,12 @@ int setenv(const char *name, const char *value, int overwrite) { rc = real_setenv(name, value, overwrite); D_MUTEX_UNLOCK(&hook_env_lock); - fprintf(stderr, "setenv(%s, %s, %d) has been hooked\n", name, value, overwrite); return rc; } -int unsetenv(const char *name) { +int unsetenv(const char *name) +{ int rc; D_MUTEX_LOCK(&hook_env_lock); @@ -1279,12 +1279,12 @@ int unsetenv(const char *name) { rc = real_unsetenv(name); D_MUTEX_UNLOCK(&hook_env_lock); - fprintf(stderr, "unsetenv(%s) has been hooked\n", name); return rc; } -int clearenv(void) { +int clearenv(void) +{ int rc; D_MUTEX_LOCK(&hook_env_lock); @@ -1295,7 +1295,6 @@ int clearenv(void) { rc = real_clearenv(); D_MUTEX_UNLOCK(&hook_env_lock); - fprintf(stderr, "clearenv() has been hooked\n"); return rc; } From 6deb540df7627b094a48343be2bf2193cc4983a0 Mon Sep 17 00:00:00 2001 From: Bruno Faccini Date: Tue, 30 May 2023 16:45:18 +0200 Subject: [PATCH 03/11] DAOS-13194 gurt: retry with dlopen() to bind Glibc Unexpectedly Glibc seems not be already/early binded upon some commands start, so try to dlopen() it !!... Required-githooks: true Signed-off-by: Bruno Faccini --- src/gurt/misc.c | 40 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 40 insertions(+) diff --git a/src/gurt/misc.c b/src/gurt/misc.c index 3eb9a3e6af0..205db63be12 100644 --- a/src/gurt/misc.c +++ b/src/gurt/misc.c @@ -1226,6 +1226,14 @@ char *getenv(const char *name) D_MUTEX_LOCK(&hook_env_lock); if (real_getenv == NULL) { real_getenv = (char * (*)(const char *))dlsym(RTLD_NEXT, "getenv"); + if (real_getenv == NULL) { + /* Glibc symbols could not be resolved !!... */ + void *handle; + + handle = dlopen("libc.so.6", RTLD_LAZY); + D_ASSERT(handle != NULL); + real_getenv = (char * (*)(const char *))dlsym(handle, "getenv"); + } D_ASSERT(real_getenv != NULL); } @@ -1242,6 +1250,14 @@ int putenv(char *name) D_MUTEX_LOCK(&hook_env_lock); if (real_putenv == NULL) { real_putenv = (int (*)(char *))dlsym(RTLD_NEXT, "putenv"); + if (real_putenv == NULL) { + /* Glibc symbols could not be resolved !!... */ + void *handle; + + handle = dlopen("libc.so.6", RTLD_LAZY); + D_ASSERT(handle != NULL); + real_putenv = (char * (*)(const char *))dlsym(handle, "getenv"); + } D_ASSERT(real_putenv != NULL); } @@ -1258,6 +1274,14 @@ int setenv(const char *name, const char *value, int overwrite) D_MUTEX_LOCK(&hook_env_lock); if (real_setenv == NULL) { real_setenv = (int (*)(const char *, const char *, int))dlsym(RTLD_NEXT, "setenv"); + if (real_setenv == NULL) { + /* Glibc symbols could not be resolved !!... */ + void *handle; + + handle = dlopen("libc.so.6", RTLD_LAZY); + D_ASSERT(handle != NULL); + real_setenv = (char * (*)(const char *))dlsym(handle, "getenv"); + } D_ASSERT(real_setenv != NULL); } @@ -1274,6 +1298,14 @@ int unsetenv(const char *name) D_MUTEX_LOCK(&hook_env_lock); if (real_unsetenv == NULL) { real_unsetenv = (int (*)(const char *))dlsym(RTLD_NEXT, "unsetenv"); + if (real_unsetenv == NULL) { + /* Glibc symbols could not be resolved !!... */ + void *handle; + + handle = dlopen("libc.so.6", RTLD_LAZY); + D_ASSERT(handle != NULL); + real_unsetenv = (char * (*)(const char *))dlsym(handle, "getenv"); + } D_ASSERT(real_unsetenv != NULL); } @@ -1290,6 +1322,14 @@ int clearenv(void) D_MUTEX_LOCK(&hook_env_lock); if (real_clearenv == NULL) { real_clearenv = (int (*)(void))dlsym(RTLD_NEXT, "clearenv"); + if (real_clearenv == NULL) { + /* Glibc symbols could not be resolved !!... */ + void *handle; + + handle = dlopen("libc.so.6", RTLD_LAZY); + D_ASSERT(handle != NULL); + real_clearenv = (char * (*)(const char *))dlsym(handle, "getenv"); + } D_ASSERT(real_clearenv != NULL); } From cdaf9ec7e1e9dc5594683ee42540c45ff85af907 Mon Sep 17 00:00:00 2001 From: Bruno Faccini Date: Wed, 31 May 2023 09:08:38 +0200 Subject: [PATCH 04/11] DAOS-13194 gurt: fix errors in previous commit All is in the title !!... Required-githooks: true Signed-off-by: Bruno Faccini --- src/gurt/misc.c | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/src/gurt/misc.c b/src/gurt/misc.c index 205db63be12..75ecd780fac 100644 --- a/src/gurt/misc.c +++ b/src/gurt/misc.c @@ -1256,7 +1256,7 @@ int putenv(char *name) handle = dlopen("libc.so.6", RTLD_LAZY); D_ASSERT(handle != NULL); - real_putenv = (char * (*)(const char *))dlsym(handle, "getenv"); + real_putenv = (int (*)(char *))dlsym(handle, "putenv"); } D_ASSERT(real_putenv != NULL); } @@ -1280,7 +1280,8 @@ int setenv(const char *name, const char *value, int overwrite) handle = dlopen("libc.so.6", RTLD_LAZY); D_ASSERT(handle != NULL); - real_setenv = (char * (*)(const char *))dlsym(handle, "getenv"); + real_setenv = (int (*)(const char *, const char *, int))dlsym(RTLD_NEXT, + "setenv"); } D_ASSERT(real_setenv != NULL); } @@ -1304,7 +1305,7 @@ int unsetenv(const char *name) handle = dlopen("libc.so.6", RTLD_LAZY); D_ASSERT(handle != NULL); - real_unsetenv = (char * (*)(const char *))dlsym(handle, "getenv"); + real_unsetenv = (int (*)(const char *))dlsym(RTLD_NEXT, "unsetenv"); } D_ASSERT(real_unsetenv != NULL); } @@ -1328,7 +1329,7 @@ int clearenv(void) handle = dlopen("libc.so.6", RTLD_LAZY); D_ASSERT(handle != NULL); - real_clearenv = (char * (*)(const char *))dlsym(handle, "getenv"); + real_clearenv = (int (*)(void))dlsym(RTLD_NEXT, "clearenv"); } D_ASSERT(real_clearenv != NULL); } From e0ff359f597317e3419f4ce2640e1fa746351124 Mon Sep 17 00:00:00 2001 From: Bruno Faccini Date: Wed, 31 May 2023 09:14:54 +0200 Subject: [PATCH 05/11] DAOS-13194 gurt: use new handle instead of RTLD_NEXT Upon 2nd try to bind Glibc symbol, use the handle we got from dlopen() !! Required-githooks: true Signed-off-by: Bruno Faccini --- src/gurt/misc.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/gurt/misc.c b/src/gurt/misc.c index 75ecd780fac..4b05201cfbd 100644 --- a/src/gurt/misc.c +++ b/src/gurt/misc.c @@ -1280,7 +1280,7 @@ int setenv(const char *name, const char *value, int overwrite) handle = dlopen("libc.so.6", RTLD_LAZY); D_ASSERT(handle != NULL); - real_setenv = (int (*)(const char *, const char *, int))dlsym(RTLD_NEXT, + real_setenv = (int (*)(const char *, const char *, int))dlsym(handle, "setenv"); } D_ASSERT(real_setenv != NULL); @@ -1305,7 +1305,7 @@ int unsetenv(const char *name) handle = dlopen("libc.so.6", RTLD_LAZY); D_ASSERT(handle != NULL); - real_unsetenv = (int (*)(const char *))dlsym(RTLD_NEXT, "unsetenv"); + real_unsetenv = (int (*)(const char *))dlsym(handle, "unsetenv"); } D_ASSERT(real_unsetenv != NULL); } @@ -1329,7 +1329,7 @@ int clearenv(void) handle = dlopen("libc.so.6", RTLD_LAZY); D_ASSERT(handle != NULL); - real_clearenv = (int (*)(void))dlsym(RTLD_NEXT, "clearenv"); + real_clearenv = (int (*)(void))dlsym(handle, "clearenv"); } D_ASSERT(real_clearenv != NULL); } From c99b48039b88f08705b896df1ce218e10989520e Mon Sep 17 00:00:00 2001 From: Bruno Faccini Date: Thu, 1 Jun 2023 16:02:50 +0200 Subject: [PATCH 06/11] DAOS-13194 gurt: simplify and optimize hack Initialize libc functions pointers all in a raw with pthread_once(). Mutualize initialisation code in a single function, with no locking now but using Atomics. Now use rw-lock for locking instead of a simple mutex. Required-githooks: true Signed-off-by: Bruno Faccini --- src/gurt/misc.c | 125 +++++++++++++++++++----------------------------- 1 file changed, 48 insertions(+), 77 deletions(-) diff --git a/src/gurt/misc.c b/src/gurt/misc.c index 4b05201cfbd..ee3b4da00c2 100644 --- a/src/gurt/misc.c +++ b/src/gurt/misc.c @@ -18,6 +18,7 @@ #include #include +#include /* state buffer for DAOS rand and srand calls, NOT thread safe */ static struct drand48_data randBuffer = {0}; @@ -1212,33 +1213,52 @@ d_vec_pointers_append(struct d_vec_pointers *pointers, void *pointer) * getenv(), ...). */ -static pthread_mutex_t hook_env_lock = PTHREAD_MUTEX_INITIALIZER; -static char *(*real_getenv)(const char *); -static int (*real_putenv)(char *); -static int (*real_setenv)(const char *, const char *, int); -static int (*real_unsetenv)(const char *); -static int (*real_clearenv)(void); +static pthread_rwlock_t hook_env_lock = PTHREAD_RWLOCK_INITIALIZER; +static char *(* ATOMIC real_getenv)(const char *); +static int (* ATOMIC real_putenv)(char *); +static int (* ATOMIC real_setenv)(const char *, const char *, int); +static int (* ATOMIC real_unsetenv)(const char *); +static int (* ATOMIC real_clearenv)(void); -char *getenv(const char *name) +static void bind_libc_symbol(void **real_ptr_addr, const char* name) { - char *p; + void *real_temp; - D_MUTEX_LOCK(&hook_env_lock); - if (real_getenv == NULL) { - real_getenv = (char * (*)(const char *))dlsym(RTLD_NEXT, "getenv"); - if (real_getenv == NULL) { - /* Glibc symbols could not be resolved !!... */ + if (atomic_load_relaxed(real_ptr_addr) == NULL) { + /* libc should be already loaded ... */ + real_temp = dlsym(RTLD_NEXT, name); + if (real_temp == NULL) { + /* try after loading libc now */ void *handle; handle = dlopen("libc.so.6", RTLD_LAZY); D_ASSERT(handle != NULL); - real_getenv = (char * (*)(const char *))dlsym(handle, "getenv"); + real_temp = dlsym(handle, name); + D_ASSERT(real_temp != NULL); } - D_ASSERT(real_getenv != NULL); + atomic_store_relaxed(real_ptr_addr, real_temp); } +} + +static pthread_once_t init_real_symbols_flag = PTHREAD_ONCE_INIT; + +static void init_real_symbols(void) +{ + bind_libc_symbol((void **)&real_getenv, "getenv"); + bind_libc_symbol((void **)&real_putenv, "putenv"); + bind_libc_symbol((void **)&real_setenv, "setenv"); + bind_libc_symbol((void **)&real_unsetenv, "unsetenv"); + bind_libc_symbol((void **)&real_clearenv, "clearenv"); +} + +char *getenv(const char *name) +{ + char *p; + pthread_once(&init_real_symbols_flag, init_real_symbols); + D_RWLOCK_RDLOCK(&hook_env_lock); p = real_getenv(name); - D_MUTEX_UNLOCK(&hook_env_lock); + D_RWLOCK_UNLOCK(&hook_env_lock); return p; } @@ -1247,22 +1267,10 @@ int putenv(char *name) { int rc; - D_MUTEX_LOCK(&hook_env_lock); - if (real_putenv == NULL) { - real_putenv = (int (*)(char *))dlsym(RTLD_NEXT, "putenv"); - if (real_putenv == NULL) { - /* Glibc symbols could not be resolved !!... */ - void *handle; - - handle = dlopen("libc.so.6", RTLD_LAZY); - D_ASSERT(handle != NULL); - real_putenv = (int (*)(char *))dlsym(handle, "putenv"); - } - D_ASSERT(real_putenv != NULL); - } - + pthread_once(&init_real_symbols_flag, init_real_symbols); + D_RWLOCK_WRLOCK(&hook_env_lock); rc = real_putenv(name); - D_MUTEX_UNLOCK(&hook_env_lock); + D_RWLOCK_UNLOCK(&hook_env_lock); return rc; } @@ -1271,23 +1279,10 @@ int setenv(const char *name, const char *value, int overwrite) { int rc; - D_MUTEX_LOCK(&hook_env_lock); - if (real_setenv == NULL) { - real_setenv = (int (*)(const char *, const char *, int))dlsym(RTLD_NEXT, "setenv"); - if (real_setenv == NULL) { - /* Glibc symbols could not be resolved !!... */ - void *handle; - - handle = dlopen("libc.so.6", RTLD_LAZY); - D_ASSERT(handle != NULL); - real_setenv = (int (*)(const char *, const char *, int))dlsym(handle, - "setenv"); - } - D_ASSERT(real_setenv != NULL); - } - + pthread_once(&init_real_symbols_flag, init_real_symbols); + D_RWLOCK_WRLOCK(&hook_env_lock); rc = real_setenv(name, value, overwrite); - D_MUTEX_UNLOCK(&hook_env_lock); + D_RWLOCK_UNLOCK(&hook_env_lock); return rc; } @@ -1296,22 +1291,10 @@ int unsetenv(const char *name) { int rc; - D_MUTEX_LOCK(&hook_env_lock); - if (real_unsetenv == NULL) { - real_unsetenv = (int (*)(const char *))dlsym(RTLD_NEXT, "unsetenv"); - if (real_unsetenv == NULL) { - /* Glibc symbols could not be resolved !!... */ - void *handle; - - handle = dlopen("libc.so.6", RTLD_LAZY); - D_ASSERT(handle != NULL); - real_unsetenv = (int (*)(const char *))dlsym(handle, "unsetenv"); - } - D_ASSERT(real_unsetenv != NULL); - } - + pthread_once(&init_real_symbols_flag, init_real_symbols); + D_RWLOCK_WRLOCK(&hook_env_lock); rc = real_unsetenv(name); - D_MUTEX_UNLOCK(&hook_env_lock); + D_RWLOCK_UNLOCK(&hook_env_lock); return rc; } @@ -1320,22 +1303,10 @@ int clearenv(void) { int rc; - D_MUTEX_LOCK(&hook_env_lock); - if (real_clearenv == NULL) { - real_clearenv = (int (*)(void))dlsym(RTLD_NEXT, "clearenv"); - if (real_clearenv == NULL) { - /* Glibc symbols could not be resolved !!... */ - void *handle; - - handle = dlopen("libc.so.6", RTLD_LAZY); - D_ASSERT(handle != NULL); - real_clearenv = (int (*)(void))dlsym(handle, "clearenv"); - } - D_ASSERT(real_clearenv != NULL); - } - + pthread_once(&init_real_symbols_flag, init_real_symbols); + D_RWLOCK_WRLOCK(&hook_env_lock); rc = real_clearenv(); - D_MUTEX_UNLOCK(&hook_env_lock); + D_RWLOCK_UNLOCK(&hook_env_lock); return rc; } From 0102060c195f686099c9f6ae1f39ce045fc4b598 Mon Sep 17 00:00:00 2001 From: Bruno Faccini Date: Thu, 1 Jun 2023 17:18:48 +0200 Subject: [PATCH 07/11] DAOS-13194 gurt: fix build errors During the "Build on Leap 15.4 with Intel-C", errors have been encountered upon compilation, due to the lack of ATOMIC attribute for the 1st parameter passed to both atomic_[load,store]_relaxed(). A cast has been added ... Required-githooks: true Signed-off-by: Bruno Faccini --- src/gurt/misc.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/gurt/misc.c b/src/gurt/misc.c index ee3b4da00c2..22a89e3f196 100644 --- a/src/gurt/misc.c +++ b/src/gurt/misc.c @@ -1224,7 +1224,7 @@ static void bind_libc_symbol(void **real_ptr_addr, const char* name) { void *real_temp; - if (atomic_load_relaxed(real_ptr_addr) == NULL) { + if (atomic_load_relaxed((ATOMIC void **)real_ptr_addr) == NULL) { /* libc should be already loaded ... */ real_temp = dlsym(RTLD_NEXT, name); if (real_temp == NULL) { @@ -1236,7 +1236,7 @@ static void bind_libc_symbol(void **real_ptr_addr, const char* name) real_temp = dlsym(handle, name); D_ASSERT(real_temp != NULL); } - atomic_store_relaxed(real_ptr_addr, real_temp); + atomic_store_relaxed((ATOMIC void **)real_ptr_addr, real_temp); } } From 31fafd48c6533b588bd029faaf5908244ea40c9b Mon Sep 17 00:00:00 2001 From: Bruno Faccini Date: Thu, 1 Jun 2023 17:31:20 +0200 Subject: [PATCH 08/11] DAOS-13194 gurt: try again to fix build errors Looks like Intel-C is more strict against ATOMIC usage... Try to use (ATOMIC char **) as the cast... Required-githooks: true Signed-off-by: Bruno Faccini --- src/gurt/misc.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/gurt/misc.c b/src/gurt/misc.c index 22a89e3f196..e4cd3f4199a 100644 --- a/src/gurt/misc.c +++ b/src/gurt/misc.c @@ -1224,7 +1224,7 @@ static void bind_libc_symbol(void **real_ptr_addr, const char* name) { void *real_temp; - if (atomic_load_relaxed((ATOMIC void **)real_ptr_addr) == NULL) { + if (atomic_load_relaxed((ATOMIC char **)real_ptr_addr) == NULL) { /* libc should be already loaded ... */ real_temp = dlsym(RTLD_NEXT, name); if (real_temp == NULL) { @@ -1236,7 +1236,7 @@ static void bind_libc_symbol(void **real_ptr_addr, const char* name) real_temp = dlsym(handle, name); D_ASSERT(real_temp != NULL); } - atomic_store_relaxed((ATOMIC void **)real_ptr_addr, real_temp); + atomic_store_relaxed((ATOMIC char **)real_ptr_addr, real_temp); } } From 2234439f9e999548a4d9dbe46bfe79621806cdd3 Mon Sep 17 00:00:00 2001 From: Bruno Faccini Date: Thu, 1 Jun 2023 17:58:28 +0200 Subject: [PATCH 09/11] DAOS-13194 gurt: try to use __atomic builtins Since Intel-C always rejects casts with Atomic, try to use the __atomic builtins ... Required-githooks: true Signed-off-by: Bruno Faccini --- src/gurt/misc.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/gurt/misc.c b/src/gurt/misc.c index e4cd3f4199a..834cba376e0 100644 --- a/src/gurt/misc.c +++ b/src/gurt/misc.c @@ -1220,11 +1220,11 @@ static int (* ATOMIC real_setenv)(const char *, const char *, int); static int (* ATOMIC real_unsetenv)(const char *); static int (* ATOMIC real_clearenv)(void); -static void bind_libc_symbol(void **real_ptr_addr, const char* name) +static void bind_libc_symbol(void **real_ptr_addr, const char *name) { void *real_temp; - if (atomic_load_relaxed((ATOMIC char **)real_ptr_addr) == NULL) { + if (__atomic_load_n(real_ptr_addr, __ATOMIC_RELAXED) == NULL) { /* libc should be already loaded ... */ real_temp = dlsym(RTLD_NEXT, name); if (real_temp == NULL) { @@ -1236,7 +1236,7 @@ static void bind_libc_symbol(void **real_ptr_addr, const char* name) real_temp = dlsym(handle, name); D_ASSERT(real_temp != NULL); } - atomic_store_relaxed((ATOMIC char **)real_ptr_addr, real_temp); + __atomic_store_n(real_ptr_addr, real_temp, __ATOMIC_RELAXED); } } From 4a3e6e1ab42fb17e4f35ae52aa50815f7160a351 Mon Sep 17 00:00:00 2001 From: Bruno Faccini Date: Fri, 2 Jun 2023 15:41:22 +0200 Subject: [PATCH 10/11] DAOS-13194 gurt: make Intel compiler happy __atomic_*() built-ins are used to avoid the need to cast each of the ATOMIC pointers of functions, that seems to be required to make Intel compiler happy ... Required-githooks: true Signed-off-by: Bruno Faccini --- src/gurt/misc.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/gurt/misc.c b/src/gurt/misc.c index 834cba376e0..a1f51a337c4 100644 --- a/src/gurt/misc.c +++ b/src/gurt/misc.c @@ -1224,6 +1224,10 @@ static void bind_libc_symbol(void **real_ptr_addr, const char *name) { void *real_temp; + /* XXX __atomic_*() built-ins are used to avoid the need to cast + * each of the ATOMIC pointers of functions, that seems to be + * required to make Intel compiler happy ... + */ if (__atomic_load_n(real_ptr_addr, __ATOMIC_RELAXED) == NULL) { /* libc should be already loaded ... */ real_temp = dlsym(RTLD_NEXT, name); From 30b1c27f445e1de8279ce8032a7f16e0cf07dc15 Mon Sep 17 00:00:00 2001 From: Bruno Faccini Date: Fri, 9 Jun 2023 11:41:21 +0200 Subject: [PATCH 11/11] DAOS-13194 gurt: fix trailing space Cosmetic fix ... Required-githooks: true Signed-off-by: Bruno Faccini --- src/gurt/misc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/gurt/misc.c b/src/gurt/misc.c index e4e5d81f176..40c27ad6004 100644 --- a/src/gurt/misc.c +++ b/src/gurt/misc.c @@ -1232,7 +1232,7 @@ static void bind_libc_symbol(void **real_ptr_addr, const char *name) /* XXX __atomic_*() built-ins are used to avoid the need to cast * each of the ATOMIC pointers of functions, that seems to be * required to make Intel compiler happy ... - */ + */ if (__atomic_load_n(real_ptr_addr, __ATOMIC_RELAXED) == NULL) { /* libc should be already loaded ... */ real_temp = dlsym(RTLD_NEXT, name);