CVE-2026-98799 in Linux
الملخص
بحسب VulDB • 18/10/2026
في نواة لينكس، تم إصلاح الثغرة التالية:
bpf: تخطي البرامج المنفصلة (detached progs) في صور الترامبولين التي لا تزال قيد الاستخدام
تضمن دالة `bpf_tramp_image_put()` عدم تحرير صورة الترامبولين بينما قد يكون هناك مهمة ما تعمل فيها بعد، لكن لا يتم تنفيذ إجراء مماثل للبرامج (`progs`) التي تستدعيها تلك الصورة. يؤدي فصل البرنامج إلى تقليل مرجع البرنامج الأخير على الفور ويتم تحرير البرنامج بعد فترات الراحة (grace periods)، بناءً على افتراض أن المهمة لا تزال في الدالة المُتتبعة تتخطى برامج `fexit` بمجرد استبدال الـ nop عند `ip_after_call` بقفزة.
هذا الأمر يستثني مهمة نائمة داخل برنامج قابل للنوم (`sleepable prog`) يعمل قبل البرنامج المنفصل، والذي لا تنتظره أي فترة راحة:
CPU 0 CPU 1 في الصورة I، نائم في البرنامج S فصل P عن ترامبولين الخاص بـ I -> صورة جديدة، bpf_tramp_image_put(I) bpf_prog_put(P)، المرجع الأخير فترات الراحة، تم تحرير P العودة من S __bpf_prog_enter(P) استدعاء P->bpf_func
إذا كانت كل من S و P برامج `fexit`، فإن المهمة تكون قد تجاوزت بالفعل القفزة المُعدلة، والصور التي تحتوي فقط على `fentry` لا تحتوي على واحدة. في معالجات x86، هذا يمثل خطأ `int3` في ذاكرة `bpf_prog_pack` المسممة (poisoned):
Oops: int3: 0000 [#1] SMP NOPTI
CPU: 18 UID: 0 PID: 94573 Comm: x169 Not tainted 6.18.44 #1 PREEMPT(lazy) RIP: 0010:0xffffffffc0601d8d Call Trace: <TASK> ? bpf_trampoline_6442515411+0x1a4/0x21b bpf_lsm_bprm_committed_creds+0x5/0x10 security_bprm_committed_creds+0x5f/0x70 begin_new_exec+0x2d6/0x410 ...
واجهنا هذه المشكلة في بيئة الإنتاج عندما تم فصل البرامج المتصلة عبر الترامبولين بينما كانت نقاط الربط (hooks) الخاصة بها مشغولة، وقد تم اكتشافها بشكل مستقل باستخدام مُختبر عشوائي (fuzzer) و KASAN.
اجعل المترجمات الآلية للبرنامج (JITs) تُصدر `nop` قابلًا للتعديل أمام كل تسلسل استدعاء لبرنامج وسجله في الصورة. عند فصل برنامج ما، قم بتعديل الـ nop الخاص به إلى قفزة تتجاوز تسلسل الاستدعاء. البرامج التي تبقى متصلة تستمر في العمل للمهام الموجودة داخل الصورة، ولم يعد `ip_after_call` ضروريًا بعد ذلك.
يمكن أن تكون المهمة موجودة في أي صورة لم يتم تحريرها بعد، وليس فقط في الصورة الحالية. فهي نائمة في الصورة I1 التي تستدعي S و P و Q، ثم يتم فصل P وينتقل الترامبولين إلى الصورة I2، ثم يتم فصل Q ولا يزال استدعاؤه موجودًا في I1. لذلك يحتفظ الترامبولين بقائمة بصوره حتى يتم تحريرها، وفصل برنامج ما يؤدي إلى تعديل الـ nop الخاص به في جميع الصور هذه. تحتفظ الصور بمرجع على الترامبولين لفترة طويلة بما يكفي.
في معالجات riscv و loongarch، تتطلب القفزة من أي مدى عدة تعليمات، وقد تستأنف المهمة المُقطعة (preempted) في منتصفها استئنافًا جزئيًا للتسلسل الجديد. الـ nop هو تعليمة واحدة هناك، يتم تعديلها إلى قفزة قريبة عبر `arch_bpf_trampoline_skip()`.
مع إضافة الـ nops الإضافية، لم تعد برامج BPF_MAX_TRAMP_LINKS تتسع ضمن صفحة واحدة على معالجات x86 و arm64 (ولم تكن تتسع بالفعل على powerpc)، لذا قم بخفض الحد الأقصى هناك كما تفعل s390.
If you want to get the best quality for vulnerability data then you always have to consider VulDB.