Skip to content

vsock transport reassignment refcount UAF (CVE-2025-21756)

Transport reassignment'ın zaten unbound bir socket'i unbind ettiği bir Linux af_vsock reference-counting kusuru; vsock_sock'u, bind table'da linkli kalırken erken free eder — root'a escalate edilebilir bir use-after-free.

Mechanism

Note

vsock, socket'leri bound/unbound listelerinde tutar ve o liste üyeliği bir reference tutar. Kırılan invariant: gerçekte gerçekleşmeyen bir liste removal'ı için bir reference düşürülür. Transport reassignment sırasında (örn. connect()'te), vsock_remove_sock(), hiçbir zaman bound listede olmamış bir socket üzerinde vsock_remove_bound()'u çağırabilir ve vsock_sock refcount'unu bir fazla decrement edebilir. Object sonra bind table ve dangling handle üzerinden hâlâ erişilebilirken free edilir — socket object'inin bir use-after-free'i. Bkz. vsock-uaf ailesi.

Walkthrough

Üst düzey, açık hoefler.dev writeup'ından. Yalnızca kavramsal aşamalar — offset yok.

  1. Refcount dengesizliğini kışkırt. Transport reassignment'ı tetikleyen bind/connect dizisini sür ki buglı unbind yolu çalışsın ve socket'in reference count'unu fazla decrement etsin, bir userland handle kalırken vsock_sock'u free etsin:
vsock_create()          -> refcnt = 1; vsock_insert_unbound() -> +1
transport reassignment  -> vsock_remove_sock() wrongly runs vsock_remove_bound() -> -1
later vsock_bind()      -> assumes still-unbound, removes again -> object freed early
  1. Reclaim the freed slot. Groom the SLUB cache and reclaim the freed object's memory with an attacker-controlled buffer of the same size class — the writeup uses pipe buffers — so the dangling socket now overlays controlled bytes. See heap-grooming-feng-shui.

  2. Defeat KASLR via a benign side channel. Most operations on the recycled socket are blocked by AppArmor LSM hooks (they panic before anything useful happens). The writeup routes around this using vsock_diag_dump() — not gated by those hooks — as an oracle to brute-force a kernel pointer and recover the kernel base.

  3. Hijack a function pointer. With the overlay controlled, overwrite a socket callback (the writeup targets sk->sk_error_report) with a stack-pivot gadget, then drive vsock_release()sk_prot->close() → the error-report callback to pivot onto a ROP chain.

  4. Escalate to root. The chain calls commit_creds(init_cred) (or equivalent) to give the process full privileges.

Why list membership matters

The object stays linked in the bind table after the early free, so the kernel will keep walking and dereferencing a freed (then attacker-reclaimed) vsock_sock during normal lookups — that is what converts a one-off over-decrement into a durable, triggerable UAF.

KASAN signature when the UAF is hit without grooming

Public n-day analysis (the "Attack of the Clones" writeup) reports a slab-use-after-free surfacing on the second removal, in the vsock_remove_bound / vsock_remove_sock path:

BUG: KASAN: slab-use-after-free in vsock_remove_bound
Call Trace:
 __vsock_remove_bound+0x...
 vsock_remove_sock+0x...
 ...
Freed by task ...: vsock_release

Detection

  • Unusual AF_VSOCK use from unprivileged/containerized processes. vsock is mainly a guest↔host channel; heavy bind/connect churn from ordinary userland is anomalous.
  • vsock_diag (NETLINK_SOCK_DIAG) queries paired with vsock socket churn can indicate the KASLR-leak oracle being exercised.
  • SLUB/grooming signals: bursts of pipe-buffer allocations sized to the vsock cache, alongside vsock socket create/free storms.
  • Crash/oops telemetry: UAF detectors (KASAN in test fleets) or oopses in vsock_remove_bound / __vsock_bind paths are strong indicators; production EDR should flag kernel oopses referencing vsock symbols.
  • commit_creds/cred-change anomalies — an unprivileged task suddenly running as root with no setuid execve is a generic post-exploit tell.

Mitigation

  • Patch: upstream commit "vsock: Keep the binding until socket destruction" (fcdd2242c0231032fc84e1404315c245ae56322a, merged for 6.14) preserves the binding for the socket's lifetime and removes it only on destruction, fixing the refcount imbalance. Apply the stable backports (5.10/5.15/6.1/6.6/6.12 and later point releases).
  • Reduce attack surface: blacklist/unload the vsock and vmw_vsock_* modules where guest↔host sockets are not needed; restrict AF_VSOCK via seccomp/LSM policy.
  • Hardening that raises cost: KASLR (forces the leak step), SMEP/SMAP/KPTI, CONFIG_SLAB_FREELIST_RANDOM / hardened freelist, and CFI (e.g. CONFIG_CFI_CLANG) break the function-pointer hijack and stack pivot.
  • Defense-in-depth: AppArmor/SELinux already blocked most operations on the recycled socket here; tightening LSM coverage of diagnostic interfaces narrows leak oracles.

References