From e678528e0593be3ffb9b42dd5d523cc0bdee1484 Mon Sep 17 00:00:00 2001 From: Carl Worth Date: Mon, 5 Aug 2013 10:23:10 -0700 Subject: [PATCH] dlwrap: Add new dlwrap_dlopen_libfips function Previously, two different pieces of fips code (both for dlopen and for glXGetProcAddress) both needed to dlopen the fips library itself. However, the two pieces were implemented differently, (one passed a symbol to dladdr to find a filename to dlopen, the other just passed NULL to dlsym and hopef for the best). Make things consistent by having a single, shared implementation in the new function dlwrap_dlopen_libfips, (and implement it with the more reliable approach of calling dladdr and then the real dlopen). --- dlwrap.c | 42 ++++++++++++++++++++++++++++-------------- dlwrap.h | 12 ++++++++++++ glxwrap.c | 6 +++++- 3 files changed, 45 insertions(+), 15 deletions(-) diff --git a/dlwrap.c b/dlwrap.c index dda7a77..036d981 100644 --- a/dlwrap.c +++ b/dlwrap.c @@ -66,6 +66,31 @@ find_wrapped_library_index (const char *filename, unsigned *index_ret) return false; } +/* Perform a dlopen on the libfips library itself. + * + * Many places in fips need to lookup symbols within the libfips + * library itself, (and not in any other library). This function + * provides a reliable way to get a handle for performing such + * lookups. + * + * The returned handle can be passed to dlwrap_real_dlsym for the + * lookups. */ +void * +dlwrap_dlopen_libfips (void) +{ + Dl_info info; + + /* We first find our own filename by looking up a function + * known to exist only in libfips. This function itself + * (dlwrap_dlopen_libfips) is a good one for that purpose. */ + if (dladdr (dlwrap_dlopen_libfips, &info) == 0) { + fprintf (stderr, "Internal error: Failed to lookup filename of libfips library with dladdr\n"); + exit (1); + } + + return dlwrap_real_dlopen (info.dli_fname, RTLD_NOW); +} + /* Many (most?) OpenGL programs dlopen libGL.so.1 rather than linking * against it directly, which means they would not be seeing our * wrapped GL symbols via LD_PRELOAD. So we catch the dlopen in a @@ -74,7 +99,6 @@ find_wrapped_library_index (const char *filename, unsigned *index_ret) void * dlopen (const char *filename, int flag) { - Dl_info info; void *ret; unsigned index; @@ -99,23 +123,13 @@ dlopen (const char *filename, int flag) assert (index < ARRAY_SIZE(orig_handles)); orig_handles[index] = ret; + if (libfips_handle == NULL) + libfips_handle = dlwrap_dlopen_libfips (); + /* Otherwise, we return our own handle so that we can intercept * future calls to dlsym. We encode the index in the return value * so that we can later map back to the originally requested * dlopen-handle if necessary. */ - if (libfips_handle) - return libfips_handle + index; - - /* We find our own filename by looking up this very function - * (that is, this "dlopen"), with dladdr).*/ - if (dladdr (dlopen, &info) == 0) { - fprintf (stderr, "Error: Failed to redirect dlopen of %s:\n", - filename); - exit (1); - } - - libfips_handle = dlwrap_real_dlopen (info.dli_fname, flag); - return libfips_handle + index; } diff --git a/dlwrap.h b/dlwrap.h index cad5a62..6460dfe 100644 --- a/dlwrap.h +++ b/dlwrap.h @@ -33,6 +33,18 @@ void * dlwrap_real_dlopen (const char *filename, int flag); +/* Perform a dlopen on the libfips library itself. + * + * Many places in fips need to lookup symbols within the libfips + * library itself, (and not in any other library). This function + * provides a reliable way to get a handle for performing such + * lookups. + * + * The returned handle can be passed to dlwrap_real_dlsym for the + * lookups. */ +void * +dlwrap_dlopen_libfips (void); + /* Call the *real* dlsym. We have our own wrapper for dlsym that, of * necessity must use claim the symbol 'dlsym'. So whenever anything * internal needs to call the real, underlying dlysm function, the diff --git a/glxwrap.c b/glxwrap.c index d7d4191..cccc05f 100644 --- a/glxwrap.c +++ b/glxwrap.c @@ -47,10 +47,14 @@ glXSwapBuffers (Display *dpy, GLXDrawable drawable) */ void (*glXGetProcAddressARB (const GLubyte *func))(void) { + static void *libfips_handle = NULL; void *ret; + if (libfips_handle == NULL) + libfips_handle = dlwrap_dlopen_libfips (); + /* If our library has this symbol, that's what we want to give. */ - ret = dlwrap_real_dlsym (NULL, (const char *) func); + ret = dlwrap_real_dlsym (libfips_handle, (const char *) func); if (ret) return ret; -- 2.43.0