Back

Linux-eBPF-Verifier-Bypass-Research

I researched Linux eBPF verifier bypass techniques and translated static candidates into practical exploitation workflows.

Repository
kerneleBPFexploitLinuxverifier internalsXDPkernel hardening

Practical Exploitation of Linux eBPF Verifier Vulnerabilities (LTS 6.8)

Polito Logo

Course: Security Verification and Testing - Second Year, First Semester
Author: Renato Mignone
Date: December 2025


Abstract

This project explores the security boundaries of eBPF (extended Berkeley Packet Filter), a revolutionary technology that allows user-defined programs to run safely inside the Linux kernel. While eBPF's verifier is designed to guarantee memory safety and prevent malicious code execution, certain logic bugs can potentially bypass these protections.


πŸ“š README Hierarchy & Navigation

This project is documented across multiple README files organized hierarchically. Start here and follow the breadcrumbs to dive deeper:

β”œβ”€β”€ README.md (you are here)
β”‚   β”œβ”€ Explains: eBPF fundamentals, verifier concepts, threat model, inherited work
β”‚   β”œβ”€ Audience: Readers unfamiliar with eBPF or the project context
β”‚   └─ Next: See "My Objective: Practical Exploitation" section below, then proceed to src/README.md
β”‚
β”œβ”€β”€ src/README.md
β”‚   β”œβ”€ Explains: Exploitation workflow, VM setup, compilation pipeline, overall methodology
β”‚   β”œβ”€ Audience: Readers ready to understand the practical approach and environment
β”‚   └─ Next: Proceed to src/exploits/README.md for detailed vulnerability analysis
β”‚
β”œβ”€β”€ src/exploits/README.md
β”‚   β”œβ”€ Explains: Multi-stage analysis methodology (bytecode β†’ verifier β†’ xlated β†’ runtime)
β”‚   β”œβ”€ Explains: 5 vulnerabilities with evidence chains and classification
β”‚   β”œβ”€ Audience: Readers interested in the analysis approach and vulnerability summaries
β”‚   └─ Next: Drill into individual vulnerabilities (5_06a, 5_06b, 5_06d, 5_39, 5_46b)
β”‚
└── src/exploits/{vulnerability}/README.md (one per vulnerability)
    β”œβ”€ Explains: Deep technical analysis, bytecode dumps, verifier logs, exploitation mechanics
    β”œβ”€ Explains: Complete evidence chain from source code to runtime traces
    β”œβ”€ Audience: Readers performing detailed technical analysis or reproducing exploits
    └─ Files: Specific PoC scripts, patch files, analysis logs

Quick Navigation:


  1. What is eBPF?
  2. Threat Model
  3. Why Target LTS 6.8?
  4. eBPF Exploitation Primitives
  5. Inherited Work: What the Previous Team Did
  6. My Objective: Practical Exploitation
  7. Repository Structure
  8. Quick Start
  9. Progress Tracking
  10. References

What is eBPF?


Origins and Evolution

eBPF (extended Berkeley Packet Filter) is a revolutionary technology that originated from the classic BPF (Berkeley Packet Filter) created in 1992 for network packet filtering. While classic BPF was limited to simple packet inspection (used by tools like tcpdump), eBPF has evolved into a general-purpose in-kernel virtual machine capable of running sandboxed programs in the Linux kernel.

Project visual

Timeline:

  • 1992: BPF created (packet filtering only).
  • 2014: eBPF introduced in Linux 3.18 (Extended instruction set, Maps, Helpers).
  • 2016: XDP (eXpress Data Path) added for programmable network processing at the driver level.
  • 2020+: eBPF becomes ubiquitous for Observability, Security, and Networking.

Architecture Overview

eBPF programs are written in a restricted C dialect, compiled to eBPF bytecode, verified by the kernel, and JIT-compiled to native machine code for execution.

Project visual

Key Components:

ComponentDescription
eBPF BytecodePlatform-independent instruction set (11 registers, 64-bit)
VerifierStatic analyzer ensuring program safety before execution
JIT CompilerTranslates bytecode to native CPU instructions
MapsKey-value stores for sharing data between eBPF programs and user space
HelpersKernel functions callable from eBPF (e.g., bpf_map_lookup_elem)
HooksAttachment points in kernel (kprobes, tracepoints, XDP, TC, LSM)

The eBPF Verifier

The verifier is the security cornerstone of eBPF. It performs static analysis on every program before allowing it to run in the kernel. Its goal is to guarantee:

Project visual

  1. Memory Safety β€” No out-of-bounds reads/writes
  2. Termination β€” Program will always complete (no infinite loops)
  3. Valid Operations β€” Only allowed helpers and operations
  4. Type Safety β€” Correct use of pointers and data types

Verifier Analysis Stages:

  1. CFG Construction: Build Control Flow Graph and identify execution paths.
  2. Instruction Walk: Simulate each instruction and track register states.
  3. Bounds Checking: Verify memory accesses and track pointer arithmetic.
  4. Loop Detection: Ensure bounded iteration.
  5. Helper Validation: Check argument types.

Verifier Limitations (The Attack Surface):

The verifier is complex (~20,000 lines of code in kernel/bpf/verifier.c) and must balance security, usability, and performance. This complexity creates potential for logic bugs where:

  • The verifier's model of program behavior differs from actual execution.
  • Edge cases in type tracking allow invalid operations.
  • Pointer arithmetic confuses the verifier's bounds tracking.

These verifier bugs are the focus of this project.


How the Verifier Tracks State (The Logic)

To ensure safety without executing the code, the verifier simulates every instruction and maintains a state for each of the 11 registers (R0-R10). A vulnerability occurs when this internal state gets out of sync with the actual runtime machine state.

What the Verifier tracks per register:

  1. Type: Is it a SCALAR (number) or a POINTER (to memory/map)?
    • Exploit Path: If we can trick the verifier into thinking a SCALAR is a POINTER, we can read arbitrary kernel memory.
  2. Range (tnum): What is the min/max value this register holds?
    • Exploit Path: If the verifier thinks a value is 0-100 but at runtime it is 1000, bounds checks are bypassed (OOB R/W).
  3. Offset: Where does this pointer point relative to the base object?

The "Pruning" Problem: To save time, if the verifier sees a code path that looks similar to one it already checked, it skips it ("pruning"). Many logic bugs hide hereβ€”where the verifier prunes a path it thought was safe, but actually wasn't.


Program Types and Use Cases

eBPF supports multiple program types, each attaching to different kernel hooks:

Program TypeHook PointUse Case
BPF_PROG_TYPE_XDPNetwork driver (pre-stack)DDoS mitigation, load balancing
BPF_PROG_TYPE_SCHED_CLSTraffic Control (TC)Packet filtering, NAT
BPF_PROG_TYPE_KPROBEKernel functionsTracing, debugging
BPF_PROG_TYPE_TRACEPOINTStatic kernel eventsPerformance monitoring
BPF_PROG_TYPE_LSMLinux Security ModulesSecurity policies
BPF_PROG_TYPE_SOCKET_FILTERSocket layerPacket inspection

XDP (eXpress Data Path) is particularly interesting for security research because it runs at the earliest point in the network stack, has direct memory access, and is performance-critical.


Security Implications

eBPF's ability to run custom code in kernel space makes it a high-value target for attackers.

Project visual

  • Intended Boundaries: Cannot access arbitrary memory, cannot call arbitrary functions.
  • If Verifier Bypassed: Arbitrary kernel read (Info disclosure), Arbitrary kernel write (Privilege escalation).

Historical eBPF Vulnerabilities:

CVEYearDescription
CVE-2020-88352020Verifier bounds tracking error, arbitrary R/W
CVE-2021-34902021ALU32 bounds tracking, privilege escalation
CVE-2021-314402021Bounds propagation bug
CVE-2022-232222022Pointer arithmetic confusion
CVE-2023-21632023Verifier log buffer overflow

This project focuses on identifying and exploiting similar verifier logic bugs in LTS 6.8.


Threat Model

Before diving into exploitation, it's essential to define the threat model β€” who is the attacker, what capabilities do they have, and what are they trying to achieve?

Attacker Profile

AttributeDescription
Access LevelUnprivileged user access to a Linux system (LTS 6.8)
CapabilitiesCan load eBPF programs (requires CAP_BPF or root, depending on kernel config)
LimitationsCannot directly modify kernel code, modules, or bypass secure boot

Attack Goals

GoalImpactSeverity
Arbitrary Kernel ReadLeak kernel addresses (defeat KASLR), credentials, cryptographic keysHigh
Arbitrary Kernel WriteModify cred structure β†’ privilege escalation to rootCritical
Code ExecutionOverwrite function pointers β†’ execute arbitrary kernel codeCritical

Attack Surface

The attack surface is specifically the eBPF verifier's static analysis logic:

  • Discrepancies between verifier's model and actual runtime behavior
  • Edge cases in type tracking (SCALAR vs. POINTER confusion)
  • Bounds tracking errors in arithmetic operations
  • Pruning logic that incorrectly assumes paths are equivalent

Out of Scope

  • Kernel exploits not involving eBPF (use-after-free, race conditions)
  • Hardware vulnerabilities (Spectre, Meltdown)
  • Social engineering or physical access attacks
  • Denial of Service (we focus on privilege escalation)

Why Target LTS 6.8?

The choice of Linux Kernel LTS 6.8 as the target is deliberate:

ReasonExplanation
Long Term SupportLTS kernels are deployed in production for 2-6 years, meaning vulnerabilities have prolonged impact
Wide DeploymentUsed in enterprise servers, cloud infrastructure (AWS, GCP, Azure), and embedded systems
Security Research ValueVulnerabilities discovered here have real-world implications
Verifier MaturityContains the latest verifier improvements β€” if we can bypass it, older kernels are likely vulnerable too
ReproducibilityStable, well-documented version ensures consistent testing environment
eBPF Feature SetSupports all modern eBPF features (BTF, CO-RE, ringbuf) that might introduce new attack vectors

Note: Findings on LTS 6.8 may also apply to other kernel versions with similar verifier code. Backporting analysis would be a valuable extension of this work.


eBPF Exploitation Primitives

Once the verifier is bypassed, attackers leverage specific primitives to achieve their goals. Understanding these is crucial for both offense and defense.

1. Out-of-Bounds Read (OOB-R)

β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚  Verifier believes: ptr can access [0, 100]         β”‚
β”‚  Reality:           ptr can access [0, 1000]        β”‚
β”‚                                                     β”‚
β”‚  Result: Read kernel memory beyond allowed bounds   β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

Use Cases:

  • Defeat KASLR: Leak kernel base address to calculate gadget locations
  • Credential Theft: Read task_struct->cred to extract UIDs, capabilities
  • Key Extraction: Leak cryptographic keys from kernel memory

2. Out-of-Bounds Write (OOB-W)

β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚  Verifier believes: ptr can write [0, 64]           β”‚
β”‚  Reality:           ptr can write [0, 512]          β”‚
β”‚                                                     β”‚
β”‚  Result: Overwrite adjacent kernel structures       β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

Use Cases:

  • Privilege Escalation: Overwrite cred->uid and cred->gid to 0 β†’ instant root
  • Security Bypass: Modify cred->cap_effective to grant all capabilities
  • Code Execution: Overwrite function pointers in kernel structures

3. Type Confusion

β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚  Verifier believes: R1 = SCALAR (safe number)       β”‚
β”‚  Reality:           R1 = POINTER (kernel address)   β”‚
β”‚                                                     β”‚
β”‚  Result: Arithmetic on "numbers" actually moves     β”‚
β”‚          pointers to arbitrary kernel locations     β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

Use Cases:

  • Convert controlled integers into arbitrary kernel pointers
  • Bypass pointer arithmetic restrictions
  • Access memory regions the verifier thought were unreachable

Common Exploitation Flow

Project visual


Inherited Work: What the Previous Team Did

The repository ebpf-exploitability-test/ contains work from a previous team (Francesco Rollo, Gianfranco Trad, Giorgio Fardo, Giovanni Nicosia) who performed a theoretical vulnerability assessment based on ISO-IEC TS 17961-2013 (C Secure Coding Standard).


The ISO-IEC TS 17961-2013 Standard

The previous team based their vulnerability assessment on ISO-IEC TS 17961-2013, titled "Information technology β€” Programming languages, their environments and system software interfaces β€” C Secure Coding Rules".

This technical specification defines 46 rules that identify common programming patterns in C that lead to undefined behavior, security vulnerabilities, or reliability issues. Each rule is numbered (5.1 through 5.46) and categorized by vulnerability type:

CategoryRule ExamplesVulnerability Type
Memory Safety5.2, 5.20, 5.21, 5.35Buffer overflows, dangling pointers, uninitialized memory
Type Safety5.1, 5.10, 5.16Pointer casts, integer conversions, aliasing violations
Control Flow5.4, 5.17Missing switch defaults, assignment in conditionals
Data Handling5.24, 5.40, 5.46Format strings, tainted input propagation
Pointer Operations5.22, 5.36Invalid pointer arithmetic, pointer comparisons

Why This Standard?

The team systematically applied each of these 46 rules to the XDP SynProxy code, asking:

"If we intentionally violate this rule, will the eBPF verifier catch it?"

This approach provides comprehensive coverage β€” rather than hunting for specific bugs, they tested the verifier against a standardized catalog of known vulnerability patterns.


Rules NOT Applicable to eBPF

Of the 46 rules, 22 are not applicable to eBPF due to fundamental architectural constraints:

ConstraintAffected RulesReason
No Dynamic Memory5.2, 5.18, 5.21, 5.23, 5.34No malloc() or free() in eBPF
No Signal Handling5.3, 5.5, 5.7No signal handlers in kernel context
No File Operations5.12, 5.27, 5.41, 5.43No FILE structs or stdio
No Standard Library5.8, 5.19, 5.29, 5.32, 5.37, 5.42Limited libc access
Not Security-Relevant5.25, 5.38, 5.44Discarded as not useful for exploitation

Applicable Rules: ~24 rules could be tested in the eBPF environment.

Key Finding: Of those 24 applicable rules, 21 violations passed the verifier β€” a concerning result that motivated this follow-up exploitation work.


What is XDP SynProxy?

The previous team focused exclusively on testing vulnerabilities within the XDP SynProxy implementation. To understand why this is a significant target, we need to understand the problem it solves.

The SYN Flood Attack

Project visual

A SYN flood is a type of Denial-of-Service (DoS) attack that exploits the TCP three-way handshake:

The problem: Each SYN packet causes the server to allocate a Transmission Control Block (TCB) and wait for the ACK. Attackers send thousands of SYN packets with spoofed source IPs, exhausting the server's connection table while never completing the handshake.


The SYN Proxy Solution

Project visual

A SYN Proxy acts as an intermediary that validates clients before forwarding connections to the real server:

SYN Cookies: Instead of storing state, the proxy encodes connection information (source IP, port, timestamp) into the sequence number of the SYN-ACK. When the client responds with ACK, the proxy can validate the cookie mathematically without having stored any state. Fake clients with spoofed IPs never receive the SYN-ACK, so they can't complete the handshake.


Why XDP for SYN Proxy?

Project visual

Traditional SYN proxies operate in user space or higher in the kernel stack, which introduces latency. XDP (eXpress Data Path) solves this by running the SYN proxy logic at the earliest possible point β€” directly in the network driver:

XDP SynProxy advantages:

  • Line-rate processing: Can handle millions of packets per second
  • Zero-copy: Operates directly on packet memory in the driver
  • Early drop: Malicious packets never enter the kernel stack
  • CPU efficient: No context switches, minimal overhead

The Target: xdp_synproxy_kern.c

The file xdp_synproxy_kern.c is an eBPF/XDP implementation of a SYN proxy, taken from the Linux kernel selftests. It performs:

  1. Packet parsing: Ethernet β†’ IP β†’ TCP header dissection
  2. SYN detection: Identifies incoming TCP SYN packets
  3. Cookie generation: Creates cryptographic SYN cookies
  4. SYN-ACK crafting: Builds response packets with embedded cookies
  5. ACK validation: Verifies returning ACKs contain valid cookies
  6. Connection forwarding: Passes validated connections to the kernel

The previous team chose this target because:

  • It's real production code from Linux kernel selftests
  • It involves complex pointer arithmetic for packet parsing
  • It uses multiple eBPF features (maps, helpers, tail calls)
  • It's security-critical β€” bugs here could disable DDoS protection or leak information
  • It's performance-critical β€” must process packets at wire speed

Important: XDP SynProxy is User Code, Not Kernel Code

Project visual

A crucial distinction to understand: xdp_synproxy_kern.c is not part of the Linux kernel itself. It's an eBPF program β€” user-provided code that gets loaded into the kernel at runtime:

This is the power and danger of eBPF: anyone with appropriate privileges can load custom code that runs inside the kernel with full kernel privileges.


The Verifier as Security Gatekeeper

Project visual

The eBPF verifier exists specifically to prevent malicious or buggy user code from compromising the kernel.


What the Testing Actually Proves

When we inject vulnerable code via patches and test against the verifier:

Project visual

The "Translation Gap": C Vulnerabilities vs. Bytecode Reality

A critical insight from this research is that a vulnerability in the C source code does not guarantee an exploit in the kernel, even if the verifier allows it to load.

This discrepancy exists because the vulnerability must survive a complex translation chain:

  1. C Source: The vulnerability exists here (e.g., ISO-17961 violation).
  2. LLVM Compilation: The compiler translates C to eBPF Bytecode.
    • The Filter Effect: The compiler may optimize away the vulnerable logic, dead-code eliminate the branch, or translate a complex memory violation into a benign register operation.
  3. JIT Compilation: The kernel translates Bytecode to Native Machine Code (x86/ARM).

Project visual

Why "Verifier Pass" $\neq$ "Exploit": For a vulnerability to be exploitable, it must be preserved through this translation. Many "theoretical" C bugs disappear because eBPF's memory model (512-byte stack, 64-bit registers) forces the compiler to generate code that, by coincidence or constraint, is safe at runtime.

Example: A buffer overflow in C (memcpy(dst, src, user_len)) might compile to eBPF instructions that use bounded loop unrolling, where the compiler statically limits the copy to a safe maximum regardless of user_len.

Conclusion: We are not just exploiting C code; we are exploiting the Bytecode that the C code produces.

Implication for This Project: When developing PoCs, examining the C source alone is insufficient. I must verify vulnerabilities survive compilation by analyzing the eBPF bytecode with tools like llvm-objdump -d or bpftool prog dump xlated.


Why This Matters

The previous team found ~21 cases where the verifier incorrectly accepted vulnerable code:

OutcomeCountMeaning
Verifier blocked~14Security works βœ“
Compiler blocked~8Never reached verifier
Verifier passed + Exploitable~9Security failure β€” PRIMARY TARGETS
Verifier passed + Limited~12Uncertain β€” SECONDARY TARGETS
Verifier passed + Safe~17Logic bugs but no security impact

The 9 "Exploitable" and 12 "Limited" cases represent situations where:

  1. Intentionally vulnerable code was written
  2. The eBPF verifier failed to detect the vulnerability
  3. The code was loaded into the kernel
  4. The vulnerability is now potentially exploitable with kernel privileges

My task: Prove these theoretical vulnerabilities are actually dangerous by building working exploits.


Theoretical vs. Practical: The Gap

Understanding the distinction between the previous team's work and mine is crucial:

AspectPrevious Team (Theoretical)My Work (Practical)
Core Question"Does this code pass the verifier?""Can I actually exploit this to get root?"
Analysis TypeSource code analysisBytecode + runtime analysis
OutputClassification (YES/LIMITED/NO)Working PoC exploits
ValidationStatic assessmentDynamic exploitation
Conclusion"This COULD be dangerous""This IS dangerous, here's proof"
DeliverableVulnerability catalogFunctional exploit code

The Gap: Knowing a vulnerability exists is different from proving it's exploitable. Many theoretical vulnerabilities fail in practice due to:

  • Compiler optimizations neutralizing the bug
  • Additional runtime checks not visible in static analysis
  • Memory layout constraints preventing useful corruption
  • Missing primitives to chain into full exploitation

My Contribution: Bridge this gap by transforming theoretical findings into practical proof.


Their Testing Environment

The previous team implemented a full client-server architecture for practical eBPF/XDP vulnerability testing. Their setup allows you to:

  • Run a netcat server and client on separate hosts (or host and VM), with the XDP SynProxy eBPF program acting as a proxy in the middle.
  • Use the start_session.sh script to launch a tmux session that sets up:
    • The XDP SynProxy loader (attaches the eBPF program to the network interface)
    • A netcat server (listening for TCP connections)
    • Kernel trace output (for debugging and observing eBPF behavior)
  • Simulate real network communication, with the XDP SynProxy program intercepting and processing packets between the client and server.

This architecture enables you to test how injected vulnerabilities in the eBPF program can be exploited via network packets, providing a realistic and interactive environment for security research.

How it works in practice:

  • The netcat server is always running on the VM, listening for incoming TCP connections on port 80.
  • The XDP SynProxy eBPF program is attached to the VM's network interface and intercepts all incoming packets before they reach the server.
  • You use a netcat client (typically from your host machine) to connect to the VM's IP and port 80, sending crafted network packets.
  • This setup allows you to observe how the XDP program processes, blocks, or is potentially exploited by these packets.

Project visual

VM Infrastructure (virt/)

The vmctl.sh script provides complete VM lifecycle management:

# VM Management Commands
./vmctl.sh create ~/.ssh/id_rsa.pub   # Create and provision new VM
./vmctl.sh connect                     # Connect to VM console
./vmctl.sh destroy                     # Tear down VM

VM Specifications:

ParameterValue
Base ImageUbuntu 24.04 (Noble) Cloud Image
Memory4096 MB
vCPUs2
Disk20 GB
HypervisorKVM/QEMU via libvirt

Cloud-Init Provisioning: The VM is automatically configured on first boot using cloud-init with:

  • Pre-installed development tools (clang, llvm, bpftool, make)
  • SSH key injection for passwordless access
  • Network configuration for XDP testing
  • All required eBPF development dependencies

Key Design Decisions

  • Single VM topology: The team initially attempted a 3-veth (virtual Ethernet) topology to simulate client/proxy/server separation. However, virtual interfaces caused checksum offloading issues with SYN cookies β€” the kernel's checksum calculation differed from hardware expectations. They simplified to a single real interface where the XDP program, server, and client all run within or connect to the same VM.

  • tmux testing sessions: The start_session.sh script creates a multi-pane tmux session with:

    • Pane 1: XDP SynProxy program output
    • Pane 2: Netcat server listening for connections
    • Pane 3: Packet monitoring / test commands

Understanding Patches and git apply

⚠️ Terminology Clarification: In standard software development, a "patch" typically means a fix for a bug or vulnerability. In this project, the meaning is inverted: our patches inject vulnerabilities into clean code, not remove them. We use the Git patch format purely as a delivery mechanism to systematically introduce specific, isolated vulnerabilities into the xdp_synproxy_kern.c codebase for testing purposes.

A patch (or diff) is a text file that describes the differences between two versions of a file. While patches are traditionally used to distribute bug fixes, in this research context they serve as vulnerability injection vectors β€” each patch transforms the clean, safe xdp_synproxy_kern.c into a version containing a specific ISO-17961 vulnerability.

Why Use Patches for Vulnerability Injection?

BenefitDescription
IsolationEach vulnerability exists in its own patch β€” no cross-contamination
ReproducibilityAnyone can recreate the exact vulnerable state
ReversibilityEasy to apply and revert (git apply -R)
DocumentationPatch metadata includes vulnerability description
Automationxvtlas can iterate through patches programmatically

Anatomy of a Patch File

From b5856aa7d76351adf1a201097c3a950c9e94502d Mon Sep 17 00:00:00 2001
From: author <email@example.com>
Date: Wed, 27 Aug 2025 13:10:03 +0200
Subject: [PATCH] feat(5.10a_exploit): intptrconv

---
 XDPs/xdp_synproxy/xdp_synproxy_kern.c | 251 ++++++++++++++++++++++++++
 1 file changed, 251 insertions(+)

diff --git a/XDPs/xdp_synproxy/xdp_synproxy_kern.c b/XDPs/xdp_synproxy/xdp_synproxy_kern.c
index 0d0d990..34a1474 100644
--- a/XDPs/xdp_synproxy/xdp_synproxy_kern.c      ← Original file
+++ b/XDPs/xdp_synproxy/xdp_synproxy_kern.c      ← Modified file
@@ -373,6 +431,9 @@ struct header_pointers {        ← Location marker
 static __always_inline int tcp_dissect(void *data, void *data_end,
 				       struct header_pointers *hdr)
 {
+	__u32 data_base_truncated;               ← Lines starting with + are ADDED
+	void *calculated_ptr;
+
 	hdr->eth = data;
-	old_line_here                            ← Lines starting with - are REMOVED
 	if (hdr->eth + 1 > data_end)

Key elements:

  • Header: Commit metadata (author, date, message)
  • File path: Which file(s) are modified
  • Hunks (@@): Location markers showing line numbers
  • + lines: Code being added
  • - lines: Code being removed
  • Context lines: Unchanged lines for positioning

Git Apply Command

Git provides the git apply command to apply patches to the working directory:

# Apply a patch (modifies files but doesn't create a commit)
git apply patches/5_10a_exploit_intptrconv/0001-feat-5_10a_exploit.patch

# Check if patch would apply cleanly (dry-run)
git apply --check patches/5_10a_exploit_intptrconv/0001-feat-5_10a_exploit.patch

# Apply in reverse (remove the patch changes)
git apply -R patches/5_10a_exploit_intptrconv/0001-feat-5_10a_exploit.patch

# Alternative: git am creates a commit from the patch
git am patches/5_10a_exploit_intptrconv/0001-feat-5_10a_exploit.patch

Workflow in This Project

Project visual

This approach allows:

  • Clean separation: Each vulnerability is isolated in its own patch
  • Easy testing: Apply one patch, test, revert, apply next
  • Version control: Patches are trackable and reviewable
  • Reproducibility: Anyone can recreate the exact vulnerable state

The xvtlas Automation Tool

xvtlas (XDP Verifier Testing Launch Automation Suite) is a custom Go tool created by the team to automate the repetitive workflow of testing vulnerability patches.

Why They Built It

Testing 60+ vulnerability patches manually would require:

  1. Apply patch to base file
  2. Compile with clang/LLVM
  3. Load program with bpftool
  4. Capture verifier output
  5. Record results
  6. Revert patch
  7. Repeat...

xvtlas automates this entire pipeline:

Project visual

Usage Modes

1. Batch Testing (All Patches)

./xvtlas --export "./output/" \
         --kernel "6.8" \
         --patch-path ./patches/ \
         --base-file ./xdp_synproxy_kern.c \
         --save-logs --verbose

Processes all patches and generates a comprehensive CSV report.

2. Single Patch Interactive Mode

./xvtlas --run-single "./patches/5_10a_exploit/*.patch" \
         --base-file "./xdp_synproxy_kern.c"

Applies one patch, compiles, and opens a tmux session for manual testing.

3. Cleanup

./xvtlas --destroy

Reverts git state and cleans up temporary files from previous sessions.

Output Structure

xvtlas_output/
β”œβ”€β”€ report.csv              # Summary: patch, compiled?, verified?, loaded?
β”œβ”€β”€ 5_06a_argcomp/
β”‚   β”œβ”€β”€ make.log            # Compiler output and warnings
β”‚   └── verifier.log        # eBPF verifier output
β”œβ”€β”€ 5_10a_exploit_intptrconv/
β”‚   β”œβ”€β”€ make.log
β”‚   └── verifier.log
└── ...

Their Methodology

Project visual

They applied 46 C vulnerability rules to the target code to test the verifier's response.


What They Produced

ArtifactDescription
60+ vulnerability patchesEach implements a specific ISO-IEC TS 17961-2013 rule violation
Base target: xdp_synproxy_kern.cReal XDP SYN proxy from Linux kernel selftests
xvtlas toolGo automation suite for patch/compile/verify workflow
patches.csvSummary table with exploitability classification
Detailed documentation1500+ lines explaining each vulnerability

Their Results Summary

  • 60 patches total
    • 8 compilation failures (rejected before verifier).
    • 14 blocked by eBPF verifier βœ“ (security works).
    • 19 passed verifier but "not exploitable" (memory bounds still enforced).
    • 9 passed verifier AND marked "exploitable" (These are my primary targets).
    • 12 passed verifier with "limited" exploitability (Secondary targets).

Vulnerabilities Marked as "Exploitable"

PatchISO RuleVulnerability TypeTheir Assessment
5_06a_argcomp5.6Function pointer mismatchRegister/stack corruption
5_06b_argcomp5.6Wrong argument countStack memory overwrite
5_10a_exploit_intptrconv5.10Pointer truncation bypassInfo disclosure
5_14_nullref5.14Null pointer dereferenceInvalid memory access
5_17_swtchdflt5.17Missing switch defaultUndefined firewall behavior
5_20a_libptr5.20Buffer overflow (8 bytes)Adjacent stack corruption
5_20c_libptr5.20Type confusion overflow12-byte buffer overflow
5_35_uninit_mem5.35Uninitialized memory readKernel stack data leak
5_35a_unint_mem5.35Uninitialized memory readKernel stack data leak

Vulnerabilities Marked as "Limited" Exploitability

These vulnerabilities passed the verifier but have uncertain or constrained exploitation potential:

PatchISO RuleVulnerability TypeTheir Assessment
5_06d_argcomp5.6Wrong argument typesValue truncation (localized impact)
5_14a_nullref5.14Null pointer dereferenceInvalid access, no escape path
5_16b_signconv5.16Signed conversionLogic errors only
5_33a_restrict5.33Restrict pointer violationLogic/data corruption in stack
5_33b_restrict5.33Restrict pointer violationLocal stack data corruption
5_36a_ptrobj5.36Pointer comparison UBMemory layout information leak
5_36b_ptrobj5.36Context pointer comparisonKernel layout info disclosure
5_36c_ptrobj5.36Map pointer comparisonHeap organization leak
5_39_taintnoproto5.39Tainted function pointerUnpredictable logic behavior
5_45_invfmtstr5.45Invalid format stringsAddress leak via logging
5_46b_taintsink5.46Tainted memory copyAttacker-controlled packet alteration

Vulnerabilities Marked as "Not Exploitable"

These vulnerabilities were either blocked by the compiler, blocked by the verifier, or passed but had no security impact:

Blocked by Compilation Errors (8 patches):

PatchReason
5_06c_argcompConflicting types for function
5_13_objdecConflicting types for variable
5_13b_objdecConflicting types for variable
5_22d_invptrArray subscript out of bounds
5_24a_usrfmtIncompatible pointer types

Blocked by eBPF Verifier (12 patches):

PatchVerifier Error
5_4a_boolasgnInfinite loop detected
5_4b_boolasgnInfinite loop detected
5_06e_argcompR1 type=scalar expected=map_ptr
5_10a_intptrconvPointer arithmetic with <<= prohibited
5_10b_intptrconvR1 invalid mem access 'scalar'
5_14b_nullrefR7 invalid mem access 'map_value_or_null'
5_16a_signconvR8 offset outside packet
5_20b_libptrInvalid indirect access to stack
5_22c_invptrInvalid access to context parameter
5_24b_usrfmtInvalid access to context parameter
5_35b_unint_memR1 invalid mem access 'scalar'
5_40_taintformatioInvalid indirect access to stack
5_46a_taintsinkUnbounded min value not allowed
5_46c_taintsinkAddress R11 invalid (VLA attempt)

Passed Verifier but Not Exploitable (19 patches):

PatchReason
5_01a/b/c_ptrcompMemory bounds still enforced by verifier
5_9_padcompLogic non-determinism only, no memory exposure
5_11_alignconvLogical misinterpretation, not memory exploitable
5_11a/c_alignconvLogical misinterpretation, not memory exploitable
5_15_addrescapeDangling pointer but stack managed per-packet
5_15a/b_addrescapeDangling pointer but stack managed per-packet
5_22_invptrVerifier-enforced memory bounds
5_22b/e/f_invptrLogical misinterpretation only
5_26a-e_diverrDivision by zero results in 0, no crash
5_28_strmodRead-only memory, program terminates
5_30_intoflowTwo's complement arithmetic, no memory violation
5_31a/b_nonnullcsControlled memory layout required

Complete Vulnerability Summary

Total: 60 patches tested
         β”‚
         β”œβ”€β”€β”€ YES (Exploitable): 9 patches ────────────► PRIMARY TARGETS
         β”‚    └── Verifier bypassed, real security impact possible
         β”‚
         β”œβ”€β”€β”€ LIMITED (Uncertain): 12 patches ─────────► SECONDARY TARGETS  
         β”‚    └── Passed verifier, constrained exploitation potential
         β”‚
         └─── NO (Not Exploitable): 39 patches
              β”œβ”€β”€ 8 blocked by compiler
              β”œβ”€β”€ 14 blocked by verifier βœ“ (security works)
              └── 17 passed but no security impact

Project visual

Potential investigation scope: 21 patches (9 YES + 12 LIMITED)


What They Did NOT Do

  • ❌ Create actual working exploits
  • ❌ Achieve arbitrary kernel read/write
  • ❌ Demonstrate privilege escalation
  • ❌ Validate impact on real kernel versions

They proved vulnerabilities can bypass the verifier, but stopped at theoretical classification.


Repository Structure

Project_EBPF/
β”œβ”€β”€ README.md                          # This file
β”œβ”€β”€ report/                            # My exploitation reports (TODO)
β”œβ”€β”€ src/                               # My PoC code (TODO)
β”‚
└── ebpf-exploitability-test/          # INHERITED FROM PREVIOUS TEAM
    └── codebase/
        β”œβ”€β”€ README.md                  # Their documentation
        β”œβ”€β”€ docs/
        β”‚   └── ISO-IEC-TS-17961-2013.pdf
        β”‚
        β”œβ”€β”€ virt/                      # VM management
        β”‚   β”œβ”€β”€ vmctl.sh               # Create/destroy/connect to test VM
        β”‚   └── meta-data.yaml
        β”‚
        β”œβ”€β”€ XDPs/
        β”‚   β”œβ”€β”€ xdp_synproxy/          # Main target
        β”‚   β”‚   β”œβ”€β”€ xdp_synproxy_kern.c    # Base vulnerable program
        β”‚   β”‚   β”œβ”€β”€ Makefile
        β”‚   β”‚   β”œβ”€β”€ patches/           # 60+ vulnerability patches
        β”‚   β”‚   β”‚   β”œβ”€β”€ 5_10a_exploit_intptrconv/
        β”‚   β”‚   β”‚   β”œβ”€β”€ 5_14_nullref/
        β”‚   β”‚   β”‚   β”œβ”€β”€ 5_20a_libptr/
        β”‚   β”‚   β”‚   └── ...
        β”‚   β”‚   β”œβ”€β”€ patches.csv        # Summary of all patches
        β”‚   β”‚   β”œβ”€β”€ apply_rules.sh
        β”‚   β”‚   β”œβ”€β”€ start_session.sh
        β”‚   β”‚   └── kill_session.sh
        β”‚   β”‚
        β”‚   β”œβ”€β”€ minimal/               # Minimal exploit examples
        β”‚   β”‚   └── 5_10a_exploit.c
        β”‚   β”‚
        β”‚   └── tools/                 # BPF headers
        β”‚
        β”œβ”€β”€ xvtlas/                    # Automation tool (Go)
        β”‚   β”œβ”€β”€ main.go
        β”‚   β”œβ”€β”€ xvtlas                 # Pre-compiled binary
        β”‚   └── README.md
        β”‚
        └── xvtlas_output/             # Previous test results
            β”œβ”€β”€ report.csv
            └── [per-patch logs]/

My Objective

My work builds directly on this existing client-server/XDP SynProxy architecture. Since the XDP program operates at the network interface, having two hosts (client and server) communicating through the proxy is essential for realistic exploitation.

My objective:

  • Leverage the previous team's infrastructure to perform practical exploitation.
  • Use network packets as the attack vector: generate and send them from a netcat client (on the host) to the netcat server (on the VM), with the XDP SynProxy eBPF program in the middle.
  • Trigger and exploit vulnerabilities injected into the XDP interface via eBPF patches, by crafting specific network traffic.
  • Demonstrate, with real network traffic, which vulnerabilities are exploitable in practice and document the exploitation process.

Goals

  1. Analyze the ~10 "exploitable" vulnerabilities in depth
  2. Develop working PoCs that demonstrate real kernel impact
  3. Document exploitation techniques and verifier bypass methods
  4. Validate severity on LTS 6.8 kernel

Quick Start (Using Inherited Infrastructure)

1. Set Up Test VM

cd ebpf-exploitability-test/codebase/virt/
./vmctl.sh create ~/.ssh/id_rsa.pub
./vmctl.sh connect

2. Test a Vulnerability Patch

# Inside VM
cd ~/ebpf-tests/XDPs/xdp_synproxy/

# Apply a patch
git apply patches/5_10a_exploit_intptrconv/0001-feat-5_10a_exploit.patch

# Compile
make

# Test
./start_session.sh

3. Use xvtlas Automation

cd xvtlas/
./xvtlas --run-single "./patches/5_10a_exploit_intptrconv/*.patch" \
         --base-file "./xdp_synproxy_kern.c"

Practical Exploitation Workflow: Step-by-Step

Prerequisite: Automated Extraction of vmlinux.h for eBPF Compilation

Before compiling the XDP SynProxy eBPF program, the vmlinux.h header is automatically generated from your running kernel's BTF data by the session script. This file provides all kernel type definitions needed for CO-RE (Compile Once, Run Everywhere) eBPF development.

Automated vmlinux.h extraction:

The following command is run automatically by start_session.sh before compilation:

sudo bpftool btf dump file /sys/kernel/btf/vmlinux format c > /mnt/shared/XDPs/xdp_synproxy/vmlinux.h

You only need to run make in /mnt/shared/XDPs/xdp_synproxy after starting the VM and session script. If your shared folder path is different, adjust the output path accordingly.

Why is this needed?

  • The eBPF kernel program uses CO-RE features and requires accurate kernel type definitions.
  • If vmlinux.h is missing, compilation will fail with an error about the missing file.

This section explains the full process for exploiting eBPF verifier vulnerabilities using the inherited infrastructure, including how the Makefile, scripts, and tmux sessions fit together. It also clarifies the difference between the previous team's theoretical work and the practical exploitation phase.

1. Compilation and Loading: The Role of the Makefile

The Makefile in ebpf-exploitability-test/codebase/XDPs/xdp_synproxy/ is responsible for compiling:

  • The eBPF kernel program (xdp_synproxy_kern.c) into bytecode (xdp_synproxy_kern.bpf.o)
  • The user-space loader (xdp_synproxy.c) into an executable (xdp_synproxy)

Workflow:

  1. Run make in the target folder to build both binaries.
  2. The user-space loader is run with sudo to load the eBPF program into the kernel. The eBPF verifier automatically checks the code at load time.
  3. If the code passes, it is loaded and runs in the kernel; if not, it is rejected.

2. Applying Vulnerability Patches

The previous team provided 60+ patches, each injecting a specific vulnerability (based on ISO-IEC TS 17961-2013) into the base code. These patches are applied using git apply:

git apply patches/<patch-folder>/<patch-file>.patch
make clean && make

This allows you to test if the eBPF verifier blocks or accepts the vulnerable code.

3. Setting Up the Test Environment: tmux Sessions and Scripts

The start_session.sh script in the same folder sets up a multi-pane tmux session for interactive testing:

  • Pane 1: Runs the XDP SynProxy loader (sudo ./xdp_synproxy ...) to attach the eBPF program to the network interface.
  • Pane 2: Starts a netcat server (sudo nc -lvnp 80) to listen for TCP connections.
  • Pane 3: Shows kernel debug output (sudo cat /sys/kernel/debug/tracing/trace_pipe).

This environment allows you to:

  • Observe how the eBPF program processes packets
  • See the effects of injected vulnerabilities
  • Test exploitation by sending crafted packets from a client (e.g., using netcat from the host)

4. Exploitation: Client-Server Interaction

After the tmux session is running:

  • The netcat server listens for incoming TCP connections.
  • The client (your host machine or another VM) connects using netcat:
    nc <VM_IP> 80 -v
  • This simulates an attacker sending packets to exploit the loaded eBPF program.
  • The kernel trace and server output help you observe if the vulnerability is exploitable.

5. Theoretical vs. Practical: What Changes

Previous Team (Theoretical):

  • Catalogued vulnerabilities and tested if the eBPF verifier would block them.
  • Did not attempt real exploitation or privilege escalation.

Your Work (Practical):

  • Apply patches, compile, and load the code.
  • Use the tmux session to simulate real attacks and observe kernel impact.
  • Document which vulnerabilities are truly exploitable in practice.

6. Automation Tools

The xvtlas tool (Go-based) can automate patch application, compilation, loading, and result collection for batch testing.


Summary of Practical Exploitation Steps

  1. Start the VM using vmctl.sh and connect.
  2. Compile the base or patched code with make.
  3. Load the eBPF program using the user-space loader (verifier checks it automatically).
  4. Start the tmux session with start_session.sh.
  5. Simulate client attacks using netcat from the host.
  6. Observe results in tmux panes and kernel trace.
  7. Document findings: Did the verifier block the vulnerability? Was it exploitable?

This workflow bridges the gap between theoretical vulnerability assessment and practical exploitation, providing a reproducible, automated environment for eBPF security research.

Progress Tracking

  • Environment setup (VM, kernel 6.8)
  • Study inherited codebase
  • Analyze priority vulnerabilities
  • Develop PoC #1: (TBD)
  • Develop PoC #2: (TBD)
  • Write exploitation report
  • Final documentation

References

Priority Vulnerabilities for Practical Exploitation

The following vulnerabilities are the primary focus for practical exploitation in this project:

  • 5.6a argcomp β€” Function pointer type incompatibility
  • 5.6b argcomp β€” Wrong number of arguments
  • 5.6d argcomp β€” Wrong argument types
  • 5.39 taintnoproto β€” Using tainted values as function pointers without prototypes
  • 5.46b taintsink β€” Memory copy with tainted length

πŸ“– Next Steps

Now that you understand the context and objectives, proceed to the practical exploitation documentation:

β†’ Continue to src/README.md to learn about the exploitation workflow, environment setup, and overall methodology.