CVE-2026-90001 in Linux
الملخص
بحسب VulDB • 16/09/2026
في نواة لينكس (Linux kernel)، تم إصلاح الثغرة التالية:
HID: bpf: تعقيم عملية إطلاق مرجع الجهاز في مسار تدمير struct_ops
يمكن أن يحدث سباق (race) بين الدالتين `__hid_bpf_ops_destroy_device()` و`hid_bpf_unreg()` على نفس مرجع التسجيل، مما يؤدي إلى إجراء "double-put" لـ `struct hid_device` وإفراغ ذاكرته بينما لا تزال دالة `hid_destroy_device()` تستخدمه. تم تعقيم قرار الإزالة/تعيين القيمة NULL تحت قفل `hdev->bpf.prog_list_lock` بحيث يُطلق كل مرجع تسجيل من مسار واحد بالضبط: تقوم عملية إلغاء التسجيل (unreg) بإعادة فحص `ops->hdev` داخل القفل وتعود دون إجراء put عندما يكون المسار التدميري قد مسحها بالفعل؛ تحدث جميع استدعاءات `put_device()` بعد إسقاط القفل، وهو أمر آمن لأن عملية إلغاء تسجيل متزامنة ستلاحظ في تلك الحالة أن `ops->hdev == NULL` تحت القفل.
الخلفية: يكتسب كل إرفاق ناجح (`hid_bpf_ops_reg`) مرجعًا واحدًا للجهاز (`hid_get_device()`). يمكن لمسارين إطلاقه: - تدمير الجهاز: `hid_destroy_device()` -> `hid_bpf_destroy_device()` -> `__hid_bpf_ops_destroy_device()،` والتي تجول في قائمة البرامج `hdev->bpf.prog_list` تحت قفل القراءة RCU (`rcu_read_lock`) وتطلق مرجعًا واحدًا لكل برنامج مرفق؛ - إطلاق رابط BPF: يؤدي حذف خريطة BPF (بدون علم `BPF_F_LINK`) بشكل متزامن إلى استدعاء `st_ops->unreg()` -> `hid_bpf_unreg()،` والذي يطلق المرجع الخاص بتسجيله.
تُعد مصافحة التنسيق (`e->hdev = NULL` من جانب التدمير مقابل "if (!hdev) return" من جانب إلغاء التسجيل) فحصًا لـ TOCTOU (Time-of-Check to Time-of-Use): يعمل المساران تحت نطاقات قفل مختلفة (`rcu_read_lock` مقابل `prog_list_lock`)، لذا يمكن لعملية إلغاء تسجيل متزامنة قراءة `ops->hdev` على أنها غير NULL، والحظر عند `prog_list_lock`، ثم الاستمرار بينما ينفذ التدمير التجولي؛ في هذه الحالة يطلق كلا المسارين نفس المرجع. يصل عداد المراجع (refcount) إلى الصفر بشكل شرعي (كل عملية إنقاص صالحة فرديًا)، لذا لا يتم تفعيل تشبع `refcount_t`: بل يُفراغ الجهاز ببساطة بينما يكون النقل (transport) لا يزال داخل `hid_destroy_device()`، وتلمس عمليات التفكيك اللاحقة ذاكرة تم إفراغها.
يتمثل الإصلاح في تعقيم قرار الإزالة/تعيين القيمة NULL تحت قفل `prog_list_lock` من الجانبين ونقل عمليات الإطلاق (puts) الخاصة بالجانب التدميري خارج القفل. مع الاحتفاظ بالقفل، تكون القراءة والكتابة العادية لـ `ops->hdev` كافية؛ لم تتم إضافة أي استدعاءات `READ_ONCE/WRITE_ONCE`، مما يحافظ على حداثة التصحيح (patch minimal).
أمان القراءة غير المقفلة: لا يمكن للقراءة غير المقفلة لـ `ops->hdev` في بداية دالة `hid_bpf_unreg()` أن تلمس جهازًا تم إفراغ ذاكرته، لأن مسار إلغاء التسجيل نفسه يظل يحتفظ بمرجع هذا التسجيل (لا يُطلق إلا بواسطة `hid_put_device()` الخاصة به بعد إسقاط القفل)، وعملية التدمير التجولي التي مسحت بالفعل `ops->hdev` تجعل إعادة الفحص داخل القفل تعود مبكرًا دون أي عملية put. يتم إطلاق كل مرجع تسجيل من قبل أحد المسارين فقط كحد أقصى.
VulDB is the best source for vulnerability data and more expert information about this specific topic.