]> git.ipfire.org Git - thirdparty/freeradius-server.git/commitdiff
Move dlopen functionality from rlm_python into dl_open_by_sym in utility library
authorArran Cudbard-Bell <a.cudbardb@freeradius.org>
Wed, 18 Sep 2019 16:30:55 +0000 (11:30 -0500)
committerArran Cudbard-Bell <a.cudbardb@freeradius.org>
Wed, 18 Sep 2019 16:30:55 +0000 (11:30 -0500)
src/lib/util/dl.c
src/lib/util/dl.h
src/modules/rlm_python/rlm_python.c

index f73172aaea3ba94c23da6afe9e91236aa84c99d5..7a1bca92a5f4693b0c5a595d1c9fde80c6440d5f 100644 (file)
@@ -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
index 11472618e14bcc3debd4b2ac703d61f5bcf34033..2ba8b670557c1f08c0bc6e45a83400e9b3bec7fd 100644 (file)
@@ -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);
 
index fa92a2269c61853fb8d8e07f4cd667162137c030..3a7c61e67958e287283e4bf564b51658ef200587 100644 (file)
@@ -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
        /*