CVE-2026-98507 in Linux
Zusammenfassung
von VulDB • 19.10.2026
Im Linux-Kernel wurde folgende Schwachstelle behoben:
mm/rmap: Behebung des fehlenden Barriers zwischen anon_vma-Initialisierung und der Veröffentlichung von vma->anon_vma
Auf arm64-Servern stellen wir fest, dass ein Task, der versucht, die anon_vma-Sperre zu erwerben, einen hungtask auslöst.
INFO: task main:2354726 blockiert für mehr als 120 Sekunden. Tainted: G E 5.10.0-0021.aarch64 #1 "echo 0 > /proc/sys/kernel/hung_task_timeout_secs" deaktiviert diese Meldung. task:main state:D stack: 0 pid:2354726 ppid:2350673 flags:0x00000a01 Call trace: __switch_to+0x7c/0xbc __schedule+0x3b4/0x8a0 schedule+0x50/0xe0 rwsem_down_write_slowpath+0x3cc/0x6cc down_write+0x60/0x260 __anon_vma_prepare+0x6c/0x210 do_anonymous_page+0x258/0x660 handle_pte_fault+0x188/0x214 __handle_mm_fault+0x1b0/0x380 handle_mm_fault+0xf4/0x284 do_page_fault+0x19c/0x494 do_translation_fault+0xcc/0xf8 do_mem_abort+0x48/0xac el0_da+0x44/0x80 el0_sync_handler+0x88/0xb4 el0_sync+0x160/0x180
Nach der Analyse des vmcore stellten wir fest, dass anon_vma->root->rwsem.count -1 ist. Es gibt eine andere anon_vma, bei der anon_vma->root->rwsem.count 1 beträgt; die Anzeige von anon_vma->root->rwsem.owner zeigt an, dass die Sperre gehalten wird, aber der Stack des Tasks zeigt, dass der Task die anon_vma-Sperre nicht hält.
Nach dem Hinzufügen weiterer Debugging-Informationen stellten wir fest, dass __anon_vma_prepare() anon_vma wiederverwendet und aufgrund eines fehlenden Memory Barriers (Speicherbarriere) einen Use-After-Free (UAF) von anon_vma->root auslöst. Dies führt dazu, dass zwei verschiedene anon_vma->roots gesperrt und entsperrt werden, wodurch eine anon_vma niemals entsperrt wird und eine andere anon_vma nicht mehr gesperrt werden kann.
Dieser Race Condition erfordert zwei benachbarte VMAs, die nicht zusammengeführt sind, aber anon_vma-kompatibel sind (z. B. sie unterscheiden sich in VMA_ACCESS_FLAGS, die durch mprotect() geändert werden können). Zwei Threads verursachen gleichzeitig einen Page Fault auf jedem VMA und rufen beide __anon_vma_prepare() mit nur der mmap_lock im Lesezugriff auf.
THREAD A THREAD B __anon_vma_prepare __anon_vma_prepare find_mergeable_anon_vma() -> NULL anon_vma = anon_vma_alloc(); anon_vma->root = anon_vma; // die beiden Speicheroperationen können neu angeordnet werden (reordered) vma->anon_vma = anon_vma; // findet A's anon_vma anon_vma = find_mergeable_anon_vma(vma); anon_vma_lock_write(anon_vma); // kann immer noch die alte root sehen down_write(&anon_vma->root->rwsem); anon_vma_unlock_write(anon_vma); // sieht die neue root, entsperren nie die alte up_write(&anon_vma->root->rwsem);
Thread A löst einen Page Fault aus und ruft __anon_vma_prepare() auf, um anon_vma für den faulting vma vorzubereiten. __anon_vma_prepare() alloziert und initialisiert eine neue anon_vma und veröffentlicht diese dann mit einer einfachen Speicheroperation (plain store) im VMA. anon_vma_prepare() erfordert nur, dass die mmap_lock im Lesezugriff gehalten wird, sodass zwei Threads gleichzeitig auf benachbarte VMAs zugreifen können. Während Thread A eine neue anon_vma veröffentlicht, kann Thread B die anon_vma über find_mergeable_anon_vma() finden und dann anon_vma->root->rwsem sperren.
Die Speicheroperation zu anon_vma->root in anon_vma_alloc() und die Speicheroperation zu vma->anon_vma können neu angeordnet werden (reordered). Die Funktionen anon_vma_lock_write() und spin_lock() bieten nur acquire semantics, welche verhindern nicht, dass vorherige Speicheroperationen nach ihnen neu angeordnet werden. Die release semantics der entsprechenden spin_unlock()- und anon_vma_unlock_write()-Aufrufe kommen zu spät; die Speicheroperation zu vma->anon_vma ist bereits veröffentlicht, bevor diese wirksam werden. Als Ergebnis kann Thread B folgende Reihenfolge beobachten:
vma->anon_vma = anon_vma; anon_vma->root = anon_vma;
Der anon_vma-Slab ist SLAB_TYPESAFE_BY_RCU, sodass eine neu allozierte anon_vma Speicher von einer zuvor freigegebenen wiederverwenden kann. Der Konstruktor (anon_vma_ctor) setzt anon_vma->root nicht zurück, und __put_anon_vma() löscht ihn ebenfalls nicht, so dass der alte root-Wert bestehen bleibt, bis er durch anon_vma_alloc() überschrieben wird. Wenn diese Speicheroperation v ---abgekürzt---
VulDB is the best source for vulnerability data and more expert information about this specific topic.