From: Arran Cudbard-Bell Date: Wed, 18 Sep 2019 16:30:55 +0000 (-0500) Subject: Move dlopen functionality from rlm_python into dl_open_by_sym in utility library X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=25422caa02f943d418f459f092989fb7e2af8f29;p=thirdparty%2Ffreeradius-server.git Move dlopen functionality from rlm_python into dl_open_by_sym in utility library --- diff --git a/src/lib/util/dl.c b/src/lib/util/dl.c index f73172aaea3..7a1bca92a5f 100644 --- a/src/lib/util/dl.c +++ b/src/lib/util/dl.c @@ -160,6 +160,50 @@ static int dl_handle_cmp(void const *one, void const *two) return strcmp(((dl_t const *)one)->name, ((dl_t const *)two)->name); } +/** Utility function to dlopen the library containing a particular symbol + * + * @note Not really part of our 'dl' API, just a convenience function. + * + * @param[in] sym_name to resolve. + * @param[in] flags to pass to dlopen. + * @return + * - NULL on error. + * - A new handle on success. + */ +void *dl_open_by_sym(char const *sym_name, int flags) +{ + Dl_info info; + void *sym; + void *handle; + + /* + * Resolve the test symbol in our own symbol space by + * iterating through all the libraries. + * This might be slow. Don't do this at runtime! + */ + sym = dlsym(RTLD_DEFAULT, sym_name); + if (!sym) { + fr_strerror_printf("Can't resolve symbol %s", sym_name); + return NULL; + } + + /* + * Lookup the library the symbol belongs to + */ + if (dladdr(sym, &info) == 0) { + fr_strerror_printf("Failed retrieving info for \"%s\" (%p)", sym_name, sym); + return NULL; + } + + handle = dlopen(info.dli_fname, flags); + if (!handle) { + fr_strerror_printf("Failed loading \"%s\": %s", info.dli_fname, dlerror()); + return NULL; + } + + return handle; +} + /** Walk over the registered init callbacks, searching for the symbols they depend on * * Allows code outside of the dl API to register initialisation functions that get diff --git a/src/lib/util/dl.h b/src/lib/util/dl.h index 11472618e14..2ba8b670557 100644 --- a/src/lib/util/dl.h +++ b/src/lib/util/dl.h @@ -86,6 +86,7 @@ typedef void (*dl_unload_t)(dl_t const *module, void *symbol, void *user_ctx); /* * Functions */ +void *dl_open_by_sym(char const *sym_name, int flags); int dl_symbol_init(dl_loader_t *dl_loader, dl_t const *dl); diff --git a/src/modules/rlm_python/rlm_python.c b/src/modules/rlm_python/rlm_python.c index fa92a2269c6..3a7c61e6795 100644 --- a/src/modules/rlm_python/rlm_python.c +++ b/src/modules/rlm_python/rlm_python.c @@ -1238,10 +1238,6 @@ static int mod_thread_detach(UNUSED fr_event_list_t *el, void *thread) static int mod_load(void) { - Dl_info info; - void *sym; - -#define PYTHON_TEST_SYMBOL "Py_IsInitialized" #define LOAD_INFO(_fmt, ...) fr_log(LOG_DST, L_INFO, __FILE__, __LINE__, "rlm_python - " _fmt, ## __VA_ARGS__) #define LOAD_WARN(_fmt, ...) fr_log(LOG_DST, L_WARN, __FILE__, __LINE__, "rlm_python - " _fmt, ## __VA_ARGS__) @@ -1251,37 +1247,12 @@ static int mod_load(void) dependency_version_number_add(NULL, "python", Py_GetVersion()); /* - * Resolve the test symbol in our own - * symbol space. - */ - sym = dlsym(RTLD_DEFAULT, PYTHON_TEST_SYMBOL); - if (!sym) { - LOAD_WARN("Can't find %s in symbol table, skipping loading python into global symbol table", - PYTHON_TEST_SYMBOL); - goto skip_dlopen; - } - - /* - * It's unclear whether passing function - * pointers will always "just work", - * which is why we resolve the symbol - * at runtime then call dladdr. + * Load python using RTLD_GLOBAL and dlopen + * This fixes issues where python C extensions + * can't find the symbols they need. */ - if (dladdr(sym, &info) == 0) { - LOAD_WARN("Failed resolving symbol %s (%p) to library path: %s " - ", skipping loading python into global symbol table", PYTHON_TEST_SYMBOL, sym, dlerror()); - goto skip_dlopen; - } - - /* - * Explicitly load libpython, so symbols will be available to lib-dynload modules - */ - python_dlhandle = dlopen(info.dli_fname, RTLD_NOW | RTLD_GLOBAL); - if (!python_dlhandle) fr_log(LOG_DST, L_WARN, __FILE__, __LINE__, - "Failed loading libpython symbols from \"%s\" into global symbol table: %s", - info.dli_fname, dlerror()); - -skip_dlopen: + python_dlhandle = dl_open_by_sym("Py_IsInitialized", RTLD_NOW | RTLD_GLOBAL); + if (!python_dlhandle) LOAD_WARN("Failed loading libpython symbols into global symbol table: %s", fr_strerror()); #if PY_MAJOR_VERSION == 3 /*