Logging & Auditing
Auditd
Recording security-relevant syscalls with audit rules.
System logs record what services choose to report. The audit subsystem records what you tell the kernel to watch, at the syscall level, whether or not any application cooperates. That difference is the whole point: an attacker can avoid writing to a log file, but they cannot avoid making the syscall that opens /etc/shadow or executes a binary. auditd sits in the kernel’s path and captures those events with full attribution (which user, which process, which time), which makes it the backbone of Linux incident forensics and a requirement in most compliance regimes.
This page covers the rule syntax, a practical starter ruleset, and how to search the events you collect.
Installing and the two rule types
The auditd daemon collects records the kernel emits; auditctl loads rules; ausearch and aureport query the log.
sudo apt-get install -y auditd audispd-plugins
systemctl is-active auditd
Expected output:
active
Audit rules come in two kinds, and knowing which to reach for is most of the skill.
| Rule type | Watches | Syntax starts with | Use for |
|---|---|---|---|
| File watch | Access to a path (read, write, attribute change, execute) | -w /path -p perms | Sensitive files and directories |
| Syscall rule | A specific system call, optionally filtered by argument | -a action,filter -S syscall | Behaviors like execve, chmod, mount |
A file watch is the simpler form: watch a path for a set of permissions and tag matches with a key. A syscall rule is more general: trigger on a named syscall, optionally narrowed by fields such as the calling UID or a file argument.
Rule syntax
A file watch declares a path, the permissions to catch (r read, w write, x execute, a attribute change), and a -k key for later searching.
-w /etc/shadow -p wra -k identity
A syscall rule declares an action and filter (-a always,exit means log on syscall exit), one or more syscalls with -S, optional field filters, and a key.
-a always,exit -F arch=b64 -S execve -F euid=0 -k root-commands
That rule logs every command executed with an effective UID of 0. The -F arch=b64 field is important: on a 64-bit system you generally add matching b64 and b32 rules so a 32-bit binary cannot slip past.
A practical starter ruleset
Rules live in /etc/audit/rules.d/ and are compiled into /etc/audit/audit.rules at load. A focused starter set watches the things attackers reliably touch without drowning you in noise.
sudo tee /etc/audit/rules.d/hardening.rules > /dev/null <<'EOF'
## Identity and auth files
-w /etc/shadow -p wra -k identity
-w /etc/passwd -p wra -k identity
-w /etc/sudoers -p wra -k scope
-w /etc/sudoers.d/ -p wra -k scope
## Commands run as root
-a always,exit -F arch=b64 -S execve -F euid=0 -k root-commands
-a always,exit -F arch=b32 -S execve -F euid=0 -k root-commands
## Loading and unloading kernel modules
-a always,exit -F arch=b64 -S init_module -S delete_module -k modules
## Changes to time
-a always,exit -F arch=b64 -S adjtimex -S settimeofday -k time-change
## Make the config immutable until reboot (must be last)
-e 2
EOF
sudo augenrules --load
sudo auditctl -l | head -n 4
Expected output:
-w /etc/shadow -p rwa -k identity
-w /etc/passwd -p rwa -k identity
-w /etc/sudoers -p rwa -k scope
-a always,exit -F arch=b64 -S execve -F euid=0 -k root-commands
The final -e 2 makes the ruleset immutable: rules cannot be changed until the next reboot, so an attacker who reaches root cannot quietly disable auditing. This tamper resistance is what the Overview meant by log integrity, applied at the kernel level.
Searching events with ausearch and aureport
Every rule tagged a -k key, and that key is how you retrieve events. Suppose someone edited /etc/shadow. Search by key:
sudo ausearch -k identity --start today | head -n 12
Expected output:
time->Sun Jul 6 10:22:31 2026
type=SYSCALL msg=audit(1751797351.442:812): arch=c000003e syscall=257 success=yes exit=3
a0=ffffff9c a1=5583a2 a2=241 a3=1b6 items=1 ppid=1980 pid=2044 auid=1000 uid=0 gid=0
euid=0 comm="vi" exe="/usr/bin/vim.basic" key="identity"
type=PATH msg=audit(1751797351.442:812): name="/etc/shadow" ...
The record ties it together: auid=1000 is the original login user (the audit UID survives sudo and su, which is why it is more trustworthy than uid), comm="vi" and exe show the tool, and the timestamp pins it. auid is the field forensics relies on because it cannot be masked by escalating privilege.
For a summary rather than raw events, aureport rolls things up.
sudo aureport --executable --summary --start today | head -n 6
Expected output:
Executable Summary Report
=========================
total file
=========================
418 /usr/bin/bash
77 /usr/bin/sudo
Use ausearch to drill into a specific key or user and aureport to get the shape of activity over a window. Both read the same /var/log/audit/audit.log, which should itself be forwarded off-host as covered in System Logs.
Practical Guidance
- Start with a focused ruleset watching identity files, root command execution, module loading, and time changes rather than auditing everything and drowning in noise.
- Tag every rule with a meaningful
-kkey, since keys are how you retrieve related events later withausearch -k. - Add both
b64andb32syscall rules on 64-bit hosts so a 32-bit binary cannot evade the rule. - Set
-e 2to make the ruleset immutable until reboot, so an attacker with root cannot silently disable auditing. - Trust
auidoveruidin investigations, because the audit login UID survivessudoandsuand ties actions to the real person. - Forward
/var/log/audit/audit.logoff the host and watch its size, since verbose rules can fill a disk and lose events under load.