This chapter provides information on the mechanics of writing and reading audit records. The following topics are covered:
Disabling auditing for the current process. (See Chapter 10 for information on managing the audit subsystem.)
Parsing audit logs. (This section provides the low-level detail needed to develop additional utilities for audit data analysis.)
Trusted programs
can use the
audgen()
system call, the
audgenl()
library routine, or the
audgen
command to generate
audit records;
audgenl()
is a front-end to
audgen()
.
For arguments, the program supplies an audit event followed by
audit data consisting of audit tokens and values.
The following code fragment shows how a program that checks boot authentication
can call
audgenl()
to audit authentication failure:
if(audgenl(AUTH_EVENT, [1] AUD_T_LOGIN, pr->ufld.fd_name, [2] AUD_T_UID, pr->ufld.fd_uid, AUD_T_CHARP, "boot authentication failed"),0)== -1) perror("audgenl");
Notes:
AUTH_EVENT
is the record event name.
[Return to example]
AUD_T_LOGIN
,
AUD_T_UID
,
and
AUD_T_CHARP
are tokens, each with a corresponding value.
[Return to example]
<sys/audit.h>
.
See
Section 19.2
and
Section 19.3
for descriptions of events and tokens.
Each audit record has an audit event associated with it.
The system
automatically adds the event when generating system call audit records.
Self-auditing
application programs pass the event as an argument to
audgen()
or
audgenl()
when generating audit records.
There are two
types of audit events available to application programs:
Trusted events, which are defined in
<sys/audit.h>
with values between
MIN_TRUSTED_EVENT
and
(MIN_TRUSTED_EVENT + N_TRUSTED_EVENTS -1)
.
For example, the
LOGIN
event.
Site-defined events, which are defined in
/etc/sec/audit_events
with values between
MIN_SITE_EVENT
and 1048576.
The default range for site-defined events is 64.
For information on defining
site events, see
Section 19.8.
The audit subsystem has no fixed record type. Instead, an audit record is a series of tuples (data objects containing two or more components). Each tuple consists of an audit token and its corresponding value; depending on the token type, the tuple might contain a length field.
The following sections describe the two types of tokens:
public tokens
and
private tokens.
Application
programs use public tokens.
19.3.1 Public Tokens
Public
tokens are available to application programs that generate audit records using
audgen()
and
audgenl()
.
Public tokens are defined
in
<sys/audit.h>
and begin with
AUD_T_
;
for example,
AUD_T_CHARP
.
There are three basic types of public tokens:
Used to represent data strings or structures
as pointers.
AUD_T_CHARP
(character string) and
AUD_T_HOMEDIR
(home directory) are two pointer-type tokens.
Used to represent data as
iovec
-formatted data.
AUD_T_OPAQUE
, and
AUD_T_INTARRAY
are two iovec-type tokens.
(Look for the
iovec
comments in
<sys/audit.h>
.
The
iovec
structure is defined in
<sys/uio.h>
.
For information about
iovec
see the
readv
(2)
and
writev
(2)
reference pages.)
Used to represent data as a 32- or
64-bit quantity.
(AUD_T_RESULT and AUD_TP_LONG are 64-bit; others are
32-bit.) Most tokens use fixed-length data.
AUD_T_AUID
(audit ID),
AUD_T_UID
(user ID), and
AUD_T_PID
(process ID) are examples of fixed-length tokens.
The following example generates an audit
record using
iovec
-formatted data:
#define AUD_COMPAT #include <sys/audit.h> #include <sys/uio.h> main() { char buf[100]; int i; struct iovec iov; for (i = 0; i < sizeof(buf); i++) buf[i] = i; iov.iov_len = sizeof(buf); iov.iov_base = buf; if (audgenl (AUDGEN8, AUD_T_CHARP, "opaque data test", AUD_T_OPAQUE, &iov, 0 ) == -1 ) perror ("audgenl"); }
Private tokens are used by the kernel; they are not
available to application programs.
The
audgen()
system
call rejects any attempts by application programs to write records that contain
private tokens.
Private tokens are defined in
<sys/audit.h>
and begin with
AUD_TP_
; for example
AUD_TP_AUID
.
The kernel uses the private tokens when creating audit records.
For
example, the kernel encapsulates each audit record with
AUD_TP_LENGTH
tuples whose value is the length of the audit record.
Another example
is the
audgen()
or
audgenl()
event
argument, from which the kernel creates a
AUD_TP_EVENT
tuple.
19.4 Audit Flag and Masks
Whether an audit event actually results in the generation of an audit record depends on the following flag and mask settings:
Process audit control flag
Process audit mask
System audit mask
The process audit control flag has four exclusive states:
An audit record is generated if either the system audit mask or the process audit mask indicates such an event should be audited.
An audit record is generated if both the system audit mask and the process audit mask indicate such an event should be audited.
No audit records are generated for the current process.
An audit record is generated if the process audit mask indicates such an event should be audited.
The process audit control flag also has two nonexclusive states:
Turns off system call record generation for the process.
Turns on the habitat system
calls in the user mask for the process even if system calls are turned off
for the system mask.
The habitat system calls are: System V -
unlink()
and
open()
; real time -
memlk()
,
memunlk()
,
psx4_time_drift()
, and
rt_setprio()
.
These habitat system calls
are turned on or off as a group.
See
Appendix B
for the habitat events.
The system administrator can establish a default audit level for users, while retaining the ability to audit any individual user at whatever level the administrator deems appropriate. (See Chapter 10 for information on configuring and administering the audit subsystem.)
From a programmer's perspective, a privileged process can set its audit
level (specify what gets audited), either as an absolute mask or in relation
to the system audit mask.
See
Section 19.6
for an example
showing how to set a process's audit mask.
See
audcntl
(2)
and
auditmask
(8)
for more information.
19.5 Disabling System-Call Auditing for the Current Process
Controlling which events are audited is an important step in fine-tuning the amount of audit data collected. System calls can generate large amounts of audit data, but this data is not necessarily useful information. In general, actively auditing the modification of fields in a security-relevant database or auditing a specific security-relevant action provides more usable information than trying to derive this information from a multitude of system-call audit records. For example, the login process executes thousands of system calls, but a single informative audit record written by the login process uses less system resources and is easier to understand.
Application programs can disable system-call
auditing but still allow trusted-event auditing.
The following code fragment
shows how to use the
audcntl()
system call to set
AUDIT_SYSCALL_OFF
:
/* OR the AUDIT_SYSCALL_OFF bit into the audcntl flag */ if ((cntlflag = audcntl(GET_PROC_ACNTL, NULL, 0, 0, 0, 0)) == -1) perror("audcntl"); else audcntl(SET_PROC_ACNTL, NULL, 0, cntlflag|AUDIT_SYSCALL_OFF, 0, 0);
19.6 Modifying System-Call Auditing for the Current Process
A process can control what is audited for itself
or another process by modifying the target process's
auditmask
and
audcntl
flags.
You can modify the current process's
audit mask as follows:
/* ex. set the process's 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, defined in
<sys/audit.h>
, takes the following
arguments:
The buffer containing the mask.
The
<sys/audit.h>
header file contains trusted event names.
The
<sys/*syscall.h>
header files contain system call names.
Indicates whether
to audit success; a
1
means audit event success.
Indicates whether
to audit failure; a
1
means audit event failure.
See
audcntl
(2)
for more information.
19.7 Application-Specific Audit Records
An application program provides application-specific audit data as arguments
to
audgen()
or
audgenl()
.
The following code fragment sends an audit record
to the kernel when the specified
event
occurs.
The
event
is either a trusted event from
<sys/audit.h>
or a site-defined event from
/etc/sec/site_events
.
(Whether the kernel actually writes an audit record to the audit
log depends on the events audited for this process.)
/* If bad_thing occurs, generate an event of type event_num, * with string "bad thing happened", and a result of 66. */ #include <sys/audit.h> if (bad_thing) { if (audgenl (event_num, AUD_T_CHARP, "bad thing happened", AUD_T_RESULT, 66, 0 ) == -1) perror ("audgenl"); }
In general, an application-generated audit record does not have to include
data for the tokens listed in
Table 19-1.
The kernel automatically adds this information to each audit record.
However,
the audit subsystem does not prevent you from putting any of the public token
tuples in an audit record; for example, you can add an
AUD_T_AUID
tuple to an audit record even though the system will later add
an
AUD_TP_AUID
to the record.
Both tuples are written to
the audit log.
19.8 Site-Defined Events
A site can define its own set of audit
events, called
site-defined events, in the locally
created and maintained file
/etc/sec/site_events
.
The file
contains one entry for each site event.
The potential range for site event numbers is
MIN_SITE_EVENT
(defined in
<sys/audit.h>
) to 1048576.
The
default range is 64.
To change this value, set
audit-site-events
in
/etc/sysconfigtab
and reboot.
For example,
to allow for up to 128 site-defined events:
sec: audit-site-events=128
Each site-event entry can contain up to
INT_MAX
subevents.
There is no default range defined for subevents.
The maximum
length for an event or subevent name is
AUD_MAXEVENT_LEN
,
defined in
<sys/audit.h>
.
Application programs can generate records containing both site-defined
events and the trusted events defined in
<sys/audit.h>
(MIN_TRUSTED_EVENT
to
MAX_TRUSTED_EVENT
).
The
auditmask
utility supports preselection for site-defined
events, and the
audit_tool
utility supposts postselection
for site-defined events and subevents.
19.8.1 Sample site_events File
The syntax for a site-defined audit event entry is:
[event_name event_number [ , subevent_name subevent_number ... ] ;
]
The following entries in a sample
/etc/sec/site_events
file demonstrate how to create site-defined events and subevents:
essence 2048, [1] ess_read 0, [2] ess_write 1; [3] rdb 2049, rdb_open 0, rdb_close 1, rdb_read 2, rdb_write 3; decinspect 2050;
Notes:
essence
is the event; 2048 is the event
number.
Note that 2048 is
MIN_SITE_EVENT
, the lowest number
available for site-defined events.
[Return to example]
ess_read
is the first subevent; 0 is the
first subevent number.
[Return to example]
ess_write
is the second subevent; 1 is the
second subevent number.
[Return to example]
See
aud_sitevent
(3)
for more information on site-defined events.
19.8.2 Example - Generating an Audit Record for a Site-Defined Audit Event
The following code fragment uses
audgenl()
to generate audit data for an
rdb_close
event:
int event_num, subevent_num; /* translate event name(s) into event numbers */ if (aud_sitevent_num ("rdb", "rdb_close", &event_num, &subevent_num )) printf ("aud_sitevent_num failed"); /* generate audit data */ else if (audgenl (event_num, AUD_T_SUBEVENT, subevent_num, AUD_T_CHARP, "Trusted RDB V1.0 Close", 0) == -1) perror ("audgenl");
Compaq recommends that you include an
AUD_T_CHARP,
event name
argument pair with
audgenl()
when
generating a record for a site-defined event.
Doing so simplifies the task
of analyzing audit data on a system that does not have a copy of the local
site_events
file.
See
aud_sitevent
(3)
and
audgenl
(3)
for more information.
19.9 Creating Your Own Audit Logs
You can use the
audgen()
system call to create your own audit log.
If the
size
argument to
audgen
() is a nonzero value, audit data is
copied to the
userbuff
specified in
audgen()
rather than written to the system audit logs.
A trusted application
can then write the data in
userbuff
to a unique
log file.
See
audgen
(2)
for more information.
You can use the
audit_tool
utility to read the new
audit log.
More detailed information can be read from the log using the information
in
Section 19.10.
19.10 Parsing an Audit Log
Most people use
audit_tool
or
dxaudit
to read audit logs.
The
audit_tool
utility is a sophisticated
program that converts audit data into useful information, formats output,
and handles audit records that span audit log files.
When
audit_tool
first reads an audit log, it creates a corresponding
.hdr
file to maintain state information.
This state information
reduces the time needed for subsequent reads of the audit logs.
Also, if an
audit record spans audit logs,
audit_tool
opens both log
files and creates a complete record in the header file.
The following sections describe the format and construction of audit logs; they provide:
A description of an audit log plus a list of the token types generally found in all audit records.
The binary record format with examples showing an octal dump of a record and its formatted output.
A table of token/tuple byte descriptions, which lists the data types and format for each public and private token.
Sample macros for parsing tuples.
These sections do not provide the design information needed
to create a program similar to
audit_tool
; they do provide
the basic information required to parse an audit log into records and tuples.
19.10.1 Overview of Audit Log Format and List of Common Tuples
Audit logs are regular UNIX data files that contain
audit records.
An audit record consists of a series of tuples whose format
is either
token:value
or
token:length:value.
Each record starts and ends with an
AUD_TP_LENGTH
tuple.
(The
audit_tool
utility uses
AUD_TP_LENGTH
to determine whether an audit record is valid.
If
the actual length of the record does not match the
AUD_TP_LENGTH
value,
audit_tool
discards the record and provides
a warning.)
Table 19-1
shows the default
tuples generally used for audit records.
Table 19-1: Default Tuples Common to Most Audit Records
Tuple | Comment | Tuple | Comment |
AUD_TP_LENGTH | AUD_TP_VERSION | ||
AUD_TP_AUID | AUD_TP_RUID | ||
AUD_TP_HOSTADDR | AUD_TP_EVENTP | if habitat | |
AUD_TP_HABITAT | if habitat | AUD_TP_EVENT | |
AUD_TP_UID | AUD_TP_PID | ||
AUD_TP_PPID | AUD_TP_DEV | if device is associated with a process | |
AUD_TP_NCPU | AUD_TP_TV_USEC | ||
AUD_TP_SET_UIDS | if uid change | AUD_TP_TID | if AUDIT_USR flag is set |
19.10.2 Binary Audit Log Record Format
The following example is an octal dump of one audit record taken from an audit log.
253 007 001 000 000 266 002 300 000 000 241 000 000 000 000 242 000 000 000 000 246 020 217 202 131 247 012 002 000 000 243 000 000 000 000 244 247 002 000 000 245 231 002 000 000 251 000 000 000 000 257 201 076 321 061 260 260 336 004 000 013 030 000 000 000 001 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 014 050 000 000 000 001 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 004 005 000 000 000 162 157 157 164 000 005 002 000 000 000 057 000 006 010 000 000 000 057 142 151 156 057 163 150 000 007 003 000 000 000 072 060 000 001 015 000 000 000 141 162 147 166 075 144 170 154 157 147 151 156 000 001 020 000 000 000 114 157 147 151 156 040 163 165 143 143 145 145 144 145 144 000 032 034 000 000 000 001 000 000 000 000 000 000 000 003 000 000 000 007 000 000 000 011 000 000 000 014 000 000 000 026 000 000 000 051 000 000 000 000 052 000 000 000 000 000 000 000 000 253 007 001 000 000
The values contained in the record are as follows:
Each token:value tuple in the record consists of a one-byte (octal) value for the audit token followed by an audit value.
Each token:length:value tuple consists of a one-byte value for the audit token, an integer specifying the length of the tuple, and a value.
The first and last tuples of the audit record are the
AUD_TP_LENGTH (253)
tuples:
007 001 000 000
indicates
the record length is 263 bytes.
In the next example, the previous audit record is disassembled into
its component tuples.
The left column contains the audit token, derived from
the octal number in parentheses.
See the
<sys/audit.h>
file for the
#define
s.
If the tuple is of type
token:length:value, the length is also included in the parentheses,
separated from the token octal value by a slash.
For example, look at the
first
T_CHARP
tuple.
The
1
indicates
the token,
T_CHARP
; the
13
indicates
that the null-terminated character string is 13 bytes in length.
The remainder
of each line is the tuple's value, shown either in octal format or as a character
string.
AUD_TP_LENGTH (253): 007 001 000 000 AUD_TP_VERSION (266): 002 300 000 000 AUD_TP_AUID (241): 000 000 000 000 AUD_TP_RUID (242): 000 000 000 000 AUD_TP_HOSTADDR (246): 020 217 202 131 AUD_TP_EVENT (247): 012 002 000 000 AUD_TP_UID (243): 000 000 000 000 AUD_TP_PID (244): 247 002 000 000 AUD_TP_PPID (245): 231 002 000 000 AUD_TP_NCPU (251): 000 000 000 000 AUD_TP_TV_SEC (257): 201 076 321 061 AUD_TP_TV_USEC (260): 260 336 004 000 AUD_T_SLABEL (13/24): 01 00 00 00 00 00 00 00 \ 00 00 00 00 00 00 00 00 \ 00 00 00 00 00 00 00 00 AUD_T_ILABEL (14/40): 01 00 00 00 00 00 00 00 \ 00 00 00 00 00 00 00 00 \ 00 00 00 00 00 00 00 00 \ 00 00 00 00 00 00 00 00 \ 00 00 00 00 00 00 00 00 AUD_T_LOGIN (4/5): root AUD_T_HOMEDIR (5/2): / AUD_T_SHELL (6/8): /bin/sh AUD_T_DEVNAME (7/3): :0 AUD_T_CHARP (1/13): argv=dxlogin AUD_T_CHARP (1/16): Login succeeded AUD_T_GIDSET (32/28): AUD_T_ERRNO (51): 000 000 000 000 AUD_T_RESULT (52): 000 000 000 000 000 000 000 000 AUD_TP_LENGTH (253): 007 001 000 000
From this entry in the audit log,
audit_tool
produces
the following record.
audit_id: 0 ruid/euid: 0/0 username: root pid: 679 ppid: 665 subj il[sl]: UNCLASSIFIED [UNCLASSIFIED] event: login login name: root home dir: / shell: /bin/sh devname: :0 char param: argv=dxlogin char param: Login succeeded groups: 1 0 3 7 9 12 22 directory: / result: 0 ip address: 16.143.130.89 (<hostname_here>) timestamp: Wed Jun 26 09:43:29.31 1996 EDT cpu # = 0x0 version # = 0xc002
19.10.3 Token/Tuple Byte Descriptions
Table 19-2
lists public and
private tokens with their octal values.
For each tuple, the third column lists
the sequence in which tuple data is written to an audit log by the kernel.
Token is a 1-byte quantity; length is a 4-byte quantity.
Sample
Parse Macro refers to the macro that
audit_tool
uses to
parse the tuple.
These macros are provided, for reference purposes only, in
Section 19.10.4.
Table 19-2: Token/Tuple Byte Descriptions
Token | Octal Value | Tuple Format and Sample Parse Macro |
AUD_T_CHARP | 001 | token:length:null-terminated ASCII string. PARSE_DEF3 |
AUD_T_SOCK | 003 | token:length:struct sockaddr (4.3 style (u_short); if family is > UCHAR_MAX, assume 4.4 style sockaddr of length (byte) then family (byte)). PARSE_DEF3 |
AUD_T_LOGIN | 004 | token:length:null-terminated ASCII string. PARSE_DEF3 |
AUD_T_HOMEDIR | 005 | token:length:null-terminated ASCII string. PARSE_DEF3 |
AUD_T_SHELL | 006 | token:length:null-terminated ASCII string. PARSE_DEF3 |
AUD_T_DEVNAME | 007 | token:length:null-terminated ASCII string. PARSE_DEF3 |
AUD_T_SERVICE | 010 | token:length:null-terminated ASCII string. (reserved for future use) |
AUD_T_HOSTNAME | 011 | token:length:null-terminated ASCII string. PARSE_DEF3 |
AUD_T_INTP | 012 | token:length:int (First element is number of elements in array; note that AUD_T_INTARRAY is the preferred tuple when generating an audit record.) PARSE_DEF3 |
AUD_T_OPAQUE | 030 | token:length:value. (proplist or truly opaque; check for proplist name/value pairs else dump as hex._ PARSE_DEF6 |
AUD_T_INTARRAY | 031 | token:length:int. PARSE_DEF3 |
AUD_T_GIDSET | 032 | token:length:int1, int2, ... (unaligned). PARSE_DEF3 |
AUD_T_XDATA | 033 | token:struct aud_xdata (See
<sys/audit.h> .) PARSE_DEF8 |
AUD_T_AUID | 040 | token:int. PARSE_DEF2 |
AUD_T_RUID | 041 | token:int. PARSE_DEF2 |
AUD_T_UID | 042 | token:int. PARSE_DEF2 |
AUD_T_PID | 043 | token:int. PARSE_DEF2 |
AUD_T_PPID | 044 | token:int. PARSE_DEF2 |
AUD_T_GID | 045 | token:unsigned int. PARSE_DEF2 |
AUD_T_EVENT | 046 | token:int. PARSE_DEF2 |
AUD_T_SUBEVENT | 047 | token:int. PARSE_DEF2 |
AUD_T_DEV | 050 | token:int (Parse using the
major ()/minor () macros from
<sys/types.h> .) PARSE_DEF2 |
AUD_T_ERRNO | 051 | token:int. PARSE_DEF1 |
AUD_T_RESULT | 052 | token:long. PARSE_DEF4 |
AUD_T_MODE | 053 | token:unsigned int. PARSE_DEF2 |
AUD_T_HOSTADDR | 054 | token:unsigned int. PARSE_DEF2 |
AUD_T_INT | 055 | token:int. PARSE_DEF2 |
AUD_T_DESCRIP | 056 | token:int (file descriptor). PARSE_DEF2 |
AUD_T_HOSTID | 057 | token:int. PARSE_DEF1 |
AUD_T_X_ATOM | 060 | token:unsigned int. PARSE_DEF2 |
AUD_T_X_CLIENT | 061 | token:int. PARSE_DEF2 |
AUD_T_X_PROPERTY | 062 | token:int. PARSE_DEF2 |
AUD_T_X_RES_CLASS | 063 | token:unsigned int. PARSE_DEF2 |
AUD_T_X_RES_TYPE | 064 | token:unsigned int. PARSE_DEF2 |
AUD_T_X_RES_ID | 065 | token:unsigned int. PARSE_DEF2 |
AUD_T_SECEVENT | 177 | token:int. PARSE_DEF2 |
AUD_TP_ACCRGHT | 201 | token:length:cmsg_data (fd1, fd2, ...
-
See
<sys/socket.h> .) PARSE_DEF3 |
AUD_TP_MSGHDR | 202 | token:length:msghdr->msg_name (See
<sys/socket.h> .) PARSE_DEF3 |
AUD_TP_EVENTP | 203 | token:length: string. PARSE_DEF3 |
AUD_TP_HABITAT | 204 | token:length:string. PARSE_DEF3 |
AUD_TP_ADDRVEC | 205 | token:length:struct sockaddr (See
socket.h .) PARSE_DEF3 |
AUD_TP_INTP | 206 | token:length:int. PARSE_DEF3 |
AUD_TP_AUID | 241 | token:int. PARSE_DEF1 |
AUD_TP_RUID | 0242 | token:int. PARSE_DEF1 |
AUD_TP_UID | 0243 | token:int. PARSE_DEF1 |
AUD_TP_PID | 0244 | token:int. PARSE_DEF1 |
AUD_TP_PPID | 0245 | token:int. PARSE_DEF1 |
AUD_TP_HOSTADDR | 246 | token:unsigned int. PARSE_DEF1 |
AUD_TP_EVENT | 247 | token:int. PARSE_DEF1 |
AUD_TP_SUBEVENT | 250 | token:int (Reserved for future use.) PARSE_DEF1 |
AUD_TP_NCPU | 251 | token:int. PARSE_DEF1 |
AUD_TP_DEV | 252 | token:int (Parse using the
major ()/minor () macros from
sys/types.h .)
PARSE_DEF1 |
AUD_TP_LENGTH | 253 | token:int. PARSE_DEF1 |
AUD_TP_IPC_GID | 254 | token:unsigned int (ipc|msg|shm_perm.gid). PARSE_DEF2 |
AUD_TP_IPC_MODE | 255 | token:unsigned int (ipc|msg|shm_perm.mode). PARSE_DEF2 |
AUD_TP_IPC_UID | 256 | token:int (ipc|msg|shm_perm.uid). PARSE_DEF2 |
AUD_TP_TV_SEC | 257 | token:timeval.tv_sec (See
<sys/time.h> .) PARSE_DEF1 |
AUD_TP_TV_USEC | 260 | token:timeval.tv_usec (See
<sys/time.h> .) PARSE_DEF1 |
AUD_TP_SHORT | 261 | token:short. PARSE_DEF2 |
AUD_TP_LONG | 262 | token:long. PARSE_DEF5 |
AUD_TP_VNODE_DEV | 263 | token:int. PARSE_DEF2 |
AUD_TP_VNODE_ID | 264 | token:unsigned int. PARSE_DEF2 |
AUD_TP_VNODE_MODE | 265 | token:unsigned int. PARSE_DEF2 |
AUD_TP_VERSION | 266 | token:unsigned int (see
<sys/audit.h> ) (AUD_VERSION
| AUD_VERS_LONG).
PARSE_DEF1 |
AUD_TP_SET_UIDS | 267 | token:int. PARSE_DEF2 |
AUD_TP_CONT | 270 | token:unsigned int (A unique int for each component of a record.) PARSE_DEF1 |
AUD_TP_TID | 271 | token:long. PARSE_DEF4 |
AUD_TP_PRIV | 272 | token:unsigned short. PARSE_DEF1 |
The algorithm for reading a stream of audit records is as follows:
Open the audit log.
Find the first audit record (starts and ends with
AUD_TP_LENGTH
tuples).
Check that the record length matches the value in the
AUD_TP_LENGTH
tuple.
(If the length does not match, discard the
record.)
Retrieve the first tuple following the
AUD_TP_LENGTH
tuple.
If the tuple length is variable, determine the size of the data.
Extract the data.
Retrieve the next tuple, check the length if necessary, and extract the data.
Repeat until no more records.
Close the audit log.
The following macros illustrate
how
audit_tool
parses tuples.
The macros are provided for
reference purposes only; they illustrate one approach.
Note that
indx
values are maintained and used by
audit_tool
;
they are not part of the audit record tuple.
/* fixed length scalar value */ #define PARSE_DEF1(tokentype,field) \ bcopy (&rec_ptr[i+sizeof token], &field, sizeof(field)); \ i += (sizeof token + sizeof(field)); \ break; /* fixed length field in array */ #define PARSE_DEF2(tokentype,field,indx) \ if (indx < AUD_NPARAM) \ bcopy (&rec_ptr[i+sizeof token], &field[indx++], sizeof(field[0])); \ i += (sizeof token + sizeof(field[0])); \ break; /* array of strings */ #define PARSE_DEF3(tokentype,len,field,indx) \ bcopy (&rec_ptr[i+sizeof token], &j, sizeof(int)); \ if (j >= rec_len) j = 0; \ if (indx < AUD_NPARAM) { \ len[indx] = j; \ field[indx++] = (char *)&rec_ptr[i+(sizeof token)+(sizeof *intp)]; \ } \ i += (sizeof token + sizeof *intp + j); \ break; /* fixed length scalar value whose size is h/w dependent (32 or 64-bit) */ #define PARSE_DEF4(tokentype,field) \ bzero (field.val, sizeof(field.val)); \ j = af->version & AUD_VERS_LONG ? sizeof(int)*2 : sizeof(int); \ bcopy (&rec_ptr[i+sizeof token], field.val, j); \ i += (sizeof token + j); \ break; /* fixed length field in array whose size is h/w dependent (32 or 64-bit) */ #define PARSE_DEF5(tokentype,field,indx) \ bzero (field[indx].val, sizeof(field[indx].val)); \ j = af->version & AUD_VERS_LONG ? sizeof(int)*2 : sizeof(int); \ if (indx < AUD_NPARAM) \ bcopy (&rec_ptr[i+sizeof token], field[indx++].val, j); \ i += (sizeof token + j); \ break; /* array of opaque data streams */ #define PARSE_DEF6 PARSE_DEF3 /* iovec element in array */ #define PARSE_DEF7(tokentype,field,indx) \ j = sizeof(field[0]); \ if (indx < AUD_NPARAM) { \ bcopy (&rec_ptr[i+sizeof token], &j, sizeof(int)); \ if (j > rec_len ) j = 0; \ bcopy (&rec_ptr[i+sizeof token+sizeof(int)], &field[indx++], j); \ } \ i += (sizeof token + sizeof(int) + j); \ break; /* array of iovec elements with variable length components */ #define PARSE_DEF8(tokentype,field,ptr,indx) \ j = sizeof(field[0]); \ if (indx < AUD_NPARAM) { \ bcopy (&rec_ptr[i+sizeof token], &j, sizeof(int)); \ if (j > rec_len) j = 0; \ bcopy (&rec_ptr[i+sizeof token+sizeof(int)], &field[indx], j); \ ptr[indx++] = ((struct aud_xdata *) \ &rec_ptr[i+sizeof token+sizeof(int)])->xdata; \ } \ i += (sizeof token + sizeof(int) + j); \ break;