audit -- audit subsystem device interface


The audit subsystem provides two minor devices for interfacing to the audit subsystem. One device, /dev/auditr (audit read), is used exclusively by the audit daemon, auditd(ADM), for the purpose of reading the subsystem audit collection file records. The other device, /dev/auditw (audit write), is used by application programs that are privileged to write audit records to the audit subsystem. This device may be opened by as many applications as necessary but may only be opened for writing. The device also supports a host of ioctl(S) functions to perform audit subsystem control.

The audit read device provides the usual character device driver open(S), read(S), and close(S) routines. Writing to this device is not permitted. Read requests are satisfied by the subsystem and optimize the efficiency of the daemon and the performance of the system. Read requests are satisfied when sufficient data has accumulated to meet an administrator-specified threshold. Until the data is available, the read request will block. In this manner, the daemon will receive sufficiently large blocks of data on each read to allow sufficient compaction. Also, the frequency of context switching is greatly reduced since the reads will not be satisfied on small blocks or when no data is available.

The audit write device provides an interface to the audit subsystem for applications that have the writeaudit authorization. The device supports the open, close, write, and ioctl entry points. Once opened, an application may compose an audit record and write it to the device for inclusion in the collection file. The entire audit record must be presented to the subsystem with a single write. It is incumbent on the application to gather the record into a single buffer before writing it to the device.

The format of an audit record depends upon the type of event being audited. All audit records begin with a common audit record header defined by the audit_header structure in the <sys/audit.h> header file.

   struct audit_header {
        ushort     rec_length;     /* total record length */
        time_t     tstamp;	        /* date/time of record */
        ulong      event_id;       /* event sequence id */
        ushort     event_type;     /* event classification */
        ushort     record_type;    /* record format */
        ushort     obj_type;       /* object type */
        ushort     pid;            /* process_id */
The event_type, record_type, and pid fields must be filled by the application; all other fields are filled by the audit subsystem. The event types are defined in the header file and provide a method of categorizing audit records into groups such as login events or system administrator events. The record type informs the subsystem of the record template type. This information is also retained with the record when it is written to the collection file by the subsystem, since it is required at data reduction time.

Some of the record types have variable-length string areas that follow the fixed portion of the audit record. Each text string that is part of the record has its size recorded in a count field. Each string is null-terminated and the count must include the null character. When the record is written to the device, the amount of data written includes the fixed portion plus all text strings. The supported record types for application programs are:

login/logout events

password modifications

protected database modifications

privileged subsystem events

terminal and account locking

audit subsystem events

Each record type indicates a unique record structure definition. The RT_LOGIN record uses the login_audit structure. It contains the following fields, defined in <sys/audit.h>:

   struct login_audit {
   	struct audit_header aud_hdr;
   	char	username[8];	/* login name */
   	ushort	code;		/* function code */
   	ushort	luid;		/* login userid */
   	ushort	rgid;		/* real gid */
   	dev_t	ttyd;		/* controlling terminal */
   	ptr_t	cdir;		/* current directory */
   	ptr_t	terminal;	/* stdin terminal name */
   #ifdef B1
   	ptr_t	sec_level;	/* login sensitivity level */
username is the login or logout user account name. The luid and rgid fields are those associated with the specified user account. The audit header, which precedes the login-specific portion of the record, must have the record_type field set to RT_LOGIN. The event_type used for login/logout is the ET_LOGIN event.

The code field is used to distinguish between specific actions that may fall into a common category. For instance, the ET_LOGIN event category includes both successful and unsuccessful logins, and also logoffs. The code values, defined in the header file, indicate which of these occurred.

The login audit record also contains two variable-length text strings. These are the login terminal and the process current directory. The string area begins immediately following the fixed portion of the record. The size of each text string field is indicated by the ptr_t typedef field which contains the length of the string including the null character. The null character is considered part of the string. Once the strings have been calculated and the record completed, the length field in the audit record header is set to the size of structure plus the total lengths of the strings. This is the amount of data to write to the audit device.

Modifications to user passwords are audited by the password management subsystem. Each attempt, whether successful or not, results in an audit record of type RT_PASSWORD being generated. The structure is defined in the <sys/audit.h> header file:

   struct passwd_audit {
   	struct audit_header aud_hdr;
   	char	username[8];	/* login user name */
   	ushort	code;		/* function code */
The code value distinguishes between successful and unsuccessful attempts to change the password on the indicated user account.

The system maintains a number of protected database files to support the system security policy. Attempts to modify the databases are audited with the RT_DATABASE type records. These records have the following format, as defined in <sys/audit.h>:

   struct database_activity {
       struct audit_header aud_hdr;
       ptr_t     command;       /* command name */
       ushort    code;          /* Type of database audit */
       ushort    object;        /* object type */
       long      expected_val;  /* Expected value of parameter */
       long      present_val;   /* Present value of parameter */
       ptr_t     action;	     /* security action that failed */
       ptr_t     result;	     /* result of failure */
The dbase and code values identify the database and the specific action, whether successful or not. A variable-length text string area is provided to identify precisely the database field along with the old and new database field values. The audit header length field includes the size of the string area and the fixed portion of the record.

Protected subsystems use the RT_SUBSYSTEM record type to record security related events that occur in subsystem components. code is used to identify the subsystem generating the record. Both the command and resulting action as well as the resulting failure are recorded in command, action, and result, respectively.

   struct subsystem_activity {
       struct audit_header aud_hdr;
       ptr_t     command;    /* command name */
       ushort    code;       /* Subsystem type */
       ptr_t     action;     /* action that failed */
       ptr_t     result;     /* result of failure */
The RT_LOCK record type is used to audit user account and terminal locking events. The username identifies the user account which was locked or unlocked. code distinguishes between the several events that result in the generation of a lock audit record.
   #include	<sys/audit.h>

struct lock_audit { struct audit_header aud_hdr; char username[12]; /* login username */ ushort code; /* lock function code */ ushort trys; /* failed attempts */ };

Programs that interact with and control the audit subsystem are audited with the RT_AUDIT record type. The subsystem is enabled and disabled by an application program. The same is true of subsystem parameter initialization and modification. Events such as the initiation and termination of the audit daemon, the execution of the recovery mechanism, data reduction and report generation, and audit file archival are all audited.

The text string portion of the audit record is only applicable for the audit enable function since the initial subsystem collection file must be specified for the daemon log file. All other audit records do not use this field. The code indicates which of the above events took place.

   struct audit_actions {
       struct audit_header aud_hdr;
       ushort    code;     /* audit function code */
       ptr_t     text1;    /* initial collection file */
The audit device supports a number of ioctl functions to control the audit subsystem. The format of the ioctl calls is:
   ioctl (fildes, command, arg)
   int fildes, command;
   struct audit_init *arg;
   struct audit_ioctl *arg;
   struct audit_stats *arg;
The audit_init structure is only used for the AUDIT_ENABLE command to perform subsystem initialization. The structure is defined as follows:
   struct audit_init {
        uint      buf_length;      /* length of data including header */
        mask_t    audit_flags[1];  /* audit control flags */
        mask_t    event_mask[AUDIT_MASK_SIZE];    /* system event mask */
        uint      read_count;      /* daemon read count to satisfy */
        uint      write_count;     /* write count for coll. file flush */
        long      write_time;      /* write flush time in seconds */
        long      switch_count;    /* collection file size maximum */
        long      caf_maxsize;     /* compacted audit file max size */
        uint      dir_count;       /* directory count */
        uint      uid_count;       /* uid selection count */
        uint      gid_count;       /* gid selection count */
        ulong     dir_offset;      /* fseek of directory names */
        ulong     uid_offset;      /* fseek of uids to select */
        ulong     gid_offset;      /* fseek of gids to select */
        uint      buff_count;      /* number of collection file buffers */
        ulong     session;         /* system boot session number */
        short     audit_uid;       /* audit user uid */
        short     audit_gid;       /* audit group gid */
The subsystem initialization parameters are established through the Audit manager or auditsh(ADM) and are written to a parameter file. This file is read and used to fill out the above structure to initialize the subsystem.

The event_mask is a bit mask of the selected events to audit during the session. Only events that are enabled will generate audit records. The read_count value is used by the subsystem to satisfy audit daemon reads. Only when the specified amount of data is available in the collection file will the read be satisfied.

The flushing of the internal subsystem buffers to the collection file is controlled by the write_count and write_time fields. When the specified amount of data has accumulated, the buffers will be flushed to disk. A time interval in seconds can also be set which will cause the flushing of data to disk after a certain period of elapsed time.

The switch_count controls the size to which subsystem collection files may grow until a file switch is performed. The size of the output compaction files written by the audit daemon are controlled by the caf_maxsize parameter. When these files reach this specified size, the daemon performs a switch to a new compaction file and records this fact in the audit session log file. session is the current session value that is used in filename generation. The buff_count value determines the number of filesystem blocksize buffers to be allocated by the subsystem for the purpose of internal buffering. At least 2 buffers are allocated, while 4-6 buffers are optimal.

dir_count is the number of collection file and compaction file directories that are available to both the subsystem and the audit daemon for the creation of their respective files. If a file write error occurs, both will attempt to use an alternate directory. Both will terminate only when all directories have been tried without success. The directory names are located in the variable-length directory area following the fixed portion of the initialization record. Each pathname is a null-terminated string. The dir_offset field points to the start of this variable-length text string area with respect to the start of the structure.

The audit subsystem is capable of selective audit record generation based on user and group IDs. These values may be specified to the subsystem at initialization time using the uid_count and gid_count values. The actual list of user and group IDs are located at the end of the structure in a variable-length table of short integers. The offsets where the ID arrays may be found are located by the uid_offset and gid_offset values.

The audit_uid and audit_gid fields are used to communicate certain ID values to the subsystem since these are used to create files with specific owners and groups for security purposes.

All remaining ioctl commands except AUDIT_STATS use the audit_ioctl structure. The audit_ioctl structure is defined by the following:

   struct audit_ioctl {
        uint       read_count;     /* daemon read count */
        uint       write_count;    /* write count for file flush */
        long       write_time;     /* write flush time */
        mask_t     user_control[AUDIT_MASK_SIZE]; /* control mask */
        mask_t     user_disp[AUDIT_MASK_SIZE];    /* disposition mask */
        mask_t     system_mask[AUDIT_MASK_SIZE];  /* system event mask */
The AUDIT_STATS ioctl command uses the following structure for the retrieval and display of statistics.
   struct audit_stats {
        uint      session;         /* current session number */
        uint      sequence;        /* current sequence number */
        ulong     total_bytes;     /* total bytes written */
        ulong     total_recs;      /* total records written */
        ulong     syscall_recs;    /* system call audit record count */
        ulong     syscall_norecs;  /* system call audit record count */
        ulong     appl_recs;       /* application audit record count */
        ulong     read_count;      /* number of device reads */
        ulong     write_count;     /* number of device writes */
        ulong     coll_files;      /* number of collection files */
        ulong     buffers_used;    /* maximum audit buffer usage */
        ulong     buffer_sleep;    /* number of audit write sleeps */
The commands supported by the audit device are:

Initialize and enable the audit subsystem for the generation of audit records.

Terminate the audit subsystem and close all collection files. The audit daemon is also terminated after the last audit record has been read from the subsystem.

Modify the audit subsystem event mask that controls the generation of audit records based on certain event types.

Modify the user event mask for a process. Each process has a mask that can be used to always or never audit certain event types regardless of the system event mask. The mask is a control mask which indicates for each bit set on that the generation of records for the corresponding event type is controlled by the second mask. The second mask is the enable/disable mask, which determines whether the event is always or never audited. If a control mask bit is 0, the event is controlled by the system event mask.

Used by the daemon to acknowledge certain events such as recognition of system shutdown and the disabling of the audit subsystem. Provides a synchronization means between the subsystem and the daemon.

Modify the audit daemon read count value.

Modify the write count and time interval values.

Specify the user and group IDs to use for selective audit generation.

The system has transitioned to multiuser state and alternate audit directories are now mounted and available.

Notify the audit subsystem that a system shutdown is in progress.

Retrieve the current audit subsystem statistics from the audit device.

ioctl calls will fail, setting one of the following values in errno, if any of these conditions are true:

An open attempt is made on the audit device and the calling process does not have the configaudit or writeaudit authorization.

fildes is not a valid open file descriptor.

An attempt is made to enable audit and it is already running.

arg points to an illegal address.

command is an illegal value.

The process required SelfAudit privilege but did not have it.


Upon successful completion, the device returns a 0. Otherwise, a -1 is returned and errno is set to indicate the error.


used by auditd(ADM) to read audit collection records

used by application programs to write to the audit subsystem

See also

auditcmd(ADM), auditd(ADM)

``Maintaining system security'' in the System Administration Guide

Standards conformance

audit is not part of any currently supported standard; it is an extension of AT&T System V provided by The Santa Cruz Operation, Inc.
© 2003 Caldera International, Inc. All rights reserved.
SCO OpenServer Release 5.0.7 -- 11 February 2003