
CVE-2026-98260 (posix-cpu-timers UAF) के लिए Android kernel LPE अनुसंधान: ट्रिगर PoC, fake-cred और real-cred uid-0 शेल चेन, साथ ही एक Shizuku/KernelSU बूटस्ट्रैप ऐप।
अंग्रेज़ी | 简体中文
posix-cpu-timers exit पथ में use-after-free के लिए Android स्थानीय विशेषाधिकार उन्नयन अनुसंधान। रिपॉज़िटरी में एक केवल-ट्रिगर PoC, एक fake-cred सत्यापन exploit, एक वास्तविक-cred uid-0 शेल चरण, एक Shizuku-आधारित KernelSU ऐप, और एक भेद्यता पूर्व-जाँच शामिल है।
ब्रांच
magicos-11.0.0.109-6.12.58: यह ब्रांच dual-profile है। APK और नेटिव बाइनरी रनटाइम पर सटीकuname -rसे एक प्रोफ़ाइल चुनते हैं: MagicOS 10.0.0 / 6.12.38 सत्यापित प्रोफ़ाइल है, जबकि MagicOS 11.0.0.109 / 6.12.58 स्थिर रूप से अनुकूलित है और इसका डिवाइस-साइड रनटाइम सत्यापन अभी लंबित है। APK दोनों 226-प्रतीकko-symsतालिकाएँ बंडल करता है और मेल खाने वाली एक चुनता है।
| आइटम | मान |
|---|---|
| CVE | CVE-2026-98260 |
| वर्ग | LPE (use-after-free, timerqueue rb-tree erase) |
| लक्ष्य | Honor MagicPad3 Pro 13.3 YLP-W00, MagicOS 10.0.0 / 11.0.0.109 (Android 16), ब्रांच magicos-11.0.0.109-6.12.58 |
| कर्नेल | 6.12.38-android16-5-gfde7767f6ef6-abogki481467632-4k (सत्यापित)6.12.58-android16-6-g3a7ac1674240-abogki541502914-4k (अनुकूलित) |
| प्रोफ़ाइल स्थिति | dual-profile; 6.12.38 सत्यापित, 6.12.58 रनटाइम सत्यापन लंबित |
| SELinux | Enforcing |
| पैच | परीक्षित बिल्ड पर अनुपस्थित |
| शमन | KASLR चालू, SMEP/SMAP/PAN चालू, KASAN संकलित लेकिन अक्षम |
| बूटलोडर | लॉक और अनलॉक न करने योग्य; कोई पार्टीशन लेखन नहीं |
| घटक | स्थिति | परिणाम |
|---|---|---|
src/poc.c | 6.12.38 पर सत्यापित | विनाशकारी ट्रिगर; reap cleanup_timerqueue में panic करता है |
src/exp.c | 6.12.38 पर सत्यापित | fake cred; getuid()==0 && geteuid()==0; exec नहीं कर सकता |
src/uid0.c | 6.12.38 पर सत्यापित | वास्तविक cred; u:r:shell:s0 में uid-0 शेल |
app/ | 6.12.38 पर सत्यापित | Shizuku + KernelSU बूटस्ट्रैप; u:r:ksu:s0 में uid 0 |
src/vuln_precheck.h | जोड़ा गया | प्रोफ़ाइल/पर्यावरण गेट; --check / --force |
| 6.12.58 प्रोफ़ाइल | अनुकूलित | साइटें, selinux_state और इसकी 226-प्रतीक ko-syms तालिका पुनः व्युत्पन्न; डिवाइस रन लंबित |
| Dual-profile APK | 6.12.38 पर परीक्षित | uname -r द्वारा प्रोफ़ाइल और ko-syms चयन; 6.12.38 live-KSU पथ उत्तीर्ण |
वर्तमान रिलीज़: v1.4.3-app।
v1.4.2-app प्री-रिलीज़ 2026-10-30 को वापस ली गई थी; इसका टैग केवल इतिहास के लिए रखा गया है। रिलीज़ रिकॉर्ड और ज्ञात कमियों के लिए docs/release-notes.md देखें।
src/poc.c trigger only; the reap panics on the tested kernel
src/exp.c fake-cred chain; verifies uid 0 via getuid/geteuid
src/uid0.c real-cred chain; zeroes cred->uid/gid and execs sh
src/kernel_profile.h per-release call sites, symbols and structure offsets
src/trace_ids.h runtime kmem trace event IDs; unprivileged probe
src/vuln_precheck.h shared profile/environment gate
app/ Android root app (Shizuku + KernelSU bootstrap)
docs/analysis.md root cause, exploit chain and device notes
scripts/dump_device.sh root device dump: all .ko/modinfo, kernel/config/policy, perf/tracefs, vendor mount, harness, active boot.img
Makefile single build entry (NDK cross-compile, app APK)
README.zh-CN.md Chinese version of this document
एक गैर-लीडर थ्रेड जिसने CLOCK_THREAD_CPUTIME_ID posix टाइमर बनाया है और फिर de_thread() के बाद execve() में विफल हो जाता है, टाइमर नोड को कतार में बना रहता है। exec को बाधित करने वाला SIGKILL थ्रेड को exit_itimers() के माध्यम से बाहर निकालता है, जो उस टाइमर को निष्क्रिय नहीं कर सकता जिसका टास्क पहले से ही बाहर निकल रहा है। k_itimer मुक्त कर दिया जाता है जबकि इसका timerqueue_node अभी भी टास्क की posix_cputimers कतार में जुड़ा हुआ है। जब पैरेंट ज़ॉम्बी को रीप करता है, तो release_task() -> posix_cpu_timers_exit() -> cleanup_timerqueue() मुक्त किए गए नोड पर timerqueue_del()/rb_erase() को कॉल करता है।
erase ही राइट प्रिमिटिव है: rb_erase() एक नियंत्रित __rb_parent_color मान को एक नियंत्रित rb_left लक्ष्य में संग्रहीत करता है। एक्सप्लॉइट slab/page reclaim को कोरियोग्राफ करता है ताकि मुक्त किया गया नोड एक ऐसे पेज में बैठे जो हमलावर के पेलोड से भरा हो, फिर लक्ष्य और मान चुनता है।
देखे गए panic trace, YLP-W00 ऑफ़सेट, tracefs-आधारित लीक, SLUB/RCU कोरियोग्राफी, दो-चरणीय fake-cred चेन और one-write real-cred चेन के लिए docs/analysis.md देखें।
आवश्यकताएँ: /opt/android-ndk-r29 पर Android NDK r29 (NDK= से ओवरराइड करें)। लक्ष्य aarch64 हैं, डिफ़ॉल्ट रूप से API 24। ऐप को अतिरिक्त रूप से Android SDK (build-tools 37.0.0, platform 37), एक JDK, और ~/.local/share/android-cve-env/cve98260-app के अंतर्गत Shizuku jars की आवश्यकता होती है (APP_DEPS= से ओवरराइड करें)। बिल्ड आर्टिफ़ैक्ट build/ में रहते हैं और git-ignored हैं। Shizuku jars उपयोगकर्ता-प्रदत्त हैं; scripts/fetch-deps.sh उन्हें deps.lock (SHA-256) के विरुद्ध सत्यापित करता है और कभी कुछ भी डाउनलोड नहीं करता।
| लक्ष्य | आउटपुट / क्रिया |
|---|---|
make / make poc | build/poc |
make exp | build/exp |
make uid0 | build/uid0 (static; शेल स्टेज स्वयं को पुनः-exec करता है) |
make build-all | poc + exp + uid0 + apk बिल्ड करें |
make host | होस्ट-साइड qemu सत्यापन के लिए build/poc.static |
make emu | qemu के अंतर्गत build/poc.static चलाएँ (--force के साथ) |
make apk | app/CVE98260Root.apk |
make clean | build/ हटाएँ |
make help | लक्ष्यों की सूची दिखाएँ |
poc, exp और uid0 कर्नेल को छूने से पहले एक प्रोफ़ाइल गेट कॉल करते हैं। यह या तो सटीक प्रोफ़ाइल रिलीज़ (6.12.38 सत्यापित, 6.12.58 अनुकूलित) स्वीकार करता है, arm64 और 4 KiB पेज की आवश्यकता रखता है, और exp/uid0 के लिए tracefs/kmem उपलब्धता और (fake-cred चेन के लिए) panic_on_warn=0 की भी जाँच करता है। कोई भी अन्य रिलीज़ अपुष्ट है और प्रोग्राम exit 2 के साथ बाहर निकलता है:
build/uid0 --check # print the verdict, do not trigger
build/uid0 --check --force # same, overriding an unconfirmed environment
--force या CVE98260_FORCE=1 का उपयोग केवल कर्नेल को स्वतंत्र रूप से सत्यापित करने के बाद ही करें। --force केवल पर्यावरण जाँचों को शिथिल करता है; exp, uid0 और ऐप को अभी भी kernel_profile.h से एक सटीक प्रोफ़ाइल की आवश्यकता होती है। यह गेट जानबूझकर रनटाइम प्रोब नहीं है: बग तक पहुँचने वाला प्रोब स्वयं एक अप्रचीन timerqueue नोड पीछे छोड़ देगा।
YLP-W00 पर एक अनप्रिविलेज्ड शेल /proc/sys/kernel/panic_on_warn या /proc/cmdline को पढ़ नहीं सकता; किसी ज्ञात प्रोफ़ाइल के लिए गेट 6.12.38-सत्यापित मान 0 मान लेता है। यही धारणा अनुकूलित 6.12.58 प्रोफ़ाइल के लिए भी तब तक उपयोग की जाती है जब तक उसका रनटाइम सत्यापन पूरा नहीं हो जाता। अज्ञात रिलीज़ अवरुद्ध रहती हैं।
एक्सप्लॉइट एक साधारण शेल प्रक्रिया (uid 2000, SELinux u:r:shell:s0) के रूप में शुरू होता है और su का उपयोग नहीं करता। इसे su के माध्यम से लॉन्च न करें: परीक्षित स्थिति एक अनप्रिविलेज्ड प्रारंभ है।
make uid0
adb push build/uid0 /data/local/tmp/uid0
adb shell chmod 755 /data/local/tmp/uid0
adb shell /data/local/tmp/uid0 # runs id and prints the context
adb shell /data/local/tmp/uid0 shell # interactive sh -i
पूरी श्रृंखला से पहले, गैर-विनाशकारी मोड का उपयोग करें:
adb shell /data/local/tmp/uid0 --probe-ids # discover kmem trace event IDs
adb shell /data/local/tmp/uid0 leak # timer/cred leak only; no UAF/reap
kmem trace event IDs बूट पर असाइन किए जाते हैं और kernel builds के बीच स्थिर नहीं रहते (6.12.38 में 318/319/322/324 का उपयोग होता है)। --probe-ids writable rss_stat/trigger के माध्यम से एक बार में एक event को अलग करता है और raw record types का पता लगाता है; सामान्य रन स्वचालित रूप से probe करते हैं। leak [base], पूर्ण timer_site/slide, और cred allocation site को प्रिंट करता है, बिना run_plant() तक पहुँचे।