CVE-2024-50194
Açıklama
Linux kernel içerisinde aşağıdaki güvenlik açığı giderilmiştir: arm64: probes: big-endian çekirdekler için uprobes düzeltmesi arm64 uprobes kodu, talimatları analiz etmeden ve simüle etmeden önce bellek içi talimat kodlamasını (her zaman little-endian'dır) çekirdeğin yerel endian yapısına dönüştürmediği için big-endian çekirdeklerde hatalı çalışmaktadır. Bu durum şu farklı sorunlara yol açabilir: * Çekirdek, güvenli bir şekilde izlenebilecek (probing) bir talimatın izlenmesini hatalı olarak reddedebilir. * Çekirdek, güvenli bir şekilde satır dışı adım ilerletilemeyecek (stepping out-of-line) bir talimatın satır dışı adım ilerletilmesine hatalı olarak izin verebilir. * Çekirdek, bayt sırası değiştirilmiş (byte-swapped) kodlamayı yorumladığı için talimatı hatalı simüle edebilir. Endian uyumsuzluğu, derleyici veya sparse tarafından şu nedenlerle tespit edilememektedir: * arch_uprobe::{insn,ixol} alanları u8 dizileri olarak kodlandığından, derleyici ve sparse bunların little-endian 32-bit değer içerdiğini bilmemektedir. Temel uprobes kodu, bunları benzer şekilde endian yapısını yönetmeyen bir memcpy() ile doldurmaktadır. * uprobe_opcode_t türü __le32 için bir takma ad olsa da, hem arch_uprobe_analyze_insn() hem de arch_uprobe_skip_sstep(), u8[] tipini benzer isimli ve u32 takma adı olan probe_opcode_t tipine dönüştürmektedir. Bu nedenle herhangi bir endian dönüşüm uyarısı oluşmamaktadır. Bu sorun, arch_uprobe::{insn,ixol} alanlarının __le32 olarak değiştirilmesi ve talimat kodlaması kullanılmadan önce uygun __le32_to_cpu() dönüşümlerinin eklenmesiyle giderilmiştir. Temel uprobes bu alanları opak bayt aralıkları olarak kopyaladığı için bu değişiklikten etkilenmez. Aynı zamanda, netlik sağlamak amacıyla MAX_UINSN_BYTES kaldırılmış ve tutarlı bir şekilde AARCH64_INSN_SIZE kullanılmıştır. Şununla test edilmiştir: | #include <stdio.h> | #include <stdbool.h> | | #define noinline __attribute__((noinline)) | | static noinline void *adrp_self(void) | { | void *addr; | | asm volatile( | " adrp %x0, adrp_self\n" | " add %x0, %x0, :lo12:adrp_self\n" | : "=r" (addr)); | } | | | int main(int argc, char *argv) | { | void *ptr = adrp_self(); | bool equal = (ptr == adrp_self); | | printf("adrp_self => %p\n" | "adrp_self() => %p\n" | "%s\n", | adrp_self, ptr, equal ? "EQUAL" : "NOT EQUAL"); | | return 0; | } .... burada adrp_self() fonksiyonu şu şekilde derlenmiştir: | 00000000004007e0 <adrp_self>: | 4007e0: 90000000 adrp x0, 400000 <__ehdr_start> | 4007e4: 911f8000 add x0, x0, #0x7e0 | 4007e8: d65f03c0 ret Bu yamadan önce ADRP tanınmamakta ve adım ilerletilebilir olduğu varsayılmakta, bu da sonucun bozulmasına neden olmaktadır: | # ./adrp-self | adrp_self => 0x4007e0 | adrp_self() => 0x4007e0 | EQUAL | # echo 'p /root/adrp-self:0x007e0' > /sys/kernel/tracing/uprobe_events | # echo 1 > /sys/kernel/tracing/events/uprobes/enable | # ./adrp-self | adrp_self => 0x4007e0 | adrp_self() => 0xffffffffff7e0 | NOT EQUAL Bu yamadan sonra ADRP doğru şekilde tanınmakta ve simüle edilmektedir: | # ./adrp-self | adrp_self => 0x4007e0 | adrp_self() => 0x4007e0 | EQUAL | # | # echo 'p /root/adrp-self:0x007e0' > /sys/kernel/tracing/uprobe_events | # echo 1 > /sys/kernel/tracing/events/uprobes/enable | # ./adrp-self | adrp_self => 0x4007e0 | adrp_self() => 0x4007e0 | EQUAL
Nasıl düzeltilir
- linux linux_kernel4.19.323, 5.4.285, 5.10.229, 5.15.170, 6.1.115, 6.6.58, 6.11.5 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 | 4.10 ≤ v < 4.19.323, 4.20 ≤ v < 5.4.285, 5.5 ≤ v < 5.10.229, 5.11 ≤ v < 5.15.170, 5.16 ≤ v < 6.1.115, 6.2 ≤ v < 6.6.58, 6.7 ≤ v < 6.11.5, 6.12 | 4.19.323, 5.4.285, 5.10.229, 5.15.170, 6.1.115, 6.6.58, 6.11.5 |
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.