
लिनक्स qdisc रेट-टेबल रेस कंडीशन के लिए प्रूफ-ऑफ-कॉन्सेप्ट लोकल प्रिविलेज एस्केलेशन एक्सप्लॉइट, जो रूट प्राप्त करने के लिए BPF हीप ग्रूमिंग और पाइप लीक का उपयोग करता है।

इस रिपॉज़िटरी में CVE-2026-68138 के लिए एक proof-of-concept लोकल privilege-escalation exploit शामिल है, जो Linux traffic-control rate-table कोड में एक race है। परीक्षित QEMU वातावरण में, PoC बाहरी UID 1000 वाली एक सामान्य प्रक्रिया से प्रारंभिक user namespace में UID 0 वाले shell तक विशेषाधिकार बढ़ाता है।
चेतावनी
यह कोड जानबूझकर kernel heap स्थिति को भ्रष्ट करता है। इसे केवल एक अलग-थलग, disposable VM में उपयोग करें जो आपका अपना हो। race चूक जाने या समय से पहले cleanup होने पर guest panic कर सकता है। इसे किसी workstation, server या तृतीय-पक्ष प्रणाली पर न चलाएँ।
qdisc_get_rtab() और qdisc_put_rtab() एक process-ग्लोबल single-linked list, qdisc_rtab_list, और एक साधारण non-atomic int refcnt का प्रबंधन करते हैं। ऐतिहासिक रूप से, callers RTNL mutex को धारण करते थे, जो list और reference count तक पहुँच को क्रमबद्ध करता था।
flower classifier TCF_PROTO_OPS_DOIT_UNLOCKED सेट करता है। एक flower rule के लिए एक RTM_NEWTFILTER अनुरोध परिणामस्वरूप बिना RTNL के police action तक पहुँच सकता है और qdisc rate-table helpers को कॉल कर सकता है:
tc_new_tfilter()
-> fl_change()
-> tcf_exts_validate_ex()
-> tcf_action_init()
-> tcf_police_init()
-> qdisc_get_rtab()/qdisc_put_rtab()
एक ही rate table का उपयोग करने वाले समवर्ती अनुरोध ग्लोबल list और उसके reference count के साथ race कर सकते हैं। परिणाम struct qdisc_rate_table का use-after-free या double-free होता है, जो परीक्षित x86-64 kernel पर kmalloc-2k से आवंटित 1056-बाइट की वस्तु है।
चूँकि list per-network-namespace के बजाय ग्लोबल है, अलग-अलग network namespaces के अनुरोध अभी भी उसी object के साथ race करते हैं।
Linux CNA रिकॉर्ड introduction commit 470502de5bdb की पहचान करता है, जो Linux 5.1 में जारी हुआ।
Distribution kernels अक्सर ऊपर दिखाए गए upstream संस्करण को बदले बिना fixes को backport करते हैं। जाँचें कि क्या दोनों में से कोई fixing commit—या समतुल्य qdisc rate-table spinlock परिवर्तन—सिस्टम द्वारा उपयोग किए गए सटीक kernel source में मौजूद है।
Exploit को भेद्य commit 92d3817649df2b0b6a008a686c8275c88d7ef594 के विरुद्ध विकसित और मान्य किया गया था, जो mainline fix का प्रत्यक्ष parent है। fixed-kernel नियंत्रण ने f43ee0c0730d6191629b5ee1ceae27b1ebfdc047 का उपयोग किया।
2026-08-12 तक, Ubuntu CVE tracker खोज ने इस CVE के लिए कोई प्रविष्टि नहीं लौटाई। इसलिए नीचे दी गई तालिका एक प्रत्यक्ष स्रोत निरीक्षण है, न कि Canonical security-status निर्धारण। प्रत्येक लिंक किया गया Ubuntu tag अभी भी बिना lock वाला qdisc_rtab_list रखता है और fixing qdisc_rtab_lock से रहित है।
उस निरीक्षण तिथि पर कोई सुधारित Ubuntu पैकेज की पहचान नहीं हुई। भविष्य के Ubuntu पैकेजों को केवल उनके संस्करण संख्या से आँकने के बजाय लिंक किए गए upstream fixes के समकक्ष backport के लिए जाँचा जाना चाहिए।
बिल्ड-विशिष्ट Ubuntu 22.04 exploit, QEMU lab, सटीक image checksum और शर्तें ubuntu/README.md में प्रलेखित हैं। इसे memory-cgroup accounting सक्षम के साथ आधिकारिक 5.15.0-187-generic #197-Ubuntu kernel के विरुद्ध मान्य किया गया था।
अंतर्निहित bug और यह विशेष exploit श्रृंखला अलग-अलग आवश्यकताएँ रखते हैं। PoC को निम्न के साथ मान्य किया गया:
CONFIG_USER_NS=y और CONFIG_NET_NS=y;CONFIG_NET_CLS=y, CONFIG_NET_CLS_FLOWER=y,
CONFIG_NET_CLS_ACT=y, और CONFIG_NET_ACT_POLICE=y;CONFIG_TMPFS_XATTR=y simple_xattr heap spray के लिए;CONFIG_MODULES=y और अंतिम root helper के लिए एक उपयोग योग्य /sbin/modprobe;CONFIG_MEMCG=n, ताकि इस श्रृंखला द्वारा उपयोग किए गए qdisc/BPF/pipe/xattr आवंटन
अपेक्षित kmalloc-2k cache साझा करें;CONFIG_SLAB_BUCKETS=y, freelist randomization और freelist hardening सफल परीक्षण kernel में सक्षम थे। KASLR को किसी hard-coded address से स्वाभाविक रूप से bypass नहीं किया जाता: PoC आवश्यक page और operations pointers को pipe leak से प्राप्त करता है। दिया गया lab डिबगिंग को सरल बनाने के लिए nokaslr का उपयोग करता था।
memory-cgroup accounting सक्षम या भिन्न allocator/cache लेआउट वाले kernels को एक भिन्न reclaim रणनीति की आवश्यकता होती है। PoC जानबूझकर मनमानी distribution configurations में portability का दावा करने से इनकार करता है।
अलग Ubuntu variant उस भिन्न reclaim रणनीति को लागू करता है; इसकी आवश्यकताएँ जानबूझकर संकुचित हैं और ubuntu/README.md में सूचीबद्ध हैं।
चार worker थ्रेड्स अलग-अलग network namespaces में प्रवेश करती हैं और police actions के साथ flower filters बनाती हैं। तीन workers सफल action पथ अपनाते हैं; एक worker दोनों rate-table references प्राप्त करने के बाद जानबूझकर अमान्य estimator प्रदान करता है, जिससे cleanup पथ बाध्य होता है। यह संयोजन workers के बीच flower classifier state साझा किए बिना समवर्ती reference-count और list manipulation को पुनरुत्पादनीय बनाता है।
qdisc_rate_table को reclaim करेंप्रत्येक netlink अनुरोध के बाद, वही CPU तुरंत 133-निर्देश वाला classic-BPF filter संलग्न करता है। इसकी 1064-बाइट instruction array kmalloc-2k से आवंटित होती है और इस प्रकार आकारित होती है कि qdisc_rate_table.next और qdisc_rate_table.refcnt को अतिव्याप्त करने वाले bytes प्रारंभ में मान्य बने रहें।
अंतिम निर्देश में एक per-socket marker होता है। SO_GET_FILTER PoC को यह पता लगाने में सक्षम बनाता है कि किसी socket का orig_prog->filter pointer कब किसी अन्य live BPF आवंटन की ओर पुनर्निर्देशित किया गया है। इससे दो socket objects उसी instruction buffer का संदर्भ देते हुए प्राप्त होते हैं।
एक owner को बंद करने से वास्तविक free sk_filter_release_rcu() के माध्यम से स्थगित हो जाता है। grace period के बाद, PoC 32-स्लॉट pipe rings आवंटित करता है:
32 * sizeof(struct pipe_buffer) = 32 * 40 = 1280 bytes -> kmalloc-2k
एक ring aliased BPF buffer को reclaim करती है। दूसरे socket को SO_GET_FILTER के साथ पढ़ने से एक live pipe_buffer का खुलासा होता है, जिसमें इसके page और ops pointers तथा /sbin/modprobe page-cache प्रविष्टि का offset शामिल है।
दूसरे socket को बंद करने से एक और RCU grace period के बाद live pipe ring मुक्त हो जाती है, जबकि संगत pipe_inode_info अभी भी उसका संदर्भ देता है। एक simple_xattr spray 1280-बाइट ring को reclaim करता है और लीक हुए pipe_buffer को PIPE_BUF_FLAG_CAN_MERGE सेट सहित अपेक्षित slot पर रखता है।
प्रत्येक उम्मीदवार pipe पर लेखन अंततः /sbin/modprobe के ELF entry point को समर्थन देने वाले page-cache page में attacker-नियंत्रित bytes जोड़ देता है। PoC फ़ाइल को वापस पढ़ता है और सटीक overwrite की पुष्टि के बाद ही आगे बढ़ता है।
हाल के kernels अब search_binary_handler() में ऐतिहासिक invalid-binfmt module-autoload fallback का उपयोग नहीं करते। यह PoC इसके बजाय असमर्थित protocol 253 के साथ एक AF_INET datagram socket बनाता है। inet_create() लापता net-pf-2-proto-253-type-2 module का अनुरोध करता है, जिससे kernel overwritten /sbin/modprobe को initial-namespace root के रूप में निष्पादित करता है।
इंजेक्ट किया गया entry-point payload एक proof फ़ाइल लिखता है और QEMU serial console पर एक root shell खोलता है।
guest binary statically linked है:
./build.sh
समतुल्य command:
gcc -O2 -static -pthread -Wall -Wextra -Werror \
-o build/exploit exploit.c
परिणामी binary को guest के अंदर /exploit/CVE-2026-68138 के रूप में उपलब्ध कराया जाना चाहिए। परीक्षित lab ने QEMU की read-write 9p share का उपयोग किया। root helper उस share को प्रारंभिक mount namespace से /chroot/exploit पर अपेक्षित करता है; यदि lab किसी अन्य लेआउट का उपयोग करता है तो exploit.c में helper_command समायोजित करें।
प्रासंगिक test-kernel विकल्प config.fragment में दर्ज हैं। वे एक fragment हैं, संपूर्ण production kernel configuration नहीं।
विशेषाधिकार-रहित guest shell से:
id
/exploit/CVE-2026-68138
race प्रायिक (probabilistic) है। चूक जाने पर PoC यह प्रिंट करता है:
[-] no BPF alias found in this attempt
पुनः प्रयास करने से पहले VM को रिबूट करें। इसे उसी guest में दोबारा न चलाएँ: ग्लोबल qdisc list पहले ही भ्रष्ट हो चुकी हो सकती है।
एक सफल निष्पादन इस बिंदु तक पहुँचता है:
[+] confirmed dangling orig_prog->filter pointer
[+] pipe leak: page=<kernel pointer> ops=<kernel pointer> off=0x60f len=1 flags=0
[+] page-cache overwrite via dangling pipe
[+] controlled page-cache write confirmed; triggering helper
[+] CVE-2026-68138 initial-namespace root shell
uid=0(root) gid=0(root) groups=0(root)
[+] ROOT PROOF: uid=0(root) gid=0(root) groups=0(root)
संपूर्ण sanitized transcript docs/example-output.txt में है।
पूरी श्रृंखला नई भेद्य VM बूटों से तीन बार पूरी की गई। अंतिम binary ने यह उत्पन्न किया:
outer identity: uid=1000(user)
alias: classic-BPF orig_prog->filter overlap
leak: live pipe_buffer page and ops pointers
write: verified /sbin/modprobe page-cache modification
final identity: uid=0(root) gid=0(root) groups=0(root)
वही binary fixed commit के विरुद्ध उसी four-vCPU topology के साथ चलाई गई। लगभग 126,000 race अनुरोध बिना किसी BPF alias के पूरे हुए, और कोई pipe या page-cache चरण प्राप्त नहीं हुआ।
Ubuntu-विशिष्ट variant को सटीक आधिकारिक 5.15.0-187.197 generic kernel के विरुद्ध भी चलाया गया। guest चार vCPUs, सामान्य memory-cgroup accounting, और एकमात्र exploit-विशिष्ट kernel तर्क के रूप में nokaslr के साथ बूट हुआ।
Ubuntu kernel को पुनर्संकलित नहीं किया गया: परीक्षण ने distribution के अपरिवर्तित vmlinuz-5.15.0-187-generic और मेल खाते आधिकारिक modules का उपयोग किया। Ubuntu prerequisite तालिका stock kernel features को runtime और QEMU lab समायोजनों से अलग करती है।
प्रारंभिक खाते के पास कोई sudo पहुँच या supplementary groups नहीं थे:
uid=1000(ubuntu) gid=1000(ubuntu) groups=1000(ubuntu)
एक नए snapshot से, exploit ने BPF alias प्राप्त किया, उसे cgroup-v2 simple_xattr objects और blocking select() bitmaps के माध्यम से reclaim किया, सत्यापित किया कि /proc/sys/kernel/modprobe में /tmp/x था, और इस बिंदु तक पहुँचा:
[+] CVE-2026-68138 Ubuntu initial-namespace root shell
uid=0(root) gid=0(root) groups=0(root)
root@cve-2026-68138-jammy:/# id
uid=0(root) gid=0(root) groups=0(root)
वास्तविक QEMU transcript और Ubuntu lab निर्देश देखें। variant इस पैकेज के लिए modprobe_path address को hard-code करता है और इसलिए nokaslr की आवश्यकता होती है; यह किसी KASLR bypass या किसी अन्य Ubuntu बिल्ड के साथ संगतता का दावा नहीं करता।
पैच पहले से ही Linux kernel का हिस्सा है और इसलिए इस रिपॉज़िटरी में दोहराया नहीं गया है। विहित stable और mainline fixing commits नीचे संदर्भों में लिंक किए गए हैं।
शोध और exploit कार्यान्वयन: A. Ramos <[email protected]> (Twitter: @aramosf)।
| लाइन | स्थिति | Commit/संस्करण |
|---|
| Linux 5.1 से पहले | प्रभावित नहीं | दोष लाने वाला परिवर्तन अनुपस्थित है |
| Linux 5.1 से 7.1.5 तक | प्रभावित, जब तक vendor backport मौजूद न हो | 470502de5bdb से stable fix से पहले वाले commit तक |
| Linux 7.1.y | सुधारित | 7.1.6, fb29e1b41052 |
| Linux 7.2 विकास श्रृंखला | rc5 से पहले प्रभावित | rc1 से rc4 तक |
| Mainline | सुधारित | 7.2-rc5, f43ee0c0730d |
| Ubuntu लाइन | निरीक्षित पैकेज/tag | स्रोत परिणाम |
|---|
| Ubuntu 22.04 GA | 5.15.0-187.197 | भेद्य कोड मौजूद; QEMU में पूर्ण exploit पुनरुत्पादित |
| Ubuntu 22.04 HWE | 6.8.0-136.136~22.04.1 | भेद्य कोड मौजूद; exploit श्रृंखला परीक्षित नहीं |
| Ubuntu 24.04 HWE | 7.0.0-28.28~24.04.1 | भेद्य कोड मौजूद; यह exploit श्रृंखला इसके allocator hardening के साथ संगत नहीं है |
| Ubuntu 26.04 | 7.0.0-28.28 | भेद्य कोड मौजूद; यह exploit श्रृंखला इसके allocator hardening के साथ संगत नहीं है |