Linker and Libraries Guide

Audit Interface Functions

The following routines are provided by the rtld-audit interface. The routines are described in their expected order of use.


Note –

References to architecture, or object class specific interfaces are reduced to their generic name to simplify the discussions. For example, a reference to la_symbind32() and la_symbind64() is specified as la_symbind().


la_version()

This routine provides the initial handshake between the runtime linker and the audit library. This interface must be provided for the audit library to be loaded.

uint_t la_version(uint_t version);

The runtime linker calls this interface with the highest version of the rtld-audit interface the runtime linker is capable of supporting. The audit library can verify this version is sufficient for its use, and return the version the audit library expects to use. This version is normally LAV_CURRENT, which is defined in /usr/include/link.h.

If the audit library return is zero, or a version that is greater than the rtld-audit interface the runtime linker supports, the audit library is discarded.

The remaining audit routines are provided one or more cookies. See Audit Interface Interactions.

Following the la_version() call, two calls are made to the la_objopen() routine. The first call provides link-map information for the dynamic executable, and the second call provides link-map information for the runtime linker.

la_objopen()

This routine is called when a new object is loaded by the runtime linker.

uint_t la_objopen(Link_map *lmp, Lmid_t lmid, uintptr_t *cookie);

lmp provides the link-map structure that describes the new object. lmid identifies the link-map list to which the object has been added. cookie provides a pointer to an identifier. This identifier is initialized to the objects lmp. This identifier can be reassigned by the audit library to better identify the object to other rtld-audit interface routines.

The la_objopen() routine returns a value that indicates the symbol bindings of interest for this object. The return value is a mask of the following values that are defined in/usr/include/link.h.

  • LA_FLG_BINDTO – Audit symbol bindings to this object.

  • LA_FLG_BINDFROM – Audit symbol bindings from this object.

These values allow an auditor to select the objects to monitor with la_symbind(). A return value of zero indicates that binding information is of no interest for this object.

For example, an auditor can monitor the bindings from libfoo.so to libbar.so. la_objopen() for libfoo.so should return LA_FLG_BINDFROM. la_objopen() for libbar.so should return LA_FLG_BINDTO.

An auditor can monitor all bindings between libfoo.so and libbar.so. la_objopen() for both objects should return LA_FLG_BINDFROM and LA_FLG_BINDTO.

An auditor can monitor all bindings to libbar.so. la_objopen() for libbar.so should return LA_FLG_BINDTO. All la_objopen() calls should return LA_FLG_BINDFROM.

With the auditing version LAV_VERSION5, an la_objopen() call that represents the dynamic executable is provided to a local auditor. In this case, the auditor should not return a symbol binding flag, as the auditor may have been loaded too late to monitor any symbol bindings associated with the dynamic executable. Any flags that are returned by the auditor are ignored. The la_objopen() call provides the local auditor an initial cookie which is required for any subsequent la_preinit() or la_activity() calls.

la_activity()

This routine informs an auditor that link-map activity is occurring.

void la_activity(uintptr_t *cookie, uint_t flags);

cookie identifies the object heading the link-map. flags indicates the type of activity as defined in /usr/include/link.h.

  • LA_ACT_ADD – Objects are being added to the link-map list.

  • LA_ACT_DELETE – Objects are being deleted from the link-map list.

  • LA_ACT_CONSISTENT – Object activity has been completed.

An LA_ACT_ADD activity is called on process start up, following the la_objopen() calls for the dynamic executable and runtime linker, to indicate that new dependencies are being added. This activity is also called for lazy loading and dlopen(3C) events. An LA_ACT_DELETE activity is also called when objects are deleted with dlclose(3C).

Both the LA_ACT_ADD and LA_ACT_DELETE activities are a hint of the events that are expected to follow. There are a number of scenarios where the events that unfold might be different. For example, the addition of new objects can result in some of the new objects being deleted should the objects fail to relocate fully. The deletion of objects can also result in new objects being added should .fini executions result in lazy loading new objects. An LA_ACT_CONSISTENT activity follows any object additions or object deletions, and can be relied upon to indicate that the application link-map list is consistent. Auditors should be careful to verify actual results rather than blindly trusting the LA_ACT_ADD and LA_ACT_DELETE hints.

For auditing versions LAV_VERSION1 through LAV_VERSION4, la_activity() was only called for global auditors. With the auditing version LAV_VERSION5, activity events can be obtained by local auditors. An activity event provides a cookie that represents the application link-map. To prepare for this activity, and allow the auditor to control the content of this cookie, an la_objopen() call is first made to the local auditor. The la_objopen() call provides an initial cookie representing the application link-map. See Audit Interface Interactions.

la_objsearch()

This routine informs an auditor that an object is about to be searched for.

char *la_objsearch(const char *name, uintptr_t *cookie, uint_t flags);

name indicates the file or path name being searched for. cookie identifies the object initiating the search. flags identifies the origin and creation of name as defined in /usr/include/link.h.

  • LA_SER_ORIG – The initial search name. Typically, this name indicates the file name that is recorded as a DT_NEEDED entry, or the argument supplied to dlopen(3C).

  • LA_SER_LIBPATH – The path name has been created from a LD_LIBRARY_PATH component.

  • LA_SER_RUNPATH – The path name has been created from a runpath component.

  • LA_SER_DEFAULT – The path name has been created from a default search path component.

  • LA_SER_CONFIG – The path component originated from a configuration file. See crle(1).

  • LA_SER_SECURE – The path component is specific to secure objects.

The return value indicates the search path name that the runtime linker should continue to process. A value of zero indicates that this path should be ignored. An audit library that monitors search paths should return name.

la_objfilter()

This routine is called when a filter loads a new filtee. See Shared Objects as Filters.

int la_objfilter(uintptr_t *fltrcook, const char *fltestr,
        uintptr_t *fltecook, uint_t flags);

fltrcook identifies the filter. fltestr points to the filtee string. fltecook identifies the filtee. flags is presently unused. la_objfilter() is called after la_objopen() for both the filter and filtee.

A return value of zero indicates that this filtee should be ignored. An audit library that monitors the use of filters should return a non-zero value.

la_preinit()

This routine is called once after all objects have been loaded for the application, but before transfer of control to the application occurs.

void la_preinit(uintptr_t *cookie);

cookie identifies the primary object that started the process, normally the dynamic executable.

For auditing versions LAV_VERSION1 through LAV_VERSION4, la_preinit() was only called for global auditors. With the auditing version LAV_VERSION5, a preinit event can be obtained by local auditors. A preinit event provides a cookie that represents the application link-map. To prepare for this preinit, and allow the auditor to control the content of this cookie, an la_objopen() call is first made to the local auditor. The la_objopen() call provides an initial cookie representing the application link-map. See Audit Interface Interactions.

la_symbind()

This routine is called when a binding occurs between two objects that have been tagged for binding notification from la_objopen().

uintptr_t la_symbind32(Elf32_Sym *sym, uint_t ndx,
        uintptr_t *refcook, uintptr_t *defcook, uint_t *flags);
 
uintptr_t la_symbind64(Elf64_Sym *sym, uint_t ndx,
        uintptr_t *refcook, uintptr_t *defcook, uint_t *flags,
        const char *sym_name);

sym is a constructed symbol structure, whose sym->st_value indicates the address of the symbol definition being bound. See /usr/include/sys/elf.h. la_symbind32() adjusts the sym->st_name to point to the actual symbol name. la_symbind64() leaves sym->st_name to be the index into the bound objects string table.

ndx indicates the symbol index within the bound object's dynamic symbol table. refcook identifies the object making reference to this symbol. This identifier is the same identifier as passed to the la_objopen() routine that returned LA_FLG_BINDFROM. defcook identifies the object defining this symbol. This identifier is the same as passed to the la_objopen() that returned LA_FLG_BINDTO.

flags points to a data item that can convey information regarding the binding. This data item can also be used to modify the continued auditing of this procedure linkage table entry. This value is a mask of the symbol binding flags that are defined in /usr/include/link.h.

The following flags can be supplied to la_symbind().

  • LA_SYMB_DLSYM – The symbol binding occurred as a result of calling dlsym(3C).

  • LA_SYMB_ALTVALUE (LAV_VERSION2) – An alternate value was returned for the symbol value by a previous call to la_symbind().

If la_pltenter() or la_pltexit() routines exist, these routines are called after la_symbind() for procedure linkage table entries. These routines are called each time that the symbol is referenced. See also Audit Interface Limitations.

The following flags can be supplied from la_symbind() to alter this default behavior. These flags are applied as a bitwise-inclusive OR with the value pointed to by the flags argument.

  • LA_SYMB_NOPLTENTER – Do not call the la_pltenter() routine for this symbol.

  • LA_SYMB_NOPLTEXIT – Do not call the la_pltexit() routine for this symbol.

The return value indicates the address to which control should be passed following this call. An audit library that monitors symbol binding should return the value of sym->st_value so that control is passed to the bound symbol definition. An audit library can intentionally redirect a symbol binding by returning a different value.

sym_name, which is applicable for la_symbind64() only, contains the name of the symbol being processed. This name is available in the sym->st_name field for the 32–bit interface.

la_pltenter()

These routines are system specific. These routines are called when a procedure linkage table entry, between two objects that have been tagged for binding notification, is called.

uintptr_t la_sparcv8_pltenter(Elf32_Sym *sym, uint_t ndx,
        uintptr_t *refcook, uintptr_t *defcook,
        La_sparcv8_regs *regs, uint_t *flags);
 
uintptr_t la_sparcv9_pltenter(Elf64_Sym *sym, uint_t ndx,
        uintptr_t *refcook, uintptr_t *defcook,
        La_sparcv9_regs *regs, uint_t *flags,
        const char *sym_name);
 
uintptr_t la_i86_pltenter(Elf32_Sym *sym, uint_t ndx,
        uintptr_t *refcook, uintptr_t *defcook,
        La_i86_regs *regs, uint_t *flags); 
uintptr_t la_amd64_pltenter(Elf64_Sym *sym, uint_t ndx,
        uintptr_t *refcook, uintptr_t *defcook,
        La_amd64_regs *regs, uint_t *flags, const char *sym_name);

sym, ndx, refcook, defcook and sym_name provide the same information as passed to la_symbind().

For la_sparcv8_pltenter() and la_sparcv9_pltenter(), regs points to the out registers. For la_i86_pltenter(), regs points to the stack and frame registers. For la_amd64_pltenter(), regs points to the stack and frame registers, and the registers used in passing integer arguments. regs are defined in /usr/include/link.h.

flags points to a data item that can convey information regarding the binding. This data item can be used to modify the continued auditing of this procedure linkage table entry. This data item is the same as pointed to by the flags from la_symbind()

The following flags can be supplied from la_pltenter() to alter the present auditing behavior. These flags are applied as a bitwise-inclusive OR with the value pointed to by the flags argument.

  • LA_SYMB_NOPLTENTERla_pltenter() is not be called again for this symbol.

  • LA_SYMB_NOPLTEXITla_pltexit() is not be called for this symbol.

The return value indicates the address to which control should be passed following this call. An audit library that monitors symbol binding should return the value of sym->st_value so that control is passed to the bound symbol definition. An audit library can intentionally redirect a symbol binding by returning a different value.

la_pltexit()

This routine is called when a procedure linkage table entry, between two objects that have been tagged for binding notification, returns. This routine is called before control reaches the caller.

uintptr_t la_pltexit(Elf32_Sym *sym, uint_t ndx, uintptr_t *refcook,
        uintptr_t *defcook, uintptr_t retval);

uintptr_t la_pltexit64(Elf64_Sym *sym, uint_t ndx, uintptr_t *refcook,
        uintptr_t *defcook, uintptr_t retval, const char *sym_name);

sym, ndx, refcook, defcook and sym_name provide the same information as passed to la_symbind(). retval is the return code from the bound function. An audit library that monitors symbol binding should return retval. An audit library can intentionally return a different value.


Note –

The la_pltexit() interface is experimental. See Audit Interface Limitations.


la_objclose()

This routine is called after any termination code for an object has been executed and prior to the object being unloaded.

uint_t la_objclose(uintptr_t *cookie);

cookie identifies the object, and was obtained from a previous la_objopen(). Any return value is presently ignored.