# auditd: file access and syscall logging

LLMS index: [llms.txt](/en/llms.txt)

---

Linux doesn't write every access to `/etc/shadow` or every `unlink` call to syslog. For incident investigation and compliance this is critical. auditd solves this: the Linux Audit kernel subsystem records system calls, file access, and more.

## Installation and Startup

auditd comes in the `audit` package available in any distribution.

```bash
# Debian/Ubuntu
apt install auditd

# RHEL/CentOS/Alma
yum install audit

# Arch
pacman -S audit
```

After installation, start the service via systemd.

```bash
systemctl enable --now auditd
```

Check status and current rules:

```bash
systemctl status auditd
auditctl -l
```

> [!NOTE]
> On RHEL-based distributions with SELinux enabled, you may need to adjust policies for auditd to work with non-standard paths. Standard installation usually covers most cases.

## File Monitoring: the -w Flag

The `-w` flag adds a watch rule for a file. By default it tracks open, read, write, truncate, chmod, and chown.

```bash
# Watch the password file
auditctl -w /etc/shadow -p rwxa -k shadow_access

# Watch the nginx config directory
auditctl -w /etc/nginx/ -p rwxa -k nginx_config
```

| Flag | Meaning |
|------|---------|
| `-w` | path to watch |
| `-p` | permissions: r(read), w(write), x(execute), a(append) |
| `-k` | keyword for searching in logs |

Verify rules:

```bash
auditctl -l
```

Remove a rule by key:

```bash
auditctl -W /etc/shadow -p rwxa -k shadow_access
```

Rules added via `auditctl` don't survive reboots. For persistence, write rules to `/etc/audit/rules.d/`:

```bash
echo "-w /etc/shadow -p rwxa -k shadow_access" >> /etc/audit/rules.d/audit.rules
```

On RHEL, rules load from `/etc/audit/audit.rules` via the `augenrules` script. Same works on Debian/Ubuntu.

## System Call Logging: the -S Flag

The `-S` flag records the specified system call for all processes or with filters.

```bash
# Log file deletions
auditctl -S unlink -S unlinkat -k file_deletion

# Log socket creation
auditctl -S socket -k network_socket
```

Check available system calls with `ausyscall --dump`. Not all calls are available on every architecture — on x86_64 some go through the compat layer.

> [!WARNING]
> Excessive syscall monitoring generates massive log volume. On production servers, limit rules with filters.

Combined rule — syscall plus path:

```bash
# Only deletions from /var/log/
auditctl -S unlink -S unlinkat -w /var/log/ -p wa -k log_deletion
```

## Filtering by UID and Executable

Without filters, rules apply globally. Add conditions for targeted monitoring.

```bash
# Only rm executions by www-data user
auditctl -S execve -a always,entry -F arch=b64 -F uid=33 -F exe=/usr/bin/rm -k rm_by_www

# All access() calls to file from any uid
auditctl -a always,entry -S access -F path=/etc/shadow -F perm=r -k shadow_read
```

Core filter fields:

| Flag | Description | Example |
|------|-------------|---------|
| `-F` | field to compare | `-F uid=1000` |
| `arch` | architecture (b32/b64) | `-F arch=b64` |
| `uid` | real UID | `-F uid=33` |
| `euid` | effective UID | `-F euid=0` |
| `exe` | full path to executable | `-F exe=/bin/bash` |
| `perm` | access permissions | `-F perm=awx` |

Combine filters into a chain via `-a`:

```bash
auditctl -a always,entry -S openat -F dir=/etc -F perm=w -F uid=0 -k etc_write_root
```

## Reading Logs: ausearch

Logs live in `/var/log/audit/audit.log`. Binary format, read with `ausearch`.

```bash
# Search by keyword
ausearch -k shadow_access

# Search by time (today, last hour)
ausearch -k shadow_access -ts today
ausearch -k shadow_access -ts recent

# Search by user
ausearch -k shadow_access -ui 0

# Search by event type
ausearch -m SYSCALL -k file_deletion

# Filter by result (success/failure)
ausearch -k shadow_access -sv success
ausearch -k shadow_access -sv failed
```

Useful output formats:

```bash
# Raw text (default)
ausearch -k shadow_access -i

# CSV for parsing
ausearch -k shadow_access --format csv
```

> [!TIP]
> For automation, use `-if` (input file) — read from a dump instead of the live log:
> ```bash
> ausearch -if /tmp/audit_events.dump -k shadow_access
> ```

## Reading Logs: aureport

aureport aggregates logs into readable reports.

```bash
# Summary of all events
aureport

# System call report
aureport -s

# File event report
aureport -f

# User report
aureport -u

# Timeline report
aureport -t

# Errors and failures only
aureport --failed
```

Typical `aureport -s` output:

```
Syscall Report
============================================
UID        Syscall    Count
--------------------------------------------
0          unlink      12
0          openat      8
33         unlink      3
```

Quick investigation combo — summary then details:

```bash
aureport -t -i | head -20
ausearch -k file_deletion -ts recent | less
```

For SIEM or ELK ingestion, convert logs to JSON or text:

```bash
ausearch -k shadow_access --format json > /var/log/audit/shadow_access.json
```

auditd doesn't require complex setup to start capturing critical events. Install the package, add a few rules with keywords, and get comfortable with ausearch and aureport for log review.
