Contact
Impressum
Why this name?
pdf

audit-filter.conf

NAME

filter.conf, filesets.conf - auditd(8) filter configuration files

DESCRIPTION

Auditd collects audit records generated by the kernel system call audit mechanism, and writes them to disk. To avoid slowing down the system too much, and swamping the logs with useless information, the administrator can configure auditd to log only those events he is interested in. For better performance, these rules are evaluated inside the kernel.

The kernel audit framework will generate messages in response to various events. The most common events are system calls, but there are other events as well, such as process termination. Each of these events can be logged unconditionally, or not at all, or depending on a filter.

A filter is a Boolean expression, using standard operators such as AND, OR, and NOT. The individual terms of an expression are called predicates, which get applied to the system call arguments, and various properties of the process performing the call, such as its process uid. The value a predicate is applied to is called a target.

The filters are commonly defined in filter.conf and the target sets of files are defined in filesets.conf, however the different filenames may be chosen using the include directive.

Introductory Examples
In order to understand the filter syntax, it is probably easiest to look at examples first.

The following statements will cause the audit subsystem to log all calls to chroot(2), and all attempts to create a directory in /etc:

syscall chroot = always;
predicate is-etc = prefix(/etc);
syscall mkdir = is-etc(arg0);

The syscall declares what filters to attach to a system call. In the case of chroot, this is the built-in filter that always matches. The second part contains a more complex filter that inspects a system call argument when deciding whether to log this call or not. We first defined a predicate that tests whether the argument (interpreted as a path name) has a prefix of /etc. The syscall statement then applies this predicate to the first argument of the mkdirsystemcall.

If we decide to monitor all directory operations within the directory /etc, we could change the example above to look like this:

predicate is-etc = prefix(/etc);
set dir-ops = {
mkdir, rmdir, creat, unlink, chmod, chown, lchown,
chown32, lchown32
};
syscall @dir-ops = is-etc(arg0);

predicate is-write-access = mask(O_CREAT, O_CREAT)
|| !mask(O_ACCMODE, O_RDONLY);
syscall open = is-etc(arg0) && o-creat(arg1);

This will create a single filter that tests whether the first system call argument has a prefix of /etc, and attach this filter to all system calls mentioned in the dir-ops set. The second part of the example creates a filter to to catch all write accesses to files inside the directory using open(2). The mask operator will be explained in the following section. One item worth noting here is the use of symbolic constants such as O_RDONLY. The filter expression parser understands a (limited) set of integer constants, in order to make writing filter expressions more portable and less error-prone.

Applying Predicates
As shown in the examples above, the approach taken here is to define predicates first, possibly combining several operations, and applying this expression to a target such as a system call argument.

The reason for this is that it is more efficient to retrieve the target data once, and perform various tests on it, than the other way round. For instance, it is very common to extract the path name argument of a system call, and check it against a list of directory names to see whether the call should be logged or not.

Another reason is that you may want to define a predicate that is applied to different targets, for instance different positional arguments of a system call.

FILTER SYNTAX

As described above, a filter is a Boolean expression built using the standard operators. They are denoted && (logical AND), || (logical OR), and ! (logical negation).

The constituent terms of an expression are predicates, and filters. A predicate is an open expression, in the sense that it must be applied to some target to become valid. For instance, eq(0) is a predicate testing for equality with zero.

A filter, on the other hand, is a closed expression, in the sense that it doesn’t require a target.

Built-in Predicates
The Linux Audit Subsystem currently supports the following set of built-in predicates:
Integer Comparison

These are the usual comparison operators, denoted by eq, ne, lt, le, ge, and gt. These predicates must be followed by an integer constant in brackets, for instance lt(123). It is not allowed to use a target in this context, i.e. lt(arg1)is not valid.

In addition, there is the mask predicate, which performs a masked comparison. It takes two integer constants m, and v. When applied to a target x, the expression evaluates to true iff (x & m) == v.

String Comparison

Currently, string targets can be matched using the streq and prefix predicates. Both must be followed by a single string constant in brackets. If the string contains special characters (such as brackets, white space, comma, semicolon, etc), it must be enclosed in double quotes. Otherwise, quoting is optional.

The streq predicate tests for string equality.

The prefix predicate checks if file’s path name starts with the given prefix.

Special Operators

There is currently one special operator, return. When the kernel encounters the return operator while processing a filter expression, processing will abort immediately, and the indicated value is returned, which can be one of log, log-verbose, or ignore. The first two instruct the kernel to generate an audit record, optionally including additional information in the record. The third causes the event to be ignored, and no record to be written.

True and false

There are also constant expressions true, and false, which always evaluate to true and false, respectively. Alternatively, one can use always, and never.

User-Defined Predicates
In addition to these built-in predicates, a filter expression may reference user-defined predicates and filters by name.

User-defined predicates can be applied to a target. The notation closely resembles that of a function call in most programming languages: predicate(target).

Note that it is not possible to apply a built-in predicate directly to a target, as in eq(0)(dumpable). This is not valid.

Predicates and filters must be defined before they can be referenced, and you cannot redefine a predicate or filter.

Supported Targets
The Linux Audit Subsystem currently supports filter expressions matching attributes of a system call (arguments and return value), properties of the current process (uid, gid etc), file attributes (if a system call argument represents a file), socket attributes, and values related to netlink messages.

Each target has a specific type, the basic types are integer (usually unsigned, except where noted), strings, and files. For instance, system call arguments representing a file descriptor or a path name are represented as file targets by the kernel.

The operations that can be performed on a target are restricted by the type. For instance, integer comparisons on file objects or strings are not allowed. However, type checks are not enforced until the kernel actually tries to evaluate the filter. If the kernel detects an invalid predicate/target type combination, it will treat the filter as if it had matched, and log the event.

Some targets have to be ‘‘nested’’. For instance, in order to create a filter expression that evaluates the owner of the file accessed by a system call, you first need to create an expression that applies a predicate to the file-mode target, and then apply this new predicate to the system call argument.

The following list covers all targets currently supported:
System Calls

System call arguments can be referenced using arg0, arg1, etc. The type of the argument depends on the context.

System call arguments representing a file (that is, file names as well as file descriptors) are treated specially. When the kernel audit module analyzes a system call argument of type file, it will look up its canonical path name. Relative path names will be converted to absolute ones, and symbolic links as well as ../ referrals will be eliminated (in other words, an operation very similar to realpath(3) is performed). The resulting string can be used in string comparisons and path prefix matches. However, in addition to the file’s name, individual file attributes such as owner, group and permission bits etc can be matched as well.

The system call return code is referenced by result, which is a signed quantity.

A few special system calls on Linux share a common entry point, for instance socketcall, which is the shared entry point for the BSD socket API (socket, connect, accept, etc), and ipc, which is the entry point for all calls related to the System V IPC framework. To distinguish between the various calls sharing the same entry point, the syscall-minor target can be used. However, this should rarely be required, as filter expressions attached to accept, connect, etc for instance, will be combined transparently by the filter configuration file parser.

Process Attributes

The process attributes currently supported are the current (real) uid and gid, the dumpable flag, and exitcode, representing the process’ exit status, and login-uid. This is the user-id associated with the session when the user logs in, and does not change when running set-user-id applications or using su(8).

The dumpable flag’s original purpose was to indicate whether the kernel is allowed to generate a core dump in case the process crashes. Normally, this flag is 1. If the process executed a setuid or setgid binary, or changed its identity using a system call such as setuid(2), the flag will be cleared.

Nowadays, the dumpable flag is being used as a general purpose indicator that a process has undergone privilege changes, and restricts other operations (such as ptrace) as well, and can thus be a useful in an audit filter expression to identify processes that may warrant closer observation (for instance, in an IDS context, it may be useful to record all execve system calls made by setuid/setgid processes).

File Attributes

These targets can only be used in building predicates that will be applied to file targets. They include file-mode, file-uid, file-gid, file-dev, and file-ino, which correspond to the familiar inode attributes known from e.g. the stat(2) system call. In addition, there are dev-major, and dev-minor, which are valid only for block and character device files, and represent the device’s major and minor number.

Socket Attributes

These targets can only be used in building predicates that will be applied to file targets, and only if this file is a socket. They currently include sock-family, and sock-type.

Netlink Attributes

These targets are valid only when used in a filter expression attached to the netlink event, which is generated whenever an application sends an rtnetlink message to the kernel. These messages are used to change and retrieve the network configuration.

Currently, this covers netlink-family, netlink-type, and netlink-flags.

Other Targets

When filtering user messages and login events, the filter may also contain the target event-name. This will match the event name against a given string. For login events, the name is always AUDIT_login.

It is not possible to filter for the messages generated by auditd when starting or stopping the audit subsystem (these are the AUDIT_start and AUDIT_stop messages), as these messages are processed within the audit daemon, and are not processed by the kernel.

Using Sets
In a filter configuration file, you can define sets of constants (strings or integers) that can the be referenced in predicates. For instance, you can define a set of sensitive directories, and want to log system calls that access files in these directories. This could be done as follows:

set sensitive = {
/etc, /root, /usr
};
# This predicate returns true if target is below any
# of the directories listed in the set above:
predicate is-sensitive = prefix(@sensitive);
#
# Log system calls accessing sensitive files
syscall chown = is-sensitive(arg0);
syscall link = is-sensitive(arg0) || is-sensitive(arg1);

When a predicate is applied to a set of values, the expression is expanded to an inclusive OR, with the attribute being applied to each value in the set. Sets are allowed to reference other sets.

SYSTEM CALL EVENTS

To audit for system call events, simply attach a filter using

syscall name = filter;

It is also possible to attach a filter to a set of system calls.
For instance, you can define a single filter expression and use that for similar system calls:

set privilege-ops = { setuid, setgid, setreuid, ... };
syscall @privilege-ops = always;

Care should be taken to use the correct spelling of system calls, as incorrectly spelt names will be ignored (the intent is to make configuration files more portable between platforms).

OTHER EVENTS

The audit subsystem allows to filter for a set of other events which are not system calls. Filtering for these can be specified using

event name = filter;

The following event names are supported at the moment:
process-login

Generated whenever a process calls the audit login method, which creates a new user session. It should be noted that these messages do not have a return value.

process-exit

Generated when a process terminates. This is not the same as attaching a filter to the exit system call, as that does not include abnormal termination due to signals.

user-message

Whenever a process tries to send a user message to the audit daemon, it is subjected to this filter. This allows to filter for specific messages using the event-name target. It should be noted that user-messages do not have a return value.

network-config

Generated when the audit subsystem receives a netlink message that modifies the network configuration.

TAGGING EVENTS

It is possible to attach an event name to a filter expression, or event. These event names will be copied to the audit record, and provide an efficient way to selectively view audit records (see augrep(1)).

Event names may be up to 15 characters, and can be defined as follows:

tag "PROC_privilege"
syscall setuid = always;

This will log all calls to setuid and include the tag PROC_privilege.

Similarly, tags can be attached to filters and predicates by preceding the filter or predicate statement with the tag command.

INCLUDING OTHER CONFIGURATION FILES

The configuration file syntax also supports including other configuration files to allow you to organize your filter rules logically into modules.

include "filename.conf";

The filename can be relative to the location of audit.conf or the full path to the desired configuration file.

CAVEATS

It should be noted that one some platforms, there may be several variants of one system call, and care must be taken to include all of them. Probably the most prominent example is the setuid(2) call on the 32-bit Intel platform. Here, the C library will map the library call to the setuid32 system call, as the original setuid call is obsolete, as it supports only 16-bit user-IDs. Similarly, there are 32-bit variants of seteuid, setgid, etc, as well as chown and lchown.

SEE ALSO

laus(7), audit.conf(5), aucat(1), augrep(1).

AUTHORS

auditd was written by Olaf Kirch <okir AT suse DOT de>

pdf
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                       

No Banana Union - No Software Patents