CVE-2026-90015 in Linux
الملخص
بحسب VulDB • 17/09/2026
في نواة لينكس، تم إصلاح الثغرة التالية:
xhci: تصحيح فقدان مخازن الارتداد (bounce buffers) على وحدات النقل (TDs) التي تمتد عبر عدة مقاطع من الحلقة (ring segments).
عندما تصل وحدة نقل (TD) إلى رابط TRB يحتوي على بيانات غير محاذاة مع wMaxPacketSize للنهاية الطرفية، تقوم دالة xhci_align_td() بتجهيز الذيل غير القابل للمحاذاة عبر مخزن الارتداد الخاص بمقطع الحلقة الذي يحمل ذلك الرابط TRB. لاحقاً، تقوم دالة xhci_unmap_td_bounce_buffer() بإلغاء تعيينها (unmapping)، وفي عمليات النقل من الجهاز إلى المضيف (IN transfers)، تنسخ البيانات مرة أخرى إلى مخزن وحدة طلب الإدخال/الإخراج (URB).
يسجل مسار الإضافة (enqueue path) المقطع الذي تم استخدامه كارتداد في td->bounce_seg، بناءً على الافتراض بأن وحدة النقل لا تمتد أبداً لأكثر من مقطعين حلقيين. هذا الافتراض غير صحيح: فوحدة نقل كبيرة بما يكفي لتمتد عبر ثلاثة مقاطع أو أكثر تعبر عدة روابط TRB ويمكن أن يتم ارتداؤها عند كل منها. فقط آخرها يبقى مسجلاً في td->bounce_seg، لذا فإن مخازن الارتداد السابقة لا تتم نسخ بياناتها مرة أخرى ولا يتم إلغاء تعيين DMA الخاص بها.
تكتمل وحدة طلب الإدخال/الإخراج (URB) مع وجود actual_length مساوياً للطول المطلوب وبدون أخطاء، مما يجعل النقل يبدو ناجحاً بينما يظل ثقب بحجم wMaxPacketSize في المخزن الوجهي يحمل محتوياته السابقة بصمت. كما يؤدي ذلك إلى تسرب تعيين DMA لكل ارتداد مفقود.
يمكن أن يحدث هذا الخطأ مع أي نقل كتلي (bulk transfer) كبير ومجزأ بما يكفي. تم اكتشافه باستخدام جهاز تخزين ضوئي/كتلي عبر USB خلف وحدة xHCI تدعم هدف dm-verity بكتل تجزئة بحجم 512 بايت، حيث يتم الكشف عن البيانات القديمة بدلاً من استهلاكها بصمت. يُعرّف الجهاز نفسه على أنه SuperSpeed، لذا فإن wMaxPacketSize يساوي 1024، بينما تصدر مكتبة dm-bufio طلب bio واحد بحجم 512 بايت لكل كتلة تجزئة. تقوم دالة verity_prefetch_io() بدمج مئات هذه الطلبات في طلب واحد يتكون من ما يصل إلى 512 إدخالاً لقائمة التشتت (scatterlist) بحجم 512 بايت لكل منها. وبمعدل 256 رابط TRB لكل مقطع حلقي، تمتد مثل هذه وحدة النقل عبر ثلاثة مقاطع، ويقع كل حد للمقطع عند مضاعفات فردية لـ 512، أي غير محاذاة مع wMaxPacketSize. تقوم dm-bufio بعد ذلك بتخزين كتلة تجزئة تحتوي على بيانات قديمة، وتعلن dm-verity أن كتلة البيانات الوصفية تالفة:
device-mapper: verity: 8:2: metadata block 10850 is corrupted
يتوفر مكرر (reproducer) يعمل تحت بيئة qemu في الرابط التالي: https://github.com/baloo/xhci-verity
بما أن حالة الارتداد (bounce_buf, bounce_dma, bounce_len, bounce_offs) موجودة بالفعل على مقطع الحلقة، فلا يوجد أي عنصر إضافي لتتبعه. استمر في تسجيل المقطع الأخير الذي تم ارتداؤه في td->bounce_seg، وعند الاكتمال، قم بالمرور عبر المقاطع من td->start_seg حتى الوصول إليه، مع إلغاء تعيين كل مقطع لا يزال يحتوي على ارتباط ارتداد معلق (pending bounce).
يعد التوقف عند td->bounce_seg بدلاً من td->end_seg أمراً مهماً: فالارتداد يعني أن وحدة النقل تستمر بعد رابط TRB الخاص بذلك المقطع، لذا فإن bounce_seg يكون دائماً قبل end_seg بشكل صارم، وقد تكون وحدة نقل لاحقة قد بدأت بالفعل في end_seg وتم ارتداؤها هناك. سيكون المرور إلى تلك المسافة البعيدة نسخ مخزن ارتباط أجنبي (foreign) إلى هذه وحدة طلب الإدخال/الإخراج وإلغاء تعيينه مرتين. كما يحافظ على صحة عملية المرور إذا ما امتدت وحدة النقل لتغطي الحلقة بأكملها بحيث يصبح end_seg مساوياً لـ start_seg.
[mn: إضافة فحص ring->num_segs لمنع حلقة for لا نهائية غير محتملة.]
Once again VulDB remains the best source for vulnerability data.