In this section

Linux Kernel and eBPF for Security

4-5 hours · Module 1 · Free
What you already know

Sections 1.1 through 1.5 covered Windows — the process model, LSASS, the registry, ETW, and the security subsystem. This section moves to Linux. Endpoint security extends beyond Windows, and the 6 RHEL servers at NE have entirely different security architectures. The process model, privilege system, telemetry infrastructure, and attack surfaces are all different. Understanding where Linux differs — and where MDE's Linux sensor has less visibility than its Windows counterpart — is essential for building cross-platform endpoint security that does not leave blind spots.

Scenario

NE's RHEL manufacturing server runs a database application as root because it requires direct hardware interface access. The backup cron job also runs as root. An attacker compromises the web-facing application on a connected Ubuntu server and pivots to the RHEL host via SSH using a stolen service account key. On the RHEL server, the attacker is already root — no privilege escalation needed. The manufacturing database, the backup credentials, and the hardware interface are all immediately accessible. The server has no endpoint security agent, no auditd rules, and no eBPF-based monitoring. The compromise is invisible until the attacker's activity causes a production outage three weeks later.

The Linux process model from a security perspective

Linux processes share fundamental concepts with Windows — PID, parent PID, file descriptors, and an execution context — but differ in security-relevant ways. Every Linux process has a UID/GID (the user and group identity), a set of capabilities (fine-grained privileges that decompose root's monolithic power), and a namespace context that determines what the process can see and interact with.

The critical difference from Windows: Linux uses UID 0 (root) as the superuser with no equivalent to Windows' token-based privilege granularity or UAC prompts. Root can do everything. There is no integrity level system that distinguishes between a medium-integrity admin and a high-integrity admin. When a process runs as root, it has unrestricted access to the kernel, all files, all processes, and all network interfaces. This means privilege escalation on Linux is binary — either you are root or you are not — and the paths from unprivileged user to root are the core attack surface.

Linux capabilities provide partial decomposition of root's powers into 40+ individual capabilities: CAP_NET_RAW for raw socket access, CAP_SYS_PTRACE for debugging other processes, CAP_SYS_ADMIN for broad administrative operations including mounting filesystems and loading kernel modules. In theory, capabilities allow granting only the specific privilege a process needs instead of full root. In practice, most server software still runs as root because configuring minimal capabilities is complex and most documentation defaults to root. CAP_SYS_ADMIN alone is so broad that granting it is effectively equivalent to granting root — it covers mounting filesystems, managing namespaces, and performing many operations that can be leveraged for privilege escalation.

LINUX SECURITY MONITORING — TRADITIONAL VS eBPF TRADITIONAL: AUDITD + LOG PARSING auditd rules → /var/log/audit/audit.log auth.log, syslog parsing with grep/awk File integrity (AIDE, Tripwire) → periodic scans MODERN: eBPF-BASED RUNTIME SECURITY eBPF programs in kernel → real-time syscall observation Process, file, network, module events at kernel speed Defender for Linux, Falco, Tracee, Cilium, Tetragon LINUX KERNEL SECURITY MECHANISMS Namespaces: PID, net, mount, user → Container isolation boundaries Cgroups: resource limits → Contain resource abuse SELinux / AppArmor: MAC → Mandatory access control seccomp: syscall filter → Restrict process syscalls

Figure ES1.6 — Linux security monitoring evolution. Traditional approaches (auditd, log parsing) provide useful but limited visibility. eBPF provides real-time kernel-level observation — the Linux equivalent of Windows ETW + kernel callbacks.

eBPF: real-time kernel visibility for Linux

eBPF (extended Berkeley Packet Filter) allows sandboxed programs to run in the Linux kernel at specific hook points — system call entry and exit, network packet processing, file system operations, scheduler events. The eBPF program observes the event, collects data — process ID, command line, file path, network destination — and sends it to a user-space program for processing and alerting. Before an eBPF program loads, the kernel's BPF verifier checks that the program terminates, does not access out-of-bounds memory, does not dereference null pointers, and does not call unauthorized kernel functions. This verification guarantees that the eBPF program cannot crash the kernel — making eBPF fundamentally safer than loadable kernel modules, which can do anything the kernel can do without verification.

For endpoint security, eBPF provides what ETW provides on Windows: real-time visibility into kernel operations without modifying the kernel itself. Defender for Linux's mdatp agent uses eBPF to monitor process execution, file access, and network connections. For Defender specifically, the eBPF programs attach to tracepoints for process creation (sched_process_exec) and termination (sched_process_exit), kprobes for file system operations (vfs_open, vfs_write), and network hooks for socket operations (tcp_connect, inet_sendmsg). Each program captures the event data and sends it to the mdatp user-space daemon for processing and cloud transmission. Falco from the CNCF uses eBPF for runtime anomaly detection in containers and Kubernetes. Tracee from Aqua Security uses eBPF for security event tracing. Tetragon from Isovalent uses eBPF for security observability and enforcement.

The eBPF advantage over traditional auditd-based monitoring is significant. Auditd writes events to /var/log/audit/audit.log as text, which must be parsed, forwarded, and correlated after the fact. eBPF programs capture events in kernel space at the moment they occur, filter in-kernel (reducing the data volume before it reaches user space), and send structured data to the security agent for immediate processing. The latency between event and detection is milliseconds with eBPF versus seconds or minutes with auditd log forwarding. For real-time threat detection — catching a container escape or a privilege escalation as it happens — this difference matters.

The eBPF verification step is what makes this approach safe for production systems. Before loading, the kernel's BPF verifier performs static analysis of the program: it traces every possible execution path to ensure termination, checks every memory access against declared boundaries, validates that the program only calls allowed kernel helper functions, and rejects programs with unbounded loops. A verified eBPF program cannot crash the kernel, corrupt kernel data structures, or consume unbounded resources. This is fundamentally safer than loadable kernel modules (LKMs), which execute with full kernel privilege and no verification — a buggy or malicious LKM can crash the entire system. The safety guarantee is why modern Linux security tools have converged on eBPF rather than kernel modules: the risk of deploying a kernel-level security monitor using eBPF is orders of magnitude lower than deploying one using a kernel module.

For security engineering, the practical implication is that eBPF-based tools can be deployed on production servers — including manufacturing control and database servers like NE's — with confidence that the monitoring infrastructure will not destabilize the workload. This is not true of all kernel-level monitoring approaches. Auditd is safe but limited. Kernel modules are powerful but risky. eBPF is both powerful and safe, which is why every major Linux security product has adopted it.

CLI Output
$ uname -r
5.14.0-362.24.1.el9_3.x86_64
$ cat /boot/config-$(uname -r) | grep CONFIG_BPF=
CONFIG_BPF=y
$ mount | grep bpf
bpf on /sys/fs/bpf type bpf (rw,nosuid,nodev,noexec,relatime,mode=700)
$ mdatp health --field real_time_protection_subsystem
ebpf

This is what a properly configured RHEL 9 server looks like: kernel 5.14+ with BPF enabled in the kernel config, the BPF filesystem mounted, and Defender for Linux running in eBPF mode. If real_time_protection_subsystem returns fanotify instead of ebpf, the agent has fallen back to a less comprehensive monitoring mode — typically because the kernel is too old or BPF kernel options are not enabled. The fanotify fallback provides file access monitoring (Defender can scan files as they are opened) but lacks the syscall-level visibility that eBPF provides — process execution arguments, network connection destinations, and file operation context are all absent or limited in fanotify mode. The practical impact: in fanotify mode, Defender for Linux can detect known malware files but cannot build the behavioral process chains that enable advanced detection patterns like "web server spawning shell spawning download tool." Kernel 5.8+ provides the complete eBPF feature set. RHEL 8.5+ and Ubuntu 20.04+ meet this requirement. If your servers run older kernels, upgrading is a prerequisite for eBPF-based security monitoring. At NE, the 6 RHEL servers run kernel 5.14 (RHEL 9.3) and support full eBPF mode. The 2 Ubuntu servers run 22.04 LTS with kernel 5.15 — also fully supported.

Namespaces and cgroups: the container security foundation

Linux containers use two kernel features for isolation: namespaces (which control what a process can see) and cgroups (which control what a process can use). Understanding these mechanisms matters for endpoint security because container escape — an attacker breaking out of a container to reach the host — targets the boundaries that namespaces and cgroups enforce.

Namespaces provide isolation for PID (the container sees only its own processes), Network (the container has its own network stack), Mount (the container sees only its own filesystem), User (the container can have UID/GID mapping allowing root inside the container without root on the host), and IPC/UTS (inter-process communication and hostname isolation). An attacker inside a container with properly configured namespaces cannot see host processes, access host network interfaces, or read host files — unless they exploit a namespace escape vulnerability.

The cross-platform comparison matters: Windows process isolation through integrity levels and Session 0 (from Section 1.1) provides weaker isolation than Linux namespaces. A Windows process in the same session can still see other processes. A Linux process in a separate PID namespace literally cannot enumerate processes in other namespaces. But namespace isolation is not security isolation — the kernel is shared between all containers and the host. A kernel vulnerability exploitable from inside any container affects the host directly. This is the fundamental limitation of container security: the isolation boundary depends on the kernel, and the kernel is shared.

Cgroups (control groups) limit resource consumption: CPU time, memory usage, IO bandwidth, and device access. For security, cgroups prevent a compromised container from consuming all host resources — a denial-of-service prevention mechanism — and restrict which host devices the container can access, preventing direct disk or device access that could bypass namespace isolation. Cgroups v2 (the default on modern kernels) also provides a unified hierarchy that eBPF programs can attach to for per-cgroup monitoring, enabling security tools to apply different detection policies per container or workload group.

Container escape techniques target these boundaries: mounting the host filesystem into the container if the Docker socket is exposed, exploiting kernel vulnerabilities like DirtyPipe (CVE-2022-0847), DirtyCow (CVE-2016-5195), or OverlayFS (CVE-2023-0386) that allow namespace transitions, and abusing misconfigured capabilities where CAP_SYS_ADMIN granted to the container provides near-root host access. The kernel is shared between all containers and the host — a kernel vulnerability exploited from inside any container affects the host directly.

Syslog Output
Feb 14 09:31:22 rhel-mfg01 kernel: audit: type=1400 msg=audit(1707903082.441:892):
  avc:  denied  { mount } for  pid=4521 comm="runc"
  scontext=system_u:system_r:container_runtime_t:s0:c12,c45
  tcontext=system_u:object_r:root_t:s0 tclass=filesystem permissive=0
Feb 14 09:31:22 rhel-mfg01 kernel: audit: type=1300 msg=audit(1707903082.441:893):
  arch=c000003e syscall=165 success=no exit=-13
  a0=7ffd2a4b1e60 a1=0 a2=0 a3=0 items=0 ppid=4510
  pid=4521 uid=0 gid=0 euid=0 comm="runc" exe="/usr/bin/runc"
Feb 14 09:31:23 rhel-mfg01 falco: Warning Process attempted mount in container
  (user=root container_id=a3f2c8d1 container_name=mfg-app
  proc.name=runc proc.cmdline=runc mount --rbind /host /mnt)

This syslog output shows three layers of defense detecting a container escape attempt. The first record is SELinux denying a mount operation from the container runtime context — the permissive=0 flag means SELinux actually blocked the action, not just logged it. The second record is the auditd capture of the denied syscall (165 is the mount syscall), showing the process details and the failure. The third record is Falco's eBPF-based runtime detection identifying the mount attempt with container context — the container ID, the container name, and the command that attempted to bind-mount the host root filesystem into the container.

Three independent detection and prevention mechanisms captured the same event: SELinux blocked it, auditd logged it, and Falco alerted on it. If SELinux were in permissive mode (logging only, not enforcing), the mount would have succeeded — but Falco would still have detected it. If Falco were not deployed, SELinux would still have blocked it. This is defense in depth at the Linux kernel level — each mechanism independently protects the namespace boundary.

KQL
// Detect suspicious process execution on Linux endpoints
DeviceProcessEvents
| where Timestamp > ago(7d)
| where DeviceName has_any ("rhel", "ubuntu", "linux")
| where FileName in~ ("curl", "wget", "nc", "ncat", "python3", "perl")
| where InitiatingProcessFileName in~ ("bash", "sh", "dash")
| project Timestamp, DeviceName, AccountName, FileName,
    ProcessCommandLine, InitiatingProcessCommandLine
| sort by Timestamp desc

This query detects the most common post-exploitation pattern on Linux: a shell spawning download or reverse-shell tools. On a production RHEL server, curl and wget invoked from an interactive bash session — rather than from cron or a management script — are anomalous. nc (netcat) on a production server is almost always suspicious. python3 and perl invoked from a shell with network-related arguments indicate reverse shell construction. The query requires Defender for Linux to be deployed and reporting to the MDE portal — without the mdatp agent, DeviceProcessEvents contains no Linux data at all.

This is the cross-platform coverage gap that matters for NE's environment: Windows endpoints without MDE still generate Windows Event Log data that can be forwarded to Sentinel through the Windows Event Forwarding infrastructure or the Log Analytics agent. Linux servers without mdatp generate nothing in the MDE tables — no process events, no network events, no file events. The only telemetry available from an unmonitored Linux server is whatever auditd and syslog produce locally, and only if those logs are forwarded to a central collection point. At NE, the 6 RHEL servers currently have no mdatp, no centralized syslog forwarding, and default auditd configuration. They are effectively invisible to the SOC. Module ES13 closes this gap by deploying mdatp in eBPF mode on all Linux servers, configuring Sysmon for Linux for additional independent telemetry, and establishing syslog forwarding to Sentinel as a fallback data path.

What we see in 90% of environments

Linux servers treated as inherently secure because they run a "hardened" OS. Ransomware groups including ESXiArgs, Akira, and BlackCat actively target Linux servers for encryption because they host databases, file shares, and virtual machine infrastructure — and because those servers often lack the endpoint monitoring that Windows systems have. Cryptomining campaigns target Linux because the servers have more CPU. Rootkits target Linux because kernel module loading provides deep persistence. The "Linux is secure" assumption creates a monitoring blind spot that attackers exploit specifically because they know the servers are unmonitored.

Endpoint Security Principle

eBPF is to Linux what ETW + kernel callbacks are to Windows — the real-time kernel-level visibility infrastructure that modern security tools depend on. Without eBPF-based monitoring, Linux endpoint security relies on log parsing after the fact. With eBPF, the security agent observes system calls in real time, detects anomalous behavior as it occurs, and provides the telemetry that KQL queries in Advanced Hunting consume. Deploying Defender for Linux in eBPF mode on every Linux server is the prerequisite for cross-platform visibility.

Next

Section 1.7 examines Linux authentication and privilege — PAM, sudo, capabilities, SUID, and the privilege escalation paths that transform a compromised web application into full root access. You'll understand why sudo logging is not optional and why SUID auditing catches escalation that process monitoring misses.

Unlock the Full Course See Full Course Agenda