Handbook sections▾
Foundations
Understanding the threats to a Linux hostWhy we hardenThe defense principles behind every ruleEffective configuration: the truth no file holdsThe standards Pavois maps toSOCLE control ID modelEvidence & exportsHow the A-E grade is computedWhat a PASS proves: the qualified verdictTrust model for the evidence bundleIs SOCLE just your own norm? (governance & the circularity question)What Pavois covers, and what it doesn'tDomains
Hardening SSHHardening PAMMandatory Access Control (SELinux / AppArmor)Hardening the host firewallHardening sudoFile Permissions & OwnershipMount & filesystem hardeningHardening kernel modulesHardening the kernel & network with sysctlAudit logging with auditdHardening logging with journald and rsyslogHardening systemd servicesPackage hygieneHardening the bootloader (GRUB)Synchronizing timeLogin banners and MOTDControlling cron and at accessHardening the GNOME desktop (dconf)Tooling
Undo a hardening run: restore pointsOperating Pavois: privileges, air-gap, timing, exceptionsRun Pavois in CI (GitHub Actions)Feature status: delivered, partial, roadmapGovernance: licence, versioning, provenance, securityAudit logging with auditd
Last reviewed
Without a tamper-resistant audit trail you cannot say who did what. auditd records, inside the kernel, privileged commands, identity and permission changes, time changes and module loads, for accountability and forensics.
Who did what, and when?
Without a tamper-resistant audit trail you cannot answer the first question after an intrusion: who did what, and when. The Linux audit subsystem (auditd) is the kernel-backed witness that records security-relevant events as the kernel sees them, independent of any application's own logging. An attacker who lands a foothold will escalate privileges, add or modify accounts, change permissions, load a kernel module (a rootkit, a packet sniffer), roll the clock to scramble timestamps, then delete the application logs. If those actions leave no kernel-level record, the incident is invisible. auditd is the record that survives a hostile process.
Why harden auditd
Application logs lie by omission: a process can simply not log, or be killed before it does. auditd records syscalls and file accesses inside the kernel, so it captures the privileged action even when the offending program is hostile. A correct ruleset gives you three things:
- Accountability : every record carries the login UID (
auid), which survivessu/sudo, so an action is tied to the real human behind it, not just the effective root identity. - Forensics : a precise, timestamped sequence of who changed what, the backbone of any incident investigation.
- Tamper resistance : an immutable ruleset (
-e 2) cannot be silently unloaded by an attacker without a reboot, which is itself a loud, auditable event.
A host with auditd installed but no rules loaded is a common false sense of security: the daemon runs, yet records nothing of interest.
The three layers of the Linux audit framework
| Layer | Role |
|---|---|
| Kernel audit subsystem | generates events at the source (syscalls, file access) |
auditd (user-space daemon) |
receives events and writes /var/log/audit/audit.log |
auditctl / ausearch / aureport |
load rules, search and summarize events |
Events are generated in the kernel, so an attacker who modifies a file cannot stop the event from being emitted. This is the source of truth a hardened host needs, and the control required by the CIS Benchmarks and ANSSI BP-028 (recommendation R73, audit-log the system activity). Note that the audit subsystem is not namespaced: it does not work inside a container (LXC, Docker), so auditd is run on a VM or bare metal.
What Pavois audits: the effective, loaded ruleset
Pavois reads the live, loaded ruleset with auditctl -l, the rules the kernel is enforcing right now, rather than parsing /etc/audit/rules.d/*.rules. This is the effective-config principle that sets Pavois apart: a rule file on disk that was never loaded (no augenrules --load, a syntax error, a rejected syscall) makes a file scanner (OVAL/oscap) falsely pass while the kernel audits nothing. auditctl -l reflects reality.
Each rule checks that a rule bearing the expected key (-k) is loaded. Across its auditd rules Pavois covers: time changes (adjtimex/settimeofday/clock_settime), identity and privilege (/etc/passwd, /etc/group, /etc/shadow, sudoers, and setuid/setgid use), permission and MAC-policy changes (chmod/chown/*xattr, SELinux/AppArmor), kernel module loading (init_module/finit_module/delete_module), privileged commands and admin actions, file deletions, the audit log directory itself, and the immutable flag (-e 2) that finalizes the ruleset.
How do you verify and operate auditd?
- Check the subsystem is live with
auditctl -s:enabled 1confirms the kernel is auditing andauditdruns (non-zeropid); watchlost(events dropped) andbacklog.enabled 0or a failing command (you are likely in a container) means nothing is recorded. - List the enforced rules with
auditctl -l. The control directives-D,-b,-fdo not appear there, by design; a non-zero count confirms the load, and a rejected rule silently lowers it. - Persist rules in
/etc/audit/rules.d/*.rules, compiled byaugenrules --load. Files load in sort order (10-base,30-rules,99-the-e 2lock) and the kernel applies first-match-wins.auditctl -Rloads rules in memory only, lost at the next boot: production always goes throughrules.d. - Double every syscall rule in
arch=b32ANDarch=b64: on a 64-bit host, a 32-bit binary can invoke the same syscall via the 32-bit ABI and escape ab64-only rule (the32/64 bit syscall mismatchwarning). - Size the backlog (
-b, for example 8192) so events are not dropped under load;auditctl -sshowinglost > 0means the kernel queue overflowed. - Choose the disk-full action deliberately in
auditd.conf:space_left_actionand especiallyadmin_space_left_actioncan behaltorsingle, so a saturated audit partition can stop the machine. Isolate/var/log/auditon its own partition and set rotation (max_log_file,max_log_file_action = ROTATE).log_format = ENRICHEDresolves UIDs and syscalls before writing, which matters for a SIEM. - Lock it for production with
-e 2(immutable): anyauditctlchange is then refused until a reboot. Enable it only once the ruleset is stable.
Pitfalls
ausearch -kis unreliable without-if. On Debian and RHEL,ausearch -k <key>often returns<no matches>while the events are in the log; always force the input file:ausearch -if /var/log/audit/audit.log -k <key>. The same applies toaureport.- Use
auid, notuid, for accountability:auidstays the login session's user even aftersu/sudo, which is exactly what answers who is behind an action. -e 2needs a reboot to change. Pavoisharden applywrites the missing rules to a managed drop-in under/etc/audit/rules.d/and loads them, but immutability is fully effective only after a reboot.
Coverage and gaps
Pavois verifies the presence of the keyed rules in the live ruleset (the CIS / ANSSI control set). It does not yet score auditd.conf tuning (admin_space_left_action, rotation, log_format = ENRICHED) nor remote-forwarding integrity via audisp; those are operator decisions, documented in the verify section above rather than failed.
FAQ
Does auditd work in a container? No. The audit subsystem is global to the host and not namespaced; run it on a VM or bare metal.
Why does Pavois read auditctl -l instead of the rule files? Because only the loaded ruleset is what the kernel enforces. A rule file present but never loaded protects nothing, and Pavois audits the effective state.
What does -e 2 change? It makes the ruleset immutable until the next reboot, so an attacker who gains root cannot silently disable auditing without a reboot, itself a visible, auditable event.