summaryrefslogtreecommitdiffstats
path: root/man7/rtld-audit.7
diff options
context:
space:
mode:
Diffstat (limited to 'man7/rtld-audit.7')
-rw-r--r--man7/rtld-audit.7606
1 files changed, 606 insertions, 0 deletions
diff --git a/man7/rtld-audit.7 b/man7/rtld-audit.7
new file mode 100644
index 0000000..df04a8c
--- /dev/null
+++ b/man7/rtld-audit.7
@@ -0,0 +1,606 @@
+.\" Copyright (c) 2009 Linux Foundation, written by Michael Kerrisk
+.\" <mtk.manpages@gmail.com>
+.\"
+.\" SPDX-License-Identifier: Linux-man-pages-copyleft
+.\"
+.\" 2009-01-12, mtk, Created
+.\"
+.TH RTLD-AUDIT 7 2023-05-03 "Linux man-pages 6.05.01"
+.SH NAME
+rtld\-audit \- auditing API for the dynamic linker
+.SH SYNOPSIS
+.nf
+.BR "#define _GNU_SOURCE" " /* See feature_test_macros(7) */"
+.B #include <link.h>
+.fi
+.SH DESCRIPTION
+The GNU dynamic linker (run-time linker)
+provides an auditing API that allows an application
+to be notified when various dynamic linking events occur.
+This API is very similar to the auditing interface provided by the
+Solaris run-time linker.
+The necessary constants and prototypes are defined by including
+.IR <link.h> .
+.PP
+To use this interface, the programmer creates a shared library
+that implements a standard set of function names.
+Not all of the functions need to be implemented: in most cases,
+if the programmer is not interested in a particular class of auditing event,
+then no implementation needs to be provided for the corresponding
+auditing function.
+.PP
+To employ the auditing interface, the environment variable
+.B LD_AUDIT
+must be defined to contain a colon-separated list of shared libraries,
+each of which can implement (parts of) the auditing API.
+When an auditable event occurs,
+the corresponding function is invoked in each library,
+in the order that the libraries are listed.
+.SS la_version()
+\&
+.nf
+.BI "unsigned int la_version(unsigned int " version );
+.fi
+.PP
+This is the only function that
+.I must
+be defined by an auditing library:
+it performs the initial handshake between the dynamic linker and
+the auditing library.
+When invoking this function, the dynamic linker passes, in
+.IR version ,
+the highest version of the auditing interface that the linker supports.
+.PP
+A typical implementation of this function simply returns the constant
+.BR LAV_CURRENT ,
+which indicates the version of
+.I <link.h>
+that was used to build the audit module.
+If the dynamic linker does
+not support this version of the audit interface, it will refuse to
+activate this audit module.
+If the function returns zero, the dynamic
+linker also does not activate this audit module.
+.PP
+In order to enable backwards compatibility with older dynamic linkers,
+an audit module can examine the
+.I version
+argument and return an earlier version than
+.BR LAV_CURRENT ,
+assuming the module can adjust its implementation to match the
+requirements of the previous version of the audit interface.
+The
+.B la_version
+function should not return the value of
+.I version
+without further checks because it could correspond to an interface
+that does not match the
+.I <link.h>
+definitions used to build the audit module.
+.SS la_objsearch()
+\&
+.nf
+.BI "char *la_objsearch(const char *" name ", uintptr_t *" cookie ,
+.BI " unsigned int " flag );
+.fi
+.PP
+The dynamic linker invokes this function to inform the auditing library
+that it is about to search for a shared object.
+The
+.I name
+argument is the filename or pathname that is to be searched for.
+.I cookie
+identifies the shared object that initiated the search.
+.I flag
+is set to one of the following values:
+.TP 17
+.B LA_SER_ORIG
+This is the original name that is being searched for.
+Typically, this name comes from an ELF
+.B DT_NEEDED
+entry, or is the
+.I filename
+argument given to
+.BR dlopen (3).
+.TP
+.B LA_SER_LIBPATH
+.I name
+was created using a directory specified in
+.BR LD_LIBRARY_PATH .
+.TP
+.B LA_SER_RUNPATH
+.I name
+was created using a directory specified in an ELF
+.B DT_RPATH
+or
+.B DT_RUNPATH
+list.
+.TP
+.B LA_SER_CONFIG
+.I name
+was found via the
+.BR ldconfig (8)
+cache
+.RI ( /etc/ld.so.cache ).
+.TP
+.B LA_SER_DEFAULT
+.I name
+was found via a search of one of the default directories.
+.TP
+.B LA_SER_SECURE
+.I name
+is specific to a secure object (unused on Linux).
+.PP
+As its function result,
+.BR la_objsearch ()
+returns the pathname that the dynamic linker should use
+for further processing.
+If NULL is returned, then this pathname is ignored for further processing.
+If this audit library simply intends to monitor search paths, then
+.I name
+should be returned.
+.SS la_activity()
+\&
+.nf
+.BI "void la_activity( uintptr_t *" cookie ", unsigned int "flag );
+.fi
+.PP
+The dynamic linker calls this function to inform the auditing library
+that link-map activity is occurring.
+.I cookie
+identifies the object at the head of the link map.
+When the dynamic linker invokes this function,
+.I flag
+is set to one of the following values:
+.TP 19
+.B LA_ACT_ADD
+New objects are being added to the link map.
+.TP
+.B LA_ACT_DELETE
+Objects are being removed from the link map.
+.TP
+.B LA_ACT_CONSISTENT
+Link-map activity has been completed: the map is once again consistent.
+.SS la_objopen()
+\&
+.nf
+.BI "unsigned int la_objopen(struct link_map *" map ", Lmid_t " lmid ,
+.BI " uintptr_t *" cookie );
+.fi
+.PP
+The dynamic linker calls this function when a new shared object is loaded.
+The
+.I map
+argument is a pointer to a link-map structure that describes the object.
+The
+.I lmid
+field has one of the following values
+.TP 17
+.B LM_ID_BASE
+Link map is part of the initial namespace.
+.TP
+.B LM_ID_NEWLM
+Link map is part of a new namespace requested via
+.BR dlmopen (3).
+.PP
+.I cookie
+is a pointer to an identifier for this object.
+The identifier is provided to later calls to functions
+in the auditing library in order to identify this object.
+This identifier is initialized to point to object's link map,
+but the audit library can change the identifier to some other value
+that it may prefer to use to identify the object.
+.PP
+As its return value,
+.BR la_objopen ()
+returns a bit mask created by ORing zero or more of the
+following constants,
+which allow the auditing library to select the objects to be monitored by
+.BR la_symbind* ():
+.TP 17
+.B LA_FLG_BINDTO
+Audit symbol bindings to this object.
+.TP
+.B LA_FLG_BINDFROM
+Audit symbol bindings from this object.
+.PP
+A return value of 0 from
+.BR la_objopen ()
+indicates that no symbol bindings should be audited for this object.
+.SS la_objclose()
+\&
+.nf
+.BI "unsigned int la_objclose(uintptr_t *" cookie );
+.fi
+.PP
+The dynamic linker invokes this function after any finalization
+code for the object has been executed,
+before the object is unloaded.
+The
+.I cookie
+argument is the identifier obtained from a previous invocation of
+.BR la_objopen ().
+.PP
+In the current implementation, the value returned by
+.BR la_objclose ()
+is ignored.
+.SS la_preinit()
+\&
+.nf
+.BI "void la_preinit(uintptr_t *" cookie );
+.fi
+.PP
+The dynamic linker invokes this function after all shared objects
+have been loaded, before control is passed to the application
+(i.e., before calling
+.IR main ()).
+Note that
+.IR main ()
+may still later dynamically load objects using
+.BR dlopen (3).
+.SS la_symbind*()
+\&
+.nf
+.BI "uintptr_t la_symbind32(Elf32_Sym *" sym ", unsigned int " ndx ,
+.BI " uintptr_t *" refcook ", uintptr_t *" defcook ,
+.BI " unsigned int *" flags ", const char *" symname );
+.BI "uintptr_t la_symbind64(Elf64_Sym *" sym ", unsigned int " ndx ,
+.BI " uintptr_t *" refcook ", uintptr_t *" defcook ,
+.BI " unsigned int *" flags ", const char *" symname );
+.fi
+.PP
+The dynamic linker invokes one of these functions
+when a symbol binding occurs between two shared objects
+that have been marked for auditing notification by
+.BR la_objopen ().
+The
+.BR la_symbind32 ()
+function is employed on 32-bit platforms;
+the
+.BR la_symbind64 ()
+function is employed on 64-bit platforms.
+.PP
+The
+.I sym
+argument is a pointer to a structure
+that provides information about the symbol being bound.
+The structure definition is shown in
+.IR <elf.h> .
+Among the fields of this structure,
+.I st_value
+indicates the address to which the symbol is bound.
+.PP
+The
+.I ndx
+argument gives the index of the symbol in the symbol table
+of the bound shared object.
+.PP
+The
+.I refcook
+argument identifies the shared object that is making the symbol reference;
+this is the same identifier that is provided to the
+.BR la_objopen ()
+function that returned
+.BR LA_FLG_BINDFROM .
+The
+.I defcook
+argument identifies the shared object that defines the referenced symbol;
+this is the same identifier that is provided to the
+.BR la_objopen ()
+function that returned
+.BR LA_FLG_BINDTO .
+.PP
+The
+.I symname
+argument points a string containing the name of the symbol.
+.PP
+The
+.I flags
+argument is a bit mask that both provides information about the symbol
+and can be used to modify further auditing of this
+PLT (Procedure Linkage Table) entry.
+The dynamic linker may supply the following bit values in this argument:
+.\" LA_SYMB_STRUCTCALL appears to be unused
+.TP 22
+.B LA_SYMB_DLSYM
+The binding resulted from a call to
+.BR dlsym (3).
+.TP
+.B LA_SYMB_ALTVALUE
+A previous
+.BR la_symbind* ()
+call returned an alternate value for this symbol.
+.PP
+By default, if the auditing library implements
+.BR la_pltenter ()
+and
+.BR la_pltexit ()
+functions (see below), then these functions are invoked, after
+.BR la_symbind (),
+for PLT entries, each time the symbol is referenced.
+.\" pltenter/pltexit are called for non-dynamically loaded libraries,
+.\" but don't seem to be called for dynamically loaded libs?
+.\" Is this the same on Solaris?
+The following flags can be ORed into
+.I *flags
+to change this default behavior:
+.TP 22
+.B LA_SYMB_NOPLTENTER
+Don't call
+.BR la_pltenter ()
+for this symbol.
+.TP 22
+.B LA_SYMB_NOPLTEXIT
+Don't call
+.BR la_pltexit ()
+for this symbol.
+.PP
+The return value of
+.BR la_symbind32 ()
+and
+.BR la_symbind64 ()
+is the address to which control should be passed after the function returns.
+If the auditing library is simply monitoring symbol bindings,
+then it should return
+.IR sym\->st_value .
+A different value may be returned if the library wishes to direct control
+to an alternate location.
+.SS la_pltenter()
+The precise name and argument types for this function
+depend on the hardware platform.
+(The appropriate definition is supplied by
+.IR <link.h> .)
+Here is the definition for x86-32:
+.PP
+.nf
+.BI "Elf32_Addr la_i86_gnu_pltenter(Elf32_Sym *" sym ", unsigned int " ndx ,
+.BI " uintptr_t *" refcook ", uintptr_t *" defcook ,
+.BI " La_i86_regs *" regs ", unsigned int *" flags ,
+.BI " const char *" symname ", long *" framesizep );
+.fi
+.PP
+This function is invoked just before a PLT entry is called,
+between two shared objects that have been marked for binding notification.
+.PP
+The
+.IR sym ,
+.IR ndx ,
+.IR refcook ,
+.IR defcook ,
+and
+.I symname
+are as for
+.BR la_symbind* ().
+.PP
+The
+.I regs
+argument points to a structure (defined in
+.IR <link.h> )
+containing the values of registers to be used for
+the call to this PLT entry.
+.PP
+The
+.I flags
+argument points to a bit mask that conveys information about,
+and can be used to modify subsequent auditing of, this PLT entry, as for
+.BR la_symbind* ().
+.PP
+.\" FIXME . Is the following correct?
+The
+.I framesizep
+argument points to a
+.I long\~int
+buffer that can be used to explicitly set the frame size
+used for the call to this PLT entry.
+If different
+.BR la_pltenter ()
+invocations for this symbol return different values,
+then the maximum returned value is used.
+The
+.BR la_pltexit ()
+function is called only if this buffer is
+explicitly set to a suitable value.
+.PP
+The return value of
+.BR la_pltenter ()
+is as for
+.BR la_symbind* ().
+.SS la_pltexit()
+The precise name and argument types for this function
+depend on the hardware platform.
+(The appropriate definition is supplied by
+.IR <link.h> .)
+Here is the definition for x86-32:
+.PP
+.nf
+.BI "unsigned int la_i86_gnu_pltexit(Elf32_Sym *" sym ", unsigned int " ndx ,
+.BI " uintptr_t *" refcook ", uintptr_t *" defcook ,
+.BI " const La_i86_regs *" inregs ", La_i86_retval *" outregs ,
+.BI " const char *" symname );
+.fi
+.PP
+This function is called when a PLT entry,
+made between two shared objects that have been marked
+for binding notification, returns.
+The function is called just before control returns to the caller
+of the PLT entry.
+.PP
+The
+.IR sym ,
+.IR ndx ,
+.IR refcook ,
+.IR defcook ,
+and
+.I symname
+are as for
+.BR la_symbind* ().
+.PP
+The
+.I inregs
+argument points to a structure (defined in
+.IR <link.h> )
+containing the values of registers used for the call to this PLT entry.
+The
+.I outregs
+argument points to a structure (defined in
+.IR <link.h> )
+containing return values for the call to this PLT entry.
+These values can be modified by the caller,
+and the changes will be visible to the caller of the PLT entry.
+.PP
+In the current GNU implementation, the return value of
+.BR la_pltexit ()
+is ignored.
+.\" This differs from Solaris, where an audit library that monitors
+.\" symbol binding should return the value of the 'retval' argument
+.\" (not provided by GNU, but equivalent to returning outregs->lrv_eax
+.\" on (say) x86-32).
+.SH VERSIONS
+This API is very similar to the Solaris API
+described in the Solaris
+.IR "Linker and Libraries Guide" ,
+in the chapter
+.IR "Runtime Linker Auditing Interface" .
+.SH STANDARDS
+None.
+.SH NOTES
+Note the following differences from the Solaris dynamic linker
+auditing API:
+.IP \[bu] 3
+The Solaris
+.BR la_objfilter ()
+interface is not supported by the GNU implementation.
+.IP \[bu]
+The Solaris
+.BR la_symbind32 ()
+and
+.BR la_pltexit ()
+functions do not provide a
+.I symname
+argument.
+.IP \[bu]
+The Solaris
+.BR la_pltexit ()
+function does not provide
+.I inregs
+and
+.I outregs
+arguments (but does provide a
+.I retval
+argument with the function return value).
+.SH BUGS
+In glibc versions up to and include 2.9,
+specifying more than one audit library in
+.B LD_AUDIT
+results in a run-time crash.
+This is reportedly fixed in glibc 2.10.
+.\" FIXME . Specifying multiple audit libraries doesn't work on GNU.
+.\" My simple tests on Solaris work okay, but not on Linux -- mtk, Jan 2009
+.\" glibc bug filed: http://sourceware.org/bugzilla/show_bug.cgi?id=9733
+.\" Reportedly, this is fixed on 16 Mar 2009 (i.e., for glibc 2.10)
+.SH EXAMPLES
+.EX
+#include <link.h>
+#include <stdio.h>
+\&
+unsigned int
+la_version(unsigned int version)
+{
+ printf("la_version(): version = %u; LAV_CURRENT = %u\en",
+ version, LAV_CURRENT);
+\&
+ return LAV_CURRENT;
+}
+\&
+char *
+la_objsearch(const char *name, uintptr_t *cookie, unsigned int flag)
+{
+ printf("la_objsearch(): name = %s; cookie = %p", name, cookie);
+ printf("; flag = %s\en",
+ (flag == LA_SER_ORIG) ? "LA_SER_ORIG" :
+ (flag == LA_SER_LIBPATH) ? "LA_SER_LIBPATH" :
+ (flag == LA_SER_RUNPATH) ? "LA_SER_RUNPATH" :
+ (flag == LA_SER_DEFAULT) ? "LA_SER_DEFAULT" :
+ (flag == LA_SER_CONFIG) ? "LA_SER_CONFIG" :
+ (flag == LA_SER_SECURE) ? "LA_SER_SECURE" :
+ "???");
+\&
+ return name;
+}
+\&
+void
+la_activity (uintptr_t *cookie, unsigned int flag)
+{
+ printf("la_activity(): cookie = %p; flag = %s\en", cookie,
+ (flag == LA_ACT_CONSISTENT) ? "LA_ACT_CONSISTENT" :
+ (flag == LA_ACT_ADD) ? "LA_ACT_ADD" :
+ (flag == LA_ACT_DELETE) ? "LA_ACT_DELETE" :
+ "???");
+}
+\&
+unsigned int
+la_objopen(struct link_map *map, Lmid_t lmid, uintptr_t *cookie)
+{
+ printf("la_objopen(): loading \e"%s\e"; lmid = %s; cookie=%p\en",
+ map\->l_name,
+ (lmid == LM_ID_BASE) ? "LM_ID_BASE" :
+ (lmid == LM_ID_NEWLM) ? "LM_ID_NEWLM" :
+ "???",
+ cookie);
+\&
+ return LA_FLG_BINDTO | LA_FLG_BINDFROM;
+}
+\&
+unsigned int
+la_objclose (uintptr_t *cookie)
+{
+ printf("la_objclose(): %p\en", cookie);
+\&
+ return 0;
+}
+\&
+void
+la_preinit(uintptr_t *cookie)
+{
+ printf("la_preinit(): %p\en", cookie);
+}
+\&
+uintptr_t
+la_symbind32(Elf32_Sym *sym, unsigned int ndx, uintptr_t *refcook,
+ uintptr_t *defcook, unsigned int *flags, const char *symname)
+{
+ printf("la_symbind32(): symname = %s; sym\->st_value = %p\en",
+ symname, sym\->st_value);
+ printf(" ndx = %u; flags = %#x", ndx, *flags);
+ printf("; refcook = %p; defcook = %p\en", refcook, defcook);
+\&
+ return sym\->st_value;
+}
+\&
+uintptr_t
+la_symbind64(Elf64_Sym *sym, unsigned int ndx, uintptr_t *refcook,
+ uintptr_t *defcook, unsigned int *flags, const char *symname)
+{
+ printf("la_symbind64(): symname = %s; sym\->st_value = %p\en",
+ symname, sym\->st_value);
+ printf(" ndx = %u; flags = %#x", ndx, *flags);
+ printf("; refcook = %p; defcook = %p\en", refcook, defcook);
+\&
+ return sym\->st_value;
+}
+\&
+Elf32_Addr
+la_i86_gnu_pltenter(Elf32_Sym *sym, unsigned int ndx,
+ uintptr_t *refcook, uintptr_t *defcook, La_i86_regs *regs,
+ unsigned int *flags, const char *symname, long *framesizep)
+{
+ printf("la_i86_gnu_pltenter(): %s (%p)\en", symname, sym\->st_value);
+\&
+ return sym\->st_value;
+}
+.EE
+.SH SEE ALSO
+.BR ldd (1),
+.BR dlopen (3),
+.BR ld.so (8),
+.BR ldconfig (8)