This chapter presents an overview of the audit concerns from a programmer's perspective. The following subjects are discussed:
Auditable events are divided into the following categories:
A list of the default auditable events can be found in the Appendix B or by looking at the /etc/sec/audit_events file as delivered on your system. You can use the audit_setup script to establish the auditable events on your system. See the audit_setup(8) reference page for more information.
Whether an auditable event actually results in the generation of an audit record depends on the following:
The process audit control flag has four exclusive states:
The process audit control flag also has two non-exclusive states:
A default audit level can be established for most users, while being able to single out specific users to audit more or less closely. A privileged process is allowed to specify what gets audited for itself either absolutely, or relative to the system audit mask.
Control over what events get audited is an important step in fine-tuning the audit data to indicate only events of interest. Sometimes too much audit data is generated by system calls. For example, the login process executes thousands of system calls, but a single audit record for the login process is easier to understand, less stressful on the system, and fewer entries in the auditlog. Modification of a security-relevant database, such as the password file, requires the auditing of information not easily picked up from the system calls, such as which field of which entry is being modified.
Use the audcntl() system call to disable auditing for the current process as follows:
audcntl ( SET_PROC_ACNTL, (char *)0, 0, AUDIT_OFF, 0, 0 );
Control over what is audited for a specific process is achieved by modifying the process' auditmask and audcntl flags. Modify the process' audit mask as follows:
/* ex. set the process' auditmask to audit only LOGIN events and successful setgroups calls */ #include <sys/audit.h> #include <sys/syscall.h> char buf[AUDIT_MASK_LEN];
bzero ( buf, sizeof(buf) ); A_PROCMASK_SET ( buf, LOGIN, 1, 1 ); A_PROCMASK_SET ( buf, SYS_setgroups, 1, 0 ); if ( audcntl ( SET_PROC_AMASK, buf, AUDIT_MASK_LEN, \ 0, 0, 0 ) == -1 ) perror ( "audcntl" );
The A_PROCMASK_SET macro (found in <sys/audit.h>), takes the following arguments:
See the audcntl(2) reference page for more information.
The audit subsystem is designed to make it easy to add application-specific auditing.
The audit subsystem has no fixed record type. Instead, the various possible elements of an audit record are tuples consisting of defined audit tokens and corresponding values. Each audit record is then built up from those elements. This approach provides flexibility in the kind and amount of data that can go into an audit record. It also avoids the problems associated with a less flexible design that defines a number of fixed audit record types and requires all software that uses the audit subsystem to work within those record types.
Most tokens specify an audit value that is fixed in length and allow four bytes for the value. Examples of fixed-length tokens are AUD_T_AUID (audit ID), AUD_TP_DEV (device number), and AUD_TP_PID (process ID number).
Some types of audit values are of variable length. These are accommodated by tokens that are pointer types. AUD_T_CHARP (character parameter) and AUD_T_HOMEDIR (home directory) are two of the pointer-type tokens.
Some pointer-type tokens use iovec structures. Examples of these are AUD_T_OPAQUE, and AUD_T_INTARRAY which is used for data in integer arrays. Opaque data is displayed as an alphanumeric or in octal format. The iovec structure is defined in <sys/uio.h>. For information about iovec see the reference pages for readv(2) and writev(2).
The tokens available to programs using the audgen() and audgenl() routines are called public tokens, and are named AUD_T_name in the <sys/audit.h> file. Example 19-1 lists the public tokens:
/* start of ptr token types */ AUD_T_CHARP character string AUD_T_SOCK socket AUD_T_LOGIN login name AUD_T_HOMEDIR home directory AUD_T_SHELL shell AUD_T_DEVNAME device name AUD_T_SERVICE service string (rfu) AUD_T_HOSTNAME host name AUD_T_INTP integer array (deprecated) /* 1st element of int array is # of data elements in array */
/* start of iovec style data */ AUD_TOKEN_IOVEC_MIN AUD_T_OPAQUE opaque data AUD_T_INTARRAY integer array AUD_T_GIDSET group set AUD_T_XDATA aud_xdata structure AUD_TOKEN_PTR_MAX /* end of iovec style data */ /* end of ptr token types */
AUD_T_AUID audit id AUD_T_RUID real uid AUD_T_UID effective uid AUD_T_PID pid AUD_T_PPID ppid AUD_T_GID gid AUD_T_EVENT event # AUD_T_SUBEVENT subevent #
AUD_T_DEV dev major,minor # AUD_T_ERRNO errno value AUD_T_RESULT result value AUD_T_MODE object mode AUD_T_HOSTADDR ip address AUD_T_INT integer data AUD_T_DESCRIP descriptor AUD_T_HOSTID hostid
AUD_T_X_ATOM X atom AUD_T_X_CLIENT X client identifier AUD_T_X_PROPERTY X property identifier AUD_T_X_RES_CLASS X resource class AUD_T_X_RES_TYPE X resource type AUD_T_X_RES_ID X resource identifier
Only the public tokens can be added to records from user space using the audgen call; the private tokens cannot.
Further, the public tokens are broken down into 3 categories:
Tokens with security implications that are not available to users are called private tokens, and are named AUD_TP_name.
Example 19-2 lists the private tokens:
AUD_TP_ACCRGHT msghdr's access rights data (sendmsg, recvmsg) AUD_TP_MSGHDR msghdr's name field (sendmsg, recvmsg) AUD_TP_EVENTP event name (for alternate habitats) AUD_TP_HABITAT habitat name AUD_TP_ADDRVEC address vectors (exportfs) AUD_TP_INTP integer array
AUD_TP_AUID audit id AUD_TP_RUID real uid AUD_TP_UID effective uid AUD_TP_PID pid AUD_TP_PPID ppid AUD_TP_HOSTADDR host address (ip) AUD_TP_EVENT event #
AUD_TP_SUBEVENT subevent # AUD_TP_NCPU cpu # AUD_TP_DEV device # AUD_TP_LENGTH audit record length AUD_TP_IPC_GID sysV structure gid value AUD_TP_IPC_MODE sysV structure mode bits AUD_TP_IPC_UID sysV structure uid value AUD_TP_TV_SEC timestamp (sec)
AUD_TP_TV_USEC timestamp (usec) AUD_TP_SHORT short data AUD_TP_LONG long data AUD_TP_VNODE_DEV device on which inode resides AUD_TP_VNODE_ID inode identifier AUD_TP_VNODE_MODE object mode AUD_TP_VERSION version # AUD_TP_SET_UIDS flag indicating a uid change occurred
AUD_TP_CONT continuation flag AUD_TP_TID thread identifier (address)
The following are examples of code to generate an application-specific audit record:
/* ex. generate an event of type `event`, with "some string", and a result of 66 */ #include <sys/audit.h>
if ( audgenl ( `event`, AUD_T_CHARP, "some string", \ AUD_T_RESULT, 66L, 0 ) == -1 ) perror ( "audgenl" );
The event can be either a trusted event (see audit.h) or an administratively defined site-specific event.
/* ex. generate audit record for administratively defined event event is "rdb", subevent is "commit" note: this event must be registered in /etc/sec/site_events link with -laud */
#include <sys/audit.h> int eventnum, subeventnum;
if ( aud_sitevent_num ( "rdb", "commit", &eventnum, \ &subeventnum ) == -1 ) return(-1);
if ( audgenl ( eventnum, AUD_T_SUBEVENT, subeventnum, \ AUD_T_CHARP, "whatever", 0 ) == -1 ) return(-1);
See the audgenl(3) and aud_sitevent(3) reference pages for more information.
The examples in this section generate audit records only if the respective event types are selected to be audited and the auditable event actually results in the generation of an audit record (see Section 19.2).