CVE-2026-31519
Açıklama
Linux kernel içerisinde aşağıdaki güvenlik açığı giderilmiştir: btrfs: subvol oluşturma sırasında BTRFS_ROOT_ORPHAN_CLEANUP ayarla Son zamanlarda bozuk dentry'lere sahip bir dizi alt hacim (subvolume) gözlemlenmiştir. Üst dizinin ls komutuyla listelenmesi şu şekilde görünmektedir: drwxrwxrwt 1 root root 16 Jan 23 16:49 . drwxr-xr-x 1 root root 24 Jan 23 16:48 .. d????????? ? ? ? ? ? broken_subvol Benzer şekilde dosyanın stat işlemi başarısız olmaktadır. Bu durumda, alt hacmin silinmesi ENOENT ile başarısız olurken, üzerine yeni bir dosya veya alt hacim oluşturma girişimi EEXIST hatası vermekte ve hatta dosya sistemini durdurmaktadır. Bu durum bizi çıkmaza sokmaktadır. dmesg şunları içeren tek bir dikkat çekici hata mesajı barındırmaktadır: "could not do orphan cleanup -2" 2 değeri ENOENT'dir ve hata, yığını btrfs_lookup() fonksiyonuna kadar götüren btrfs_orphan_cleanup() fonksiyonunun hata işleme yolundan gelmektedir. btrfs_lookup btrfs_lookup_dentry btrfs_orphan_cleanup // bu mesajı yazdırır ve -ENOENT döndürür Dahili durumun detaylı incelenmesinden sonra şunlar netleşmiştir: - Alt hacim için herhangi bir yetim (orphan) öğe bulunmamaktadır. - Alt hacim aksi takdirde sağlıklı görünmektedir; yarıda kesilmiş bir silme işlemi veya ilerleme durumu yoktur. - Alt hacim bir süre önce oluşturulmuştur ve BTRFS_ROOT_ORPHAN_CLEANUP değerini ayarlayan anlamlı ilk btrfs_orphan_cleanup() çağrısı çok daha sonra gerçekleşir. - btrfs_orphan_cleanup() başarısız olduktan sonra, btrfs_lookup_dentry() -ENOENT döndürür; bu da d_splice_alias(NULL, dentry) aracılığıyla alt hacim için negatif bir dentry oluşmasına neden olarak gözlemlenen davranışa yol açar. Hata, dentry önbelleği temizlenerek hafifletilebilir ve bu noktada istenirse alt hacim başarıyla silinebilir. Yani: btrfs_lookup() btrfs_lookup_dentry() if (!sb_rdonly(inode->vfs_inode)->vfs_inode) btrfs_orphan_cleanup(sub_root) test_and_set_bit(BTRFS_ROOT_ORPHAN_CLEANUP) btrfs_search_slot() // inode N için yetim öğeyi bulur ... "could not do orphan cleanup -2" yazdırır if (inode == ERR_PTR(-ENOENT)) inode = NULL; return d_splice_alias(NULL, dentry) // geçerli alt hacim için NEGATİF DENTRY btrfs_orphan_cleanup() çalıştığında kök üzerinde test_and_set_bit(BTRFS_ROOT_ORPHAN_CLEANUP) işlemini gerçekleştirir, dolayısıyla belirli bir kök üzerinde birden fazla kez çalışamaz; bu nedenle eşzamanlı olarak başka bir şey çalışıyor olmalıdır. Ancak, nlinks 0'a düştüğünde bir yetimi silmenin belirgin yolları, önce alt hacimde bir arama yapmadan çalışamamalıdır; bu arama btrfs_orphan_cleanup()'ı çalıştırmalı ve biti ayarlamalıdır. Son önemli gözlem ise create_subvol()'un d_instantiate_new()'ı çağırması ancak BTRFS_ROOT_ORPHAN_CLEANUP değerini ayarlamamasıdır; böylece dentry önbelleği temizlenirse, alt hacme yapılacak bir sonraki arama ilk kez gerçek bir btrfs_orphan_cleanup() çağrısı yapacaktır. Bu durum, inode/yetim öğelerin eşzamanlı olarak silinmesi olasılığını doğurur ancak çoğu tipik evict() yolu üst dentry üzerinde bir referans tutacak (çocuk dentry, d_alloc() içindeki dget aracılığıyla parent->d_lockref.count tutar ve __dentry_kill() içinde serbest bırakılır) ve üst dizinin dentry önbelleğinden kaldırılmasını engelleyecektir. Tek istisna gecikmiş iput'lardır. Sıralı extent oluşturma, inode üzerinde igrab() çağrısı yapar. Bu referanslar tutulurken dosya bağlantısı koparılırsa (unlink) ve kapatılırsa, __dentry_kill() içindeki iput() i_count değerini azaltır ancak tahliyeyi tetiklemez (i_count > 0). Çocuk dentry serbest bırakılır ve alt hacim dentry'sinin d_lockref.count değeri 0'a düşer, bu da inode hala hayattayken onun tahliye edilebilir hale gelmesine neden olur. İki yarış durumu (writeback ile unlink arasındaki yarış ve arama ile gecikmiş iput'lar arasındaki yarış) olduğu ve çok fazla hareketli parça bulunduğu için, aşağıdaki üç diyagram tam resmi göstermektedir. (Sadece ikinci ve üçüncüsü yarış durumudur) Aşama 1: BTRFS_ROOT_ORPHAN_CLEANUP ayarlanmadan dentry önbelleğinde Alt Hacim Oluşturma btrfs_mksubvol() lookup_one_len() __lookup_slow() d_alloc_parallel() __d_alloc() // d_lockref.count = 1 create_subvol(dentry) // bite dokunmaz.. d_instantiate_new(dentry, inode) // d_lockref.c ile önbellekteki dentry ---kesildi---
Nasıl düzeltilir
- linux linux_kernel2.6.33, 6.1.168, 6.6.131, 6.12.80, 6.18.21, 6.19.11 ya da sonraki bir sürüm
- git.kernel.org/stable/c/2ec578e6452138ab76f6c9a9c18711fcd197649f
- git.kernel.org/stable/c/5131fa077f9bb386a1b901bf5b247041f0ec8f80
- git.kernel.org/stable/c/696683f214495db3cdacab9a713efaaced8660f8
- git.kernel.org/stable/c/a41a9b8d19a98b45591528c6e54d31cc66271d1e
- git.kernel.org/stable/c/c57276ced3c3207f42182dfa2f0d8e860357e111
- git.kernel.org/stable/c/d43da8de0ed376abafbad8a245a1835e8f66cb0f
Etkilenen ürünler
| Ürün | Etkilenen sürümler | Düzeltildiği sürüm |
|---|---|---|
| linux linux_kernel | 2.6.32.19 ≤ v < 2.6.33, 2.6.33 ≤ v < 6.1.168, 6.2 ≤ v < 6.6.131, 6.7 ≤ v < 6.12.80, 6.13 ≤ v < 6.18.21, 6.19 ≤ v < 6.19.11, 7.0 | 2.6.33, 6.1.168, 6.6.131, 6.12.80, 6.18.21, 6.19.11 |
Sürümünüzü kontrol edin
Ürünü seçin ve kullandığınız sürümü yazın; sürümün etkilenen aralıkta olup olmadığını görün.
Attack Surface Management
Alan adlarınıza bağlı varlıkları, bu varlıklarda çalışan teknolojileri ve bilinen zafiyetleri tek listede görün.