CVE-2026-31415
Açıklama
Linux çekirdeğinde aşağıdaki güvenlik açığı giderilmiştir: ipv6: ip6_datagram_send_ctl() fonksiyonundaki taşmaların önlenmesi Yiming Qian şunları bildirmiştir: IPv6 sendmsg yardımcı veri yolunda, `skb_under_panic()` aracılığıyla çekirdek paniğine (yerel hizmet reddi - DoS) neden olabilen ve yerel olarak tetiklenebilen bir çekirdek hatası bulduğuma inanıyorum. Temel sorun, birden fazla `IPV6_DSTOPTS` kontrol mesajı (cmsg) sağlandığında şunlar arasındaki uyumsuzluktur: - 16 bitlik bir uzunluk akümülatörü (`struct ipv6_txoptions::opt_flen`, türü `__u16`) ve - Sağlanan son hedef seçenekler başlığına işaret eden bir işaretçi (`opt->dst1opt`) - `include/net/ipv6.h`: - `struct ipv6_txoptions::opt_flen` değeri `__u16`'dır (taşma mümkündür). (satırlar 291-307, özellikle 298) - `net/ipv6/datagram.c:ip6_datagram_send_ctl()`: - Tekrarlanan `IPV6_DSTOPTS` mesajlarını kabul eder ve kopyaları reddetmeden `opt_flen` içinde toplar. (satırlar 909-933) - `net/ipv6/ip6_output.c:__ip6_append_data()`: - Başlık boyutlarını ve boş alan (headroom) kararlarını hesaplamak için `opt->opt_flen + opt->opt_nflen` değerini kullanır. (satırlar 1448-1466, özellikle 1463-1465) - `net/ipv6/ip6_output.c:__ip6_make_skb()`: - Eğer `opt->opt_flen` sıfırdan farklıysa `ipv6_push_frag_opts()` fonksiyonunu çağırır. (satırlar 1930-1934) - `net/ipv6/exthdrs.c:ipv6_push_frag_opts()` / `ipv6_push_exthdr()`: - İtilecek boyut, (işaret edilen başlığa dayalı olarak) `ipv6_optlen(opt->dst1opt)` üzerinden gelir. (satırlar 1179-1185 ve 1206-1211) 1. `opt_flen` 16 bitlik bir akümülatördür: - `include/net/ipv6.h:298`, `__u16 opt_flen; /* fragment hdr sonrası */` şeklinde tanımlanmıştır. 2. `ip6_datagram_send_ctl()` tekrarlanan `IPV6_DSTOPTS` cmsg'lerini kabul eder ve her seferinde `opt_flen` değerini artırır: - `net/ipv6/datagram.c:909-933` içerisinde `IPV6_DSTOPTS` için: - `len = ((hdr->hdrlen + 1) << 3);` hesaplanır. - `ns_capable(net->user_ns, CAP_NET_RAW)` kullanılarak `CAP_NET_RAW` yetkisi kontrol edilir. (satır 922) - Ardından şu işlemler yapılır: - `opt->opt_flen += len;` (satır 927) - `opt->dst1opt = hdr;` (satır 928) Burada herhangi bir kopya reddi yoktur (kopya kayıtları `net/ipv6/datagram.c:901-904` adresinde reddeden eski `IPV6_2292DSTOPTS` yolunun aksine). Yeterli miktarda büyük `IPV6_DSTOPTS` cmsg sağlanırsa, `dst1opt` hala büyük (2048 bayt) bir hedef seçenekler başlığına işaret ederken `opt_flen` taşma yapar. Ekli PoC'de (`poc.c`): - `hdrlen=255` olan 32 cmsg => `len = (255+1)*8 = 2048` - `hdrlen=0` olan 1 cmsg => `len = 8` - Toplam artış: `32*2048 + 8 = 65544`, dolayısıyla `(__u16)opt_flen == 8` olur. - Son cmsg 2048 bayttır, bu nedenle `dst1opt` 2048 baytlık bir başlığa işaret eder. 3. İletim yolu, taşmış `opt_flen` değerini kullanarak başlık boyutlarını belirler: - `net/ipv6/ip6_output.c:1463-1465` içerisinde: - `headersize = sizeof(struct ipv6hdr) + (opt ? opt->opt_flen + opt->opt_nflen : 0) + ...;` Taşmış `opt_flen` ile, `headersize`/boş alan kararları daha sonra itilecek veriyi olduğundan az tahmin eder. 4. Nihai skb oluşturulurken gerçek itme uzunluğu `dst1opt` üzerinden gelir ve taşmış `opt_flen` ile sınırlandırılmaz: - `net/ipv6/ip6_output.c:1930-1934` içerisinde: - `if (opt->opt_flen) proto = ipv6_push_frag_opts(skb, opt, proto);` - `net/ipv6/exthdrs.c:1206-1211` içerisinde, `ipv6_push_frag_opts()` fonksiyonu `ipv6_push_exthdr()` aracılığıyla `dst1opt`'yi iter. - `net/ipv6/exthdrs.c:1179-1184` içerisinde, `ipv6_push_exthdr()` şunu yapar: - `skb_push(skb, ipv6_optlen(opt));` - `memcpy(h, opt, ipv6_optlen(opt));` Yetersiz boş alan durumunda, `skb_push()` alt taşmaya uğrar ve `skb_under_panic()` -> `BUG()` işlemini tetikler: - `net/core/skbuff.c:2669-2675` (`skb_push()`, `skb_under_panic()` fonksiyonunu çağırır) - `net/core/skbuff.c:207-214` (`skb_panic()` işlemi `BUG()` ile sonuçlanır) - `IPV6_DSTOPTS` cmsg yolu, hedef netns kullanıcı ad alanında `CAP_NET_RAW` yetkisi gerektirir (`ns_capable(net->user_ns, CAP_NET_RAW)`). - Root (veya `CAP_NET_RAW` yetkisine sahip herhangi bir görev), kullanıcı ad alanları olmadan bunu tetikleyebilir. - Ayrıcalıksız bir `uid=1000` kullanıcısı, ayrıcalıksız kullanıcı ad alanları etkinse ve ad alanı bazlı `CAP_NET_RAW` elde etmek için bir userns+netns oluşturabiliyorsa bunu tetikleyebilir (ekli PoC bunu yapmaktadır). Etki: Yerel hizmet reddi: çekirdek BUG/panik (sistem çökmesi).
Nasıl düzeltilir
- linux linux_kernel5.10.253, 5.15.203, 6.1.168, 6.6.134, 6.12.81, 6.18.22, 6.19.12 ya da sonraki bir sürüm
- git.kernel.org/stable/c/0bdaf54d3aaddfe8df29371260fa8d4939b4fd6f
- git.kernel.org/stable/c/2dbfb003bbf3fc0e94f07efefab0ebcf83029a2a
- git.kernel.org/stable/c/4082f9984a694829153115d28c956a3534f52f29
- git.kernel.org/stable/c/4e453375561fc60820e6b9d8ebeb6b3ee177d42e
- git.kernel.org/stable/c/5e4ee5dbea134e9257f205e31a96040bed71e83f
- git.kernel.org/stable/c/63fda74885555e6bd1623b5d811feec998740ba4
- git.kernel.org/stable/c/872b74900d5daa37067ac676d9001bb929fc6a2a
- git.kernel.org/stable/c/9ed81d692758dfb9471d7799b24bfa7a08224c31
Etkilenen ürünler
| Ürün | Etkilenen sürümler | Düzeltildiği sürüm |
|---|---|---|
| linux linux_kernel | 2.6.14 ≤ v < 5.10.253, 5.11 ≤ v < 5.15.203, 5.16 ≤ v < 6.1.168, 6.2 ≤ v < 6.6.134, 6.7 ≤ v < 6.12.81, 6.13 ≤ v < 6.18.22, 6.19 ≤ v < 6.19.12, 7.0 | 5.10.253, 5.15.203, 6.1.168, 6.6.134, 6.12.81, 6.18.22, 6.19.12 |
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.