Skip to content
Snippets Groups Projects
Commit aaedf0c9 authored by Simon McVittie's avatar Simon McVittie
Browse files

Simplify the special case for exporting dlopen()


Now that it's the same for every capsule, we can make it a lot more
streamlined.

Signed-off-by: default avatarSimon McVittie <smcv@collabora.com>
parent be9a029b
No related branches found
No related tags found
1 merge request!311Build capsule-capture-libs from a bundled copy of libcapsule
...@@ -28,7 +28,6 @@ ...@@ -28,7 +28,6 @@
" const char *default_prefix; %s" "\n" \ " const char *default_prefix; %s" "\n" \
" const char **exclude; %p" "\n" \ " const char **exclude; %p" "\n" \
" const char **export; %p" "\n" \ " const char **export; %p" "\n" \
" const char **nowrap; %p" "\n" \
" };" "\n" \ " };" "\n" \
" capsule_namespace *ns; %p" "\n" \ " capsule_namespace *ns; %p" "\n" \
" {" "\n" \ " {" "\n" \
...@@ -36,7 +35,6 @@ ...@@ -36,7 +35,6 @@
" char *prefix; %s" "\n" \ " char *prefix; %s" "\n" \
" char **combined_exclude; %p" "\n" \ " char **combined_exclude; %p" "\n" \
" char **combined_export; %p" "\n" \ " char **combined_export; %p" "\n" \
" char **combined_nowrap; %p" "\n" \
" };" "\n" \ " };" "\n" \
"};" "\n", \ "};" "\n", \
cap , \ cap , \
...@@ -46,13 +44,11 @@ ...@@ -46,13 +44,11 @@
cap->meta->default_prefix , \ cap->meta->default_prefix , \
cap->meta->exclude , \ cap->meta->exclude , \
cap->meta->export , \ cap->meta->export , \
cap->meta->nowrap , \
cap->ns , \ cap->ns , \
cap->ns->ns , \ cap->ns->ns , \
cap->ns->prefix , \ cap->ns->prefix , \
cap->ns->combined_exclude , \ cap->ns->combined_exclude , \
cap->ns->combined_export , \ cap->ns->combined_export);})
cap->ns->combined_nowrap);})
static ptr_list *namespaces = NULL; static ptr_list *namespaces = NULL;
...@@ -102,7 +98,6 @@ get_namespace (const char *default_prefix, const char *soname) ...@@ -102,7 +98,6 @@ get_namespace (const char *default_prefix, const char *soname)
ns->prefix = strdup( prefix ); ns->prefix = strdup( prefix );
ns->exclusions = ptr_list_alloc( 4 ); ns->exclusions = ptr_list_alloc( 4 );
ns->exports = ptr_list_alloc( 4 ); ns->exports = ptr_list_alloc( 4 );
ns->nowrap = ptr_list_alloc( 4 );
ptr_list_push_ptr( namespaces, ns ); ptr_list_push_ptr( namespaces, ns );
...@@ -291,12 +286,11 @@ update_namespaces (void) ...@@ -291,12 +286,11 @@ update_namespaces (void)
// just truncate the list to 0 entries // just truncate the list to 0 entries
ns->exclusions->next = 0; ns->exclusions->next = 0;
ns->exports->next = 0; ns->exports->next = 0;
ns->nowrap->next = 0;
} }
// merge the string lists for each active prefix: // merge the string lists for each active prefix:
// ie all excludes for /host should be in one exclude list, // 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: // excludes for /badgerbadger should be in another, etc etc:
for( size_t i = 0; i < _capsule_list->next; i++ ) for( size_t i = 0; i < _capsule_list->next; i++ )
{ {
...@@ -312,7 +306,6 @@ update_namespaces (void) ...@@ -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->exclusions, cap->meta->exclude );
add_new_strings_to_ptrlist( cap->ns->exports, cap->meta->export ); 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 // now squash the meta data ptr_lists into char** that
...@@ -326,11 +319,9 @@ update_namespaces (void) ...@@ -326,11 +319,9 @@ update_namespaces (void)
free_strv( ns->combined_exclude ); free_strv( ns->combined_exclude );
free_strv( ns->combined_export ); free_strv( ns->combined_export );
free_strv( ns->combined_nowrap );
ns->combined_exclude = cook_list( ns->exclusions ); ns->combined_exclude = cook_list( ns->exclusions );
ns->combined_export = cook_list( ns->exports ); ns->combined_export = cook_list( ns->exports );
ns->combined_nowrap = cook_list( ns->nowrap );
} }
} }
...@@ -473,7 +464,6 @@ capsule_init (const char *soname) ...@@ -473,7 +464,6 @@ capsule_init (const char *soname)
DUMP_CAPSULE( i, other ); DUMP_CAPSULE( i, other );
DUMP_STRV( excluded, other->ns->combined_exclude ); DUMP_STRV( excluded, other->ns->combined_exclude );
DUMP_STRV( exported, other->ns->combined_export ); DUMP_STRV( exported, other->ns->combined_export );
DUMP_STRV( nowrap, other->ns->combined_nowrap );
} }
return cap; return cap;
......
...@@ -12,10 +12,8 @@ typedef struct _capsule_namespace ...@@ -12,10 +12,8 @@ typedef struct _capsule_namespace
const char *prefix; const char *prefix;
ptr_list *exclusions; ptr_list *exclusions;
ptr_list *exports; ptr_list *exports;
ptr_list *nowrap;
char **combined_exclude; char **combined_exclude;
char **combined_export; char **combined_export;
char **combined_nowrap;
} capsule_namespace; } capsule_namespace;
struct _capsule struct _capsule
......
...@@ -75,20 +75,25 @@ process_phdr (struct dl_phdr_info *info, ...@@ -75,20 +75,25 @@ process_phdr (struct dl_phdr_info *info,
} }
static int 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 *soname;
const char * const libc[] =
{
"libc.so",
"libdl.so",
"libpthread.so",
NULL
};
static const char *never = "libcapsule.so"; static const char *never = "libcapsule.so";
if( soname_matches_path( never, path ) ) if( soname_matches_path( never, path ) )
return 1; return 1;
if( blacklist == NULL ) if( flags & RELOCATION_FLAGS_AVOID_LIBC )
return 0; for( soname = libc; soname && *soname; soname++ )
if( soname_matches_path( *soname, path ) )
for( soname = (const char * const *) blacklist; soname && *soname; soname++ ) return 1;
if( soname_matches_path( *soname, path ) )
return 1;
return 0; return 0;
} }
...@@ -116,7 +121,7 @@ relocate_cb (struct dl_phdr_info *info, size_t size, void *data) ...@@ -116,7 +121,7 @@ relocate_cb (struct dl_phdr_info *info, size_t size, void *data)
relocation_data *rdata = data; relocation_data *rdata = data;
const char *dso_path = *info->dlpi_name ? info->dlpi_name : "-elf-"; 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)", DEBUG( DEBUG_RELOCS, "skipping %s %p (blacklisted)",
dso_path, (void *) info->dlpi_addr ); dso_path, (void *) info->dlpi_addr );
...@@ -138,7 +143,7 @@ relocate_cb (struct dl_phdr_info *info, size_t size, void *data) ...@@ -138,7 +143,7 @@ relocate_cb (struct dl_phdr_info *info, size_t size, void *data)
static int relocate (const capsule cap, static int relocate (const capsule cap,
capsule_item *relocations, capsule_item *relocations,
const char * const *dso_blacklist, relocation_flags flags,
ptr_list *seen, ptr_list *seen,
char **error) char **error)
{ {
...@@ -151,7 +156,7 @@ static int relocate (const capsule cap, ...@@ -151,7 +156,7 @@ static int relocate (const capsule cap,
// load the relevant metadata into the callback argument: // load the relevant metadata into the callback argument:
rdata.debug = debug_flags; rdata.debug = debug_flags;
rdata.error = NULL; rdata.error = NULL;
rdata.blacklist = dso_blacklist; rdata.flags = flags;
rdata.mmap_info = load_mmap_info( &mmap_errno, &mmap_error ); rdata.mmap_info = load_mmap_info( &mmap_errno, &mmap_error );
rdata.relocs = relocations; rdata.relocs = relocations;
rdata.seen = seen; rdata.seen = seen;
...@@ -213,13 +218,19 @@ int ...@@ -213,13 +218,19 @@ int
capsule_relocate (const capsule cap, char **error) capsule_relocate (const capsule cap, char **error)
{ {
DEBUG( DEBUG_RELOCS, "beginning global symbol relocation:" ); 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 int
capsule_relocate_except (const capsule cap, capsule_relocate_dlopen (const capsule cap,
capsule_item *relocations,
const char * const *except,
char **error) char **error)
{ {
unsigned long df = debug_flags; unsigned long df = debug_flags;
...@@ -228,7 +239,8 @@ capsule_relocate_except (const capsule cap, ...@@ -228,7 +239,8 @@ capsule_relocate_except (const capsule cap,
debug_flags |= DEBUG_RELOCS; debug_flags |= DEBUG_RELOCS;
DEBUG( DEBUG_RELOCS, "beginning restricted symbol relocation:" ); 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; debug_flags = df;
......
...@@ -9,14 +9,6 @@ ...@@ -9,14 +9,6 @@
#include <string.h> #include <string.h>
#include <errno.h> #include <errno.h>
capsule_item capsule_external_dl_relocs[] =
{
{ "dlopen",
(capsule_addr) capsule_external_dlopen ,
(capsule_addr) capsule_external_dlopen },
{ NULL }
};
static int static int
dso_is_exported (const char *dsopath, char **exported) dso_is_exported (const char *dsopath, char **exported)
{ {
...@@ -139,10 +131,7 @@ capsule_external_dlopen(const char *file, int flag) ...@@ -139,10 +131,7 @@ capsule_external_dlopen(const char *file, int flag)
free( error ); free( error );
} }
if( capsule_relocate_except( c, if( capsule_relocate_dlopen( c, &error ) != 0 )
c->meta->dl_wrappers,
(const char **)c->ns->combined_nowrap,
&error ) != 0 )
{ {
fprintf( stderr, fprintf( stderr,
"dl-wrapper relocation from %s after " "dl-wrapper relocation from %s after "
......
...@@ -78,10 +78,6 @@ struct _capsule_item ...@@ -78,10 +78,6 @@ struct _capsule_item
* @export: (array zero-terminated=1): an array of char *, each * @export: (array zero-terminated=1): an array of char *, each
* specifying a DSO whose symbols should be exported from this * specifying a DSO whose symbols should be exported from this
* capsule * 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 * @items: (array zero-terminated=1): Array of capsule_item
* specifying which symbols to export, terminated by a * specifying which symbols to export, terminated by a
* #capsule_item whose @name is %NULL * #capsule_item whose @name is %NULL
...@@ -105,8 +101,6 @@ struct _capsule_metadata ...@@ -105,8 +101,6 @@ struct _capsule_metadata
const char *default_prefix; const char *default_prefix;
const char **exclude; const char **exclude;
const char **export; const char **export;
const char * const *nowrap;
capsule_item *dl_wrappers;
capsule_item *items; capsule_item *items;
/*< private >*/ /*< private >*/
capsule handle; capsule handle;
...@@ -149,38 +143,23 @@ int capsule_relocate (const capsule capsule, ...@@ -149,38 +143,23 @@ int capsule_relocate (const capsule capsule,
char **error); char **error);
/** /**
* capsule_relocate_except: * capsule_relocate_dlopen:
* @capsule: a #capsule handle as returned by capsule_init() * @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 * @error: (out) (transfer full) (optional): location in which to store
* an error message on failure, or %NULL to ignore. * an error message on failure, or %NULL to ignore.
* Free with free(). * Free with free().
* *
* Returns: 0 on success, non-zero on failure. * 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 * This function updates the GOT entries in all DSOs outside the capsule
* _except_ those listed in @except: When they call any function * _except_ those listed in @except: When they call dlopen(), instead
* listed in @relocations they invoke the copy of that function inside * they invoke the copy of that function provided by libcapsule.
* 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.
* *
* In the unlikely event that an error message is returned in @error it is the * In the unlikely event that an error message is returned in @error it is the
* caller's responsibility to free() it. * caller's responsibility to free() it.
*/ */
_CAPSULE_PUBLIC _CAPSULE_PUBLIC
int capsule_relocate_except (const capsule capsule, int capsule_relocate_dlopen (const capsule capsule,
capsule_item *relocations,
const char * const *except,
char **error); char **error);
/** /**
...@@ -337,12 +316,3 @@ void capsule_close (capsule cap); ...@@ -337,12 +316,3 @@ void capsule_close (capsule cap);
**/ **/
_CAPSULE_PUBLIC _CAPSULE_PUBLIC
char *capsule_get_prefix(const char *dflt, const char *soname); 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[];
...@@ -270,15 +270,6 @@ cat - <<EOF ...@@ -270,15 +270,6 @@ cat - <<EOF
NULL 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: // this is an array of the functions we want to act as a shim for:
static capsule_item relocs[] = static capsule_item relocs[] =
...@@ -308,8 +299,6 @@ capsule_metadata capsule_meta = ...@@ -308,8 +299,6 @@ capsule_metadata capsule_meta =
.default_prefix = "/host", .default_prefix = "/host",
.exclude = exclude, .exclude = exclude,
.export = valid_dlsym_sources, .export = valid_dlsym_sources,
.nowrap = invalid_dl_reloc_targets,
.dl_wrappers = capsule_external_dl_relocs,
.items = relocs, .items = relocs,
}; };
...@@ -364,9 +353,7 @@ static void __attribute__ ((constructor)) _capsule_init (void) ...@@ -364,9 +353,7 @@ static void __attribute__ ((constructor)) _capsule_init (void)
if( rloc != 0 ) // relocation failed. we're dead. if( rloc != 0 ) // relocation failed. we're dead.
abort(); abort();
rloc = capsule_relocate_except( cap, capsule_external_dl_relocs, rloc = capsule_relocate_dlopen( cap, &capsule_error );
&invalid_dl_reloc_targets[0],
&capsule_error );
if( rloc != 0 ) // we may survive this depending on how dlopen is used if( rloc != 0 ) // we may survive this depending on how dlopen is used
fprintf( stderr, fprintf( stderr,
"Warning: %s:%s could not install dlopen() wrappers: " "Warning: %s:%s could not install dlopen() wrappers: "
......
...@@ -45,7 +45,7 @@ f) In its constructor: ...@@ -45,7 +45,7 @@ f) In its constructor:
call capsule_relocate to replace all current references to the capsules' call capsule_relocate to replace all current references to the capsules'
symbols with the real symbols acquired by capsule_load 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 capsule
g) In its destructor: g) In its destructor:
...@@ -62,17 +62,6 @@ static const char *exclude[] = ...@@ -62,17 +62,6 @@ static const char *exclude[] =
NULL 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 // make sure this symbol has global visibility so
// that the libcapsule initialisation can find it // that the libcapsule initialisation can find it
__attribute__ ((visibility("default"))) __attribute__ ((visibility("default")))
...@@ -83,9 +72,7 @@ capsule_metadata capsule_meta = ...@@ -83,9 +72,7 @@ capsule_metadata capsule_meta =
.default_prefix = "/host", .default_prefix = "/host",
.exclude = exclude, .exclude = exclude,
.export = valid_dlsym_sources, .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: Sequences of events:
...@@ -116,7 +103,7 @@ The constructor for libcapsule runs, and does the following: ...@@ -116,7 +103,7 @@ The constructor for libcapsule runs, and does the following:
- the CAPSULE_PREFIX env var - the CAPSULE_PREFIX env var
- the static prefix in the capsule's metadata - the static prefix in the capsule's metadata
- NOTE: env vars don't apply here to setuid/setgid processes - 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) them by prefix (and deduplicating the resulting lists)
- eg the ‘export’ list from a namespace will be all the sonames from - eg the ‘export’ list from a namespace will be all the sonames from
all the .export entries from all capsules that share that namespace 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: ...@@ -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 of all DSOs outside the capsule to use the real symbols from the
target instead of the dummy entries in the capsule 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) functions (typically just dlopen - dlsym is handled by capsule_relocate)
that require careful handling. that require careful handling.
...@@ -144,12 +131,12 @@ This is similar to normal linking, except: ...@@ -144,12 +131,12 @@ This is similar to normal linking, except:
- The libcapsule constructor does not run - The libcapsule constructor does not run
- the capsule's constructor's call to capsule_init triggers a re-harvesting - the capsule's constructor's call to capsule_init triggers a re-harvesting
of available metadata, and a re-calculation of the aggregated lists 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 capsules are triggered
dlopen() of a normal library (from outside the capsule): 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 capsules are triggered
dlopen() of a normal library inside the capsule: dlopen() of a normal library inside the capsule:
......
...@@ -29,6 +29,12 @@ ...@@ -29,6 +29,12 @@
#define ELFW_ST_BIND(a) ELF32_ST_BIND(a) #define ELFW_ST_BIND(a) ELF32_ST_BIND(a)
#define ELFW_ST_VISIBILITY(a) ELF32_ST_VISIBILITY(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 typedef struct
{ {
capsule_item *relocs; capsule_item *relocs;
...@@ -36,7 +42,7 @@ typedef struct ...@@ -36,7 +42,7 @@ typedef struct
int debug; int debug;
char *error; char *error;
mmapinfo *mmap_info; mmapinfo *mmap_info;
const char * const *blacklist; relocation_flags flags;
ptr_list *seen; ptr_list *seen;
} relocation_data; } relocation_data;
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment