capsule

capsule

Functions

Types and Values

typedef capsule_addr
struct capsule
struct capsule_item
struct capsule_metadata

Description

Functions

capsule_init ()

capsule
capsule_init (const char *soname);

Parameters

soname

the soname of the target library

 

Returns

a capsule handle.

Does any initialisation necessary to use libcapsule’s functions.

Initialises internal accounting structures within the capsule and triggers the metadata setup if this caspsule has been acquired via dlopen(), and finishes registering the capsule proxy with libcapsule itself.


capsule_shim_dlopen ()

return
capsule_shim_dlopen (cap Param1,
                     filename Param2,
                     flag Param3);

Parameters

cap

The capsule from which dlopen was called

 

file

SONAME or filename to be opened

 

flag

dlopen flags to pass to the real dlopen call

 

Returns

A handle as if for dlopen

An implementation of dlopen suitable to be called from inside a namespace. Load file into cap namespace.

If cap has a non-trivial prefix, load file and its recursive dependencies from cap prefix instead of from the root filesystem.

This helper function exists because dlopen() cannot safely be called by a DSO opened into a private namespace. It takes file and flag arguments cf dlopen() and a cap handle, and performs a safe dlmopen() call instead.

Typically this function is used to implement a safe wrapper for dlopen() which is assigned to the int_dlopen member of the capsule_metadata. This * replaces calls to dlopen() by all DSOs in the capsule, allowing libraries which use dlopen() to work inside the capsule.

Limitations: RTLD_GLOBAL is not supported in flag . This is a glibc limitation in the dlmopen() implementation.


capsule_external_dlsym ()

void *
capsule_external_dlsym (void *handle,
                        const char *symbol);

An implementation of dlsym, used when it is called by the executable or by a library outside the capsule.

Some libraries have a use pattern in which their caller/user uses dlsym() to obtain symbols rather than using those symbols directly in its own code (libGL is an example of this).

Since the target library may have a different symbol set than the one the libcapsule proxy shim was generated from we can’t rely on dlsym() finding those symbols in the shim’s symbol table.

Instead we must intercept dlsym() calls made outside the capsule and attempt to look for the required symbol in the namespace defined by the active capsules first - If the required symbol is found there AND is from one of the DSO names present in the exported list then that symbol is returned. If either of those conditions is not met then a normal dlsym call with the passed handle is made.

This function provides the functionality described above, and is normally used automatically by libcapsule. It is exposed as API in case a libcapsule proxy library needs to provide its own specialised symbol lookup mechanism.

Parameters

handle

A dl handle, as passed to dlsym()

 

symbol

A symbol name, as passed to dlsym()

 

Returns

The address associated with symbol (as if for dlsym), or NULL


capsule_external_dlopen ()

void *
capsule_external_dlopen (const char *file,
                         int flag);

An implementation of dlopen, used when it is called by the executable or by a library outside the capsule.

This wrapper is meant to be replace normal calls to dlopen() made by the main program or a non-capsule library - it is necessary because en ELF object loaded by dlopen() may need us to trigger the _capsule_relocate() operation in order to make sure its GOT entries are correctly updated.

This wrapper carries out a normal dlopen() and then re-triggers the initial _capsule_relocate() call immediately, before returning the same value that dlopen() would have, given the same file and flag arguments.

Parameters

file

A soname, filename or path as passed to dlopen()

 

flag

The dl flags, as per dlopen()

 

Returns

The handle returned by dlopen


capsule_close ()

void
capsule_close (capsule cap);

This function should be called from a capsule proxy library’s destructor: Its job is to clean up capsule-specific allocated memory and metadata when a capsule proxy is discarded via dlclose(), and ensure that libproxy itself won’t try to access any related invalidated memory afterwards.

Parameters

cap

a capsule handle as returned by capsule_init()

 

capsule_get_prefix ()

char *
capsule_get_prefix (const char *dflt,
                    const char *soname);

Parameters

dflt

A default capsule prefix path

 

soname

The soname of the library we are encapsulating

 

Returns

A newly allocated char * pointing to the prefix path

libcapsule provides a proxy to a library, potentially from a foreign filesystem tree (found at, for example, ‘/host’).

Since it is useful for this location to be overrideable at startup on a per-target-library basis this function standardises the prefix selection algorithm as follows:

  • An environment variable based on soname : libGL.so.1 would map to CAPSULE_LIBGL_SO_1_PREFIX

  • If that is unset, the CAPSULE_PREFIX environment variable

  • Next: The default to the value passed in dflt

  • And if all that failed, NULL (which is internally equivalent to "/")

The environment variables are ignored if the process is privileged (setuid, setgid, given special capabilities, or marked as privileged by a LSM), or if libcapsule was compiled against a glibc version older than 2.17.

Although the value is newly allocated it will typically be cached in a structure that needs to survive the entire lifespan of the running program, so freeing it is unlikely to be a concern.


capsule_shim_free ()

void
capsule_shim_free (const capsule cap,
                   void *ptr);

Tries to safely route an allocated pointer to the correct free() implementation.

Parameters

cap

The capsule from which free was called

 

ptr

The pointer to be freed

 

capsule_shim_realloc ()

return
capsule_shim_realloc (cap Param1,
                      ptr Param2,
                      size Param3);

Types and Values

capsule_addr

typedef ElfW(Addr) capsule_addr;

Identical to an ElfW(Addr) from libelf. You may treat this as equivalent to a void * when assigning to it.


struct capsule

struct capsule {
    void  *dl_handle;
    struct { ptr_list *all; ptr_list *some; } seen;
    capsule_metadata *meta;
    capsule_namespace *ns;
    capsule_item internal_wrappers[7];
};

A handle returned by capsule_init: A required parameter for all other capsule calls.


struct capsule_item

struct capsule_item {
    const char *name;
    capsule_addr real;
    capsule_addr shim;
};

real and shim may typically be left empty by the shim library.

Both slots will typically hold the correct values after a successful capsule… call. While this is sometimes important internally it is not usually of interest to the caller (except maybe for debugging)

Members

const char *name;

The name of the symbol to be relocated

 

capsule_addr real;

address of the ‘real’ symbol in the target library

 

capsule_addr shim;

address of the ‘fake’ symbol in the proxy library

 

struct capsule_metadata

struct capsule_metadata {
    const int     capsule_abi;
    const char   *soname;
    const char   *default_prefix;
    const char  **exclude;
    const char  **export;
    capsule_item *items;
    void *(*int_dlopen) (const char *filename, int flag);
    void  (*int_free) (void *ptr);
    void *(*int_realloc) (void *ptr, size_t size);
};

This struct allows libcapsule proxy libraries to statically declare metadata about themselves that libcapsule needs at link time in order to function properly.

The capsule_item entries in items 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).

Members

const int capsule_abi;

Version of the libcapsule ABI implmented by this struct

 

const char *soname;

The soname of the encapsulated library

 

const char *default_prefix;

The default root location of the filesystem from which the encapsulated library should be loaded

 

const char **exclude;

an array of char *, each specifying a DSO not to load, terminated by a NULL entry.

[array zero-terminated=1]

const char **export;

an array of char *, each specifying a DSO whose symbols should be exported from this capsule.

[array zero-terminated=1]

capsule_item *items;

Array of capsule_item specifying which symbols to export, terminated by a capsule_item whose name is NULL.

[array zero-terminated=1]

int_dlopen ()

Implementation of the same API as dlopen

 

int_free ()

   

int_realloc ()