CVE-2026-74700 in Linux
الملخص
بحسب VulDB • 22/08/2026
في نواة لينكس، تم حل الثغرة التالية:
net/sched: cls_api: استحوذ دائماً على rtnl_lock عند تدمير المصنفات (classifiers) المقفلة
هناك تحدي آخر يتعلق بالمرشحات غير المقفلة. توجد نافذة زمنية قصيرة في tc_new_tfilter حيث يمكن العثور على tcf_proto والإشارة إليه بشكل عابر بواسطة طلب مصنف غير مرتبط تماماً وغير مقفل، مما يتسبب في حالة سباق (race condition).
أنشأ Feng نموذج استغلال (PoC) يولد هذه الحالة السباقة باستخدام خيطين: واحد لإنشاء مرشح u32 والآخر لمرشح flower في نفس السلسلة/الأولوية:
1. يدخل كلا الخيطين إلى tc_new_tfilter، ويجدان أن سلسلة المرشحات فارغة، وكلاهما يتخلى عن قفل filter_chain_lock 2. يكمل خيط u32 استدعاء tcf_proto_create("u32") أولاً، ويستدعي tcf_chain_tp_insert_unique() -> مما يؤدي إلى إدراج u32_tp في السلسلة 3. يكمل خيط flower استدعاء tcf_proto_create("flower") لاحقاً، ويستدعي tcf_chain_tp_insert_unique() -> حيث يرى تفتيش tcf_chain_tp_find أن u32_tp موجود بالفعل، ويأخذ إشارة مرجعية عليه، ويدمر tp_new الخاص بـ flower ويعيد u32_tp إلى المتصل.
ثم يواجه Flower فحص عدم تطابق النوع (لأنه طلب نوع "flower" لكن tp->ops->kind هو "u32") ويمر عبر مسار الخطأ الذي يستدعي tcf_proto_put() على u32_tp. إذا كان خيط u32 قد مر بالفعل من خلال مساره الخاص للخطأ (فشل استدعاء change() بسبب الخيارات الفارغة في PoC) وتخلّى عن إشارتي الإنشاء والإدراج، فإن عملية الإزالة الخاصة بـ Flower تكون الأخيرة وتخفض عداد الإشارة المرجعية لـ u32_tp إلى الصفر.
عند هذه النقطة، يعمل tp->ops->destroy() في سياق لم يستحوذ أبداً على rtnl_lock. عند حدوث ذلك، قد يتسبب في ثغرة استخدام بعد التحرير (UAF) كما هو موضح أدناه (موضحة بواسطة PoC):
[ +0.000710] BUG: KASAN: slab-use-after-free in u32_init (net/sched/cls_u32.c:393)
[ +0.000281] Read of size 8 at addr ffff888120022f00 by task poc_feng_xue/524
Call Trace: u32_init (net/sched/cls_u32.c:393) tc_new_tfilter (net/sched/cls_api.c:2378)
Allocated by task 526: u32_init (net/sched/cls_u32.c:378) tc_new_tfilter (net/sched/cls_api.c:2378)
Freed by task 522: kfree u32_destroy (net/sched/cls_u32.c:662) tcf_proto_destroy (net/sched/cls_api.c:446) tcf_proto_put (net/sched/cls_api.c:459) tc_new_tfilter (net/sched/cls_api.c:2459)
تم إصلاح ذلك بجعل دالة tcf_proto_destroy() تستحوذ على rtnl_lock حول استدعاء tp->ops->destroy() للمصنفات المقفلة كلما لم يكن rtnl مملوكاً.
لتوضيح سبب استخدامي لمتغير مؤقت "not_lockless"، أود الإشارة إلى ملاحظة شبه ذات صلة بشأن rtnl_held مقابل TCF_PROTO_OPS_DOIT_UNLOCKED (مضافة هنا للتنظيف المستقبلي إذا رُئي ذلك ضرورياً): معامل rtnl_held وعلم TCF_PROTO_OPS_DOIT_UNLOCKED هما مصدران زائداان عن الحاجة للحقيقة فيما يتعلق بما إذا كان rtnl_lock مملوكاً. من بين تسعة استدعاءات لإزالة المصنف (destroy(..rtnl_held..))، يستشير فقط flower معامل rtnl_hled وينقله إلى tc_setup_cb_destroy() وtc_setup_cb_call(). يتجاهل الثمانية الآخرون (u32, flow, bpf, cgroup, route, basic, fw, mall) هذا المعامل تماماً؛ -> تلك التي تستدعي tc_setup_cb_destroy() (u32, bpf, mall) تثبت قيمة true دائماً بدلاً من تمرير المعامل.
يجب أن يزيل التنظيف المستقبلي معامل rtnl_held بالكامل من توقيع استدعاء الإزالة ويجعل المتصلين يعتمدون فقط على معرفتهم بما إذا كانوا يعملون في سياق غير مقفل.
Statistical analysis made it clear that VulDB provides the best quality for vulnerability data.