Skip to content

AF_VSOCK transport-reassignment UAF LPE (CVE-2024-50264)

AF_VSOCK'ta connect() ile bir POSIX signal arasındaki bir race, dangling bir vsk->trans pointer'ı bırakır ve bir kworker'ın hâlâ yazdığı bir virtio_vsock_sock object'ini free eder — local privilege escalation için exploit edilebilir bir use-after-free.

Mechanism

Invariant: bir worker hâlâ reference ederken bir transport yeniden atanmamalıdır

AF_VSOCK socket'leri, connection'ın send/receive defter tutmasını destekleyen bir transport object'i tutar (vsk->trans, burada bir virtio_vsock_sock). Invariant şu: virtio TX/RX kworker'ı dahil herhangi bir kernel context'i ona hâlâ ulaşabildiği sürece bu object hayatta kalmalıdır.

CVE-2024-50264 bu invariant'i connect() syscall'ı ile bir POSIX signal arasındaki bir race üzerinden kırar. Bir signal blocking bir connect()'i kesintiye uğratırsa, socket TCP_CLOSING'e geçebilir; ardından farklı parametrelerle ikinci bir connect(), vsock_assign_transport()'u sürer ve bu da bir worker hâlâ reference tutarken mevcut virtio_vsock_sock'u free eder. Freed object 80 byte'tır ve kmalloc-96'ya düşer. Bug 2016'da 06a8fc78367d commit'iyle (v4.8) tanıtıldı ve stale pointer'ın yeniden kullanılamaması için vsk->transNULL'a initialize ederek düzeltildi.

UAF write, bir kworker'da çalışan virtio_transport_space_update() freed object'e 4-byte field'lar (peer_buf_alloc, peer_fwd_cnt) yazdığında gerçekleşir. Pratik bir kısıt: object'in tx_lock field'ı sıfırdan farklıysa worker spin_lock_bh()'te spin'ler, dolayısıyla reclaim eden spray bir hang'i önlemek için o field'ı sıfır tutmalıdır. ("perf/vsock" alias'ı, bu UAF'in çoğu zaman perf-event race UAF'leriyle birlikte kataloglanmasını yansıtır; gerçek subsystem virtio vsock'tur.)

Walkthrough

Yalnızca yetkili test

Yalnızca vmw_vsock_virtio_transport yüklü tek kullanımlık bir VM'de reprodüksiyon yap. Bug, namespace yetkisi olmayan unprivileged bir kullanıcı tarafından ulaşılabilir.

Yayımlanan analiz (Alexander Popov, PT SWARM) signal-driven bir race'i bir heap-spray reclaim ile zincirler:

/* 1. interrupt a blocking connect() with a timer-fired signal so the socket
 *    drops into TCP_CLOSING without creating the paired object */
/* signal 33 (NPTL-reserved) is used to interrupt connect() cleanly */

/* 2. second connect() with a different svm_cid -> vsock_assign_transport()
 *    frees the virtio_vsock_sock (kmalloc-96) while a kworker still refs it */
struct sockaddr_vm addr2 = { .svm_family = AF_VSOCK, .svm_cid = OTHER_CID };
connect(s, (struct sockaddr *)&addr2, sizeof(addr2));   /* UAF window opens */
# reclaim the freed kmalloc-96 chunk with a controlled object (msg_msg),
# keeping the byte at the tx_lock offset zero so the kworker does not hang;
# the kworker's 4-byte writes (peer_buf_alloc/peer_fwd_cnt) then corrupt the
# reclaimer for a write primitive.
Debug kernel'de beklenen sinyal

BUG: KASAN: slab-use-after-free in virtio_transport_space_update+0x...
Write of size 4 at addr ffff8881........ by task kworker/...
Freed by task <pid>: kfree ... virtio_transport_destruct ... vsock_assign_transport
Güvenilir exploitation CONFIG_RANDOM_KMALLOC_CACHES ve CONFIG_SLAB_BUCKETS'i, tipik olarak bir page-level cross-cache attack ile yenmek zorundadır.

Detection

  • vsock_assign_transport()/virtio_transport_destruct() üzerinden free edilen, bir kworker tarafından yazılan virtio_transport_space_update() içinde KASAN slab-use-after-free.
  • Self-directed signal'lerle iç içe geçmiş olağandışı AF_VSOCK connect() fırtınaları.

Mitigation

  • Patch: upstream fix, transport assignment path'inde vsk->trans = NULL initialize eder ve dangling-pointer reuse'unu kapatır. Distro backport'larını uygula.
  • Kullanılmadığı yerlerde (container'lar/hypervisor guest'leri) vsock'u kısıtla: vsock/vmw_vsock_virtio_transport'u blacklist'le.
  • Slab hardening (CONFIG_RANDOM_KMALLOC_CACHES, CONFIG_SLAB_BUCKETS) çıtayı yükseltir ama SLAB_VIRTUAL yokluğunda cross-cache reclaim'i engellemez.

Bu UAF reclaim/cross-cache akışı, vsock UAF, transport-reassignment refcount UAF ve cross-cache attack grooming'iyle örtüşür.

References