Skip to content
GitLab
Menu
Projects
Groups
Snippets
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
Menu
Open sidebar
Vivek Das Mohapatra
libcapsule
Commits
adb6c4aa
Commit
adb6c4aa
authored
Nov 10, 2017
by
Vivek Das Mohapatra
Browse files
Revert "Merge branch 'data-structures' into 'master'"
This reverts merge request
!5
parent
65a6e3e1
Changes
9
Expand all
Hide whitespace changes
Inline
Side-by-side
capsule/capsule-dlmopen.c
View file @
adb6c4aa
...
...
@@ -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
;
...
...
capsule/capsule-init.c
View file @
adb6c4aa
This diff is collapsed.
Click to expand it.
capsule/capsule-private.h
View file @
adb6c4aa
...
...
@@ -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_
li
st
;
extern
dlsymfunc
_
capsule_
original_
dlsym
;
extern
dlopnfunc
_
capsule_
original_
dlopen
;
extern
ptr_list
*
capsule_
manife
st
;
extern
dlsymfunc
capsule_dl
_
sym
bol
;
extern
dlopnfunc
capsule_dl
_
open
;
capsule/capsule-relocate.c
View file @
adb6c4aa
...
...
@@ -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
_
sym
bol
(
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
_
sym
bol
(
cap
->
dl_handle
,
map
->
name
);
}
// time to enter some sort of ... dangerous... zone:
...
...
capsule/capsule-wrappers.c
View file @
adb6c4aa
...
...
@@ -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_
li
st
->
next
;
n
++
)
for
(
size_t
n
=
0
;
n
<
capsule_
manife
st
->
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
_
sym
bol
(
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_
li
st
->
next
;
n
++
)
for
(
size_t
n
=
0
;
n
<
capsule_
manife
st
->
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
,
...
...
capsule/capsule.h
View file @
adb6c4aa
...
...
@@ -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
);
...
...
data/capsule-mkstublib
View file @
adb6c4aa
...
...
@@ -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 )
{
...
...
doc/Capsules.txt
View file @
adb6c4aa
...
...
@@ -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,
...
...
tests/notgl.pl
View file @
adb6c4aa
...
...
@@ -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:
Write
Preview
Supports
Markdown
0%
Try again
or
attach a new file
.
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment