ipv6_frag_escape: Linux LPE - Reliable Jail/Container Escape
Summary
Proof of concept for a Linux local privilege escalation and container/jail escape via an IPv6 fragmentation bug in the kernel, targeting CentOS/RHEL 10.
View Cached Full Text
Cached at: 06/29/26, 06:30 PM
sgkdev/ipv6_frag_escape
Source: https://github.com/sgkdev/ipv6_frag_escape
IPV6_FRAG_ESCAPE
A reliable unprivileged container / jail escape proof of concept for CentOS / RHEL 10.
It rides a now fixed IPv6 fragmentation bug in __ip6_append_data() (closed upstream by
38becddc, no CVE), an in-slab linear overflow into the skb_shared_info at the tail of a
packet’s own head object. This README documents the exploitation chain only. It does not
cover the trigger.
Scope
- Target: CentOS / RHEL 10 (kernel 6.12.x, e.g.
6.12.0-242.el10). - Start: an unprivileged process inside a network isolated container, with access to unprivileged user namespaces.
- Result: an interactive root shell in the host’s initial namespaces and root filesystem.
Notes
This is a proof of concept, deliberately not a turnkey weapon. The reliability scaffolding
is intentionally left out: no per-CPU PCP grooming, no cross-cache SLUB armoring, and the
skb head is placed in a shared, not so quiet cache. What ships fires often enough to
prove the chain, and not much more. It is scoped to CentOS / RHEL 10 only.
Requirements
CONFIG_INIT_ON_ALLOC_DEFAULT_ONoff, the RHEL / CentOS default. This PoC plants a stale pointer in uninitialised slab bytes; withinit_on_alloc=1that slot is zeroed and this particular technique only crashes the kernel (a NULL deref). That is a limit of the technique, not of the bug: a full exploit that also covers those kernels, with a different technique, will follow once the fix and CVE are public.- 5-level paging (LA57, 57-bit linear addresses). The page table walk is wired for five levels and a startup check refuses to run without it. A 4-level CPU would need the walk refactored.
/sys/kernel/btf/vmlinuxpresent and world readable (stock on RHEL / CentOS).
Tested kernels
| Distro | Kernel | Result |
|---|---|---|
| CentOS Stream 10 | 6.12.0-242.el10 | root, container escape |
| RHEL 10 | 6.12.0-228.el10 | httpd_t context escape |
Exploitation chain
-
In-slab overflow to a self-UAF. The bug yields control of the single
nr_fragsbyte inskb_shared_info. The free path (skb_release_data()) walksfrags[0 .. nr_frags)andput_page()s each entry, andfrags[]is never initialised. We pre-plant astruct page *for a pipe buffer page into that slab slot through controlled cache reuse, then setnr_fragsto 1, so the teardown drops a reference on a page we still own. The linear overflow becomes a page use-after-free. The overflow never touchesfrags[0], so it need not be timed against the spray, which is most of what makes it forgiving. -
Page UAF to Dirty-Pagetable. The freed pipe page is reclaimed as a last-level page table by faulting a fresh anonymous mapping. One physical page is now both a live leaf page table and the page the pipe still reads and writes. Writing eight bytes to the pipe installs a forged PTE; reading the pipe reads the table back. This is a finite arbitrary physical read/write, on the order of 460 PTE windows per table.
-
Defeat KASLR. With the physical read we scan the fixed low-memory SMP trampoline page table, which KASLR never relocates; its kernel half entry points at
level4_kernel_pgt, the kernel’s physical base. From thereinit_top_pgt(recognisable by its self-referencing entry 511) is a universal virtual to physical translator, recovering the kernel virtual base and tying our address space to physical memory. -
Finite to infinite read/write. We forge one PTE in the leaf table that points at the table’s own physical address. The matching virtual window then aliases the page table itself, so PTEs become plain memory: unlimited, random access kernel read/write, with no pipe in the loop. Ring 3 TLB coherence is handled by forcing a full mm flush with an oversized
mprotect(). -
Resolve offsets and take credentials. Struct member offsets are read at runtime from
/sys/kernel/btf/vmlinux, not baked in. We locate our owntask_structthrough the vmemmapstruct pagewalk andmm_struct.owner, zero the credential ids, and fill all capability sets oncredandreal_cred. Symbol addresses come from an internal resolver that parses the kernel’s ownkallsymstables through our arbitrary read; only if that fails do we fall back to pointingcred.user_nsatinit_user_ns(soCAP_SYSLOGholds in the initial namespace) and reading the real addresses from/proc/kallsyms. -
Disable SELinux without flipping enforcing. We overwrite the prologue of
avc_denied()with axor eax, eax ; retstub (stepping overendbr64under IBT). Every denial now returns granted, process wide, whilegetenforcestill reportsEnforcing. This is also a prerequisite for the escape: the core-dump handler’s cross domain re-exec would otherwise be denied. -
Escape through core_pattern. We overwrite the global
core_patternwith a|prefixed handler pointing back at our own binary through/proc/<PID>/root(the crashing task’s container chroot), then crash a child. The kernel runs the handler as a usermodehelper, root in the initial namespaces, and we relay an interactive root shell over a Unix socket bound inside the container. The handler is born inside the init namespaces, so no in-place namespace surgery, and none of its PID-namespace hazards, is needed.
Similar Articles
Dirtyfrag: Universal Linux LPE
A report titled 'Dirty Frag' details a universal Linux Local Privilege Escalation (LPE) vulnerability that allows root access on major distributions by chaining two kernel bugs. The disclosure notes that due to a broken embargo, no patches currently exist for this critical security issue.
Fragnesia: New Linux Privilege Escalation Exploit
A new Linux privilege escalation exploit called Fragnesia has been released with proof-of-concept code on GitHub.
Linux Compromises, Broken Embargoes, and the Shrinking Patch Window
A report on three serious Linux local privilege escalation vulnerabilities discovered in May 2026, highlighting breakdowns in the disclosure model and implications for production environments.
Zapscape - Guest to host escape in KVM/x86
Zapscape (CVE-2026-64561) is a KVM/x86 shadow MMU use-after-free vulnerability that allows a guest VM to escape to the host and execute code with kernel privileges. The published PoC demonstrates a full guest-to-host escape targeting AMD SVM/NPT on Linux 7.1.3, posing a serious threat to multi-tenant public clouds.
CVE-2026-45257: LPE in FreeBSD via kTLS-RX
A critical local privilege escalation vulnerability in FreeBSD (CVE-2026-45257) allows an unprivileged user to write arbitrary data into the page cache of any readable file, bypassing file permissions and flags, leading to full root compromise. The bug affects default installations of FreeBSD 13.0 and later via unsafe composition of sendfile, KTLS, and in-kernel AES-GCM decryption.