
CVE-2026-52910 के लिए रेस रिप्रोड्यूसर और स्ट्रेस टूलकिट, जो reuseport cBPF सेलेक्टर प्रोग्राम्स में Linux kernel use-after-free है, dmesg और leak जाँच के साथ।
CVE-2026-52910 के लिए एक रेस रिप्रोड्यूसर और स्ट्रेस टूलकिट, जो Linux kernel के classic BPF (cBPF) reuseport selector प्रोग्राम के हैंडलिंग में एक use-after-free (UAF) है, जिसे upstream में commit "bpf: Free reuseport cBPF prog after RCU grace period" द्वारा ठीक किया गया है।
| CVE | CVE-2026-52910 |
| प्रकार | Use-after-free / out-of-bounds read (CWE-125), CVSS 3.1 7.8 HIGH AV:L/AC:L/PR:L/UI:N/S:U/C:H/I:H/A:H |
| शुरू हुआ | v4.5 (reuseport cBPF समर्थन के साथ) |
| में ठीक किया गया | 5.10.259, 5.15.210, 6.1.176, 6.6.143, 6.12.94, 6.18.36, 7.0.13 (stable); mainline v7.1 |
| Upstream splat | BUG: KASAN: vmalloc-out-of-bounds in reuseport_select_sock (net/core/sock_reuseport.c:596) |
| रिपोर्ट करने वाले | Eulgyu Kim |
[!WARNING] यह एक kernel स्ट्रेस टूल है। कमजोर kernel पर यह जानबूझकर एक use-after-free रेस विंडो को चौड़ा करता है; एक हिट मशीन को क्रैश या करप्ट कर सकती है। इसे केवल उन मशीनों पर चलाएँ जिनके आप मालिक हैं या जिन्हें परीक्षण के लिए स्पष्ट रूप से अधिकृत किया गया है (टेस्ट VM, अस्थायी CI मशीनें), कभी भी प्रोडक्शन सिस्टम पर नहीं।
SO_REUSEPORT कई sockets को एक ही UDP पोर्ट बाइंड करने देता है; प्रत्येक
आने वाले पैकेट के लिए kernel reuseport_select_sock()
(net/core/sock_reuseport.c) में समूह के एक socket को चुनता है। एक समूह एक
selector प्रोग्राम इंस्टॉल कर सकता है — एक classic BPF प्रोग्राम जो
setsockopt(SO_ATTACH_REUSEPORT_CBPF) के साथ अटैच किया जाता है — जो प्रति
पैकेट तय करता है कि समूह का कौन सा socket इसे प्राप्त करेगा। प्रोग्राम RX
softirq (नेटवर्क रिसीव प्रोसेसिंग) में एक RCU read-side critical section के
अंदर निष्पादित होता है।
बग: जब प्रोग्राम को setsockopt() (reuseport_attach_prog() /
reuseport_detach_prog()) के माध्यम से बदला या डिटैच किया जाता है, तो पुराना
cBPF प्रोग्राम sk_reuseport_prog_free() द्वारा तुरंत फ्री कर दिया जाता
है, बिना इन-फ्लाइट RCU रीडर्स की प्रतीक्षा किए। एक CPU जो अभी भी फ्री किए गए
प्रोग्राम के निर्देशों को चला रहा है, फ्री की गई vmalloc'd मेमोरी पढ़ता है:
sequenceDiagram
autonumber
participant C as CPU0 — churner thread
participant K as setsockopt() path
participant R as CPU1 — RX softirq
R->>R: rcu_read_lock()
R->>R: prog = rcu_dereference(reuse->prog)
C->>K: setsockopt(SO_ATTACH_REUSEPORT_CBPF, progB)
K->>K: swap progA → progB
K->>K: sk_reuseport_prog_free(progA)
Note right of K: unfixed kernels: bpf_prog_free()<br/>runs NOW — no RCU grace period
R->>R: execute progA->insns (run_bpf_filter)
Note right of R: progA was already freed<br/>KASAN: vmalloc-out-of-bounds
Note over K: fix: call_rcu(sk_reuseport_prog_free_rcu) —<br/>free deferred by one RCU grace period
eBPF selector पथ (SO_ATTACH_REUSEPORT_EBPF) प्रभावित नहीं है: यह पहले से
ही प्रोग्राम को deferred bpf_prog_put() चरणों के माध्यम से रिलीज़ करता है।
फिक्स cBPF पथ को भी वही व्यवहार देता है — पुराने प्रोग्राम के फ्री होने से
पहले एक RCU grace period।
Upstream KASAN रिपोर्ट (7.0 डीबग kernel पर):
BUG: KASAN: vmalloc-out-of-bounds in reuseport_select_sock+0xedc/0x1220
Read of size 4 at addr ffffc9000051e004 by task slowme/10208
net/core/sock_reuseport.c:596
| फ़ाइल | उद्देश्य |
|---|---|
reuseport_race_hammer.c | रिप्रोड्यूसर: मल्टीथ्रेडेड हैमर जो पूर्ण UDP लोड के तहत cBPF selector को churn करता है, फिर डिलीवरी इंटीग्रिटी सत्यापित करता है। |
run_hammer.sh | वन-रन रैपर: net.core.optmem_max बढ़ाता है, हैमर चलाता है, फिर dmesg में splats, /proc/vmallocinfo में लीक हुए bpf_prog allocations, और वैकल्पिक रूप से kmemleak की जाँच करता है। |
livepatch_cycle.sh | हैमर चलते समय फिक्स ले जाने वाला livepatch लागू/रिवर्ट करता है — call_rcu()-आधारित फिक्स के livepatch लाइफसाइकल खतरों की खोज करता है। |
Makefile | हैमर बिल्ड करता है। |
.github/workflows/ci.yml | CI: build + shellcheck (कोई रनटाइम kernel टेस्ट नहीं; देखें CI)। |
एक Linux टेस्ट बॉक्स पर:
$ make
$ sudo ./run_hammer.sh 600 # 10-minute run
...
== result: RC=0 (0 clean / 1 setup / 2 splat / 3 leak / 4 integrity) ==
आवश्यकताएँ:
gcc और bash।dmesg, /proc/vmallocinfo, sysctl);
हैमर स्वयं अनप्रिविलेज्ड चलता है (upstream रिप्रो UID 1000 के रूप में चला)।अपेक्षित परिणाम:
RC=2; कभी-कभी हैमर की
इंटीग्रिटी चेक पहले फायर होती है → RC=4।RC=0, स्थिर bpf_prog vmalloc गिनती।रेस विंडो बहुत छोटी है (फ्री बनाम इन-फ्लाइट RX निष्पादन), इसलिए एकल साफ़ रन को अनिर्णायक मानें। वास्तविक परीक्षण के लिए घंटों चलाएँ, उदाहरण:
$ sudo ./run_hammer.sh 86400 512 8 16 4 127.0.0.1 0
reuseport_race_hammer$ ./reuseport_race_hammer [dur_sec] [insns] [nports] [nsocks] [nsenders] [ip] [ebpf]
| तर्क | डिफ़ॉल्ट | अर्थ |
|---|---|---|
dur_sec | 300 (न्यूनतम 45) | कुल रन सेकंड |
insns | 256 | churned cBPF प्रोग्राम में filler निर्देश; बड़ा प्रोग्राम हिट करने के लिए बड़ा फ्री किया गया क्षेत्र है। यदि attach ENOMEM के साथ विफल होता है, तो net.core.optmem_max बढ़ाएँ (रैपर यह आपके लिए करता है)। |
nports | 4 (अधिकतम 64) | reuseport समूह (प्रत्येक एक UDP पोर्ट, 21000 से) |
nsocks | 8 (अधिकतम 512) | प्रति समूह sockets |
nsenders | 4 (अधिकतम 32) | प्रति समूह UDP sender थ्रेड्स |
ip | 127.0.0.1 | लक्ष्य पता; RX softirqs को CPUs (RSS) में फैलाने के लिए एक फिजिकल NIC IP का उपयोग करें |
ebpf | 0 | 1 = SO_ATTACH_REUSEPORT_EBPF attach/detach को भी churn करें (CAP_BPF/CAP_NET_ADMIN चाहिए); वह पथ कमजोर नहीं है, यह तुलना/कवरेज के लिए है |
प्रत्येक समूह एक churner थ्रेड चलाता है जो एक टाइट लूप में setsockopt()
के माध्यम से cBPF selector को स्वैप और डिटैच करता है, और sender थ्रेड्स
समूह पर 64-बाइट UDP डेटाग्राम फ्लड करते हैं जबकि रिसीवर्स प्रति-socket
डिलीवरी गिनते हैं।
रन चरण (T = dur_sec):
time ──────────────────────────────────────────────────────────────►
[0 ──────────── T-15s) [T-15s ── T-10s) [T-10s ─────────── T]
CHURN + FLOOD SETTLE MEASURE
churner swaps/detaches churn frozen, deterministic program
the selector prog at final program (selects the LAST
max rate under full attached socket): EVERY packet
UDP flood — THE (selects LAST must land on the LAST
race window open socket) socket; snapshot A →
run → snapshot B
इंटीग्रिटी चेक: माप चरण के दौरान अंतिम प्रोग्राम समूह के अंतिम socket को नियतात्मक रूप से चुनता है। यदि उस विंडो के दौरान समूह द्वारा प्राप्त पैकेट सभी उस socket पर नहीं पहुँचे, तो चयन गलत हुआ (KASAN के बिना भी एक संभावित UAF प्रभाव) → exit code 2।
हैमर exit codes: 0 PASS · 1 setup/runtime error · 2 integrity WARN।
run_hammer.sh — वन-रन रैपरहैमर चलाता है और वे जाँचें जोड़ता है जो एकल रन को सार्थक बनाती हैं: