19    Audit Record Generation

This chapter presents an overview of the audit concerns from a programmer's perspective. The following subjects are discussed:

19.1    Categories of Auditable Events

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.

19.2    Generation of Audit Records

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:

AUDIT_OR

An audit record is generated if either the system audit mask or the process audit mask indicates such an event should be audited.

AUDIT_AND

An audit record is generated if both the system audit mask and the process audit mask indicate such an event should be audited.

AUDIT_OFF

No audit records are generated for the current process.

AUDIT_USR

An audit record gets generated if the process audit mask indicates such an event should be audited.

The process audit control flag also has two nonexclusive states:

AUDIT_SYSCALL_OFF

Turns off system call record generation for the application. The system calls specified in the system mask continue to be audited.

AUDIT_HABITAT_USR

Allows turning on the habitat system calls in the user mask for an application while system calls are turned off for the system mask. See Appendix B for the habitat events.

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. The process audit control flag can be set with with the audcntl() system call (privileged process only).

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.

19.3    Disabling Auditing

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 );

19.4    Modifying Process Audit Attributes

Control over what events are 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:

gbuf

The buffer in which the mask gets built

gevent name

The <sys/audit.h> header file contains application event names. The <sys/*syscall.h> header files contains system call names.

gsucceed

Indicates whether to audit successful occurrences of the event. A 1 means audit success.

gfail

Indicates whether to audit failed occurrences of the event. A 1 means audit failure.

See the audcntl(2) reference page for more information.

19.5    Audit Records and Tokens

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).

19.5.1    Public Tokens

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:

Example 19-1:  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:

pointer types

Represent data strings or structures

iovec style data

Added as iovec-formated data

default

32 or 64-bit quantities (AUD_T_RESULT is 64-bit; others are 32-bit)

19.5.2    Private Tokens

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:

Example 19-2:  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)

19.6    Application-Specific Audit Records

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).