
محوّل GhostLock (CVE-2026-43499) لنواة أندرويد 4.19.152-perf+
استغلال نواة (kernel exploit) لأجهزة OnePlus/OPPO/realme ذات محمل إقلاع مقفل. يحقق تثبيت root + KernelSU دون فتح قفل محمل الإقلاع أو تعديل صورة الإقلاع. كشف تلقائي لإصدار النواة في وقت التشغيل مع جدول إزاحات متعدد الأجهزة.
CVE-2026-43499 — Futex PI (توريث الأولوية) استخدام بعد التحرير (Use-After-Free)
يؤثر على نواة لينكس 2.6.39 ~ 7.1. تم إصلاحه في الفرع الرئيسي (mainline) 7.1 (commit 3bfdc63936dd). لا يزال Android GKI 6.12.x عرضة للخطر.
ينسخ استدعاء النظام pselect6 بيانات fd_set إلى مكدس النواة. عند دمجه مع آلية انتظار futex PI، يمكن استعادة إطار مكدس مُحرر كبنية rt_mutex_waiter. ثم تكتب إعادة توازن شجرة rb أثناء اجتياز سلسلة PI قيمًا مُتحكمًا بها إلى عناوين نواة عشوائية.
| الجهاز | SoC | النواة | الحالة |
|---|---|---|---|
| OnePlus Ace 6T (PLR110) | SM8845 | 6.12.38-...-ab14275539 | يعمل |
| OnePlus Ace 6T (PLR110) | SM8845 | 6.12.38-...-ab14552068 | يعمل |
| OnePlus 15 (CPH2749) | SM8850 | 6.12.23-...-ab14541642 | يعمل |
| Xiaomi 17 (pudding) | SM8850 | 6.12.23-...-abogki463945075 | يعمل |
| Xiaomi 17 (pudding) | SM8850 | 6.12.69-...-abogki514973465 | يعمل (تحديث أغسطس 2026) |
| OnePlus 13 (IN2060) | SM8750 | 6.6.89-...-abogki446052083 | يعمل (PSELECT_SHIFT=-2) |
| OPPO Pad 4 Pro | SM8750 | 6.6.89-...-ab14358676 | يعمل (PSELECT_SHIFT=-2) |
| الجهاز | SoC | النواة | ملاحظات |
|---|---|---|---|
| OnePlus 15T (PLZ110) | SM8845 | 6.12.38-...-ab14552068 | نفس نواة Ace 6T. تم التحقق عبر QEMU بفرق SP=-64. |
يعمل تراكب pselect على المكدس فقط عندما يقع rt_mutex_waiter المُحرر داخل المنطقة القابلة للتحكم من المستخدم في مخزن stack_fds. يُحدد مكان وقوع الويتر بواسطة مخرجات المترجم (PGO + LTO)، وليس إصدار النواة. راجع تخطيط المكدس للتفاصيل.
| الجهاز | SoC | النواة | السبب |
|---|---|---|---|
| OPPO Find X9 Ultra | SM8750 | 6.12.58-android16-6 | PGO يزيل إطار do_futex → فرق SP=+32، كلمة الويتر=14. لا توجد إزاحة آمنة. |
| OPPO Find X7 | — | 6.1.157 | 6.1 GKI: الويتر عند الكلمة 13 (جميع أجهزة OPLUS/GKI ذات 6.1) |
| realme RMX5070 | SM6650 | 6.1.141 | 6.1 GKI: الويتر عند الكلمة 13 |
| realme RMX3852 | SM8635 | 6.1.141 | نفس فرع 6.1 الخاص بـ RMX5070 |
| OnePlus 13R / Ace 5 | SM8650 | 6.1.x | نفس فرع 6.1 |
| OnePlus 12 | SM8650 | 6.1.141 | 6.1 GKI: do_futex مضمّن عبر PGO، كلمة الويتر=13/19 |
| OPPO Pad 5 (OPD2502) | MT6878 | 6.1.134 | نفس فرع 6.1 |
| OPPO PKW110 | — | 5.15.180 | إطار do_futex 0x140 (4.5x الطبيعي) → كلمة الويتر=-29، لا يمكن الوصول إليها |
| Motorola Edge 60 Fusion | MT6878 | 6.1.145 | 6.1 GKI: الويتر عند الكلمة 13 (غير OPLUS، نفس النتيجة) |
| iQOO Z9 5G | — | 5.15.178 | إطار do_futex كبير جدًا، لا يمكن الوصول إلى الويتر. ليس جهاز OPLUS (vivo). |
مساران للوصول إلى root، يتم اختيارهما تلقائيًا بناءً على قدرات الجهاز:
يتطلب off_ashmem_misc_fops != 0 (C ashmem مع miscdevice ثابت في BSS).
PI write (mode=4) → redirect miscdevice fops to fake fops (via W0 pi_tree)
configfs r/w established
→ pipe physrw (1-byte precise kernel r/w)
→ SELinux enforcing = 0 (single byte, no policycap corruption)
→ UMH: inject work_struct into system_unbound_wq
kernel executes /data/local/tmp/a/e --umh as UID 0
→ root script → ksud late-load → KSU installed
المزايا على المسار B:
selinux_state.policycap (يصلح مشاكل الشبكة على OnePlus 13)متاح حاليًا على: OnePlus 13 (kernel 6.6، C ashmem). غير متاح على أجهزة Rust ashmem (6.12 GKI) — يُخصص miscdevice في الكومة (heap)، والعنوان غير قابل للتنبؤ وقت الترجمة.
يُستخدم عندما تكون إزاحات UMH أو misc_fops الخاصة بـ C ashmem غير متاحة.
Write 1 (mode=1) → SELinux enforcing = 0
(low byte of kernel ptr = 0x00, 8-byte write)
Write 2 (mode=2) → task->cred = init_cred
(uid=0, all capabilities)
Root shell → ksud late-load (KernelSU LKM)
→ su -c load_policy (fix SELinux policycap)
→ dynamic manager registration
App (seccomp) → Write 1 (no perf needed)
→ mini-adb connect TCP (port from /data/local/tmp/a/adb_port, default 5555)
→ adb shell: full exploit (perf works, no seccomp)
→ root → KSU → network fix
BOOT_COMPLETED → BootCompletedReceiver
├─ su available → skip (soft reboot / already rooted)
└─ no root → GhostlockService → setsid exploit --bootstrap
مع NFDS=320، تخصص دالة النواة core_sys_select مخزنًا بحجم 256 بايت باسم stack_fds:
stack_fds: 0 5 10 14 | 15 20 25 29
├─in─┤─out─┤─ex──┤ ├res_in┤res_out┤res_ex┤
◄── USER CONTROLLED ──►│◄── KERNEL ZEROED ──►
يكتب الاستغلال حقول الويتر المزيفة (task, lock) في خرائط البت المدخلة لـ fd_set. لكي يعمل هذا، يجب أن يقع حقلا task وlock الخاصان بالويتر في المنطقة القابلة للتحكم (الكلمات 0-14).
Ace 6T ✅ (waiter at word 2):
░░████████████████░░│░░░░░░░░░░░░░░░░░░
▲waiter t l │
task/lock controllable
RMX5070 ❌ (waiter at word 13):
░░░░░░░░░░░░░████│██████████████░░░░░░
▲ │ t l
waiter task/lock ZEROED
قاعدة الجدوى: يجب أن تكون كلمة الويتر + 11 (إزاحة lock في rt_waiter_node) ≤ 14. أقصى كلمة ويتر مجدية هي 3.
يُحدد موضع الويتر بواسطة تخطيط إطار المكدس في المترجم (ملفات تحسين PGO + LTO + BOLT)، والذي يختلف حسب فرع SoC. قد يكون لإصدار النواة نفسه تخطيطات مختلفة على SoCs مختلفة.
تمر جميع عمليات الكتابة إلى النواة عبر اسم مستعار للخريطة الخطية للصورة:
data_addr(x) = PAGE_OFFSET + (kernel_phys_load - PHYS_OFFSET) + (x - KIMAGE_TEXT_BASE)
يختار محمل الإقلاع kernel_phys_load، لذلك يختلف حسب SoC وليس موجودًا في boot.img أو DT. حقل خاص بكل جهاز في struct kernel_offsets؛ 0 = استخدام الافتراضي في target.h.
| SoC | kernel_phys_load |
|---|---|
| SM8845 (Ace 6T, 15T) | 0xa8000000 |
| SM8750 (OnePlus 13, OPPO Pad 4 Pro) | 0xa8000000 |
| SM8850 (OnePlus 15, Xiaomi 17) | 0xc7800000 |
القيمة الخاطئة تفشل بصمت — فلا تزال الكتابة تصل إلى ذاكرة RAM المعينة، لذلك لا يحدث انهيار ولا تأثير. لا تخلط بينها وبين مشكلة PSELECT_SHIFT. اقرأها من جهاز مخترق (rooted) من نفس الطراز (يبدأ Kernel code عند _stext؛ ويكون _text أقل بـ 0x10000):
su -c 'grep -i "Kernel code" /proc/iomem' # c7810000-... -> 0xc7800000
تضع النوى المختلفة الويتر في مواضع مختلفة داخل المنطقة القابلة للتحكم. استخدم PSELECT_SHIFT للضبط:
# Default (Ace 6T + OnePlus 15, 6.12): shift=0
/data/local/tmp/a/e
# OnePlus 13 (6.6): shift=-2
PSELECT_SHIFT=-2 /data/local/tmp/a/e
# Override kernel_phys_load for new SoCs (when /proc/iomem is not accessible):
KPHYS=0xc7800000 /data/local/tmp/a/e