# Linux Kernel Exploitation

> Use when turning a Linux kernel memory-safety, race, reference-count, or logic flaw into a stable local privilege-escalation chain across SLUB, modern mitigations, distro kernels, QEMU labs, and production-like builds.

- Skill: `netvar1337/linux-kernel-exploitation` (Agent Skill, multi-file: 2 files)
- Install (CLI): `npx skillmds@latest add netvar1337/linux-kernel-exploitation`
- Raw SKILL.md: https://api.skillmd.com/api/skills/netvar1337/linux-kernel-exploitation/raw
- Safety review: pending
- Works with: Claude Code, Claude.ai, OpenAI Codex
- Category: Coding & Dev Tools
- License: MIT
- Author: netvar1337 (https://skillmd.com/u/netvar1337)
- Updated: 2026-09-17
- Page: https://skillmd.com/skills/netvar1337/linux-kernel-exploitation

---

# Linux kernel exploitation

Use this skill to convert a confirmed Linux kernel bug into measured capabilities and a repeatable local privilege-escalation chain. Treat every layout, symbol, mitigation, and allocator behavior as specific to the exact kernel build.

## When to use

Use this skill when the task involves:

- a Linux kernel use-after-free, overflow, out-of-bounds access, race, refcount bug, or type confusion;
- SLUB grooming, slab spraying, cross-cache reclaim, page allocator reuse, or page-table UAF work;
- `msg_msg`, `pipe_buffer`, `sk_buff`, keyring, seq-file, io_uring, or similar reclaim objects;
- KASLR leaks, kernel ROP/JOP, SMEP, SMAP, KPTI, CFI, CET/IBT, or FG-KASLR constraints;
- data-only escalation through credentials, namespaces, usermode-helper state, page cache, or page tables;
- a QEMU, GDB, KASAN, KFENCE, KCOV, or syzkaller exploit-development lab.

Do not use it for initial bug discovery without a kernel-specific primitive; route broad discovery to `vuln-research` or `offensive-fuzzing`. Route verifier/JIT-specific eBPF bugs to `ebpf-offensive` until a generic kernel capability exists.

## Completion standard

A completed case pins the target build, states the root cause, proves each primitive independently, explains the chosen escalation path, and records reliability on both instrumented and production-like kernels. A root shell without a capability trace, negative control, and cleanup result is not completion.

## Core workflow

### 1. Freeze target identity

Record the kernel, distribution, module, configuration, boot line, and CPU before interpreting a crash:

```bash
uname -a
cat /etc/os-release
cat /proc/version
cat /proc/cmdline
sha256sum /boot/vmlinuz-"$(uname -r)" 2>/dev/null
zcat /proc/config.gz 2>/dev/null || cat /boot/config-"$(uname -r)"
cat /sys/kernel/security/lockdown 2>/dev/null
sysctl kernel.kptr_restrict kernel.dmesg_restrict kernel.unprivileged_userns_clone 2>/dev/null
```

Preserve `vmlinux`, `System.map`, modules, initramfs, BTF, compiler version, config, patch set, and package build ID together. Hash each artifact. For a module, capture `modinfo`, ELF build ID, vermagic, signer, load address evidence, and source revision when available.

Extract and validate symbols rather than borrowing offsets from a nearby release:

```bash
readelf -n ./vmlinux | grep -A4 'Build ID'
nm -n ./vmlinux > symbols.sorted
pahole -C task_struct ./vmlinux
bpftool btf dump file /sys/kernel/btf/vmlinux format c > vmlinux.btf.h
```

Record allocator and mitigation configuration explicitly: `CONFIG_SLUB`, `CONFIG_SLAB_FREELIST_RANDOM`, `CONFIG_SLAB_FREELIST_HARDENED`, `CONFIG_RANDOM_KMALLOC_CACHES`, `CONFIG_KASAN`, `CONFIG_KFENCE`, `CONFIG_KPTI`, `CONFIG_CFI_CLANG`, `CONFIG_X86_KERNEL_IBT`, `CONFIG_HARDENED_USERCOPY`, `CONFIG_REFCOUNT_FULL`, `CONFIG_STATIC_USERMODEHELPER`, and unprivileged namespace policy.

### 2. Turn the root cause into a capability contract

Write the object lifetime as an event sequence:

```text
allocation -> publication -> references -> mutation -> release -> stale use -> final cleanup
```

For each stage identify the allocating cache, size, GFP flags, CPU, lock or RCU domain, refcount owner, destructor, and attacker-controlled fields. Then score the actual capability:

| Property | Evidence to capture |
| --- | --- |
| Trigger | Exact syscall/ioctl/netlink/file operation and required privilege |
| Lifetime | Which event creates the stale reference and which event consumes it |
| Control | Controlled bytes, alignment, width, encoding, and write count |
| Read | Address choice, length, repeatability, and fault behavior |
| Write | Relative or absolute target, mask, width, and atomicity |
| Leak | Pointer class, entropy removed, provenance, and stability |
| Overlap | Original and reclaim object, cache/page identity, and proof |
| Race | Winning event, losing event, synchronization signal, and rate |

Separate these milestones: reproducible trigger, controlled overlap, disclosure, constrained corruption, arbitrary read/write, mitigation bypass, stronger identity, and stable cleanup. Never collapse an API that exposes data into an arbitrary-read claim without proving address selection and width.

### 3. Build a deterministic lab

Keep two builds:

- an instrumented diagnosis kernel with KASAN or KFENCE, debug info, frame pointers, and aggressive panic settings;
- a production-like kernel matching the target allocator, optimization, hardening, preemption, and mitigation state.

A reproducible x86-64 launch records all inputs and exposes serial, GDB, QMP, and snapshot control:

```bash
qemu-system-x86_64 \
  -m 2048 -smp 2 -cpu host \
  -kernel "$BZIMAGE" -initrd "$INITRAMFS" \
  -append "console=ttyS0 panic_on_warn=1 oops=panic" \
  -nographic -snapshot -enable-kvm -s \
  -qmp unix:"$CASE/qmp.sock",server=on,wait=off
```

Use `nokaslr` only to establish the root cause; restore KASLR before claiming an exploit chain. Save the exact QEMU binary version, command line, disk hash, kernel hash, initramfs hash, and guest CPU count.

Synchronize races on the event that matters: a breakpoint, completion, eventfd, FUSE request, userfaultfd fault when policy permits it, netlink acknowledgment, or observed object state. Do not use fixed sleeps as proof of a race window. Pin threads with `sched_setaffinity`, record scheduler policy, and vary CPU count deliberately.

In GDB, break at allocation, free, stale use, and corrupted dereference. Assert object address, cache identity, refcount, and field values at each stop. Capture the first bad access and the earlier lifetime violation; the final panic alone is insufficient.

### 4. Model allocator behavior before spraying

Derive the target cache from the actual allocation path and object size. Inspect `/proc/slabinfo`, `/sys/kernel/slab`, tracepoints, `kmem` events, or allocator breakpoints. Account for:

- dedicated versus generic `kmalloc-*` caches;
- cgroup-accounted `kmalloc-cg-*` caches;
- per-CPU freelists, partial slabs, and NUMA nodes;
- freelist randomization and hardened pointer encoding;
- cache merging, random kmalloc caches, constructors, and RCU-delayed free;
- order-N page allocations and when reclaim crosses from SLUB to the buddy allocator.

Choose spray objects by matching size, cache domain, allocation flags, lifetime control, data control, and teardown behavior. Common candidates are starting points, not universal recipes:

| Object family | Useful property | Constraint to prove |
| --- | --- | --- |
| `msg_msg` | Sized payload and linked objects | Namespace policy, segment layout, and queue cleanup |
| `pipe_buffer` | Function pointer and page references | Pipe sizing, merge flags, and reference ownership |
| `sk_buff` data | Network-driven payload and repeated allocation | Cache path, headroom, protocol, and namespace limits |
| key payloads | Persistent controlled data | Quotas, type behavior, revocation, and RCU lifetime |
| seq operations | Callable operations table | File lifetime, target cache, and indirect-call policy |
| io_uring objects | Rich asynchronous lifetimes | Kernel version, disabled features, and worker teardown |

Prove overlap with allocator traces or debugger state. Payload resemblance at a stale pointer is suggestive; matching slab/page identity and object lifetime is proof.

### 5. Construct disclosure and corruption primitives

For a disclosure, identify the leaked pointer's object and mapping class before deriving a base. Validate the base against at least two symbols or section bounds. Distinguish direct-map, heap, module, text, vmemmap, and userspace pointers.

For a write, record whether it is relative, absolute, additive, bitwise, repeated, or single-shot. Build read/write tests against disposable sentinel objects before touching escalation state. Check unaligned access, page crossing, fault recovery, and concurrent readers.

When a corrupted callback is considered, validate the exact prototype, calling convention, CFI type hash, IBT landing requirement, execution context, preemption state, locks held, and cleanup path. Prefer data-only chains when they are narrower and more reliable.

### 6. Select the escalation path by constraints

Use the least fragile capability that reaches the required identity:

1. **Credential API path:** resolve exact-build `prepare_kernel_cred` and `commit_creds` prototypes and calling constraints; preserve a valid return path.
2. **Credential data path:** prove ownership and references for the current task's `cred`; account for `kuid_t`, `kgid_t`, capability sets, securebits, LSM state, and user namespace identity.
3. **Namespace path:** root inside a user namespace is not host root; map `user_ns`, `mnt_ns`, `pid_ns`, and cgroup boundaries before claiming escape.
4. **Usermode-helper path:** verify the relevant global remains writable and callable on this build; account for `CONFIG_STATIC_USERMODEHELPER`, lockdown, namespaces, and filesystem reachability.
5. **Page-cache path:** prove the page, mapping, offset, writeback behavior, and filesystem semantics; avoid assuming a Dirty Pipe-era flag state exists.
6. **Page-table path:** prove page ownership, PTE level, TLB coherency, writable alias, and teardown; a page UAF does not automatically become a page-table UAF.
7. **ROP/JOP path:** use only when data paths are blocked; build from the exact image and model KASLR, CFI, IBT, KPTI, SMEP, SMAP, and interrupt state.

For x86-64 kernel return-to-user chains, preserve `CS`, `SS`, `RSP`, `RFLAGS`, GS state, and the build's KPTI return machinery. Do not transplant a `swapgs` trampoline or gadget offsets between builds.

### 7. Measure mitigation survival

Create a per-target matrix rather than a generic bypass list:

| Mitigation | What to measure |
| --- | --- |
| KASLR / FG-KASLR | Required leak, remaining entropy, text/function ordering |
| SMEP / SMAP | Whether execution or access enters userspace and under what AC state |
| KPTI | Active page tables and valid return path |
| CFI | Indirect-call type compatibility and enforcement mode |
| CET / IBT | Valid indirect targets, shadow-stack state, and kernel support |
| Hardened usercopy | Object/cache bounds and copy direction |
| Refcount hardening | Saturation behavior and failed decrement semantics |
| Read-only data | Section permissions and viable alternative target |
| Lockdown / LSM | Blocked interfaces, policy mode, and post-escalation boundary |

A mitigation is bypassed only when the complete chain survives with it enabled on the claimed build.

### 8. Engineer reliability and cleanup

Run diagnosis and production-like variants separately. Record at least trigger rate, overlap rate, leak rate, corruption rate, escalation rate, panic rate, and median/maximum completion time. A 100-run campaign is a useful release gate when reboot automation and cleanup are deterministic.

Classify each failure at the earliest missing milestone. Preserve serial logs, panic dumps, allocator traces, and exploit state. Do not hide failed attempts inside one aggregate success percentage.

On both success and failure:

- close message queues, pipes, sockets, keys, files, and io_uring instances;
- restore modified namespace, sysctl, CPU-affinity, and resource-limit state;
- release sprays in an order that cannot re-trigger the stale reference;
- verify no delayed work, RCU callback, reference leak, or corrupted global remains;
- reboot or restore the snapshot when invariant restoration cannot be proven.

## Key structures & interfaces

- `task_struct`: current identity, parentage, `cred`, `real_cred`, files, namespaces, and scheduling state.
- `cred`: immutable-by-contract credential object with refcounted ownership, UID/GID wrappers, capability sets, securebits, and keyrings.
- `nsproxy`, `user_namespace`, `mnt_namespace`, `pid_namespace`: determine whether an apparent UID 0 crosses the intended boundary.
- `kmem_cache`, `slab`, freelist state, and page allocator metadata: allocator provenance and reclaim behavior.
- `msg_msg` / `msg_msgseg`: queue payload layout and segmented allocation.
- `pipe_inode_info` / `pipe_buffer`: ring entries, page references, offsets, lengths, flags, and operations.
- `sk_buff`: head/data/tail/end geometry, fragments, ownership, destructor, and protocol context.
- `key` and payload types: quota, reference, RCU, revoke, and destructor semantics.
- `file`, `file_operations`, `seq_file`, `seq_operations`: callback-bearing lifetime surfaces.
- `mm_struct`, `vm_area_struct`, PGD/P4D/PUD/PMD/PTE, and `struct page`: virtual-to-physical and page-ownership chains.
- `refcount_t`, `kref`, RCU, workqueues, timers, completions, wait queues, and locks: lifetime and race boundaries.
- Syscall, ioctl, netlink, filesystem, BPF, and io_uring entry points: preserve the exact user-to-kernel trigger schema.

## Tooling

| Need | Preferred tools |
| --- | --- |
| Build identity and symbols | `readelf`, `eu-readelf`, `nm`, `pahole`, `objdump`, `bpftool btf` |
| Static root-cause analysis | IDA, Ghidra, source plus exact compiler/config, Coccinelle |
| Dynamic kernel debugging | QEMU, GDB, Pwndbg/GEF, `drgn`, crash, kdump |
| Memory diagnostics | KASAN, KFENCE, KMSAN, UBSAN, SLUB debug, page poisoning |
| Coverage and discovery | KCOV, syzkaller, kAFL, perf, tracefs |
| Allocator/lifetime tracing | kmem tracepoints, ftrace, perf, bpftrace in a diagnosis build |
| Reproducible automation | QMP, VM snapshots, initramfs scripts, serial capture, build manifests |

Keep instrumentation effects visible. KASAN changes object size and timing; SLUB debug changes freelists; tracing changes races. Reconfirm every primitive without diagnosis-only features.

## Evidence outputs

Maintain a compact case directory:

```text
target.md          distro, kernel, config, boot line, mitigations, hashes
root-cause.md      allocation/lifetime timeline and first invalid operation
capabilities.md    trigger, overlap, leak, read/write, controls, confidence
allocator.md       caches, sizes, CPUs, spray/reclaim evidence
chain.md           escalation decision, offsets, symbols, return and cleanup
runs.csv           build, seed, CPU count, milestones, result, timing, crash
artifacts/         vmlinux, BTF, logs, dumps, traces, minimized reproducer
```

Label claims **observed**, **inferred**, or **unverified**. Keep exploit-only offsets tied to image hash and validation method.

## Pitfalls & OPSEC

- Do not borrow offsets, cache sizes, gadgets, or struct layouts from a nominally similar distribution release.
- Do not equate KASAN reproducibility with production exploitability; diagnostics alter layout and timing.
- Do not use fixed sleeps for races. Synchronize on the precise kernel event and bound every wait.
- Do not assume `msg_msg`, userfaultfd, unprivileged user namespaces, io_uring, or eBPF is available under target policy.
- Do not call an overlap controlled until cache/page identity and lifetime are evidenced.
- Do not mutate shared `cred` objects blindly; incorrect reference or namespace handling can affect unrelated tasks or crash cleanup.
- Do not treat UID 0 in a container or user namespace as host-root impact.
- Keep crash collection, reboot behavior, disk writes, core dumps, and serial logs inside the case artifact plan.
- Record all kernel taint, module loading, sysctl changes, debug mounts, BPF probes, and VM-side files.
- Remove secrets and environment-specific tokens from reproducer bundles while retaining hashes and provenance.
- Use snapshot rollback when page tables, globals, refcounts, or RCU state cannot be proven restored.

## Routing

- Route generic crash-to-capability reasoning and cross-platform exploit planning to `exploit-dev`.
- Route verifier, JIT, map, helper, or hook-specific eBPF work to batch-B sibling `ebpf-offensive`.
- Route post-root host enumeration, secret provenance, persistence assessment, and lateral pivots to batch-B sibling `linux-host-post-exploitation`.
- Route custom beacon runtime or task-protocol work to batch-B sibling `c2-implant-engineering`.
- Route COFF/BOF module construction to batch-A sibling `bof-coff-development`.
- Route Windows RPC, COM, DCOM, NDR, or ALPC boundaries to batch-A sibling `windows-rpc-com-attack`.
- Route ETW, WPP, TraceLogging, or Windows provider measurement to batch-A sibling `windows-telemetry-etw`.
- Route Hyper-V hypercalls, VMBus, worker processes, or partition boundaries to batch-A sibling `hyper-v-offensive`.
- Route broad kernel discovery to `vuln-research` and `offensive-fuzzing`; route memory-image reconstruction to `memory-forensics`.

## Final gate

- [ ] Exact kernel, config, modules, symbols, BTF, mitigations, and launch state are pinned.
- [ ] Root cause and object lifetime are evidenced before exploit construction.
- [ ] Overlap, leak, read, and write capabilities are tested independently with negative controls.
- [ ] Escalation path accounts for credentials, namespaces, LSM, and active mitigations.
- [ ] Race synchronization observes a real event and uses no timing luck.
- [ ] Reliability results separate each milestone and both kernel variants.
- [ ] Cleanup or snapshot restoration is verified after success and failure.

