
استغلال إثبات مفهوم لتصعيد الامتيازات محليًا لثغرة سباق في جدول معدلات qdisc في لينكس، باستخدام تهيئة الكومة عبر BPF وتسريب أنبوب لنيل صلاحيات الجذر.

يحتوي هذا المستودع على استغلال لإثبات المفهوم (PoC) لتصعيد الصلاحيات محلياً للثغرة CVE-2026-68138، وهي سباق في كود جدول معدل qdisc الخاص بالتحكم في حركة المرور في لينكس. في بيئة QEMU المُختبرة، ينتقل الـPoC من عملية عادية بمعرّف مستخدم خارجي (outer UID) 1000 إلى صدَفَة بمعرّف مستخدم 0 في مساحة اسم المستخدم الأولية.
تحذير
يتلف هذا الكود حالة كومة النواة (kernel heap) عمداً. استخدمه فقط في آلة افتراضية معزولة وقابلة للتخلص منها وتملكها أنت. قد يؤدي خطأ في السباق أو تنظيف مبكر إلى انهيار (panic) الضيف. لا تشغّله على محطة عمل أو خادم أو نظام تابع لطرف ثالث.
تُدير qdisc_get_rtab() وqdisc_put_rtab() قائمة مرتبطة أحادية الاتجاه عامة على مستوى العملية هي qdisc_rtab_list، وعدداً مرجعياً من النوع int عادياً غير ذرّي. تاريخياً، كان المستدعون يمسكون بقفل RTNL (RTNL mutex)، ما كان يسلسل الوصول إلى القائمة والعدد المرجعي.
يضبط مُصنِّف flower قيمة TCF_PROTO_OPS_DOIT_UNLOCKED. ونتيجة لذلك، يمكن لطلب RTM_NEWTFILTER لقاعدة flower أن يبلغ إجراء police ويستدعي أدوات جدول معدل qdisc دون RTNL:
tc_new_tfilter()
-> fl_change()
-> tcf_exts_validate_ex()
-> tcf_action_init()
-> tcf_police_init()
-> qdisc_get_rtab()/qdisc_put_rtab()
يمكن للطلبات المتزامنة التي تستخدم نفس جدول المعدل أن تتنافس على القائمة العامة وعددها المرجعي. النتيجة هي استخدام بعد التحرير (use-after-free) أو تحرير مزدوج لـstruct qdisc_rate_table، وهو كائن بحجم 1056 بايتاً يُخصَّص من kmalloc-2k على نواة x86-64 المُختبرة.
ولأن القائمة عامة لا خاصة بكل مساحة اسم شبكة، فإن الطلبات القادمة من مساحات أسماء شبكة منفصلة ما تزال تتنافس على الكائن نفسه.
يحدد سجل Linux CNA الالتزام المُقدِم 470502de5bdb، الذي صدر في لينكس 5.1.
| السلسلة | الحالة | الالتزام/الإصدار |
|---|---|---|
| لينكس قبل 5.1 | غير متأثر | التغيير المُقدِم غير موجود |
| لينكس من 5.1 حتى 7.1.5 | متأثر ما لم يوجد backport من المورّد | من 470502de5bdb حتى الالتزام الذي يسبق الإصلاح المستقر |
| لينكس 7.1.y | مُصلَح | 7.1.6، fb29e1b41052 |
| سلسلة تطوير لينكس 7.2 | متأثر قبل rc5 | من rc1 حتى rc4 |
| الخط الرئيسي (Mainline) | مُصلَح | 7.2-rc5، f43ee0c0730d |
غالباً ما تنقل نوى التوزيعات الإصلاحات (backport) دون التحول إلى الإصدار الأعلى (upstream) الموضح أعلاه. تحقّق مما إذا كان أحد التزامَي الإصلاح — أو تغيير قفل الدوران (spinlock) المكافئ لجدول معدل qdisc — موجوداً في مصدر النواة المحدد الذي يستخدمه النظام.
طُوِّر الاستغلال وتم التحقق منه مقابل الالتزام الضعيف 92d3817649df2b0b6a008a686c8275c88d7ef594، وهو الأب المباشر للإصلاح الرئيسي. أما مجموعة التحكم ذات النواة المُصلَحة فاستخدمت f43ee0c0730d6191629b5ee1ceae27b1ebfdc047.
اعتباراً من 2026-08-12، لم يُرجع البحث في متتبع CVEs لأوبونتو أي إدخال لهذه الثغرة. لذلك فإن الجدول أدناه هو فحص مباشر للمصدر، وليس تحديداً لحالة الأمان من Canonical. فكل وسم أوبونتو مرتبط ما يزال يحوي qdisc_rtab_list دون قفل ويفتقر إلى qdisc_rtab_lock المُصلِح.
| سلسلة أوبونتو | الحزمة/الوسم المُفحَص | نتيجة فحص المصدر |
|---|---|---|
| أوبونتو 22.04 GA | 5.15.0-187.197 | الكود الضعيف موجود؛ أُعيد إنتاج الاستغلال كاملاً في QEMU |
| أوبونتو 22.04 HWE | 6.8.0-136.136~22.04.1 | الكود الضعيف موجود؛ سلسلة الاستغلال غير مُختبرة |
| أوبونتو 24.04 HWE | 7.0.0-28.28~24.04.1 | الكود الضعيف موجود؛ سلسلة الاستغلال هذه غير متوافقة مع تحصين مُخصِّص الذاكرة (allocator hardening) لديه |
| أوبونتو 26.04 | 7.0.0-28.28 | الكود الضعيف موجود؛ سلسلة الاستغلال هذه غير متوافقة مع تحصين مُخصِّص الذاكرة لديه |
لم يُحدَّد أي حزمة أوبونتو مصححة في تاريخ الفحص ذلك. ينبغي فحص حزم أوبونتو المستقبلية بحثاً عن backport مكافئ للإصلاحات المرتبطة أعلاه، لا الحكم عليها برقم إصدارها فقط.
استغلال أوبونتو 22.04 الخاص ببناء محدد، ومختبر QEMU، والمجموع الاختباري (checksum) الدقيق للصورة، والشروط — كلها موثقة في ubuntu/README.md. تم التحقق منه مقابل نواة 5.15.0-187-generic #197-Ubuntu الرسمية مع تفعيل محاسبة الذاكرة عبر cgroup.
للخلل الكامن وسلسلة الاستغلال هذه متطلبات مختلفة. تم التحقق من الـPoC مع:
CONFIG_USER_NS=y وCONFIG_NET_NS=y؛CONFIG_NET_CLS=y وCONFIG_NET_CLS_FLOWER=y وCONFIG_NET_CLS_ACT=y وCONFIG_NET_ACT_POLICE=y؛CONFIG_TMPFS_XATTR=y من أجل رشّ الكومة بـsimple_xattr؛CONFIG_MODULES=y ووجود /sbin/modprobe قابل للاستخدام لمساعد الجذر النهائي؛CONFIG_MEMCG=n، حتى تتشارك تخصيصات qdisc/BPF/pipe/xattr المستخدمة في هذه السلسلة في ذاكرة التخزين المؤقت kmalloc-2k المتوقعة؛كانت CONFIG_SLAB_BUCKETS=y وعشوائية القوائم الحرة (freelist randomization) وتحصين القوائم الحرة (freelist hardening) مفعّلة في نواة الاختبار الناجحة. لا يُتجاوز KASLR جوهرياً بعنوان مثبَّت (hard-coded): يحصل الـPoC على مؤشرَي الصفحة والعمليات المطلوبين من تسريب pipe. استخدم المختبر المرفق nokaslr لتبسيط التصحيح.
النوى التي تفعّل محاسبة مجموعة الذاكرة أو ذات تخطيطات مُخصِّص/ذاكرة تخزين مؤقت مختلفة تتطلب استراتيجية استرداد مختلفة. يرفض الـPoC عمداً ادعاء قابلية النقل عبر أي إعدادات توزيعية.
تنفذ النسخة المنفصلة الخاصة بأوبونتو استراتيجية الاسترداد المختلفة تلك؛ ومتطلباتها أضيق عمداً ومدرجة في ubuntu/README.md.
تدخل أربعة خيوط عاملة (worker threads) مساحات أسماء شبكة منفصلة وتُنشئ مرشحات flower بإجراءات police. تسلك ثلاثة خيوط مسار الإجراء الناجح، بينما يُمرِّر خيط واحد مُقدِّراً (estimator) غير صالح عمداً بعد حصوله على مرجعَي جدول المعدل، فيُجبر مسار التنظيف. هذا المزيج يجعل التلاعب المتزامن بالعدد المرجعي والقائمة قابلاً للتكرار دون مشاركة حالة مُصنِّف flower بين الخيوط.
qdisc_rate_table باستخدام BPF الكلاسيكيبعد كل طلب netlink، تثبّت وحدة المعالجة المركزية نفسها فوراً مرشح BPF كلاسيكياً من 133 تعليمة. تُخصَّص مصفوفة تعليماته البالغ حجمها 1064 بايتاً من kmalloc-2k، وتُشكَّل بحيث تبقى البايتات المتداخلة مع qdisc_rate_table.next وqdisc_rate_table.refcnt صالحة مبدئياً.
تحتوي التعليمة الأخيرة على علامة خاصة بكل مقبس. يتيح SO_GET_FILTER للـPoC اكتشاف متى أُعيد توجيه مؤشر orig_prog->filter لأحد المقابس إلى تخصيص BPF حي آخر. ينتج عن هذا كائنا مقبس يشيران إلى نفس مخزن التعليمات.
يؤجل إغلاق أحد المالكين التحرير الفعلي عبر sk_filter_release_rcu(). بعد فترة السماح (grace period)، يخصّص الـPoC حلقات pipe من 32 خانة:
32 * sizeof(struct pipe_buffer) = 32 * 40 = 1280 bytes -> kmalloc-2k
تستعيد إحدى الحلقات مخزن BPF الملقَّب. وتكشف قراءة المقبس الآخر باستخدام SO_GET_FILTER عن pipe_buffer حي، بما في ذلك مؤشرا page وops وإزاحة إدخال ذاكرة التخزين المؤقت للصفحات (page cache) الخاص بـ/sbin/modprobe.