audit(HW) 19 June 1992 audit(HW) Name audit - audit subsystem interface device Description 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 satis- fied 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 applica- tion 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 file sysaudit.h. 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 eventtype, recordtype, and pid fields must be filled by the appli- cation; 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 writ- ten 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: RTLOGIN login/logout events RTPASSWORD password modifications RTDATABASE protected database modifications RTSUBSYSTEM privileged subsystem events RTLOCK terminal and account locking RTAUDIT audit subsystem events Each record type indicates a unique record structure definition. The RTLOGIN record uses the loginaudit 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 */ #endif }; 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 recordtype field set to RTLOGIN. The eventtype used for log- in/logout is the ETLOGIN event. The code field is used to distinguish between specific actions that may fall into a common category. For instance, the ETLOGIN 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 ptrt typedef field which contains the length of the string including the null charac- ter. 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 RTPASSWORD being generated. The structure is defined in the sys/sudit.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 RTDATABASE 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 data- base 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 RTSUBSYSTEM record type to record security related events that occur in subsystem components. code is used to iden- tify 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 RTLOCK record type is used to audit user account and terminal lock- ing 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 RTAUDIT record type. The subsystem is enabled and disabled by an application program. The same is true of subsystem parameter initiali- zation 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(S) functions to control the audit subsystem. The format of the ioctl calls is: ioctl (fildes, command, arg) int fildes, command; struct audit_init *arg; -or- struct audit_ioctl *arg; -or- struct audit_stats *arg; The auditinit structure is only used for the AUDITENABLE 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 sysadmsh interface and are written to a parameter file. This file is read and used to fill out the above structure to initialize the subsystem. The eventmask is a bit mask of the selected events to audit during the session. Only events that are enabled will generate audit records. The readcount 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 writecount and writetime 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 switchcount controls the size to which subsystem collection files may grow until a file switch is performed. The size of the output com- paction files written by the audit daemon are controlled by the cafmaxsize 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 buffcount value determines the num- ber of file system 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. dircount is the number of collection file and compaction file direc- tories 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 diroffset 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 uidcount and gidcount 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 uidoffset and gidoffset values. The audituid and auditgid fields are used to communicate certain ID values to the subsystem since these are used to create files with specif- ic owners and groups for security purposes. All remaining ioctl(S) commands except AUDITSTATS use the auditioctl structure. The auditioctl 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 AUDITSTATS 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: ENABLE Initialize and enable the audit subsystem for the genera- tion of audit records. SHUTDOWN Notify the audit subsystem that a system shutdown is in progress. DISABLE 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. SYSMASK Modify the audit subsystem event mask that controls the generation of audit records based on certain event types. USERMASK Modify the user event mask for a process. Each process has a mask which 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. FLUSH Modify the write count and time interval values. DAEMON Modify the audit daemon read count value. ACK 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. MOUNT The system has transitioned to multi-user state and alter- nate audit directories are now mounted and available. STATS Retrieve the current audit subsystem statistics from the audit device. IDS Specify the user and group IDs to use for selective audit generation. ioctl calls will fail if any of the following are true: [EPERM] The process required SelfAudit privilege but did not have it. [EEXIST] An attempt is made to enable audit and it is already run- ning. [EACCES] An open attempt is made on the audit device and the calling process does not have the configaudit or writeaudit author- ization. [EBADF] fildes is not a valid open file descriptor. [EFAULT] arg points to an illegal address. [EINVAL] command is an illegal value. Files /dev/auditr /dev/auditw See also auditcmd(ADM), auditd(ADM) ``Maintaining system security'' chapter of the System Administrator's Guide Diagnostics Upon successful completion, the device returns a 0. Otherwise, a -1 is returned and ERRNO is set to indicate the error. Value added audit is an extension of AT&T System V provided by The Santa Cruz Opera- tion, Inc.