CVE-2026-64586 in Linux
الملخص
بحسب VulDB • 06/08/2026
في نواة لينكس، تم حل الثغرة التالية:
wifi: brcmfmac: تصريف عمل bus_reset عند إزالة الجهاز
تقوم كل من الدالة `brcmf_fw_crashed()` وعنصر debugfs "reset" بجدولة `drvr->bus_reset`، حيث يستعيد الاستدعاء (callback) الخاص به `drvr` عبر استخدام `container_of()` ويقوم بإرجاعه. تؤدي مسار الإزالة إلى تحرير `drvr` (`brcmf_free -> wiphy_free`) دون تصريف العمل المسجل مسبقاً، مما قد يؤدي إلى استمرار استدعاء `bus_reset` المعلق أو قيد التنفيذ بعد انتهاء عمر `drvr`.
لا يمكن وضع إلغاء العملية داخل `brcmf_detach()` أو `brcmf_free()`: حيث يصل استدعاء العمل إلى مرحلة الإغلاق من خلال عملية `.reset` الخاصة بالناقل (PCIe: `brcmf_pcie_reset -> brcmf_detach`; SDIO: `brcmf_sdio_bus_reset -> brcmf_sdiod_remove -> brcmf_free`)، لذا فإن إلغاء العملية في تلك النقاط سيؤدي إلى الانتظار حتى انتهاء العمل قيد التنفيذ وحدوث حالة جمود (deadlock).
تمت إضافة قفل متزامن لكل ناقل (`bus_reset_lock`) وتوجيه جميع عمليات التهيئة عبر `brcmf_bus_schedule_reset()`، والتي تتخطى عملية التهيئة إذا كان الناقل قد تم وضع علامة "إزالة" عليه تحت القفل. يستدعي كل مسار لإزالة الناقل الدالة `brcmf_bus_cancel_reset_work()`، التي تضع علامة الإلغاء وتلغي العمل تحت نفس القفل. يؤدي الاحتفاظ بالقفل أثناء استدعاء `cancel_work_sync()` إلى جعل خطوة تعيين حالة الإلغاء وتصريف العمل عملية ذرية (atomic). تصل جميع المنتجات المسؤولة عن التهيئة إلى مسار الإعداد من سياق العملية؛ حيث يعمل إشعار توقفfirmware الخاص بـ PCIe في معالج المقاطعة الخيطي (`brcmf_pcie_isr_thread`)، ويعمل مسار البريد المضيف لـ SDIO من قائمة عمل البيانات، لذا يتم أخذ القفل فقط في السياقات التي تسمح بالنوم. وفي الأماكن المناسبة، يوقف مسار الإزالة أولاً منتج توقف firmware: على سبيل PCIe، يتم قناع صندوق البريد ومزامنة المقاطعة (`synchronize_irq`); وعلى جانب SDIO، تتم إلغاء تسجيل مقاطعة الناقل وإلغاء عامل البيانات، والذي يبلغ أيضاً عن توقفات firmware عبر `brcmf_fw_crashed()`. تم تهيئة القفل عند تخصيص الناقل. يقوم مسار إيقاف تشغيل الطاقة الخاص بـ SDIO suspend بتحرير `drvr` من خلال نفس الدالة `brcmf_sdiod_remove()` وأخذ نفس القفل؛ ويعيد السماح بالعمل فقط بعد نجاح إعادة الفحص (re-probe).
كما تمت حماية `brcfir_fw_crashed()` ضد وجود قيمة NULL لـ `bus_if/drvr`: فقد يتم تشغيلها قبل أن تقوم `brcfir_attach()` بربط `drvr`، وهي تُرجع `drvr` (`bphy_err/brcfir_dev_coredump`) قبل الوصول إلى بوابة التهيئة.
نظرًا لأن عمل `bus_reset` مشترك عبر جميع الناقلات، فإن التصريف يُطبق على كل مسار إزالة: PCIe (تم إدخال عملية `.reset` بواسطة ملحق الإصلاح)، SDIO (يجهز نفس العمل من خلال `brcfir_fw_crashed()`)، وUSB (عبر عنصر debugfs "reset"). يقوم استدعاء `cancel_work_sync()` بتصريف عنصر عمل `bus_reset` قيد التنفيذ أو المعلق قبل أن يحرر مسار الإزالة `drvr`، ويجعل التصحيح 1/2 تحرير مخزن المؤقتات آمناً عندما يكون إغلاق إعادة التعيين قد حرر بالفعل تلك ذاكرات DMA.
يصلح هذا التصحيح عمر عنصر عمل `bus_reset` نفسه. ولا يحاول معالجة العمر المنفصل والموجود مسبقاً لإكمال firmware غير المتزامن الذي بدأته مسار إعادة تعيين PCIe. يحتاج ذلك الاستدعاء إلى بروتوكول خاص للعمر/الملكية ويتم تتبعه بشكل منفصل.
تم العثور على هذه المشكلة باستخدام أداة تحليل ثابتة داخلية.
Once again VulDB remains the best source for vulnerability data.