## https://sploitus.com/exploit?id=2D48CF48-2431-5D7F-9C50-4A5EEB275A49
# FreeBSD PF_KEY `sa_len` stack overflow
```
_._ _,-""`-._
(,-.`._,'( |\`-/|
`-.-' \ )-`( , o o)
`- \`_`"'-
meow. _SiCk // afflicted.sh
```
Sibling of **CVE-2026-3038** (rtsock `sa_len` overflow). Same mistake, different socket: PF_KEY's `key_updateaddresses()` copies an attacker-controlled `sa_len` into a stack-local `secasindex` without checking the destination size.
Target: **FreeBSD 15.1-RELEASE-p2** amd64 (offsets + gadgets are for that build).
## The bug
`SADB_UPDATE` can carry `SADB_X_EXT_NEW_ADDRESS_SRC` (and friends). The kernel pulls a `sockaddr` out of that extension and updates the SA address index.
Roughly:
```c
/* key_updateaddresses() - conceptual */
bcopy(newaddr, &saidx->src, newaddr->sa_len);
```
`saidx` lives on the stack inside `key_update()`. `newaddr->sa_len` is under your control (up to what fits in the PF_KEY message). There is no clamp to `sizeof(saidx->src)`.
So you get a classic stack smash: overwrite locals past `saidx->src`, then the saved frame / return address of `key_update()`.
This is the same class as the rtsock bug (trust `sa_len`, copy into a fixed buffer). Different subsystem, same bad habit.
## Why it matters
- Needs a **PF_KEY** socket (`socket(AF_KEY, SOCK_RAW, PF_KEY_V2)`), which needs **`PRIV_NET_RAW`** (root / suser).
- Once you hold the fd, FreeBSD does **not** revoke it on `setuid` drop. Open as root, drop to unpriv, still talk PF_KEY.
- Controlled stack overflow in kernel context β ROP β clear SMEP/SMAP β userspace shellcode β zero creds β root shell.
So: not a pure "from unpriv open raw" bug. It is a **kernel LPE once you can open PF_KEY** (or inherit the fd). The PoC uses `mdo` only as a lab stool to get that socket + `/dev/mem` for leaks; the overflow itself runs after `setuid(1002)`.
## Exploit outline
1. Open PF_KEY as root, FLUSH, REGISTER, ADD an ESP SA.
2. Leave reply mbufs on `so_rcv` (don't drain). Walk own `kinfo_proc` / fd table via `kvm` + `/dev/mem` to leak:
- `struct socket *` for the keysock
- an `M_PKTHDR` mbuf on the receive chain
- a quiet BSS page for a fake `sav` with refcnt 0
3. Drop to unprivileged uid.
4. Send `SADB_UPDATE` with `SADB_X_EXT_NEW_ADDRESS_SRC` and `sa_len = 255`.
5. Overflow plants:
- fake `sav` (BSS - refcnt offset)
- leaked `so`
- real pkthdr `m`
- ROP at saved RIP (`saidx->src + 152` on this kernel):
- `pop rsi; ret`
- CR4 with SMEP/SMAP cleared
- `mov cr4, rsi; ret`
- userspace shellcode
6. Shellcode zeros uid/gid on the cred, `swapgs; iretq` back into `got_root()` β `/bin/sh`.
SIGSEGV handler is a backup if the iretq frame is wrong; creds may already be zeroed.
## Build / run
On the FreeBSD target:
```sh
cc -o pfkey_lpe pfkey_lpe.c -lkvm
# needs root for the socket + mem setup in this PoC
mdo ./pfkey_lpe
# or: su / doas / whatever gets you uid 0 for the open
```
Hardcoded for lab:
- drop target uid `1002` (testuser) - edit `real_uid` if yours differs
- CR4 safe value `0x506E0` (measured on the box; re-measure if CPU/features differ)
- ROP gadgets and struct offsets for **15.1-RELEASE-p2** only
Wrong kernel β wrong offsets β panic. Don't run this on a machine you care about.
## Files
| file | what |
|------|------|
| `pfkey_lpe.c` | full chain PoC |
## Notes / limits
- **Not** unprivileged-from-cold without another bug or a misconfig that hands you PF_KEY / root.
- `/dev/mem` + `kvm` are for leak and fake objects in this PoC; a pure-info-leak variant would drop that dependency.
- Gadgets and `OFF_*` need a retarget pass per kernel build.
- Related: CVE-2026-3038 (rtsock). Patch audits should cover every `sa_len` copy into fixed storage, not just routing sockets.
## Author
**_SiCk** / [0xdeadbeefnetwork](https://github.com/0xdeadbeefnetwork)
afflicted.sh
```
meow.
```