Skip to content

struct file spray

Çok sayıda file descriptor aç ve dedicated filp slab cache'ini taze struct file object'leriyle doldur; free edilmiş bir struct file slot'unu reclaim ederek controlled ya da privileged bir file takas et (file-based DirtyCred'in arkasındaki çekirdek primitive).

Mechanism

Note

Her açık file, bir struct file tarafından desteklenir; bu da generic bir kmalloc-N cache'inden değil, filp adlı dedicated bir slab cache'inden (filp_cachep) allocate edilir — dolayısıyla reclaim, arbitrary bir heap object yerine başka bir struct file allocation'ından gelmelidir. İlgili field'lar şunlardır: f_op (operation başına hangi handler'ın çalışacağını seçen file_operations tablosuna pointer), f_mode (read/write permission dahil access-mode bit'leri) ve f_count (refcount). Spray, bir struct file üzerindeki bir UAF/double-free'yi istismar eder: vulnerable object'i free et, sonra free edilmiş slot'u privileged bir target için bir struct file ile reclaim etmek üzere çok sayıda open() çağrısı ver. !(file->f_mode & FMODE_WRITE) gibi bir permission check bir noktada değerlendirildiği ama write handler (artık takas edilmiş) file'ı daha sonra çözdüğü için, bir attacker check'i writable bir file üzerinde geçebilir ama altında privileged file'a sahip olabilir.

Walkthrough

  1. Çok sayıda open() çağrısıyla spray et — her open(), filp_cachep'te yeni bir struct file allocation'ı üretir:
for (int i = 0; i < N; i++)
    fd[i] = open("/some/target", O_RDONLY);   /* each = one fresh struct file */

Not: dup(), yeni bir struct file allocate etmez; yalnızca mevcut olanın f_count'unu artırır, dolayısıyla bir spray primitive'i değildir. 2. UAF/double-free'yi tetikle, böylece vulnerable struct file filp_cachep'e geri free edilsin. 3. Free edilmiş chunk'ı controlled / privileged bir file ile reclaim etmek için open()'ı yeniden spray et (filp cache'i file ve socket işlemleriyle yoğun çalıştırılır, dolayısıyla reclaim güvenilirdir). 4. Takası istismar et: reclaim edilmiş object'in f_mode'u (permission bit'leri) ve f_op'u (operation handler'ları), önceki permission check'in validate ettiğinden farklıdır — write zaten f_mode check'inden geçmişti ama altındaki struct file artık privileged bir file'a işaret eder; bu da privileged bir write'ı (örn. /proc/sys/kernel/modprobe'a) ya da hijack edilmiş bir file işlemini mümkün kılar.

Warning

struct file kendi cache'inde yaşar, dolayısıyla generic bir kmalloc spray'i onu reclaim edemez — reclaim allocation'ının kendisi bir struct file olmalıdır (bir target file'ın open'ı). Onu farklı bir object tipiyle reclaim etmek için bir page-level cross-cache adımı gerekir.

Mitigation

  • Dedicated filp_cachep'in kendisi kısmî bir savunmadır — cross-type reclaim'i sınırlar.
  • CONFIG_SLAB_FREELIST_HARDENED / CONFIG_SLAB_FREELIST_RANDOM, deterministik reclaim'i zorlaştırır.
  • DirtyCred-sınıfı mitigation'lar, privileged credential/file object'lerini izole eder (örn. elevated struct cred / struct file'ı ayıran virtual isolation).

References