Audit rules¶
Synopsis¶
auditctl [-D] [-b N] [-f 0|1|2] [-e 0|1|2] [-r N] [--backlog_wait_time N]
auditctl -a LIST,ACTION [-F arch=b64|b32] [-S SYSCALL[,SYSCALL…]] [-F FIELD OP VALUE]… [-C F1 OP F2] [-k KEY]
auditctl -A LIST,ACTION … (insert at the start of the list)
auditctl -d LIST,ACTION … (delete a matching rule)
auditctl -w PATH [-p rwxa] [-k KEY] (deprecated watch form)
auditctl -l | -s | -D | -R FILE | -v
A rules file (/etc/audit/audit.rules, /etc/audit/rules.d/*.rules) contains one auditctl argument list per line, without the command name; # starts a comment.
Description¶
The Linux kernel's audit subsystem checks system calls and other events against a set of rules and, for each match, produces records that the audit daemon auditd writes to /var/log/audit/audit.log.
auditctl configures the kernel side: it adds and removes rules and sets control parameters.
Rules live only in kernel memory, so a service loads them from a file at boot.
Every record of one event shares a timestamp and serial number, for example audit(1794059314.608:108).
Rules on the exit list are evaluated in order and the first matching rule decides, so never rules that suppress noise go before the always rules they would otherwise affect.
Checked against audit 4.0.2 on Debian 13, 4.1.2 on Ubuntu 26.04, 4.0.3 on AlmaLinux 10 and Rocky Linux 10, 4.2.1 on Arch Linux and 4.1.4 on Gentoo (November 2026).
Availability¶
| Family | Packages | Installed by default | Service | How rules are loaded at boot |
|---|---|---|---|---|
| Debian, Ubuntu | auditd (daemon, auditctl, augenrules, ausearch, aureport) |
No | auditd.service, enabled on installation |
audit-rules.service runs augenrules --load |
| RHEL, AlmaLinux, Rocky Linux | audit (daemon, ausearch, aureport), audit-rules (auditctl, augenrules, audit-rules.service) |
audit yes; audit-rules not in every image |
auditd.service, enabled and running |
audit-rules.service runs augenrules --load |
| Arch Linux | audit |
Yes | auditd.service, not enabled |
audit-rules.service runs augenrules --load; auditd.service wants it. /etc/audit/rules.d/ is empty, so the generated rules have no -D until a base file such as 10-base-config.rules is copied in |
| Gentoo | sys-process/audit |
No | OpenRC auditd init script |
The init script runs auditctl -R on RULEFILE_STARTUP (default /etc/audit/audit.rules), set in /etc/conf.d/auditd; the file isn't generated from rules.d |
On the RHEL family and Arch, auditd.service has RefuseManualStop=yes, so systemctl stop and systemctl restart are refused; on Debian and Ubuntu it doesn't. On every systemd distribution, rules are reloaded with augenrules --load, without restarting the daemon.
On Gentoo with OpenRC, rc-service auditd reload_rules reloads the rules file.
Control rules¶
| Option | Effect |
|---|---|
-D |
Delete every rule and watch |
-b N |
Maximum number of outstanding audit buffers in the kernel (the backlog) |
--backlog_wait_time N |
Time the kernel waits for backlog space before applying the failure mode |
-f 0\|1\|2 |
Failure mode when records can't be delivered: 0 silent, 1 log to the kernel log (printk), 2 panic |
-e 0\|1\|2 |
0 disable auditing, 1 enable, 2 enable and lock the configuration until reboot (immutable) |
-r N |
Maximum records per second; 0 is no limit |
-c |
Continue loading a rules file after an error |
-i |
Ignore errors when reading rules from a file |
--loginuid-immutable |
Make the login UID unchangeable once set |
-s |
Print the status: enabled, failure, pid of the daemon, backlog_limit, lost, … |
-l |
List the loaded rules |
-R FILE |
Read rules from a file |
Rule lists and actions¶
| List | Evaluated |
|---|---|
exit |
When a system call returns; file and system call rules go here |
task |
When a process is created (fork, clone); only fields known at that time can be used |
user |
For events sent from user space; filters them before they reach auditd |
exclude |
For every event; removes events by type (msgtype) or subject. The action is always never |
filesystem |
For whole filesystems, selected with fstype (debugfs, tracefs) |
io_uring |
For operations submitted through io_uring |
| Action | Effect |
|---|---|
always |
Record a matching event |
never |
Don't record it, and stop evaluating the list |
Fields¶
-F FIELD OP VALUE adds a condition. Operators: =, !=, <, >, <=, >=, & (bit test) and &= (all bits set). Quote rules containing < or > on a shell command line.
| Field | Meaning |
|---|---|
arch |
System call ABI: b64, b32, or a machine name such as x86_64. Give it with -S, because syscall numbers depend on it |
path |
A file to watch (inode-based); with perm |
dir |
A directory tree to watch, recursively, stopping at mount points; with perm |
perm |
Access types for path/dir: r read, w write, x execute, a attribute change |
auid |
Audit (login) user ID, kept across su and sudo; unset (shown as -1) for processes not started from a login |
uid, euid, suid, fsuid |
Real, effective, saved and filesystem user ID; names or numbers |
gid, egid, sgid, fsgid |
The corresponding group IDs |
pid, ppid |
Process ID, parent process ID |
exe |
Absolute path of the executable; = and != only |
success |
1 if the system call succeeded (return value ≥ 0), 0 if it failed |
exit |
The return value, or an error name such as -EACCES |
key |
The filter key, as with -k |
msgtype |
Record type, such as AVC or CWD; for the exclude and user lists |
filetype |
Type of the target: file, dir, socket, link, character, block, fifo |
obj_uid, obj_gid |
Owner of the object |
subj_type, obj_type (and _user, _role, _sen, _clr, _lev_low) |
SELinux labels of the process and of the object |
sessionid |
Login session ID |
a0 … a3 |
The first four system call arguments |
-C FIELD OP FIELD compares two fields of the same event, for example -C auid!=obj_uid (files accessed by someone other than their owner).
-S takes a system call name or number, a comma-separated list, or all; several -S options in one rule are also accepted.
ausyscall x86_64 <NAME> shows the number of a system call; ausyscall --dump lists them all.
Keys¶
-k KEY (or -F key=KEY) tags every event a rule produces, so it can be found with ausearch -k and counted with aureport -k.
A key is up to 31 bytes long; several rules can share a key, and one rule can have several.
auditctl -l shows keys in the -F key= form.
File rules¶
-a always,exit -F arch=b64 -F path=FILE -F perm=PERMS -k KEY
-a always,exit -F arch=b64 -F dir=DIRECTORY -F perm=PERMS -k KEY
-w PATH -p PERMS -k KEY (deprecated)
auditctl translates perm into the set of system calls that perform that kind of access for the given arch, which auditctl -l prints in full.
Without arch, the rule is evaluated for every system call, which is slower.
The -w form is kept for compatibility; current versions print Old style watch rules are slower when one is added.
The rules.d directory and augenrules¶
augenrules concatenates the files in /etc/audit/rules.d/ whose names end in .rules, in natural sort order (as ls -v), drops empty and comment lines, and writes the result to /etc/audit/audit.rules, replacing it only if it changed.
In the result, the last -D without an argument is moved to the first line, the last -b to the second, the last -f to the third, and the last -e to the end.
| Command | Effect |
|---|---|
augenrules --check |
Report whether audit.rules would change |
augenrules --load |
Regenerate audit.rules and load it into the kernel |
The RHEL family (in the audit-rules package) and Arch ship sample rule sets in /usr/share/audit-rules/ (for example 30-stig.rules, 30-pci-dss-v31.rules, 43-module-load.rules), meant to be copied into rules.d.
ausearch¶
| Option | Searches for |
|---|---|
-k, --key KEY |
Events with this key |
-m, --message TYPE[,TYPE…] |
Record types, such as AVC, USER_AVC, SYSCALL, USER_LOGIN, CONFIG_CHANGE |
-f, --file NAME |
A file name |
-x, --executable PATH |
An executable |
-c, --comm NAME |
A command name |
-p, --pid PID |
A process ID |
-ui, --uid UID; -ue, --uid-effective UID; -ul, --loginuid AUID; -ua, --uid-all UID |
A user ID, effective user ID, login user ID, or any of them |
-gi, --gid GID |
A group ID |
-sv, --success yes\|no |
Successful or failed events |
-sc, --syscall NAME |
A system call |
-se, --context CONTEXT; -su, --subject CONTEXT; -o, --object CONTEXT |
SELinux contexts |
-ts, --start [DATE] [TIME] |
Events at or after this time |
-te, --end [DATE] [TIME] |
Events at or before this time |
-a, --event ID |
An event serial number |
| Option | Output and input |
|---|---|
-i, --interpret |
Translate numbers (user IDs, system calls, flags) into names |
--format raw\|default\|interpret\|csv\|text |
Output format |
-r, --raw |
Unformatted records, as in the log |
--just-one |
Stop after the first matching event |
-if, --input FILE |
Search this file instead of the logs |
--input-logs |
Read the logs configured in auditd.conf even when standard input is a pipe (as in scripts and cron jobs); otherwise ausearch reads standard input when it isn't a terminal |
--checkpoint FILE |
Continue from the last event found in a previous run |
Dates and times follow the locale (date '+%x'); the time uses the 24-hour clock.
The keywords now, recent (ten minutes ago), this-hour, boot, today, yesterday, this-week, week-ago, this-month, this-year and checkpoint can be used instead.
aureport¶
| Option | Report |
|---|---|
| (none) | Summary of all event types |
-f, --file |
File accesses |
-k, --key |
Events per key |
-a, --avc |
AVC (access control) messages |
-ma, --mac |
Mandatory access control events |
-au, --auth |
Authentication attempts |
-l, --login |
Logins |
-m, --mods |
Account modifications |
-c, --config |
Audit configuration changes |
-x, --executable |
Executables |
-u, --user |
Users |
-s, --syscall |
System calls |
-e, --event |
Events |
-n, --anomaly |
Anomalies, such as promiscuous mode or crashing programs |
-t, --log |
Time range covered by each log file |
--summary turns a report into totals sorted by count, --failed and --success limit it, and -ts, -te, -i, -if and --input-logs work as in ausearch.
ausearch … --raw | aureport -f reports on the result of a search.
Examples¶
Record changes to /etc/sudoers and the files in /etc/sudoers.d/:
-a always,exit -F arch=b64 -F path=/etc/sudoers -F perm=wa -k sudoers
-a always,exit -F arch=b64 -F dir=/etc/sudoers.d -F perm=wa -k sudoers
Record every file deletion by users who logged in, but not by system services:
-a always,exit -F arch=b64 -S unlink,unlinkat,rename,renameat -F auid>=1000 -F auid!=unset -k delete
Record failed attempts to open files under /srv:
Make the configuration immutable until the next reboot (last line of the rules):
Search for today's events with the key sudoers, with readable values:
Files¶
| Path | Purpose |
|---|---|
/etc/audit/audit.rules |
Rules loaded at boot; generated by augenrules except on Gentoo |
/etc/audit/rules.d/*.rules |
Rule fragments read by augenrules |
/etc/audit/auditd.conf |
Daemon configuration: log file, format, rotation (max_log_file, num_logs), actions on low disk space |
/var/log/audit/audit.log |
The audit log |
/etc/conf.d/auditd |
Gentoo: rule files used by the OpenRC init script |
See also¶
auditctl(8),audit.rules(7),augenrules(8),ausearch(8),aureport(8),auditd(8),auditd.conf(5),ausyscall(8), from the audit 4.x packages listed above- Linux audit userspace project
Related¶
- How-to guide: How to audit access to a file
- How-to guide: How to troubleshoot SELinux or AppArmor denials
- Reference: PAM configuration
- Explanation: SELinux and AppArmor