CVE-2024-35970
Açıklama
Linux kernel içerisinde aşağıdaki güvenlik açığı giderilmiştir: af_unix: Bayat u->oob_skb temizleniyor. syzkaller, 4090fa373f0e ("af_unix: Replace garbage collection algorithm.") commit'inden sonra unix_gc_lock üzerinde bir deadlock raporlamaya başlamıştır; ancak bu durum sadece 314001f0bf92 ("af_unix: Add OOB support") commit'inden beri orada olan hatayı ortaya çıkarmaktadır. Yeniden üretim süreci temel olarak şunları yapar: from socket import * from array import array c1, c2 = socketpair(AF_UNIX, SOCK_STREAM) c1.sendmsg([b'a'], [(SOL_SOCKET, SCM_RIGHTS, array("i", [c2.fileno()]))], MSG_OOB) c2.recv(1) # alım kuyruğunda normal veri olmadığı için engellendi c2.close() # asenkron olarak tamamlanır ve recv() engelini kaldırır c1.close() # asenkron olarak tamamlanır ve GC tetikler Bir soket, kendi dosya tanımlayıcısını kendisine OOB verisi olarak gönderir ve normal veri almaya çalışır, ancak sonunda asenkron close() nedeniyle recv() başarısız olur. Buradaki sorun, manage_oob() içerisindeki OOB skb işleminin yanlış yönetilmesidir. recvmsg(), MSG_OOB olmadan çağrıldığında, gözlenen skb'nin OOB skb olup olmadığını kontrol etmek için manage_oob() çağrılır. Böyle bir durumda manage_oob(), onu alım kuyruğundan çıkarır ancak unix_sock(sk)->oob_skb değerini temizlemez. Bu, uAPI açısından yanlıştır. Diyelim ki MSG_OOB ile "hello" ve MSG_OOB olmadan "world" gönderiyoruz. 'o' harfi OOB verisi olarak işlenir. recv() fonksiyonu MSG_OOB olmadan iki kez çağrıldığında, OOB verisi kaybolmalıdır. >>> from socket import * >>> c1, c2 = socketpair(AF_UNIX, SOCK_STREAM, 0) >>> c1.send(b'hello', MSG_OOB) # 'o' OOB verisidir 5 >>> c1.send(b'world') 5 >>> c2.recv(5) # OOB verisi alınmaz b'hell' >>> c2.recv(5) # OOB verisi atlanır b'world' >>> c2.recv(5, MSG_OOB) # Bunun hata döndürmesi gerekir b'o' Aynı durumda TCP, son recv() için aslında -EINVAL döndürür. Ayrıca, unix_sk(sk)->oob_skb değerini temizlemezsek, veri önceki recv() tarafından geçilmiş olsa bile unix_poll() her zaman EPOLLPRI ayarlar. Bu sorunlardan kaçınmak için, onu alım kuyruğundan çıkardığımızda unix_sk(sk)->oob_skb değerini temizlemeliyiz. Eski GC'nin deadlock tetiklememesinin nedeni, eski GC'nin döngüyü tespit etmek için alım kuyruğuna güvenmesiydi. Tetiklendiğinde, OOB verisine sahip soket, dosya referans sayısı == inflight sayısı (1) olduğu için GC adayı olarak işaretlenir. Ancak tüm inflight soketler gezildikten sonra, soketin hala pozitif bir inflight sayısı (1) vardır, dolayısıyla soket adaylar arasından çıkarılır. Ardından, eski GC soketi çöp toplama (garbage-collect) fırsatını kaybeder. Eski GC ile yeniden üretim süreci, küresel inflight listesine bağlı olduğu için asla serbest bırakılmayacak ve kmemleak tarafından tespit edilmeyecek gerçek çöpler oluşturmaya devam eder. Sorunun fark edilememesinin nedeni budur.
Nasıl düzeltilir
- linux linux_kernel5.15.156, 6.1.87, 6.6.28, 6.8.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 | 5.15 ≤ v < 5.15.156, 5.16 ≤ v < 6.1.87, 6.2 ≤ v < 6.6.28, 6.7 ≤ v < 6.8.7, 6.9 | 5.15.156, 6.1.87, 6.6.28, 6.8.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.