Follow @Openwall on Twitter for new release announcements and other news
[<prev] [next>] [thread-next>] [day] [month] [year] [list]
Message-ID: <N3qCs2mm52MjtGQdhL__9yEHYhVTbFIkpD8lRZK89ThlWgvKoVMgOhNel9Ke6bwC8g3-z7eaJLKLfHVTwy4ONvh0FZcwTCm5dZO3ScS56FQ=@proton.me>
Date: Wed, 10 Jun 2026 19:19:28 +0000
From: bumsrakete <bumsrakede@...ton.me>
To: oss-security@...ts.openwall.com
Subject: CVE-2026-45257: FreeBSD kTLS-RX in-place AES-GCM decrypt over sendfile(2) EXTPG mbufs to page-cache write / local root

## Summary

An unprivileged local user on a default FreeBSD >= 13.0 system (any
PMAP_HAS_DMAP architecture: amd64, arm64, riscv) can write
attacker-influenced bytes into the page-cache page of any file they can
*read*. The write reaches the backing physical page through the kernel
direct map (DMAP) and never traverses the VFS layer, so it bypasses file
permissions, mount options, and `chflags schg`. This yields a reliable
local privilege escalation (shellcode injection into a SUID-root binary)
and persistent on-disk corruption on UFS.

It is the FreeBSD analogue of Linux's Dirty Pipe. Tracked as
CVE-2026-45257 / FreeBSD-SA-26:26.kTLS.

## Website (Of course, it's a LPE bug!)
https://bumsrake.de

## Merchandise
Sold out! Sorry! :(

## Affected versions

Vulnerable (verified or by inspection):
  - FreeBSD 13.0, 13.1, 13.2, 13.3, 13.4
  - FreeBSD 14.0, 14.1, 14.2
  - FreeBSD 15.0-RELEASE (verified on 15.0-RELEASE-p5/amd64)

Not affected:
  - FreeBSD 12.x and earlier

Preconditions are the stock GENERIC defaults: kern.ipc.mb_use_ext_pgs=1
(the boot-time default on every PMAP_HAS_DMAP arch) and a kernel built
with MK_KERN_TLS (default). No extra module, sysctl, hardware, or
privileged group is required. The vulnerable path was introduced around
2020 (commit 3c0e56850511) and first shipped in 13.0 (April 2021).

## Root cause

The bug is page-cache corruption via an attacker-influenced in-kernel
AES-GCM decrypt running in place over M_EXTPG mbufs produced by
sendfile(2). Three individually-correct subsystems compose unsafely:

  (1) sendfile(2) produces vnode-backed EXTPG mbufs.

      sys/kern/kern_sendfile.c:963
          m0 = mb_alloc_ext_pgs(M_WAITOK, sendfile_free_mext_pg, M_RDONLY);

      m_epg_pa[] then holds the physical addresses of the file's actual
      page-cache pages.

  (2) TCP_RXTLS_ENABLE performs no privilege check.

      sys/netinet/tcp_usrreq.c:2222
          case TCP_RXTLS_ENABLE:
              INP_WUNLOCK(inp);
              error = ktls_copyin_tls_enable(sopt, &tls);
              ...
              error = ktls_enable_rx(so, &tls);

      Any unprivileged user can enable software kTLS RX on a TCP socket
      they own and supply the AES-128-GCM key, salt, and rec_seq of their
      choice.

  (3) The decrypt runs in place against the page-cache page.

      sys/opencrypto/criov.c:273
          return (PHYS_TO_DMAP(m->m_epg_pa[i] + pgoff + skip));

      sys/crypto/aesni/aesni.c:599-605 (AES_GCM_decrypt, in==out)
      The "output buffer" is a DMAP pointer at the file's page-cache page;
      the plaintext is written there.

Because plaintext = ciphertext XOR keystream(K, IV), and both the
ciphertext (the file's existing bytes, delivered by sendfile) and K/IV
(the attacker's) are known, the attacker fully controls every byte
written into the page.

## The three incomplete guards

The kernel has three mechanisms that would normally prevent an EXTPG
mbuf from reaching an in-place decrypt; each is bypassable here:

  Guard 1 - mb_unmapped_compress (uipc_sockbuf.c:153, :1441):
    copies EXTPG bytes into a flat mbuf (kern_mbuf.c:859-897), but is
    gated on m_len <= MLEN (~224 on amd64). Sending records with a
    240-byte payload walks past it.

  Guard 2 - mb_unmapped_to_ext (ip_output.c:746): converts EXTPG chains
    when the outbound ifp lacks IFCAP_MEXTPG (true for loopback). But
    _mb_unmapped_to_ext (kern_mbuf.c:940-1077) does not copy bytes; it
    allocates an sf_buf per page, and on these architectures
    sf_buf_kva == PHYS_TO_DMAP(pa). The "mapped" mbuf still points at the
    same physical page.

  Guard 3 - sb_mark_notready (uipc_ktls.c:1183-1207): moves queued data
    from sb_mb into the kTLS decrypt queue sb_mtls with no M_EXTPG check
    at all.

## Exploitation

A rather stable (who would have thought) exploit (bumsrakete.c) is attached.

Flow: the attacker sendfile(2)s the target file into a TCP socket looped
back to itself (lo0), with TCP_RXTLS_ENABLE configured using its own
key/IV. lo0 lacks IFCAP_MEXTPG, so Guard 2 remaps (not copies) the EXTPG
onto the same physical page; the kTLS RX path then decrypts in place into
the page cache.

To produce a record whose on-wire ciphertext equals the file's current
bytes (so GMAC validates) while the decrypt yields chosen plaintext:

    compute_ks(key, salt, iv8, RECORD_W, ks);   /* AES-CTR keystream */
    for (i = 0; i < RECORD_W; i++)
        pt[i] = file_bytes[i] ^ ks[i];          /* so ct == file_bytes */
    gcm_encrypt(key, iv12, aad, sizeof aad,
                pt, RECORD_W, ct, tag);          /* valid tag for wire */

The PoC injects a 36-byte setuid(0)+execve("/bin/sh") shellcode into the
entry of /usr/bin/su (36 records) or any other suid binary, executes it
for the privilege gain, then restores the original bytes.
End-to-end LPE wall time is ~1.5s.

The target's schg,uarch flags do NOT prevent the overwrite and the
corruption persists to disk (UFS). The chflags schg bypass is a nice
bonus.

## Impact

- Local privilege escalation to root (default, reliable, no race).
- Arbitrary modification of any file the attacker can read, bypassing
  permissions, immutable flags, and read-only intent.
- Affects any multi-tenant FreeBSD deployment (jails, hosting,
  containers) with the default capability set.

## Mitigation

The vendor fix is FreeBSD-SA-26:26.kTLS. Subscribe to
freebsd-security-notifications@ and apply when available.

## Timeline

2026-05-13  Reported to secteam@...eBSD.org
2026-06-09  Advisory and patch published; this disclosure; merchandise sale

## Credit

Discovered, analyzed, and reported by Bumsrakete.
Responsibly disclosed to secteam@...eBSD.org.

## References

- CVE-2026-45257
- FreeBSD-SA-26:26.kTLS

View attachment "bumsrakete.c" of type "text/x-csrc" (19377 bytes)

Powered by blists - more mailing lists

Please check out the Open Source Software Security Wiki, which is counterpart to this mailing list.

Confused about mailing lists and their use? Read about mailing lists on Wikipedia and check out these guidelines on proper formatting of your messages.