Commit adb6c4aa authored by Vivek Das Mohapatra's avatar Vivek Das Mohapatra

Revert "Merge branch 'data-structures' into 'master'"

This reverts merge request !5
parent 65a6e3e1
......@@ -233,16 +233,68 @@ dump_link_map( void *dl_handle )
// ==========================================================================
void *
capsule_load (const capsule cap,
const char *dso,
Lmid_t *namespace,
capsule_item *wrappers,
int *errcode,
char **error)
{
void *ret = NULL;
ld_libs ldlibs = {};
capsule_metadata *cm = NULL;
// if we were passed a default new-namespace flag see
// if we've already established a namespace for this
// filesystem prefix in the global cache and use that:
DEBUG( DEBUG_CAPSULE, "requested namespace %ld for %s (newlm: %d)",
*namespace, dso, LM_ID_NEWLM );
if( *namespace == LM_ID_NEWLM )
{
// first fetch the subcapsule metadata for this specific
// target DSO if it exists:
for( size_t n = 0; n < capsule_manifest->next; n++ )
{
capsule_metadata *m = ptr_list_nth_ptr( capsule_manifest, n );
DEBUG( DEBUG_CAPSULE, "checking metadata %d for %p, %s",
(int) n, m, m ? m->soname : "---" );
if( !m || strcmp( dso, m->soname ) )
continue;
cm = m;
break;
}
DEBUG( DEBUG_CAPSULE, "metadata %p found for %s (LM: %ld)",
cm, cm->soname, cm->namespace );
// next, if we have subcapsule metadata, see if there's
// a Lmid_t value alrady allocated for it:
if( cm && cm->namespace == LM_ID_NEWLM )
for( size_t n = 0; n < capsule_manifest->next; n++ )
{
capsule_metadata *m = ptr_list_nth_ptr( capsule_manifest, n );
// this subcapsule is for a different prefix. skip it:
//DEBUG( DEBUG_CAPSULE, "checking prefix match: %p vs %p",
// cap->prefix, m->active_prefix );
if( strcmp( cap->prefix, m->active_prefix ) )
continue;
// we found a pre-allocated Lmid_t. Use it:
if( m->namespace != LM_ID_NEWLM )
{
DEBUG( DEBUG_CAPSULE, "re-using LM: %ld from %s",
m->namespace, m->soname );
*namespace = cm->namespace = m->namespace;
break;
}
}
}
if( !ld_libs_init( &ldlibs,
(const char **) cap->ns->combined_exclude,
cap->ns->prefix, debug_flags, errcode, error ) )
(const char **) cap->meta->combined_exclude,
cap->meta->active_prefix, debug_flags, errcode, error ) )
return NULL;
// ==================================================================
......@@ -260,7 +312,7 @@ capsule_load (const capsule cap,
// ==================================================================
// find the starting point of our capsule
if( !ld_libs_set_target( &ldlibs, cap->meta->soname, errcode, error ) )
if( !ld_libs_set_target( &ldlibs, dso, errcode, error ) )
goto cleanup;
// ==================================================================
......@@ -272,7 +324,12 @@ capsule_load (const capsule cap,
// ==================================================================
// load the stack of DSOs we need:
ret = ld_libs_load( &ldlibs, &cap->ns->ns, 0, errcode, error );
ret = ld_libs_load( &ldlibs, namespace, 0, errcode, error );
cap->meta->namespace = *namespace;
if( cm )
cm->namespace = *namespace;
if( debug_flags & DEBUG_CAPSULE )
{
......@@ -287,7 +344,7 @@ capsule_load (const capsule cap,
if( ret != NULL && // no errors so far
wrappers != NULL ) // have a dlopen fixup function
install_wrappers( ret, wrappers,
(const char **)cap->ns->combined_exclude,
(const char **)cap->meta->combined_exclude,
errcode, error );
cap->dl_handle = ret;
......
This diff is collapsed.
......@@ -6,27 +6,15 @@
typedef void * (*dlsymfunc) (void *handle, const char *symbol);
typedef void * (*dlopnfunc) (const char *file, int flags);
typedef struct _capsule_namespace
{
Lmid_t ns;
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
{
void *dl_handle;
const char *prefix;
capsule_item *relocations;
struct { ptr_list *all; ptr_list *some; } seen;
capsule_metadata *meta;
capsule_namespace *ns;
};
extern ptr_list *_capsule_list;
extern dlsymfunc _capsule_original_dlsym;
extern dlopnfunc _capsule_original_dlopen;
extern ptr_list *capsule_manifest;
extern dlsymfunc capsule_dl_symbol;
extern dlopnfunc capsule_dl_open;
......@@ -209,10 +209,10 @@ static int relocate (const capsule cap,
for( map = cap->relocations; map->name; map++ )
{
if( !map->shim )
map->shim = (ElfW(Addr)) _capsule_original_dlsym( RTLD_DEFAULT, map->name );
map->shim = (ElfW(Addr)) capsule_dl_symbol( RTLD_DEFAULT, map->name );
if( !map->real )
map->real = (ElfW(Addr)) _capsule_original_dlsym( cap->dl_handle, map->name );
map->real = (ElfW(Addr)) capsule_dl_symbol( cap->dl_handle, map->name );
}
// time to enter some sort of ... dangerous... zone:
......
......@@ -27,36 +27,16 @@ dso_is_exported (const char *dsopath, char **exported)
return 0;
}
// TODO: Implement dlvsym()?
/**
* capsule_external_dlsym:
* @handle: A handle returned by `dlopen`, or %RTLD_DEFAULT or %RTLD_NEXT
* @symbol: A symbol to be looked up
*
* An implementation of `dlsym`, used when it is called by the executable
* or by a library outside the capsule.
*
* If @symbol is exported by a library that is part of the exported ABI
* of a capsule, return that implementation.
*
* If not, return the implementation from the `LM_ID_BASE` namespace if
* there is one, or %NULL.
*
* Returns: The address associated with @symbol, or %NULL
*/
void *
capsule_external_dlsym (void *handle, const char *symbol)
{
DEBUG( DEBUG_DLFUNC|DEBUG_WRAPPERS, "dlsym(%s)", symbol );
void *addr = NULL;
for( size_t n = 0; n < _capsule_list->next; n++ )
for( size_t n = 0; n < capsule_manifest->next; n++ )
{
capsule cap = ptr_list_nth_ptr( _capsule_list, n );
// TODO: If handle != cap->dl_handle, should we skip it?
// TODO: RTLD_NEXT isn't implemented (is it implementable?)
addr = _capsule_original_dlsym ( cap->dl_handle, symbol );
capsule_metadata *m = ptr_list_nth_ptr( capsule_manifest, n );
addr = capsule_dl_symbol ( m->handle->dl_handle, symbol );
if( addr )
{
......@@ -66,7 +46,7 @@ capsule_external_dlsym (void *handle, const char *symbol)
// or if we are unable to determine where it came from (what?)
if( dladdr( addr, &dso ) )
{
if( !dso_is_exported( dso.dli_fname, cap->ns->combined_export ) )
if( !dso_is_exported( dso.dli_fname, m->combined_export ) )
addr = NULL;
DEBUG( DEBUG_DLFUNC|DEBUG_WRAPPERS,
......@@ -83,34 +63,21 @@ capsule_external_dlsym (void *handle, const char *symbol)
{
DEBUG( DEBUG_DLFUNC|DEBUG_WRAPPERS,
"symbol %s not found: fall back to default", symbol );
addr = _capsule_original_dlsym ( handle, symbol );
addr = capsule_dl_symbol ( handle, symbol );
}
return addr;
}
/**
* capsule_external_dlopen:
* @file: A SONAME or filename to be opened
* @flag: Flags affecting how we open the library
*
* An implementation of `dlopen`, used when it is called by the executable
* or by a library outside the capsule.
*
* Load @file with the ordinary `dlopen`. If successful, adjust
* relocations before returning the resulting handle.
*
* Returns: The handle returned by `dlopen`
*/
void *
capsule_external_dlopen(const char *file, int flag)
{
void *handle = NULL;
char *error = NULL;
if( _capsule_original_dlopen )
if( capsule_dl_open )
{
handle = _capsule_original_dlopen ( file, flag );
handle = capsule_dl_open ( file, flag );
}
else
{
......@@ -127,27 +94,28 @@ capsule_external_dlopen(const char *file, int flag)
debug_flags |= DEBUG_RELOCS;
// This may not even be necessary, so it should not be fatal.
// We do want to log it though as it might be an important clue:
for( size_t n = 0; n < _capsule_list->next; n++ )
for( size_t n = 0; n < capsule_manifest->next; n++ )
{
const capsule c = ptr_list_nth_ptr( _capsule_list, n );
capsule_metadata *m = ptr_list_nth_ptr( capsule_manifest, n );
const capsule c = m->handle;
if( capsule_relocate( c, NULL, &error ) != 0 )
{
fprintf( stderr,
"relocation from %s after dlopen(%s, …) failed: %s\n",
c->meta->soname, file, error );
m->soname, file, error );
free( error );
}
if( capsule_relocate_except( c,
c->meta->dl_wrappers,
(const char **)c->ns->combined_nowrap,
m->dl_wrappers,
(const char **)m->combined_nowrap,
&error ) != 0 )
{
fprintf( stderr,
"dl-wrapper relocation from %s after "
"dlopen(%s, …) failed: %s\n",
c->meta->soname, file, error );
m->soname, file, error );
free( error );
}
}
......@@ -158,20 +126,6 @@ capsule_external_dlopen(const char *file, int flag)
return handle;
}
/**
* capsule_shim_dlopen:
* @cap: The capsule from which `dlopen` was called
* @file: SONAME or filename to be opened
* @flag: Flags affecting how @file is opened
*
* An implementation of `dlopen` suitable to be called from inside a
* namespace. Load @file into @cap's namespace.
*
* If @cap has a non-trivial prefix, load @file and its recursive
* dependencies from @cap's prefix instead of from the root filesystem.
*
* Returns: A handle as if for `dlopen`
*/
void *
capsule_shim_dlopen(const capsule cap, const char *file, int flag)
{
......@@ -182,12 +136,12 @@ capsule_shim_dlopen(const capsule cap, const char *file, int flag)
DEBUG( DEBUG_WRAPPERS|DEBUG_DLFUNC,
"dlopen(%s, %x) wrapper: LMID: %ld; prefix: %s;",
file, flag, cap->ns->ns, cap->ns->prefix );
file, flag, cap->meta->namespace, cap->meta->active_prefix );
if( cap->ns->prefix && strcmp(cap->ns->prefix, "/") )
if( cap->prefix && strcmp(cap->prefix, "/") )
{
if( !ld_libs_init( &ldlibs, (const char **)cap->ns->combined_exclude,
cap->ns->prefix, debug_flags, &code, &errors ) )
if( !ld_libs_init( &ldlibs, (const char **)cap->meta->combined_exclude,
cap->prefix, debug_flags, &code, &errors ) )
{
DEBUG( DEBUG_LDCACHE|DEBUG_WRAPPERS|DEBUG_DLFUNC,
"Initialising ld_libs data failed: error %d: %s",
......@@ -198,7 +152,7 @@ capsule_shim_dlopen(const capsule cap, const char *file, int flag)
if( !ld_libs_load_cache( &ldlibs, "/etc/ld.so.cache", &code, &errors ) )
{
DEBUG( DEBUG_LDCACHE|DEBUG_WRAPPERS|DEBUG_DLFUNC,
"Loading ld.so.cache from %s: error %d: %s", cap->ns->prefix,
"Loading ld.so.cache from %s: error %d: %s", cap->prefix,
code, errors );
goto cleanup;
}
......@@ -208,7 +162,7 @@ capsule_shim_dlopen(const capsule cap, const char *file, int flag)
{
DEBUG( DEBUG_SEARCH|DEBUG_WRAPPERS|DEBUG_DLFUNC,
"Not found: %s under %s: error %d: %s",
file, cap->ns->prefix, code, errors );
file, cap->prefix, code, errors );
goto cleanup;
}
......@@ -221,7 +175,7 @@ capsule_shim_dlopen(const capsule cap, const char *file, int flag)
}
// load them up in reverse dependency order:
res = ld_libs_load( &ldlibs, &cap->ns->ns, flag, &code, &errors );
res = ld_libs_load( &ldlibs, &cap->meta->namespace, flag, &code, &errors );
if( !res )
DEBUG( DEBUG_WRAPPERS|DEBUG_DLFUNC,
......@@ -231,7 +185,7 @@ capsule_shim_dlopen(const capsule cap, const char *file, int flag)
}
else // no prefix: straightforward dlmopen into our capsule namespace:
{
res = dlmopen( cap->ns->ns, file, flag );
res = dlmopen( cap->meta->namespace, file, flag );
if( !res )
DEBUG( DEBUG_WRAPPERS|DEBUG_DLFUNC,
......
......@@ -92,14 +92,20 @@ typedef struct _capsule_metadata capsule_metadata;
struct _capsule_metadata
{
/*< public >*/
const int capsule_abi;
Lmid_t namespace;
const char *soname;
const char *default_prefix;
const char **exclude;
const char **export;
const char **nowrap;
capsule_item *dl_wrappers;
const int capsule_abi;
/*< private >*/
int closed;
char *active_prefix;
char **combined_exclude;
char **combined_export;
char **combined_nowrap;
capsule handle;
};
......@@ -219,6 +225,8 @@ int capsule_relocate_except (const capsule capsule,
*/
_CAPSULE_PUBLIC
void *capsule_load (const capsule capsule,
const char *dso,
Lmid_t *namespace,
capsule_item *wrappers,
int *errcode,
char **error);
......
......@@ -243,7 +243,6 @@ done < $symbol_file;
cat - <<EOF
static capsule cap;
static const char soname[] = "$proxied_dso";
// _int_dlopen() from libcapsule or a locally overridden version
#include "capsule/_int_dlopen.h"
......@@ -283,7 +282,7 @@ cat - <<EOF
// DSOs to restrict dlsym lookups to:
static const char *valid_dlsym_sources[] =
{
soname,
"$proxied_dso",
EOF
if [ -f "${proxy_extra}" ];
......@@ -302,7 +301,7 @@ cat - <<EOF
static const char *invalid_dl_reloc_targets[] =
{
soname,
"$proxied_dso",
"libc.so",
"libdl.so",
"libpthread.so",
......@@ -328,13 +327,14 @@ static capsule_item _external_dl_relocs[] =
__attribute__ ((visibility("default")))
capsule_metadata capsule_meta =
{
.capsule_abi = 0,
.soname = soname,
.namespace = LM_ID_NEWLM,
.soname = "$proxied_dso",
.default_prefix = "/host",
.exclude = exclude,
.export = valid_dlsym_sources,
.nowrap = invalid_dl_reloc_targets,
.dl_wrappers = EXT_DLOPEN_WRAPPERS,
.capsule_abi = 0,
};
// -------------------------------------------------------------
......@@ -376,6 +376,7 @@ static void __attribute__ ((constructor)) _capsule_init (void)
{
int capsule_errno = 0;
char *capsule_error = NULL;
Lmid_t symbol_ns;
void * dso;
// and this is an aray of functions we must override in the DSOs
......@@ -390,15 +391,14 @@ static void __attribute__ ((constructor)) _capsule_init (void)
{ NULL }
};
// Don't use capsule_meta.soname here, because if we did, it would be
// a relocatable, interposable reference to capsule_meta (assuming the
// shim library wasn't linked with -Bsymbolic). At runtime, we'd get
// an arbitrarily chosen one of the capsule_meta symbols defined by
// the other shim libraries sharing our global symbol namespace,
// and in particular not necessarily our own, with predictably bad
// results.
cap = capsule_init( soname );
dso = capsule_load( cap, wrappers, &capsule_errno, &capsule_error );
symbol_ns = LM_ID_NEWLM;
// Don't use capsule_meta.soname here - use a static value.
// Trust me when I say you don't want to know why.
cap = capsule_init( "$proxied_dso" );
dso = capsule_load( cap, "$proxied_dso", &symbol_ns, wrappers,
&capsule_errno, &capsule_error );
if( dso )
{
......
......@@ -78,7 +78,7 @@ static const char *invalid_dl_reloc_targets[] =
__attribute__ ((visibility("default")))
capsule_metadata capsule_meta =
{
.capsule_abi = 0,
.namespace = LM_ID_NEWLM,
.soname = "libGL.so.1",
.default_prefix = "/host",
.exclude = exclude,
......
......@@ -35,10 +35,7 @@ use CapsuleTest;
skip_all_unless_bwrap;
my $temp = File::Temp->newdir();
my $capsule_prefix = "$temp/prefix";
mkdir $capsule_prefix;
my $capsule_prefix = File::Temp->newdir();
my $libs = '';
my $notgl_user = "$builddir/tests/notgl-user";
my $notgl_helper_user = "$builddir/tests/notgl-helper-user";
......@@ -272,50 +269,6 @@ like($stdout,
like($stdout, qr/^notgles_extension_red: red-only extension$/m);
like($stdout, qr/^notgles_extension_green: \(not found\)$/m);
# We can use separate prefixes for different encapsulated libraries.
my $red_capsule_prefix = "$temp/red";
mkdir $red_capsule_prefix;
my $green_capsule_prefix = "$temp/green";
mkdir $green_capsule_prefix;
diag 'With libcapsule loading disparate implementations, via dlopen:';
run_ok([qw(bwrap
--ro-bind / /
--dev-bind /dev /dev
--ro-bind /), $red_capsule_prefix,
qw(--ro-bind /), $green_capsule_prefix,
'--tmpfs', realpath("$builddir/tests/lib$libs"),
'--tmpfs', $red_capsule_prefix.realpath($builddir),
'--tmpfs', $green_capsule_prefix.realpath($builddir),
'--ro-bind', realpath("$builddir/tests/red"),
$red_capsule_prefix.realpath("$builddir/tests/lib"),
'--ro-bind', realpath("$builddir/tests/green"),
$green_capsule_prefix.realpath("$builddir/tests/lib"),
'--setenv', 'CAPSULE_LIBNOTGL_SO_0_PREFIX', $red_capsule_prefix,
# We don't specify CAPSULE_LIBNOTGLES_SO_1_PREFIX, so the
# generic version gets used.
'--setenv', 'CAPSULE_PREFIX', $green_capsule_prefix,
'--setenv', 'LD_LIBRARY_PATH', join(':',
realpath("$builddir/tests/shim$libs"),
realpath("$builddir/tests/helper$libs"),
realpath("$builddir/tests/lib$libs"),
),
$notgl_dlopener],
'>', \$stdout);
diag_multiline $stdout;
like($stdout, qr/^NotGL implementation: red$/m);
like($stdout, qr/^NotGL helper implementation: host \(red\)$/m);
like($stdout,
qr/^notgl_extension_both: red implementation of common extension$/m);
like($stdout, qr/^notgl_extension_red: red-only extension$/m);
like($stdout, qr/^notgl_extension_green: \(not found\)$/m);
like($stdout, qr/^NotGLES implementation: green$/m);
like($stdout, qr/^NotGLES helper implementation: host \(green\)$/m);
like($stdout,
qr/^notgles_extension_both: green implementation of common extension$/m);
like($stdout, qr/^notgles_extension_red: \(not found\)$/m);
like($stdout, qr/^notgles_extension_green: green-only extension$/m);
done_testing;
# vim:set sw=4 sts=4 et:
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment