
شرح منظم لـ CVE-2026-31431 (Copy Fail)، يربط بين التغييرات الثلاثة في النواة التي أدخلت الثغرة الأمنية ومكّنت من استغلالها.
خلل منطقي في authencesn يُمرَّر عبر AF_ALG وsplice() ليصل إلى كتابة محكومة من 4 بايتات في page cache لأي ملف قابل للقراءة على النظام. لا سباق في التوقيت، ولا إزاحات، ولا حمولة مُترجَمة. السكربت نفسه بحجم 732 بايت يمنح صلاحيات الجذر على كل توزيعات لينكس منذ 2017.
CVE-2026-31431 - Copy Fail هو خلل منطقي في قالب التشفير authencesn في نواة لينكس. يسمح لمستخدم محلي غير مميز بإجراء كتابة محكومة من 4 بايتات في page cache لأي ملف قابل للقراءة على النظام، دون تعديل الملف على القرص.
الخلل غير موجود في أي من المكونات الثلاثة على حدة. بل ينشأ من تفاعلها:``` 2011 ────────────────────────────────────────────────────────────────────── - authencesn added to the kernel (a5079d084f8b). - Uses the caller's destination scatterlist as scratch space. - Reorder ESN bytes before HMAC computation. - Only caller: internal xfrm layer. Harmless.
2015 ────────────────────────────────────────────────────────────────────── - algif_aead.c gains AEAD support with splice() path (104880a6b470). - splice() can deliver page cache pages to the TX scatterlist. - AF_ALG uses out-of-place operation: req->src != req->dst. - Page cache pages remain read-only. Not exploitable.
2017 ────────────────────────────────────────────────────────────────────── - In-place optimization in algif_aead.c (72548b093ee3). - Copies AAD+CT to RX buffer but chains authentication tag pages via sg_chain(). - Sets req->src = req->dst. - Page cache pages now reside in WRITABLE dst. - authencesn writes past boundary → page cache corruption.
2026 ────────────────────────────────────────────────────────────────────── - Copy Fail - CVE-2026-31431. Discovered by Theori / Xint Code. - Exploitable across all distros since 2017.
---
---
---
<div id='root-cause'/>
## ***🧬 تحليل السبب الجذري***
<div id='primitive'/>
### ***أولية AF_ALG + splice()***
AF_ALG (*[AF_ALG = 38](https://docs.kernel.org/crypto/userspace-if.html#user-space-api-general-remarks)*) هو نوع مقبس (socket) يكشف واجهة برمجة تطبيقات التشفير للنواة إلى مساحة المستخدم غير المميزة. يمكن لعملية غير مميزة أن:
1. افتح مقبس AF_ALG / SOCK_SEQPACKET.
2. استدعِ bind() على أي قالب AEAD متاح توفره واجهة برمجة تطبيقات التشفير للنواة.
3. عيّن مفتاح تشفير عبر setsockopt(SOL_ALG, ALG_SET_KEY, ...) على الخوارزمية المهيأة.
4. استدعِ accept() للحصول على مقبس عمليات مخصص سيتعامل مع طلبات التشفير وفك التشفير
5. أرسل بيانات مصممة باستخدام sendmsg() واستلم النتيجة المعالجة عبر recvmsg()، متفاعلاً بالكامل مع نظام التشفير الفرعي للنواة.
إنه مفعّل افتراضيًا في إعدادات النواة لجميع التوزيعات الرئيسية (CONFIG_CRYPTO_USER_API_AEAD=y).
**[splice(2)](https://man7.org/linux/man-pages/man2/splice.2.html)** ينقل البيانات بين واصفات الملفات دون نسخ - يمرر مراجع إلى الصفحات وليس نسخًا. التدفق ذو الصلة:```
open("/usr/bin/su") -> fd_file
pipe() -> pipe_rd, pipe_wr
# moves N bytes from the file into the pipe
# the pipe buffer now contains a reference to the same physical page in the page cache
splice(fd_file, pipe_wr, N)
# delivers that reference to the AF_ALG socket
# the TX scatterlist of algif_aead now points to the page cache page of /usr/bin/su
splice(pipe_rd, alg_fd, N)
تحتوي قائمة التشتت الخاصة بمقبس AF_ALG على مراجع مباشرة لنفس الصفحات المادية التي تستخدمها النواة لكل read() وmmap() وexecve() على الملف. لا يتم إجراء أي نسخ.
الالتزام 72548b093ee3، algif_aead.c. بالنسبة لفك التشفير، يقوم التنفيذ بما يلي:
In-place operation: RX SGL (req->dst): [ user buffer: AAD (copy) || CT (copy) ] --sg_chain--> [ Tag (page cache pages) ] req->src = req->dst = RX SGL
Result: page cache pages from /usr/bin/su are now part of the WRITABLE scatterlist passed to the crypto algorithm.
<div id='authencesn'/>
### ***الكتابة خارج الحدود في authencesn***
authencesn هو غلاف AEAD في النواة يُستخدم بواسطة IPsec مع أرقام التسلسل الموسعة (RFC 4303). يستخدم IPsec أرقام تسلسل 64-بت:
- seqno_hi - البتات الـ 32 العلوية (البايتات 0-3 من AAD)
- seqno_lo - البتات الـ 32 السفلية (البايتات 4-7 من AAD)
يتم إرسال seqno_lo فقط عبر الشبكة؛ أما seqno_hi فهو سياق ضمني. لحساب HMAC، يحتاج authencesn إلى إعادة ترتيب هذه البايتات: seqno_hi في البداية وseqno_lo في نهاية مدخلات التجزئة.
يقوم بهذه إعادة الترتيب باستخدام scatterlist الوجهة الخاصة بالمستدعي كمساحة عمل مؤقتة:```c
/* crypto/authencesn.c - crypto_authenc_esn_decrypt() */
// [1] Read bytes 0-7 of the AAD from dst
scatterwalk_map_and_copy(tmp, dst, 0, 8, 0);
// [2] Overwrite dst[4..7] with seqno_hi (temporary modification for HMAC)
scatterwalk_map_and_copy(tmp, dst, 4, 4, 1);