
Research repository for CVE-2026-68121, a Linux kernel PPPoE use-after-free in pppoe_sendmsg() enabling local privilege escalation, with PoC, root-cause analysis, and lab setup.
PPPoEject
A Linux kernel memory-corruption vulnerability in the PPPoE transmit path,
caused by a stale pointer to an sk_buff header after a device header callback
reallocates the skb head.
This repository is intended for authorized security research, kernel vulnerability analysis, CTF environments, and defensive testing only.
Do not execute proof-of-concept code against systems without explicit authorization.
| Field | Details |
|---|---|
| CVE | CVE-2026-68121 |
| Codename | PPPoEject |
| Component | Linux Kernel |
| Subsystem | PPPoE / Networking |
| Affected File | drivers/net/ppp/pppoe.c |
| Primary Function | pppoe_sendmsg() |
| Bug Class | Use-After-Free |
| Impact | Kernel memory corruption |
| Potential Impact | Local Privilege Escalation |
| CVSS v3.1 | 7.8 — High |
| Attack Vector | Local |
| Attack Complexity | Low |
| Privileges Required | Low |
| User Interaction | None |
| Status | Patched |
The CVE record identifies the vulnerability as a stale PPPoE header pointer that
can become invalid when dev_hard_header() reallocates the skb head.
The vulnerability exists in:
drivers/net/ppp/pppoe.c
within:
pppoe_sendmsg()
The vulnerable sequence is conceptually:
pppoe_sendmsg()
│
▼
Save PPPoE header pointer
│
▼
dev_hard_header()
│
▼
skb head may be reallocated
│
▼
Old pointer becomes stale
│
▼
PPPoE writes through stale pointer
│
▼
Use-After-Free
│
▼
Kernel memory corruption
Linux networking code allows device header callbacks to reallocate the
sk_buff head. A pointer into the old head therefore cannot safely be reused
after dev_hard_header() returns.
The core issue is a lifetime violation.
pppoe_sendmsg() obtains a pointer to the PPPoE header before invoking:
dev_hard_header()
However, that callback can cause the skb head to move.
Conceptually:
Before callback:
skb
┌──────────────────────────────┐
│ Ethernet │ PPPoE │ Payload │
└──────────┴───────┴───────────┘
▲
│
stale pointer
After skb expansion:
old skb head ──X──► freed
new skb head
┌────────────────────────────────────┐
│ Ethernet │ PPPoE │ Payload │
└──────────┴───────┴─────────────────┘
▲
│
valid location
The old pointer still references the freed allocation.
When PPPoE subsequently writes the header through that pointer, the kernel performs a use-after-free write.
The documented trigger involves a race around copy_from_user() and changes
to a team device's header operations.
One described sequence is:
PPPoE sendmsg()
│
▼
copy_from_user() blocks
│
│
├───────────────┐
│ │
▼ ▼
Team device changes First non-Ethernet
header operations port is added
│
▼
Delegated GRE callback
│
▼
skb head expansion
│ │
└───────────────┘
│
▼
stale PPPoE pointer
│
▼
use-after-free write
The CVE record notes that this can occur when the first non-Ethernet port is added to an empty team device and the delegated GRE header callback expands the skb head.
The vulnerability can result in:
The CVE's published CVSS vector is:
CVSS:3.1/AV:L/AC:L/PR:L/UI:N/S:U/C:H/I:H/A:H
with a base score of 7.8 High.
The relevant components are:
PF_PPPOX / PPPoE socket
│
▼
pppoe_sendmsg()
│
▼
sk_buff (skb)
│
▼
dev_hard_header()
│
▼
Network device header callback
│
▼
Potential skb head expansion
│
▼
PPPoE stale header pointer
│
▼
UAF write
The vulnerable code is therefore not simply a generic PPPoE packet parser; the critical condition is the interaction between PPPoE socket transmission and dynamic skb head reallocation.
The upstream fix is titled:
pppoe: reload header pointer after dev_hard_header()
The fix reloads the PPPoE header through the skb's network-header offset after device header creation.
The important property is:
Before:
header pointer
│
▼
dev_hard_header()
│
▼
skb moves
│
▼
pointer = stale ❌
After:
dev_hard_header()
│
▼
skb may move
│
▼
reload header using skb offset
│
▼
pointer = valid ✅
pskb_expand_head() updates the relevant skb offset when the skb head is
relocated, making the offset-based lookup safe after reallocation.
| Security Property | Vulnerable | Patched |
|---|---|---|
| Header pointer saved before callback | ✅ | — |
| skb head can move | ✅ | ✅ |
| Pointer refreshed after callback | ❌ | ✅ |
| Stale pointer dereference | Possible | Prevented |
| Use-after-free write | Possible | Mitigated |
| Kernel memory corruption | Possible | Mitigated |
A controlled laboratory can be structured as: