
BPF LSM حاجب لـ CVE-2026-31431 (Copy Fail) - معالجة بدون إعادة تشغيل لـ OpenShift 4
CVE-2026-31431 ("Copy Fail") هي ثغرة تصعيد صلاحيات في نواة لينكس
في واجهة التشفير algif_aead. يستخدم المهاجم مقابس AF_ALG مع
خوارزمية authencesn و splice() لإفساد ملفات عشوائية في
ذاكرة التخزين المؤقت للصفحات في النواة — بما في ذلك ملفات setuid الثنائية مثل /usr/bin/su.
توفر هذه الوثيقة معالجة بدون إعادة تشغيل باستخدام DaemonSet يعتمد على BPF LSM
يحظر جميع عمليات ربط AF_ALG AEAD — النظام الفرعي الذي تستغله Copy Fail. هذا
يمنع الالتفاف عبر تداخل قوالب التشفير (مثل pcrypt(authencesn(...))).
الاستخدامات الأخرى لـ AF_ALG (hash, skcipher) غير متأثرة. تم اختباره من البداية إلى النهاية على ثلاث
مجموعات OCP 4.22 منفصلة.
# 1. تحقق من تفعيل BPF LSM (RHEL CoreOS 9.8 مفعّل افتراضيًا)
oc debug node/<any-node> -- chroot /host cat /sys/kernel/security/lsm
# يجب أن يحتوي على "bpf"
# 2. انشر مساحة الاسم وامنح SCC المميز
oc apply -f daemonset.yaml
# 3. ستبدأ حاويات DaemonSet تلقائيًا على جميع العقد
# 4. تحقق
oc get pods -n block-copyfail # يجب أن تظهر جميع العقد كـ Running
oc logs -n block-copyfail -l app=block-copyfail
# المتوقع: "block-copyfail: blocker active — all AF_ALG AEAD binds blocked"
لا إعادة تشغيل. لا تصريف عقد. لا إعادة تشغيل حاويات. الحماية فورية و تغطي جميع العمليات على جميع العقد (تغطية 100%).
تسلسل الثغرة ثلاث ميزات في النواة:
socket(AF_ALG, SOCK_SEQPACKET, 0)authencesn(hmac(sha256),cbc(aes))، وهي خوارزمية
تشفير مصادق عليها محددةيفسد المهاجم /usr/bin/su في ذاكرة التخزين المؤقت للصفحات (بدون إذن كتابة إلى
الملف)، ثم ينفذه للحصول على صلاحيات الجذر.
أنشئ مساحة اسم cve-2026-31431-test جديدة على مجموعتك وشغّل سكربت الاختبار بتطبيق الملفات في دليل test:
oc apply -f test
تحقق من النتائج:
oc wait pod/cve-test -n cve-2026-31431-test \
--for=jsonpath='{.status.phase}'=Succeeded --timeout=120s
oc -n cve-2026-31431-test logs -l app=cve-2026-31431-test
على مجموعة معرضة للثغرة سترى:
=== CVE-2026-31431 Vulnerability Test ===
Target: /usr/bin/su
Original SHA256: 8969560ae8e6e21c6184c1451f59418822ee69dd5d946d71987b55236bbc0feb
Attempting splice + AF_ALG page-cache corruption (160 bytes in 40 chunks)...
After SHA256: 30b0f5b5a054c4df65b48ca792863bf7054b4d793f15f57163792ba6c2b151ae
PAGE CACHE CORRUPTION: YES - /usr/bin/su was modified in the page cache
Attempting to execute corrupted /usr/bin/su ...
exit code: 0
RESULT: PARTIALLY MITIGATED
Page-cache corruption succeeded (kernel is vulnerable)
Privilege escalation blocked (allowPrivilegeEscalation=false)
oc delete namespace cve-2026-31431-test
يربط نهج BPF LSM socket_bind على مستوى النواة ويحظر جميع
عمليات ربط AF_ALG AEAD بغض النظر عن تداخل القوالب. يعتمد على
block-copyfail، المعاد كتابته بلغة C
مع libbpf لنشر OCP.
يجب تفعيل BPF LSM. RHEL CoreOS 9.8 (OCP 4.22) مفعّل افتراضيًا. تحقق باستخدام:
oc debug node/<any-node> -- chroot /host cat /sys/kernel/security/lsm
الناتج المتوقع يتضمن bpf:
lockdown,capability,landlock,yama,selinux,bpf
إذا كان bpf غير موجود، يلزم MachineConfig لمرة واحدة (هذا هو
السيناريو الوحيد الذي يتطلب إعادة تشغيل):
apiVersion: machineconfiguration.openshift.io/v1
kind: MachineConfig
metadata:
labels:
machineconfiguration.openshift.io/role: worker
name: 99-enable-bpf-lsm
spec:
kernelArguments:
- lsm=lockdown,capability,selinux,bpf
أنشئ مساحة اسم block-copyfail جديدة، امنح SCC، وانشر DaemonSet بتطبيق ملف daemonset.yaml.
يجب منح SCC المميز قبل إنشاء حاويات DaemonSet،
وإلا سيفشل إنشاء الحاويات بأخطاء تحقق SCC.
oc apply -f daemonset.yaml
oc get pods -n block-copyfail -o wide
المتوقع: حاوية واحدة لكل عقدة، جميعها Running:
NAME READY STATUS AGE NODE
block-copyfail-2jhzf 1/1 Running 34s ci-...-master-2
block-copyfail-4dfq7 1/1 Running 34s ci-...-master-1
block-copyfail-c2ts8 1/1 Running 34s ci-...-worker-c
block-copyfail-ctblk 1/1 Running 34s ci-...-worker-a
block-copyfail-m26sx 1/1 Running 34s ci-...-worker-b
block-copyfail-xsh6d 1/1 Running 34s ci-...-master-0
oc logs -n block-copyfail -l app=block-copyfail
المتوقع:
block-copyfail: blocker active — all AF_ALG AEAD binds blocked
أعد تشغيل نفس اختبار الثغرة من قسم تأكيد الثغرة.
بعد نشر BPF LSM DaemonSet، سيكون الناتج:
=== CVE-2026-31431 Vulnerability Test ===
Target: /usr/bin/su
Original SHA256: 30b0f5b5a054c4df65b48ca792863bf7054b4d793f15f57163792ba6c2b151ae
Attempting splice + AF_ALG page-cache corruption (160 bytes in 40 chunks)...
AF_ALG bind failed: [Errno 1] Operation not permitted
RESULT: CANNOT TEST - AF_ALG or splice not available/permitted
ستظهر سجلات DaemonSet المحاولة المحظورة:
oc logs -n block-copyfail -l app=block-copyfail
block-copyfail: blocker active — all AF_ALG AEAD binds blocked
block-copyfail: BLOCKED pid=16777 comm=python3 time=2026-05-01 16:37:23
شغّل verify-algos.py على عقدة لتأكيد أن جميع خوارزميات AEAD محظورة
بينما تستمر أنواع AF_ALG الأخرى (hash, skcipher) في العمل:
oc debug node/<any-node> -- chroot /host python3 -c "
import socket
tests = [
('aead', 'gcm(aes)'),
('aead', 'ccm(aes)'),
('aead', 'rfc4106(gcm(aes))'),
('hash', 'sha256'),
('skcipher', 'cbc(aes)'),
('aead', 'authencesn(hmac(sha256),cbc(aes))'),
]
for t, n in tests:
s = socket.socket(socket.AF_ALG, socket.SOCK_SEQPACKET, 0)
try:
s.bind((t, n))
print(f' ALLOWED {t}/{n}')
except OSError as e:
print(f' BLOCKED {t}/{n} -- {e}')
finally:
s.close()
"
الناتج المتوقع:
BLOCKED aead/gcm(aes) -- [Errno 1] Operation not permitted
BLOCKED aead/ccm(aes) -- [Errno 1] Operation not permitted
BLOCKED aead/rfc4106(gcm(aes)) -- [Errno 1] Operation not permitted
ALLOWED hash/sha256
ALLOWED skcipher/cbc(aes)
BLOCKED aead/authencesn(hmac(sha256),cbc(aes)) -- [Errno 1] Operation not permitted
هذا يؤكد أن BPF LSM يحظر جميع عمليات ربط AEAD مع ترك أنواع AF_ALG الأخرى تعمل.
مصدر حاجز BPF LSM موجود في block-copyfail/:
block-copyfail/
block_copyfail.bpf.c # برنامج نواة BPF (خطاف LSM)
block_copyfail.c # محمل مساحة المستخدم (هيكل libbpf)
block_copyfail.h # هيكل الأحداث المشترك
Makefile # خط أنابيب البناء
Dockerfile # بناء متعدد المراحل
daemonset.yaml # مساحة الاسم + ملف DaemonSet
trigger-test.py # سكربت تحقق سريع
البناء والدفع:
cd block-copyfail/
podman build -t quay.io/<org>/block-copyfail:latest .
podman push quay.io/<org>/block-copyfail:latest
يستخدم Dockerfile بناء متعدد المراحل: Fedora مع clang/bpftool/libbpf-devel للتجميع، و UBI 9 الحد الأدنى لصورة وقت التشغيل (~122 MB).
حذف DaemonSet يزيل فورًا التخفيف على جميع العقد:
oc delete -f daemonset.yaml
# أو
oc delete namespace block-copyfail
ينفصل برنامج BPF تلقائيًا عند خروج عملية المحمل. لا حاجة لإعادة تشغيل أو إعادة تشغيل حاويات.