
دور Ansible وسكربت Python يكتشفان تعرّض نواة Linux للثغرة CVE-2026-98432 ويطبّقان قاعدة nftables تُسقط حزم SYN الواردة عبر IPv4 التي تحمل خيارات IP.
ثغرة use-after-free في شيفرة TCP عبر IPv4 في نواة لينكس
(CVE-2026-98432، CVSS 9.8):
يمكن تحرير خيارات IPv4 المحفوظة من حزمة SYN الواردة بينما لا يزال معالج آخر
يقرأها لبناء حزمة SYNACK، لأن مساري التدمير يحررانها باستخدام
kfree() مباشرة بدلاً من انتظار فترة سماح RCU.
الإصلاح في المستودع الأصلي هو
e3f33b0a1d89
("ipv4: free inet_opt and ireq_opt after an RCU grace period").
اعتبارًا من 2026-10-29 لم تُصدر أي نواة مُصلحة لأي إصدار من Ubuntu. كل حالة متأثرة على متتبع Ubuntu تقرأ "work in progress" أو ببساطة قابلة للاستغلال، ولا تسرد الصفحة أي تخفيف. هذه الحزمة هي التخفيف.
يقرأ كلا المسارين المتسابقين ireq->ireq_opt، وهي خيارات IPv4 التي حفظتها النواة
من حزمة SYN الواردة (tcp_v4_save_options()): بناء SYNACK يقرأها
بينما يمكن أن يؤدي تفكيك مقبس الابن إلى تحريرها، وترحيل مقبس الطلب
(net.ipv4.tcp_migrate_req=1، أو برنامج
BPF_SK_REUSEPORT_SELECT_OR_MIGRATE) يشاركها ثم يحرر نفس
الخيارات. عندما لا تحمل حزمة SYN أي خيارات IPv4، يكون ireq_opt مساويًا لـ NULL: لا يوجد
شيء لتحريره ولا شيء لقراءته. لقد قرأنا التزام الإصلاح قبل الاعتماد
على ذلك؛ كلا الشقين يبدأ من حزمة SYN حملت خيارات IPv4.
لذلك تثبّت الحزمة قاعدة nftables واحدة تُسقط حزم SYN الواردة لبروتوكول TCP عبر IPv4 التي تحمل خيارات IP، في جدول خاص بها حتى لا تتعارض أبدًا مع قواعد Docker أو قواعد الركيزة أو قواعد التوزيعة:
table inet samp_cve_2026_98432 {
chain prerouting {
type filter hook prerouting priority -300; policy accept;
ip hdrlength > 5 tcp flags & (syn | ack) == syn counter drop \
comment "CVE-2026-98432: drop inbound IPv4 SYN carrying IP options"
}
}
تم التحقق منه على نواة حقيقية قبل الإصدار: SYN IPv4 يحمل خيارات يصطدم بالعدّاد ويُسقط؛ أما SYN العادي فيمر دون تأثر. فحركة TCP لا تكاد تحمل خيارات IP أبدًا (فعدة أنواع من الخيارات تُسقطها كثير من الشبكات بشكل اعتيادي، وفق RFC 7126)، لذا فإن الكلفة التشغيلية للقاعدة تقارب الصفر.
pve الخاصة بها،
وهي غير مغطاة في صفحة Ubuntu) فتُبلّغ unknown: راجع
نشراتها الأمنية. القاعدة نفسها من شأنها حماية أي مضيف Linux؛ أما جداول
الأحكام فهي وحدها الخاصة بـ Ubuntu.تعيش القاعدة في ذاكرة النواة ولا تُحفظ على القرص. فلا يجوز لحزمة
تخفيف أن تكتب إلى مسارات الاستمرارية (units، cron)، كما أن ملف تضمين
nftables لا يُحمّل إلا حيث تكون خدمة nftables الخاصة بالتوزيعة مفعّلة، وهي
في هذه البيئات غير مفعّلة بشكل موحّد. لذا: بعد
إعادة التشغيل، يقرأ الكشف القاعدة على أنها غائبة (rule_live=0،
persistent=0 في كل سطر نتيجة) ويعيدها التطبيق التالي.
إعادة تشغيل التطبيق بعد عمليات إعادة التشغيل هي نموذج التشغيل، وسطر
النتيجة لا يدّعي غير ذلك أبدًا.
للقراءة فقط، يهيّئ نفسه في دليل مؤقت خاص يزيله، ويبلّغ عن:
uname -r، مقابلة بإصدار حزمتها)
مقابل إصدارات Ubuntu المُصلحة لكل إصدار ونكهة. لا إصلاح صادر
لإصدار الجهاز: no_fix. نواة مُصلحة صدرت لكنها غير
قيد التشغيل: vulnerable، مع restart_needed=1 عندما تكون مثبّتة
بانتظار إعادة تشغيل (الإصلاح المثبّت لا يُبلّغ عنه أبدًا fixed).fixed مع workaround: true على
سطر النتيجة ما دامت القاعدة تغطي نواة غير مُصلحة؛ وfixed مجردة
بمجرد أن تصبح النواة قيد التشغيل مُصلحة.not_affected للإصدارات التي يبرّئها المتتبع، وunknown للإصدارات
والتوزيعات التي لا تغطيها الجداول.0 نظيف (fixed، not_affected)، 2 مكشوف أو
غير محسوم (no_fix، vulnerable، unknown: ليس نظيفًا أبدًا)، 1 فشل
التشغيل نفسه، 130 مقاطَع.syn_options_mitigation/files/samp_common.py نسخة مطابقة بايتًا ببايت من
samp-common 1.0.4 (مقارنات إصدارات dpkg وrpm وapk،
وسطر النتيجة، وتحميل الإعدادات). وsha256 الخاص به في
samp.yaml، ويفشل tests/test_samp_pack.py إذا اختلفت النسخة. لا
تحرّره هنا أبدًا؛ أعد توريده باستخدام scripts/vendor.py الخاص بـ samp-common.samp/v<version> (هذا الإصدار:
samp/v1.0.1)، موقّعة بمفتاح مدعوم عتاديًا. تستورد الطبقة الأساسية
وسمًا موقّعًا، لا فرعًا أبدًا.خطوة سكربت واحدة، سطر نتيجة واحد. ما دامت النواة قيد التشغيل غير مُصلحة،
فإنه يحمّل القاعدة؛ وبمجرد تشغيل نواة مُصلحة، يزيل القاعدة
وجدولها. ولا يحرّر أي ملفات عدا السكربت والمكتبة والإعدادات التي
ينشرها (المعلنة في touches ضمن samp.yaml)، لذا فإن قائمة النسخ الاحتياطي في سطر
النتيجة فارغة. وإزالة التخفيف يدويًا أمر واحد:
nft delete table inet samp_cve_2026_98432
ansible-playbook -i inventory play.yml # a play that runs the role
python3 syn_options_mitigator.py --config syn_options_config.yaml # detect
sudo python3 syn_options_mitigator.py --config syn_options_config.yaml --apply
عندما تصدر Ubuntu نوى مُصلحة، الصق الإصدارات من المتتبع
في syn_options_fixed_versions في إعدادات الدور الافتراضية (إصدارات
قيد العمل موجودة بالفعل هناك في تعليق) وأصدر التغيير كالوسم الموقّع
التالي؛ عندها يبدأ الكشف بالإبلاغ عن vulnerable/restart_needed
مقابلها، وتزيل عملية التطبيق القاعدة من الأجهزة التي تُعيد التشغيل إلى
نواة مُصلحة.
python3 -m pytest tests/
تتظاهر اختبارات الوحدة بكل أمر خارجي؛ يتحقق اختبار العقد
(tests/test_samp_pack.py، الخاص بـ samp-common) من المانيفست مقابل
الدور، ويشغّل كشفًا حقيقيًا من دليل مؤقت ويُلزم مدخل apply
بقاعدة سطر النتيجة الواحدة وقواعد needrestart.
MIT. راجع LICENSE.
طلبات السحب والتحسينات مرحّب بها -> يُرجى عمل fork وتقديم طلب دمج.