diff --git a/capsule/capsule-init.c b/capsule/capsule-init.c index 89955f71406e409ee52fff0e3f2fed14037e54f6..66ca24dab6a092e01d1a5e6db7782e7764113bb7 100644 --- a/capsule/capsule-init.c +++ b/capsule/capsule-init.c @@ -28,7 +28,6 @@ " const char *default_prefix; %s" "\n" \ " const char **exclude; %p" "\n" \ " const char **export; %p" "\n" \ - " const char **nowrap; %p" "\n" \ " };" "\n" \ " capsule_namespace *ns; %p" "\n" \ " {" "\n" \ @@ -36,7 +35,6 @@ " char *prefix; %s" "\n" \ " char **combined_exclude; %p" "\n" \ " char **combined_export; %p" "\n" \ - " char **combined_nowrap; %p" "\n" \ " };" "\n" \ "};" "\n", \ cap , \ @@ -46,13 +44,11 @@ cap->meta->default_prefix , \ cap->meta->exclude , \ cap->meta->export , \ - cap->meta->nowrap , \ cap->ns , \ cap->ns->ns , \ cap->ns->prefix , \ cap->ns->combined_exclude , \ - cap->ns->combined_export , \ - cap->ns->combined_nowrap);}) + cap->ns->combined_export);}) static ptr_list *namespaces = NULL; @@ -102,7 +98,6 @@ get_namespace (const char *default_prefix, const char *soname) ns->prefix = strdup( prefix ); ns->exclusions = ptr_list_alloc( 4 ); ns->exports = ptr_list_alloc( 4 ); - ns->nowrap = ptr_list_alloc( 4 ); ptr_list_push_ptr( namespaces, ns ); @@ -291,12 +286,11 @@ update_namespaces (void) // just truncate the list to 0 entries ns->exclusions->next = 0; ns->exports->next = 0; - ns->nowrap->next = 0; } // merge the string lists for each active prefix: // ie all excludes for /host should be in one exclude list, - // all nowrap entries for /host should bein another list, all + // all export entries for /host should bein another list, all // excludes for /badgerbadger should be in another, etc etc: for( size_t i = 0; i < _capsule_list->next; i++ ) { @@ -312,7 +306,6 @@ update_namespaces (void) add_new_strings_to_ptrlist( cap->ns->exclusions, cap->meta->exclude ); add_new_strings_to_ptrlist( cap->ns->exports, cap->meta->export ); - add_new_strings_to_ptrlist( cap->ns->nowrap, cap->meta->nowrap ); } // now squash the meta data ptr_lists into char** that @@ -326,11 +319,9 @@ update_namespaces (void) free_strv( ns->combined_exclude ); free_strv( ns->combined_export ); - free_strv( ns->combined_nowrap ); ns->combined_exclude = cook_list( ns->exclusions ); ns->combined_export = cook_list( ns->exports ); - ns->combined_nowrap = cook_list( ns->nowrap ); } } @@ -473,7 +464,6 @@ capsule_init (const char *soname) DUMP_CAPSULE( i, other ); DUMP_STRV( excluded, other->ns->combined_exclude ); DUMP_STRV( exported, other->ns->combined_export ); - DUMP_STRV( nowrap, other->ns->combined_nowrap ); } return cap; diff --git a/capsule/capsule-private.h b/capsule/capsule-private.h index 7b4f68b0ac579cddc8e3bbcf3fea8f4d65f155fd..7f716682b344e28d236edff460437c62b6a69022 100644 --- a/capsule/capsule-private.h +++ b/capsule/capsule-private.h @@ -12,10 +12,8 @@ typedef struct _capsule_namespace const char *prefix; ptr_list *exclusions; ptr_list *exports; - ptr_list *nowrap; char **combined_exclude; char **combined_export; - char **combined_nowrap; } capsule_namespace; struct _capsule diff --git a/capsule/capsule-relocate.c b/capsule/capsule-relocate.c index 23c10b1135f1120382719fd2ed7e57fe36e8491c..d5fa2e0bad2992f60b465603f68ffc5adef5a2ab 100644 --- a/capsule/capsule-relocate.c +++ b/capsule/capsule-relocate.c @@ -75,20 +75,25 @@ process_phdr (struct dl_phdr_info *info, } static int -dso_is_blacklisted (const char *path, const char * const *blacklist) +dso_is_blacklisted (const char *path, relocation_flags flags) { const char * const *soname; + const char * const libc[] = + { + "libc.so", + "libdl.so", + "libpthread.so", + NULL + }; static const char *never = "libcapsule.so"; if( soname_matches_path( never, path ) ) return 1; - if( blacklist == NULL ) - return 0; - - for( soname = (const char * const *) blacklist; soname && *soname; soname++ ) - if( soname_matches_path( *soname, path ) ) - return 1; + if( flags & RELOCATION_FLAGS_AVOID_LIBC ) + for( soname = libc; soname && *soname; soname++ ) + if( soname_matches_path( *soname, path ) ) + return 1; return 0; } @@ -116,7 +121,7 @@ relocate_cb (struct dl_phdr_info *info, size_t size, void *data) relocation_data *rdata = data; const char *dso_path = *info->dlpi_name ? info->dlpi_name : "-elf-"; - if( dso_is_blacklisted( dso_path, rdata->blacklist ) ) + if( dso_is_blacklisted( dso_path, rdata->flags ) ) { DEBUG( DEBUG_RELOCS, "skipping %s %p (blacklisted)", dso_path, (void *) info->dlpi_addr ); @@ -138,7 +143,7 @@ relocate_cb (struct dl_phdr_info *info, size_t size, void *data) static int relocate (const capsule cap, capsule_item *relocations, - const char * const *dso_blacklist, + relocation_flags flags, ptr_list *seen, char **error) { @@ -151,7 +156,7 @@ static int relocate (const capsule cap, // load the relevant metadata into the callback argument: rdata.debug = debug_flags; rdata.error = NULL; - rdata.blacklist = dso_blacklist; + rdata.flags = flags; rdata.mmap_info = load_mmap_info( &mmap_errno, &mmap_error ); rdata.relocs = relocations; rdata.seen = seen; @@ -213,13 +218,19 @@ int capsule_relocate (const capsule cap, char **error) { DEBUG( DEBUG_RELOCS, "beginning global symbol relocation:" ); - return relocate( cap, cap->meta->items, NULL, cap->seen.all, error ); + return relocate( cap, cap->meta->items, RELOCATION_FLAGS_NONE, cap->seen.all, error ); } +static capsule_item capsule_external_dl_relocs[] = +{ + { "dlopen", + (capsule_addr) capsule_external_dlopen , + (capsule_addr) capsule_external_dlopen }, + { NULL } +}; + int -capsule_relocate_except (const capsule cap, - capsule_item *relocations, - const char * const *except, +capsule_relocate_dlopen (const capsule cap, char **error) { unsigned long df = debug_flags; @@ -228,7 +239,8 @@ capsule_relocate_except (const capsule cap, debug_flags |= DEBUG_RELOCS; DEBUG( DEBUG_RELOCS, "beginning restricted symbol relocation:" ); - int rv = relocate( cap, relocations, except, cap->seen.some, error ); + int rv = relocate( cap, capsule_external_dl_relocs, + RELOCATION_FLAGS_AVOID_LIBC, cap->seen.some, error ); debug_flags = df; diff --git a/capsule/capsule-wrappers.c b/capsule/capsule-wrappers.c index 40a6aa9c3b37f8b0c0c4e1ef31ef97474903ddb5..2845be85d38132cfdfb4f7a39459d348ca99e439 100644 --- a/capsule/capsule-wrappers.c +++ b/capsule/capsule-wrappers.c @@ -9,14 +9,6 @@ #include <string.h> #include <errno.h> -capsule_item capsule_external_dl_relocs[] = -{ - { "dlopen", - (capsule_addr) capsule_external_dlopen , - (capsule_addr) capsule_external_dlopen }, - { NULL } -}; - static int dso_is_exported (const char *dsopath, char **exported) { @@ -139,10 +131,7 @@ capsule_external_dlopen(const char *file, int flag) free( error ); } - if( capsule_relocate_except( c, - c->meta->dl_wrappers, - (const char **)c->ns->combined_nowrap, - &error ) != 0 ) + if( capsule_relocate_dlopen( c, &error ) != 0 ) { fprintf( stderr, "dl-wrapper relocation from %s after " diff --git a/capsule/capsule.h b/capsule/capsule.h index b3306006ff663433eb0e9b39823292c056f52268..3f7bb08ac8f3bb3ffd0195150221892796839928 100644 --- a/capsule/capsule.h +++ b/capsule/capsule.h @@ -78,10 +78,6 @@ struct _capsule_item * @export: (array zero-terminated=1): an array of char *, each * specifying a DSO whose symbols should be exported from this * capsule - * @nowrap: (array zero-terminated=1): an array of char *, each specifying - * a DSO outside the capsule whose dlopen() implementation should - * _not_ be wrapped should typically contain the libc cluster and - * the capsule proxy library (libcapsule.so) itself * @items: (array zero-terminated=1): Array of capsule_item * specifying which symbols to export, terminated by a * #capsule_item whose @name is %NULL @@ -105,8 +101,6 @@ struct _capsule_metadata const char *default_prefix; const char **exclude; const char **export; - const char * const *nowrap; - capsule_item *dl_wrappers; capsule_item *items; /*< private >*/ capsule handle; @@ -149,38 +143,23 @@ int capsule_relocate (const capsule capsule, char **error); /** - * capsule_relocate_except: + * capsule_relocate_dlopen: * @capsule: a #capsule handle as returned by capsule_init() - * @relocations: (array zero-terminated=1): Array of capsule_item - * specifying which symbols to export, terminated by a - * #capsule_item whose @name is %NULL - * @except: (array zero-terminated=1) (optional): Array of sonames - * which should not have their GOT entries updated. * @error: (out) (transfer full) (optional): location in which to store * an error message on failure, or %NULL to ignore. * Free with free(). * * Returns: 0 on success, non-zero on failure. * - * The #capsule_item entries in @relocations need only specify the symbol - * name: The shim and real fields will be populated automatically if they - * are not pre-filled (this is the normal use case, as it would be unusual - * to know these value in advance). - * * This function updates the GOT entries in all DSOs outside the capsule - * _except_ those listed in @except: When they call any function - * listed in @relocations they invoke the copy of that function inside - * the capsule. The sonames should be of the form "libfoo.so.X" - * or "libfoo.so". You may specify further minor version numbers in the - * usual "libfoo.so.X.Y" format if you wish. + * _except_ those listed in @except: When they call dlopen(), instead + * they invoke the copy of that function provided by libcapsule. * * In the unlikely event that an error message is returned in @error it is the * caller's responsibility to free() it. */ _CAPSULE_PUBLIC -int capsule_relocate_except (const capsule capsule, - capsule_item *relocations, - const char * const *except, +int capsule_relocate_dlopen (const capsule capsule, char **error); /** @@ -337,12 +316,3 @@ void capsule_close (capsule cap); **/ _CAPSULE_PUBLIC char *capsule_get_prefix(const char *dflt, const char *soname); - -/** - * capsule_external_dl_relocs: - * - * An array of #capsule_item entries, %NULL terminated, which provides the - * default list of functions outside the capsule which need to be wrapped. - */ -_CAPSULE_PUBLIC -capsule_item capsule_external_dl_relocs[]; diff --git a/data/capsule-mkstublib b/data/capsule-mkstublib index f7865f7252e7563483f7b7a30d811a53d16ec07c..f89c35607b75a59fdd6f214ea4fab0c611c8472c 100755 --- a/data/capsule-mkstublib +++ b/data/capsule-mkstublib @@ -270,15 +270,6 @@ cat - <<EOF NULL }; -static const char * const invalid_dl_reloc_targets[] = -{ - "libc.so", - "libdl.so", - "libpthread.so", - "libcapsule.so", - NULL -}; - // ------------------------------------------------------------- // this is an array of the functions we want to act as a shim for: static capsule_item relocs[] = @@ -308,8 +299,6 @@ capsule_metadata capsule_meta = .default_prefix = "/host", .exclude = exclude, .export = valid_dlsym_sources, - .nowrap = invalid_dl_reloc_targets, - .dl_wrappers = capsule_external_dl_relocs, .items = relocs, }; @@ -364,9 +353,7 @@ static void __attribute__ ((constructor)) _capsule_init (void) if( rloc != 0 ) // relocation failed. we're dead. abort(); - rloc = capsule_relocate_except( cap, capsule_external_dl_relocs, - &invalid_dl_reloc_targets[0], - &capsule_error ); + rloc = capsule_relocate_dlopen( cap, &capsule_error ); if( rloc != 0 ) // we may survive this depending on how dlopen is used fprintf( stderr, "Warning: %s:%s could not install dlopen() wrappers: " diff --git a/doc/Capsules.txt b/doc/Capsules.txt index f95e13fe28b87489d02a794b846442a2d2389b0d..da5475976c6da84373e9e0a99357008fdc9766a7 100644 --- a/doc/Capsules.txt +++ b/doc/Capsules.txt @@ -45,7 +45,7 @@ f) In its constructor: call capsule_relocate to replace all current references to the capsules' symbols with the real symbols acquired by capsule_load - call capsule_relocate_except to install a wrapper for dlopen outside the + call capsule_relocate_dlopen to install a wrapper for dlopen outside the capsule g) In its destructor: @@ -62,17 +62,6 @@ static const char *exclude[] = NULL }; -// do not intercept dlopen (or any other call) in these DSOs: -static const char *invalid_dl_reloc_targets[] = -{ - "libGL.so.1", // this is the capsule itself, ie this library - "libc.so", - "libdl.so", - "libpthread.so", - "libcapsule.so", - NULL -}; - // make sure this symbol has global visibility so // that the libcapsule initialisation can find it __attribute__ ((visibility("default"))) @@ -83,9 +72,7 @@ capsule_metadata capsule_meta = .default_prefix = "/host", .exclude = exclude, .export = valid_dlsym_sources, - .nowrap = invalid_dl_reloc_targets, - .dl_wrappers = capsule_external_dl_relocs, // this is predeclared -}; // you can replace it with your own list of needed +}; ============================================================================ Sequences of events: @@ -116,7 +103,7 @@ The constructor for libcapsule runs, and does the following: - the CAPSULE_PREFIX env var - the static prefix in the capsule's metadata - NOTE: env vars don't apply here to setuid/setgid processes - - aggregates the exclude, export and nowrap metadata lists, grouping + - aggregates the exclude and export metadata lists, grouping them by prefix (and deduplicating the resulting lists) - eg the ‘export’ list from a namespace will be all the sonames from all the .export entries from all capsules that share that namespace @@ -133,7 +120,7 @@ The constructor for each loaded capsule runs, and does the following: of all DSOs outside the capsule to use the real symbols from the target instead of the dummy entries in the capsule - - calls capsule_relocate_except to install wrappers for any special-case + - calls capsule_relocate_dlopen to install wrappers for any special-case functions (typically just dlopen - dlsym is handled by capsule_relocate) that require careful handling. @@ -144,12 +131,12 @@ This is similar to normal linking, except: - The libcapsule constructor does not run - the capsule's constructor's call to capsule_init triggers a re-harvesting of available metadata, and a re-calculation of the aggregated lists - - the capsule_relocate and capsule_relocate_except sequences for _all_ + - the capsule_relocate and capsule_relocate_dlopen sequences for _all_ capsules are triggered dlopen() of a normal library (from outside the capsule): - - the capsule_relocate and capsule_relocate_except sequences for _all_ + - the capsule_relocate and capsule_relocate_dlopen sequences for _all_ capsules are triggered dlopen() of a normal library inside the capsule: diff --git a/utils/process-pt-dynamic.h b/utils/process-pt-dynamic.h index 939af0fb809cbf14775ee1dda59ad26477c9b7ab..ee52f005e2d7d33110be62af1996eaaefbfdf388 100644 --- a/utils/process-pt-dynamic.h +++ b/utils/process-pt-dynamic.h @@ -29,6 +29,12 @@ #define ELFW_ST_BIND(a) ELF32_ST_BIND(a) #define ELFW_ST_VISIBILITY(a) ELF32_ST_VISIBILITY(a) +typedef enum +{ + RELOCATION_FLAGS_NONE = 0, + RELOCATION_FLAGS_AVOID_LIBC = (1 << 0), +} relocation_flags; + typedef struct { capsule_item *relocs; @@ -36,7 +42,7 @@ typedef struct int debug; char *error; mmapinfo *mmap_info; - const char * const *blacklist; + relocation_flags flags; ptr_list *seen; } relocation_data;