CVE-2025-21932
Açıklama
Linux çekirdeğinde aşağıdaki güvenlik açığı giderilmiştir: mm: bellek yetersizliği nedeniyle başarısız olan birleştirme işleminde vma_modify() işlemini durdur vma_modify() fonksiyonunun geri kalanı, bir birleştirme denemesinden sonra vmg durumunun bozulmamış kaldığına dayanır. Genellikle durum böyledir; ancak, bir birleştirme denemesinin belirtilen aralığın birleştirilemez olmasından değil, birleştirmeyi onaylamaya çalışırken ortaya çıkan bir bellek yetersizliği hatası nedeniyle başarısız olduğu uç senaryoda bu varsayım geçersiz hale gelir. Bu durum vmg->start ve end değerlerinin değiştirilmesine yol açar ve böylece VMA'yı bölmeye yönelik sonraki girişimler geçersiz başlangıç/bitiş değerleri ile gerçekleştirilir. Neyse ki gerçekte buna rastlamak muhtemelen pratik olarak imkansızdır; çünkü bu, 'başarısız olmak için çok küçük' olduğu için muhtemelen asla gerçekleşmeyecek bir maple tree düğümü ön tahsis hatası gerektirir, yani çekirdek başarılı olana kadar geri kazanmayı yeniden denemeye devam edecektir. Buna rağmen, bu senaryo teorik olarak mümkün olmaya devam etmektedir ve burada yaptığımız işlem yanlıştır, bu nedenle düzeltilmesi gerekir. En güvenli seçenek, bu senaryo gerçekleştiğinde işlemi basitçe sonlandırmaktır. Birleştirme yapmak için bellek ayıramıyorsak, bölmek için de bellek ayıramayız (belki daha da fazla!). Bunun gerçekleşebileceği herhangi bir senaryo, çok aşırı (muhtemelen ölümcül) bellek baskısı altında olacaktır, bu nedenle erken vazgeçmek en iyisidir. Dolayısıyla, bu senaryoda işlemi sonlandırmanın uygun olduğundan şüphe yoktur. Ancak genel olarak, birleştirme işlemleri VMG alanlarını güncellediği için, mümkünse bir birleştirme denemesinden sonra VMG durumunun kararlı olduğunu asla varsaymamalıyız. Sonuç olarak, start ve end değerlerini yerel değişkenlerde saklayarak bunu ayrıca netleştiriyoruz. Sorun ilk olarak syzkaller ve Brad Spengler (liste dışı bir tartışma aracılığıyla) tarafından rapor edilmiştir ve her iki durumda da şu assert ifadesinin tetiklenmesi şeklinde ortaya çıkmıştır: VM_WARN_ON_VMG(start >= end, vmg); vma_merge_existing_range() içerisinde. Bunun meydana geldiği en az bir senaryonun, birden fazla VMA üzerinde yapılan bir madvise() nedeniyle denenilen birleştirme olduğu görülmektedir ve şöyle görünür: start end |<------>| |----------|------| | vma | next | |----------|------| madvise_walk_vmas() çağrıldığında, önce yukarıdaki vma'yı buluruz (vma içinde kaymış olduğumuz için prev'in vma'ya eşit olduğunu belirleriz) ve ardından döngüye gireriz. madvise() yaptığımız aralığın bir parçası olan vma'nın sonunu, 'tmp'yi bu değere ayarlayarak belirleriz: /* Burada vma->vm_start <= start < (end|vma->vm_end) */ tmp = vma->vm_end; Ardından, operasyonun bir parçası olarak prev'in vma'yı işaret edecek şekilde güncellenmesine izin vererek visit() aracılığıyla madvise() işlemini çağırırız: /* Burada vma->vm_start <= start < tmp <= (end|vma->vm_end). */ error = visit(vma, &prev, start, tmp, arg); Burada visit() fonksiyon göstericisi bu örnekte madvise_vma_behavior()'dır. syzkaller raporlarında gözlemlendiği gibi, nihayetinde madvise_update_vma() çağrılır, bu da sırasıyla vma_modify_flags_name() ve vma_modify()'yi çağırır. Ardından, vma_modify() içerisinde birleştirmeyi deneriz: merged = vma_merge_existing_range(vmg); if (merged) return merged; Bunu, vmg->start ve end değerleri start ve tmp olarak ayarlanmış şekilde çağırırız: start tmp |<--->| |----------|------| | vma | next | |----------|------| Sağ tarafa birleştirme senaryosunda kalıyoruz, ancak ortayı kaldıramadığımız senaryodayız (vma içine kaymış durumdayız). Burada vmg->start ve end değerlerinin belki sezgisel olmayan değerlere ayarlandığı özel bir durumumuz var - orta VMA'yı küçültmeyi ve sonrakini genişletmeyi amaçladık. Bu, vmg->start ve end değerlerinin... vma->vm_start ve start olarak ayarlandığı anlamına gelir. Şimdi commit_merge() başarısız olur ve vmg->start ile end bu şekilde kalır. Bu, vma_modify()'nin geri kalanına vmg->start ve end (burada start' ve end' olarak belirtilmiştir) şu şekilde ayarlanmış olarak döndüğümüz anlamına gelir: start' end' |<-->| |----------|------| | vma | next | |----------|------| Böylece şimdi hatalı bir şekilde buna göre bölmeye çalışıyoruz. İşte talihsiz olan kısım burasıdır...
Nasıl düzeltilir
- linux linux_kernel6.12.19, 6.13.7 ya da sonraki bir sürüm
Etkilenen ürünler
| Ürün | Etkilenen sürümler | Düzeltildiği sürüm |
|---|---|---|
| linux linux_kernel | 6.12 ≤ v < 6.12.19, 6.13 ≤ v < 6.13.7, 6.14 | 6.12.19, 6.13.7 |
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.