Skip to content

shiftfs double free (CVE-2021-3492)

Ubuntu'nun out-of-tree shiftfs'i, btrfs ioctl'lerini alttaki filesystem'e geçirirken bir copy fault'u yanlış ele alır; cleanup path'ini iki kez çalıştırır ve local privilege escalation için kernel object'lerini double-free eder.

Mechanism

Note

İhlal edilen invariant şu: "bir error/cleanup path'i ile success path'i aynı object'i birlikte release etmemeli." shiftfs belirli btrfs ioctl'lerini proxy'lediğinde kernel object'leri (file descriptor'lar / memdup_user ile heap buffer'ları) allocate eder ve bir copy_*_user fault'unda error handling içinde restore/cleanup helper'ını (shiftfs_btrfs_ioctl_fd_restore) çağırır — ama ana fonksiyon sonra aynı cleanup'ı tekrar çalıştırır. Sonuç, kfree/__close_fd'nin aynı object'ler üzerinde iki kez yürümesidir: bir double-free. Bir double-free, attacker'ın tek bir slab object'ine iki referans elde etmesine ve reallocation'dan sonra use-after-free-tarzı kontrollü bir örtüşmeye (overlap) izin verir.

shiftfs, unprivileged user'ların mount edebileceği (ör. container'lar / user namespace'ler içinde) Ubuntu'ya özgü bir stacking filesystem olduğundan, açık veren ioctl path'i etkilenen Ubuntu kernel'lerinde root olmadan erişilebilirdir.

Walkthrough

Bu, ZDI'nin Pwn2Own Vancouver 2021'inde (ZDI-CAN-13562) bir local privilege escalation olarak gösterildi.

Kavramsal fault-injection şekli
1. Mount shiftfs (reachable from an unprivileged/container context).
2. Issue a btrfs passthrough ioctl that shiftfs marshals via memdup_user.
3. Arrange copy_to_user to fault mid-operation (e.g., userfaultfd-backed
   destination) so the error path runs the fd-restore/cleanup helper...
4. ...and then the main function runs the SAME cleanup again -> double free.
Fix'in şekli (public write-up'tan)
if (!ret) {        /* success: hand ownership back */
    *b1 = v1;
    *b2 = v2;
} else {           /* failure: clean up exactly once */
    shiftfs_btrfs_ioctl_fd_restore(cmd, *newfd, arg, v1, v2);
}

Mantıksal escalation: double-free edilmiş object attacker-kontrollü data ile reclaim edilir ve hassas bir yapıyla örtüştürülür (public write-up bir function pointer'ı corrupt etmek için bir sysctl table'ı hedefler); bu da KASLR/SMAP'i bypass ederken arbitrary read/write ve code execution verir. arbitrary-write-primitive ve cross-cache-attack'e bak.

Detection

  • shiftfs'i mount edip hemen btrfs ioctl'leri veren unprivileged/container process'leri için alert ver — normal workload'lar için atipiktir.
  • Güvenilmeyen process'ler tarafından userfaultfd kullanımı, double-free/UAF race'leri için güçlü bir fault-injection sinyalidir; gerekmediği yerde logla.
  • KASAN kernel'leri shiftfs ioctl path'lerinde "double-free" / "invalid-free" splat'ları üretir.
  • Tek bir process/container'a kümelenmiş kernel slab corruption uyarıları ya da oops'ları için monitor et.

Mitigation

Warning

Ubuntu'nun fix'ini uygula: USN-4917-1 uyarınca linux 5.4.0-72.80 (Focal) / 5.8.0-50.56 (Groovy) ya da sonrasına güncelle. Patch, fd-restore cleanup'ının tam olarak bir kez çalışmasını sağlar.

  • shiftfs gerekli değilse, attack surface'ı kaldırmak için modülü blacklist'e al/unload et (modprobe -r shiftfs; blacklist'e al); shiftfs Ubuntu'ya özgüdür ve 18.04 ile 21.04+ üzerinde yoktur.
  • Onu kimin mount edebileceğini sınırlamak için unprivileged user namespace'leri kısıtla (kernel.unprivileged_userns_clone=0).
  • Defense-in-depth: slab-freelist-hardening ve freelist randomization, double-free'yi silah haline getirmenin maliyetini artırır.

References