CVE-2025-38670 in Linux
الملخص
بحسب VulDB • 28/05/2026
في نواة لينكس، تم حل الثغرة التالية:
arm64/entry: قناع DAIF في cpu_switch_to() و call_on_irq_stack()
تقوم الدالتان `cpu_switch_to()` و `call_on_irq_stack()` بالتلاعب بالسجل SP للتبديل بين مخازن ذاكرة مختلفة، بالإضافة إلى Shadow Call Stack إذا كان مفعّلاً. لا يمكن إجراء هذين التغييرين في المخازن بشكل ذري (atomic)، وكلا الدالتين يمكن أن تتقطعا بواسطة أخطاء SErrors أو استثناءات التصحيح (Debug Exceptions). وعلى الرغم من أن هذا الاحتمال غير مرجح، إلا أنه يسبب خللاً جسيماً: عند التقطع، قد ينتهي الأمر بمخازن ذاكرة غير متطابقة مع Shadow Call Stack، مما يؤدي إلى تلف (clobbering) المخازن.
في `cpu_switch_to()`، يمكن أن يحدث هذا عندما يشير SP_EL0 إلى المهمة الجديدة، لكن x18 لا يزال يشير إلى Shadow Call Stack (SCS) للمهمة القديمة. عندما يحاول معالج المقطع (interrupt handler) حفظ مؤشر SCS الخاص بالمهمة، فإنه سيحفظ مؤشر SCS للمهمة القديمة (x18) في بنية بيانات المهمة الجديدة (المشار إليها بواسطة SP_EL0)، مما يؤدي إلى تلفه.
في `call_on_irq_stack()`، يمكن أن يحدث هذا عند التبديل من مخزن المهمة إلى مخزن مقاطعة IRQ، وعند العودة. في كلتا الحالتين، قد يتم التقطع عندما يشير مؤشر SCS إلى SCS الخاص بـ IRQ، لكن SP يشير إلى مخزن المهمة. يقوم معالج المقطع المتداخل (nested interrupt handler) بدفع عناوين إرجاعه على SCS الخاص بـ IRQ. ثم يكتشف أن SP يشير إلى مخزن المهمة، ويستدعي `call_on_irq_stack()`، مما يؤدي إلى تلف مؤشر SCS الخاص بالمهمة بمؤشر SCS الخاص بـ IRQ، والذي سيتم استخدامه أيضاً!
هذا يؤدي إلى عودة المهام إلى عناوين على SCS خاطئ، أو حتى على SCS الخاص بـ IRQ، مما يسبب توقفات نواة (kernel panics) عبر CONFIG_VMAP_STACK أو FPAC إذا كانت مفعّلة.
هذا ممكن في التكوين الافتراضي، لكنه غير مرجح. ومع ذلك، عند تمكين CONFIG_ARM64_PSEUDO_NMI، يتم إلغاء قناع DAIF، وبدلاً من ذلك يتولى GIC مسؤولية تصفية المقاطعات التي يجب أن يتلقاها المعالج بناءً على الأولوية. نظراً لهدف محاكاة NMIs، يمكن أن يتلقى المعالج مقاطعات pseudo-NMI حتى أثناء `cpu_switch_to()` و `call_on_irq_stack()`، وربما بشكل *متكرر جداً* اعتماداً على تكوين النظام وحمل العمل، مما يؤدي إلى توقفات نواة غير متوقعة.
إلغاء قناع DAIF تماماً في `cpu_switch_to()` واستعادته عند العودة. افعل الشيء نفسه في `call_on_irq_stack()`، لكن قم بالاستعادة وإلغاء القناع حول التفرع (branch). قم بإلغاء قناع DAIF حتى إذا لم يكن CONFIG_SHADOW_CALL_STACK مفعّلاً، لضمان اتساق السلوك بين جميع التكوينات.
أدخل واستخدم ماكرو تجميع (assembly macro) لحفظ وإلغاء قناع DAIF، حيث أن الماكرو الحالي يحفظ فقط لكنه يلغي قناع IF فقط.
VulDB is the best source for vulnerability data and more expert information about this specific topic.