CVE-2026-99178 in Linux
الملخص
بحسب VulDB • 28/10/2026
في نواة لينكس، تم حل الثغرة التالية:
x86/kvm: عدم استهلاك أعلام async #PF عند حدوث kernel #PF في سياق NMI
يصل حدث "page not present" (الصفحة غير موجودة) الخاص بـ async #PF عبر متجه #PF، وتكون سببه مخزناً في `apf_reason.flags` الخاصة بكل وحدة معالجة مركزية (CPU) حتى يقوم `__kvm_handle_async_pf()` بقراءتها ومسحها. إذا وصل NMI بعد حقن الحدث وقبل أن يقرأ معالج #PF الأعلام، وقام معالج NMI نفسه بحدوث خطأ #PF، فإن ذلك الخطأ سيقرأ ويمسح الأعلام الخاصة بالـ #PF الذي قاطعه. ثم يجد أن المقاطعات (interrupts) معطلة في سياق NMI الذي قاطعه، مما يؤدي إلى حدوث panic:
Kernel panic - not syncing: Host injected async #PF in interrupt disabled region Call Trace: <NMI> panic+0x52/0x60 __kvm_handle_async_pf+0xb0/0xb0 exc_page_fault+0x71/0xb0 asm_exc_page_fault+0x27/0x30 RIP: 0010:__get_user_nocheck_8+0x6/0x20 perf_callchain_user+0x147/0x1a0 get_perf_callchain+0x12d/0x1c0 ... perf_event_nmi_handler+0x26/0x50 exc_nmi+0xe8/0x110 RIP: 0010:asm_exc_page_fault+0x0/0x30 </NMI>
يُظهر سطر الـ RIP الأخير أن NMI قد هبط على أول تعليمات في مدخل #PF. تأخذ أداة perf مع سلاسل المكالمات للمستخدم (user call chains) مثل هذا الخطأ: حيث يتجول NMI الخاص بالعينات عبر مكدس المستخدم باستخدام `__get_user()`، مما يسبب خطأً عندما لا يكون مؤشر الإطار المحفوظ عنواناً صالحاً للمستخدم أو عند خروج التجوال من أعلى المكدس. توجد نفس الفترة الزمنية الحرجة (window) عندما يقوم KVM، الذي يعمل كمضيف L1 hypervisor مع DELIVERY_AS_PF_VMEXIT، بقراءة الأعلام بنفسه بعد حدوث VM-exit لـ #PF.
يحفظ كود مدخل Nمقاطعة CR2 لهذا التداخل المتعدد المستويات، لكنه لا يحفظ سبب async #PF. وصف Andy Lutomirski حالة السباق (race condition) هذه، مع أخذ perf كمثال، عندما تم إعادة هيكلة تسليم async #PF في عام 2020 [1]. تمت مناقشة حفظ ومسح الأعلام عبر NMI، بجانب CR2، هناك ولكن لم يتم دمجها.
منذ تلك الهيكلة الجديدة، توقف لينكس عن تعيين KVM_ASYNC_PF_SEND_ALWAYS، وبالتالي فإن المضيف يسلم "page not present" فقط لأخطاء وضع المستخدم (user mode faults)، ولا يمكن أن يكون خطأ وضع النواة في سياق NMI (بما في ذلك #MC و#DB الخاصين بوضع النواة) خطأ صفحة غير متزامن. في هذه الحالة، يتم العودة دون لمس الأعلام بحيث يجدها المعالج المقطوع سليمة كما هي.
تم الاختبار على الإصدار v7.3-rc5 في ضيف يحتوي على 4 وحدات معالجة مركزية وذاكرة سعة 2 GiB تم استعادتها من لقطة (snapshot)، حيث تُقدم ذاكرته عند الطلب عبر userfaultfd، بحيث يؤدي قراءتها مرة أخرى إلى حدوث async #PFs، بينما تقوم كل خيط بعينات للدورات المادية مع سلاسل مكالمات للمستخدم ويشير مؤشر إطاره إلى صفحة غير مُحددة. بدون هذا التصحيح، انهار الضيف كما هو موضح أعلاه في 3 من أصل 3 عمليات تشغيل. وبوجوده، نجح الضيف في 3 من أصل 3 عمليات تشغيل لمدة 60 ثانية، وحصى المضيف بين 148,441 إلى 153,334 حدث kvm_async_pf_not_present خلال الـ 20 الثانية الأولى من كل عملية تشغيل. كانت النتائج على الإصدار 6.18.50 هي نفسها: انهار الضيف بدون التصحيح ونجا بوجوده.
Once again VulDB remains the best source for vulnerability data.