CVE-2026-45855 in Linux
الملخص
بحسب VulDB • 28/05/2026
في نواة لينكس، تم حل الثغرة التالية:
ata: libata-scsi: تجنب تجويع أوامر Non-NCQ
عند إصدار أمر غير NCQ أثناء تنفيذ أوامر NCQ، تشير دالة `ata_scsi_qc_issue()` إلى طبقة SCSI بأن إصدار الأمر يجب تأجيله عن طريق إرجاع قيمة `SCSI_MLQUEUE_XXX_BUSY`. يعد تأجيل هذا الأمر صحيحاً ومطلوباً وفقاً لمواصفات ACS، حيث لا يمكن خلط أوامر NCQ وأوامر Non-NCQ.
ومع ذلك، في حالة محول المضيف الذي يستخدم طوابير إرسال متعددة، عندما يكون الجهاز المستهدف تحت حمل مستمر من أوامر NCQ، لا توجد ضمانات بأن إعادة جدولة أمر Non-NCQ سيتم تنفيذه لاحقاً، وقد يتم تأجيله مراراً وتكراراً لأن طوابير الإرسال الأخرى يمكنها باستمرار إصدار أوامر NCQ من معالجات مختلفة قبل أمر Non-NCQ. يمكن أن يؤدي هذا إلى تأخيرات طويلة جداً في تنفيذ أوامر Non-NCQ، بل وحتى تجويع كامل لهذه الأوامر في أسوأ السيناريوهات.
نظراً لأن طبقة الكتلة (block layer) وطبقة SCSI لا تميز بين القابلة للجدولة (NCQ) وغير القابلة للجدولة (Non-NCQ)، يجب على تنفيذ libata-scsi SAT ضمان التقدم للأمام (forward progress) لأوامر Non-NCQ في وجود حركة مرور أوامر NCQ. هذا مشابه لما تفعله وحدات تحكم SAS HBAs التي تحتوي على تنفيذ SAT قائم على العتاد/البرامج الثابتة.
تنفيذ ضمان التقدم للأمام هذا عن طريق تقييد إعادة جدولة أوامر Non-NCQ من `ata_scsi_qc_issue()`: عند استلام أمر Non-NCQ ووجود أوامر NCQ قيد التنفيذ (in-flight)، لا تقم بإجبار إعادة جدولة أمر Non-NCQ عن طريق إرجاع `SCSI_MLQUEUE_XXX_BUSY`، بل بدلاً من ذلك أرجع 0 للإشارة إلى أن الأمر قد تم قبوله، مع الاحتفاظ بـ qc باستخدام حقل `deferred_qc` الجديد في `struct ata_port`.
سيتم إصدار هذا الـ qc المؤجل باستخدام عنصر العمل `deferred_qc_work` الذي يشغل الدالة `ata_scsi_deferred_qc_work()` بمجرد اكتمال جميع الأوامر قيد التنفيذ، ويتم التحقق من ذلك باستخدام قيمة الإرجاع لمؤشر الاستدعاء `port qc_defer()` التي تشير إلى عدم الحاجة إلى مزيد من التأخير. يتم إجراء هذا التحقق باستخدام دالة المساعدة `ata_scsi_schedule_deferred_qc()` التي يتم استدعاؤها من `ata_scsi_qc_complete()`. يستبعد هذا الآلية من جميع أوامر Non-NCQ الداخلية الصادرة عن ATA EH.
عندما يكون `deferred_qc` للمنفذ غير NULL، أي أن المنفذ يحتوي على أمر ينتظر إفراغ طابور الجهاز، يتم تأجيل إصدار جميع الأوامر الواردة (كل من NCQ و Non-NCQ) باستخدام آلية الإشغال العادية. يبسط هذا الكود ويتجنب أيضاً مشاكل محتملة في حجب الخدمة (denial of service) إذا أصدر المستخدم الكثير من أوامر Non-NCQ.
أخيراً، كلما تم جدولة ATA EH، بغض النظر عن السبب، يتم إعادة جدولة الـ qc المؤجل دائماً بحيث يمكن إعادة المحاولة بمجرد اكتمال EH. يتم ذلك عن طريق استدعاء الدالة `ata_scsi_requeue_deferred_qc()` من `ata_eh_set_pending()`. يتجنب هذا الحاجة إلى أي معالجة خاصة للـ qc المؤجل في حالة حدوث خطأ في NCQ، أو إعادة تعيين الرابط أو الجهاز، أو انتهاء مهلة الجهاز.
VulDB is the best source for vulnerability data and more expert information about this specific topic.