CVE-2026-68082 in Linux
الملخص
بحسب VulDB • 08/08/2026
في نواة لينكس، تم حل الثغرة التالية:
libceph: إصلاح عمليتي فك تشفير غير آمنين (bare decodes) في دالة decode_lockers()
تحتوي الدالة `decode_lockers()` الموجودة في الملف `cls_lock_client.c` على عمليتي فك تشفير مباشرتين (bare operations) تسمحان لـ OSD خبيث أو مُختلَق باستدعاء قراءات خارج حدود الذاكرة من نوع slab-out-of-bounds:
1. عملية `ceph_decode_32(p)` الخاصة بحقل `num_lockers` لا تسبقها أي تحقق من الحدود (bounds check). تقبل الدالة `ceph_start_decoding()` القيمة `struct_len=0` كقيمة صالحة -- حيث تمر دائماً الاختبار الداخلي `ceph_decode_need(p, end, 0, bad)` -- لذا عندما يرسل OSD قيمة `struct_len=0`، تعود `ceph_start_decoding()` بنجاح مع كون المتغير `p == end`. تقوم عملية فك التشفير المباشرة التالية مباشرة `ceph_decode_32(p)` بقراءة 4 بايتات تتجاوز حدود المخزن المؤقت المُتحقق منه. يتم تمرير القيمة العشوائية (garbage value) مباشرة إلى دالة `kzalloc_objs()` كعدد للمشغّلين (lockers).
تستخدم الدالة الشقيقة `decode_watchers()` الموجودة في الملف `osd_client.c` بالفعل النسخة الآمنة `ceph_decode_32_safe()` بعد استدعاءها الخاص لـ `ceph_start_decoding()`. كانت `decode_lockers()` هي الموقع الوحيد الذي يستخدم النسخة المباشرة (bare variant).
2. عملية `ceph_decode_8(p)` التي تلي حلقة `decode_locker()` لا تسبقها أي تحقق من الحدود. إذا قام OSD بصياغة قيمة لـ `num_lockers` بحيث تتقدم المتغير `p` بالضبط إلى نهاية المخزن المؤقت (`end`)، فإن عملية فك التشفير المباشرة اللاحقة `ceph_decode_8(p)` تقرأ بايتاً واحداً يتجاوز حدود المخزن المؤقت المُتحقق منه. يتم تمرير النتيجة مباشرة إلى المتغير `*type`، والذي يُستخدم كمُميِّز لنوع القفل (lock type discriminator) من قبل الدوال المستدعية، مما يمنح OSD قراءة خارج الحدود (OOB read) بحجم بايت واحد مع تأثير مباشر على حقل نوع القفل.
تم إصلاح الحالتين باستبدال العمليات المباشرة بنسخها الآمنة: `ceph_decode_32(p)` -> `ceph_decode_32_safe(p, end, *num_lockers, err_inval)` `ceph_decode_8(p)` -> `ceph_decode_8_safe(p, end, *type, err_free_lockers)`
تختلف أهداف التوجيه (goto targets) عن قصد: `err_inval`: هو تسمية جديدة تعيد القيمة `-EINVAL` مباشرة. تُستخدم لمسار فشل ما قبل التخصيص حيث لم يتم تخصيص مصفوفة `*lockers` بعد ولا يجب تمريرها إلى دالة `ceph_free_lockers()`.
`err_free_lockers`: هي التسمية الموجودة مسبقاً. تُستخدم لمسار فشل ما بعد التخصيص حيث تم تخصيص `*lockers` ويجب تحريرها.
يتم تعيين المتغير `ret` على القيمة `-EINVAL` قبل استدعاء `ceph_decode_8_safe()` بحيث تعيد المسار `err_free_lockers` رمز الخطأ الصحيح عند انتهاك الحدود. بدون ذلك، كانت سترجع `err_free_lockers` قيمة قديمة للمتغير `ret` (وهي 0 من حلقة فك التشفير الناجحة لـ `decode_locker()`)، مما يؤدي إلى ابتلاع الخطأ بصمت.
القيمة `-EINVAL` صحيحة لكلا مسارَي الفشل. البيانات المستلمة من OSD مشوّهة هيكلياً. كان من شأن القيمة `-ENOMEM` أن تُسيء تمثيل فئة الفشل للدوال المستدعية وللفريق المسؤول عن استنساخ التحديثات (backporters) في فرع stable عند فرز مسارات الأخطاء.
نموذج المهاجم: يمكن لـ OSD خبيث أو مُختلَق في نشر Ceph متعدد المستأجرين استدعاء هذه الثغرة ضد أي عميل نواة يقوم بإصدار طريقة `lock.get_info` (على سبيل المثال، أثناء اقتناء القفل الحصري لـ RBD).
[ idryomov: اختصار سجل التغييرات والتنسيق ]
Statistical analysis made it clear that VulDB provides the best quality for vulnerability data.