AUDIT(HW) UNIX System V
Name
audit - audit subsystem interface device
Description
The audit subsystem provides two minor devices for
interfacing to the audit subsystem. One device,
/dev/auditr, 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, is
used by application programs which are privileged to write
audit records to the audit subsystem. This device may be
opened by as many applications as is necessary but may only
be opened for writing. The device also support 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, context
switch frequency 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
privilege. The device supports the openR(S), close(S),
write(S), and ioctl(S) entry points. Once opened, an
application may compose an audit record and write(S) it to
the device for inclusion in the collection file. The writing
of an audit record is an atomic action in that the entire
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 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:
RTLOGIN login/logoff 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 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 */
#endif
};
Username is the login or logoff 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 RTLOGIN. The event_type used for login/logoff
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 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(S) 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 what
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 RTSUBSYSTEM 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 RTLOCK 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 RTAUDIT 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(S) functions to
control the audit subsystem. The format of the ioctl(S)
calls is:
ioctl (fildes, command, arg)
int fildes, command;
struct auditinit *arg;
-or-
struct auditioctl *arg;
-or-
struct auditstats *arg;
The audit_init structure is only used for AUDITENABLE
command to perform subsystem initialization. The structure
is defined as follows:
struct audit_init {
uint buf_length; /* lngth 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 menu 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 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 file name generation. The buff_count
value determines the number 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 is
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(S) 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 statistic retrieval and display.
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 generation 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 alternate 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(S) 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 running.
[EACCES] An open attempt is made on the audit device and
the calling process does not have the
configaudit or writeaudit authorization.
[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
auditd(ADM), auditcmd(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 Operation.
(printed 8/30/89) AUDIT(HW)