【Linux内核】CVE-2026-46242:Bad Epoll Linux 内核 epoll UAF 漏洞修复指南(99%可靠root的云安全噩梦)

2026 年 5 月 30 日,Linux 内核社区正式发布 CVE-2026-46242(代号 "Bad Epoll")的修复补丁。这是一个潜伏近三年的 Use-After-Free 竞态条件漏洞,位于 epoll 子系统的 ep_remove() 函数中,影响所有基于 Linux 6.4+ 内核的服务器、桌面与 Android 设备。漏洞由首尔国立大学 CompSec Lab 的博士研究员 Jaeyoung Chung 在 2026 年 2 月 17 日报告,公开 PoC 在 kernelCTF 环境(lts-6.12.67 / COS 121-18867.294.100)上实现约 99% 成功率的本地提权到 root。更值得警惕的是:Anthropic 的 Mythos AI 模型此前在同一代码段发现了 CVE-2026-43074 并完成修复,却完全错过了 Bad Epoll------竞态窗口仅约 6 条指令宽,KASAN 不触发,日志几乎无信号。本文从根因、攻击链、检测、修复到内核热补丁与云多租户加固,提供完整实战指南。

1. 漏洞全景概览

1.1 漏洞速览

项目 详情
CVE 编号 CVE-2026-46242
漏洞代号 Bad Epoll
漏洞类型 Use-After-Free(竞态条件,CWE-416 / CWE-362)
CVSS v3.1 7.8(High,本地提权到 root)
CVSS 向量 AV:L/AC:L/PR:L/UI:N/S:U/C:H/I:H/A:H
影响组件 Linux 内核 epoll 子系统 fs/eventpoll.cep_remove()
引入 commit 58c9b016e128(2023 年 4 月,Linux 6.4 epoll 锁竞争优化)
修复 commit a6dc643c6931
发现者 Jaeyoung Chung(首尔国立大学 CompSec Lab 博士研究员)
报告时间 2026 年 2 月 17 日
CVE 发布 2026 年 5 月 30 日
PoC 状态 已公开(GitHub: J-jaeyoung/bad-epoll),约 99% 成功率获得 root
攻击向量 本地(无需特殊权限,普通用户即可)
运行时缓解 (无法通过配置禁用 epoll,必须打补丁 + 重启或热补丁)
影响版本 Linux 6.4 → 6.18.32、6.19 → 7.0.9(含 Android 6.6 系列内核)
修复版本 6.18.33、7.0.10、7.1-rc1+

1.2 Bad Epoll 与 CVE-2026-43074 关联(AI 发现 vs 人工发现)

Bad Epoll 最具警示意义的一段故事,是它与 CVE-2026-43074 的"邻居关系"。两个漏洞位于同一份 fs/eventpoll.c 文件、同一轮 epoll 锁竞争优化引入的代码段,但发现路径截然不同。
#mermaid-svg-jDbQ7Y6gVa3vqZPY{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-jDbQ7Y6gVa3vqZPY .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-jDbQ7Y6gVa3vqZPY .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-jDbQ7Y6gVa3vqZPY .error-icon{fill:#552222;}#mermaid-svg-jDbQ7Y6gVa3vqZPY .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-jDbQ7Y6gVa3vqZPY .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-jDbQ7Y6gVa3vqZPY .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-jDbQ7Y6gVa3vqZPY .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-jDbQ7Y6gVa3vqZPY .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-jDbQ7Y6gVa3vqZPY .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-jDbQ7Y6gVa3vqZPY .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-jDbQ7Y6gVa3vqZPY .marker{fill:#333333;stroke:#333333;}#mermaid-svg-jDbQ7Y6gVa3vqZPY .marker.cross{stroke:#333333;}#mermaid-svg-jDbQ7Y6gVa3vqZPY svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-jDbQ7Y6gVa3vqZPY p{margin:0;}#mermaid-svg-jDbQ7Y6gVa3vqZPY .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-jDbQ7Y6gVa3vqZPY .cluster-label text{fill:#333;}#mermaid-svg-jDbQ7Y6gVa3vqZPY .cluster-label span{color:#333;}#mermaid-svg-jDbQ7Y6gVa3vqZPY .cluster-label span p{background-color:transparent;}#mermaid-svg-jDbQ7Y6gVa3vqZPY .label text,#mermaid-svg-jDbQ7Y6gVa3vqZPY span{fill:#333;color:#333;}#mermaid-svg-jDbQ7Y6gVa3vqZPY .node rect,#mermaid-svg-jDbQ7Y6gVa3vqZPY .node circle,#mermaid-svg-jDbQ7Y6gVa3vqZPY .node ellipse,#mermaid-svg-jDbQ7Y6gVa3vqZPY .node polygon,#mermaid-svg-jDbQ7Y6gVa3vqZPY .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-jDbQ7Y6gVa3vqZPY .rough-node .label text,#mermaid-svg-jDbQ7Y6gVa3vqZPY .node .label text,#mermaid-svg-jDbQ7Y6gVa3vqZPY .image-shape .label,#mermaid-svg-jDbQ7Y6gVa3vqZPY .icon-shape .label{text-anchor:middle;}#mermaid-svg-jDbQ7Y6gVa3vqZPY .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-jDbQ7Y6gVa3vqZPY .rough-node .label,#mermaid-svg-jDbQ7Y6gVa3vqZPY .node .label,#mermaid-svg-jDbQ7Y6gVa3vqZPY .image-shape .label,#mermaid-svg-jDbQ7Y6gVa3vqZPY .icon-shape .label{text-align:center;}#mermaid-svg-jDbQ7Y6gVa3vqZPY .node.clickable{cursor:pointer;}#mermaid-svg-jDbQ7Y6gVa3vqZPY .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-jDbQ7Y6gVa3vqZPY .arrowheadPath{fill:#333333;}#mermaid-svg-jDbQ7Y6gVa3vqZPY .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-jDbQ7Y6gVa3vqZPY .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-jDbQ7Y6gVa3vqZPY .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-jDbQ7Y6gVa3vqZPY .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-jDbQ7Y6gVa3vqZPY .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-jDbQ7Y6gVa3vqZPY .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-jDbQ7Y6gVa3vqZPY .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-jDbQ7Y6gVa3vqZPY .cluster text{fill:#333;}#mermaid-svg-jDbQ7Y6gVa3vqZPY .cluster span{color:#333;}#mermaid-svg-jDbQ7Y6gVa3vqZPY div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-jDbQ7Y6gVa3vqZPY .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-jDbQ7Y6gVa3vqZPY rect.text{fill:none;stroke-width:0;}#mermaid-svg-jDbQ7Y6gVa3vqZPY .icon-shape,#mermaid-svg-jDbQ7Y6gVa3vqZPY .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-jDbQ7Y6gVa3vqZPY .icon-shape p,#mermaid-svg-jDbQ7Y6gVa3vqZPY .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-jDbQ7Y6gVa3vqZPY .icon-shape .label rect,#mermaid-svg-jDbQ7Y6gVa3vqZPY .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-jDbQ7Y6gVa3vqZPY .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-jDbQ7Y6gVa3vqZPY .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-jDbQ7Y6gVa3vqZPY :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} 2023年4月

commit 58c9b016e128

epoll锁优化
引入两处缺陷
CVE-2026-43074

Mythos AI发现
CVE-2026-46242 Bad Epoll

Jaeyoung Chung人工发现
Mythos完成修复

2026年初
Mythos再次审计同代码段
❌ 未发现Bad Epoll
2026-02-17

Chung人工代码审查发现
2026-05-30

修复发布CVE-2026-46242

关键启示 :Mythos AI 在发现并修复 CVE-2026-43074 后,再次审计同一代码段,但完全错过了 Bad Epoll。原因是该漏洞的竞态窗口极窄(约 6 条指令),KASAN 因 struct file 标记为 SLAB_TYPESAFE_BY_RCU 而无法触发告警,运行时日志几乎不留痕迹。Chung 通过人工代码审查发现该问题------这给"AI 代码审计可替代人工"的乐观论断敲了一记警钟。

1.3 漏洞核心特征

#mermaid-svg-Op7TvzpSqzbCZIin{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-Op7TvzpSqzbCZIin .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-Op7TvzpSqzbCZIin .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-Op7TvzpSqzbCZIin .error-icon{fill:#552222;}#mermaid-svg-Op7TvzpSqzbCZIin .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-Op7TvzpSqzbCZIin .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-Op7TvzpSqzbCZIin .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-Op7TvzpSqzbCZIin .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-Op7TvzpSqzbCZIin .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-Op7TvzpSqzbCZIin .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-Op7TvzpSqzbCZIin .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-Op7TvzpSqzbCZIin .marker{fill:#333333;stroke:#333333;}#mermaid-svg-Op7TvzpSqzbCZIin .marker.cross{stroke:#333333;}#mermaid-svg-Op7TvzpSqzbCZIin svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-Op7TvzpSqzbCZIin p{margin:0;}#mermaid-svg-Op7TvzpSqzbCZIin .edge{stroke-width:3;}#mermaid-svg-Op7TvzpSqzbCZIin .section--1 rect,#mermaid-svg-Op7TvzpSqzbCZIin .section--1 path,#mermaid-svg-Op7TvzpSqzbCZIin .section--1 circle,#mermaid-svg-Op7TvzpSqzbCZIin .section--1 polygon,#mermaid-svg-Op7TvzpSqzbCZIin .section--1 path{fill:hsl(240, 100%, 76.2745098039%);}#mermaid-svg-Op7TvzpSqzbCZIin .section--1 text{fill:#ffffff;}#mermaid-svg-Op7TvzpSqzbCZIin .node-icon--1{font-size:40px;color:#ffffff;}#mermaid-svg-Op7TvzpSqzbCZIin .section-edge--1{stroke:hsl(240, 100%, 76.2745098039%);}#mermaid-svg-Op7TvzpSqzbCZIin .edge-depth--1{stroke-width:17;}#mermaid-svg-Op7TvzpSqzbCZIin .section--1 line{stroke:hsl(60, 100%, 86.2745098039%);stroke-width:3;}#mermaid-svg-Op7TvzpSqzbCZIin .disabled,#mermaid-svg-Op7TvzpSqzbCZIin .disabled circle,#mermaid-svg-Op7TvzpSqzbCZIin .disabled text{fill:lightgray;}#mermaid-svg-Op7TvzpSqzbCZIin .disabled text{fill:#efefef;}#mermaid-svg-Op7TvzpSqzbCZIin .section-0 rect,#mermaid-svg-Op7TvzpSqzbCZIin .section-0 path,#mermaid-svg-Op7TvzpSqzbCZIin .section-0 circle,#mermaid-svg-Op7TvzpSqzbCZIin .section-0 polygon,#mermaid-svg-Op7TvzpSqzbCZIin .section-0 path{fill:hsl(60, 100%, 73.5294117647%);}#mermaid-svg-Op7TvzpSqzbCZIin .section-0 text{fill:black;}#mermaid-svg-Op7TvzpSqzbCZIin .node-icon-0{font-size:40px;color:black;}#mermaid-svg-Op7TvzpSqzbCZIin .section-edge-0{stroke:hsl(60, 100%, 73.5294117647%);}#mermaid-svg-Op7TvzpSqzbCZIin .edge-depth-0{stroke-width:14;}#mermaid-svg-Op7TvzpSqzbCZIin .section-0 line{stroke:hsl(240, 100%, 83.5294117647%);stroke-width:3;}#mermaid-svg-Op7TvzpSqzbCZIin .disabled,#mermaid-svg-Op7TvzpSqzbCZIin .disabled circle,#mermaid-svg-Op7TvzpSqzbCZIin .disabled text{fill:lightgray;}#mermaid-svg-Op7TvzpSqzbCZIin .disabled text{fill:#efefef;}#mermaid-svg-Op7TvzpSqzbCZIin .section-1 rect,#mermaid-svg-Op7TvzpSqzbCZIin .section-1 path,#mermaid-svg-Op7TvzpSqzbCZIin .section-1 circle,#mermaid-svg-Op7TvzpSqzbCZIin .section-1 polygon,#mermaid-svg-Op7TvzpSqzbCZIin .section-1 path{fill:hsl(80, 100%, 76.2745098039%);}#mermaid-svg-Op7TvzpSqzbCZIin .section-1 text{fill:black;}#mermaid-svg-Op7TvzpSqzbCZIin .node-icon-1{font-size:40px;color:black;}#mermaid-svg-Op7TvzpSqzbCZIin .section-edge-1{stroke:hsl(80, 100%, 76.2745098039%);}#mermaid-svg-Op7TvzpSqzbCZIin .edge-depth-1{stroke-width:11;}#mermaid-svg-Op7TvzpSqzbCZIin .section-1 line{stroke:hsl(260, 100%, 86.2745098039%);stroke-width:3;}#mermaid-svg-Op7TvzpSqzbCZIin .disabled,#mermaid-svg-Op7TvzpSqzbCZIin .disabled circle,#mermaid-svg-Op7TvzpSqzbCZIin .disabled text{fill:lightgray;}#mermaid-svg-Op7TvzpSqzbCZIin .disabled text{fill:#efefef;}#mermaid-svg-Op7TvzpSqzbCZIin .section-2 rect,#mermaid-svg-Op7TvzpSqzbCZIin .section-2 path,#mermaid-svg-Op7TvzpSqzbCZIin .section-2 circle,#mermaid-svg-Op7TvzpSqzbCZIin .section-2 polygon,#mermaid-svg-Op7TvzpSqzbCZIin .section-2 path{fill:hsl(270, 100%, 76.2745098039%);}#mermaid-svg-Op7TvzpSqzbCZIin .section-2 text{fill:#ffffff;}#mermaid-svg-Op7TvzpSqzbCZIin .node-icon-2{font-size:40px;color:#ffffff;}#mermaid-svg-Op7TvzpSqzbCZIin .section-edge-2{stroke:hsl(270, 100%, 76.2745098039%);}#mermaid-svg-Op7TvzpSqzbCZIin .edge-depth-2{stroke-width:8;}#mermaid-svg-Op7TvzpSqzbCZIin .section-2 line{stroke:hsl(90, 100%, 86.2745098039%);stroke-width:3;}#mermaid-svg-Op7TvzpSqzbCZIin .disabled,#mermaid-svg-Op7TvzpSqzbCZIin .disabled circle,#mermaid-svg-Op7TvzpSqzbCZIin .disabled text{fill:lightgray;}#mermaid-svg-Op7TvzpSqzbCZIin .disabled text{fill:#efefef;}#mermaid-svg-Op7TvzpSqzbCZIin .section-3 rect,#mermaid-svg-Op7TvzpSqzbCZIin .section-3 path,#mermaid-svg-Op7TvzpSqzbCZIin .section-3 circle,#mermaid-svg-Op7TvzpSqzbCZIin .section-3 polygon,#mermaid-svg-Op7TvzpSqzbCZIin .section-3 path{fill:hsl(300, 100%, 76.2745098039%);}#mermaid-svg-Op7TvzpSqzbCZIin .section-3 text{fill:black;}#mermaid-svg-Op7TvzpSqzbCZIin .node-icon-3{font-size:40px;color:black;}#mermaid-svg-Op7TvzpSqzbCZIin .section-edge-3{stroke:hsl(300, 100%, 76.2745098039%);}#mermaid-svg-Op7TvzpSqzbCZIin .edge-depth-3{stroke-width:5;}#mermaid-svg-Op7TvzpSqzbCZIin .section-3 line{stroke:hsl(120, 100%, 86.2745098039%);stroke-width:3;}#mermaid-svg-Op7TvzpSqzbCZIin .disabled,#mermaid-svg-Op7TvzpSqzbCZIin .disabled circle,#mermaid-svg-Op7TvzpSqzbCZIin .disabled text{fill:lightgray;}#mermaid-svg-Op7TvzpSqzbCZIin .disabled text{fill:#efefef;}#mermaid-svg-Op7TvzpSqzbCZIin .section-4 rect,#mermaid-svg-Op7TvzpSqzbCZIin .section-4 path,#mermaid-svg-Op7TvzpSqzbCZIin .section-4 circle,#mermaid-svg-Op7TvzpSqzbCZIin .section-4 polygon,#mermaid-svg-Op7TvzpSqzbCZIin .section-4 path{fill:hsl(330, 100%, 76.2745098039%);}#mermaid-svg-Op7TvzpSqzbCZIin .section-4 text{fill:black;}#mermaid-svg-Op7TvzpSqzbCZIin .node-icon-4{font-size:40px;color:black;}#mermaid-svg-Op7TvzpSqzbCZIin .section-edge-4{stroke:hsl(330, 100%, 76.2745098039%);}#mermaid-svg-Op7TvzpSqzbCZIin .edge-depth-4{stroke-width:2;}#mermaid-svg-Op7TvzpSqzbCZIin .section-4 line{stroke:hsl(150, 100%, 86.2745098039%);stroke-width:3;}#mermaid-svg-Op7TvzpSqzbCZIin .disabled,#mermaid-svg-Op7TvzpSqzbCZIin .disabled circle,#mermaid-svg-Op7TvzpSqzbCZIin .disabled text{fill:lightgray;}#mermaid-svg-Op7TvzpSqzbCZIin .disabled text{fill:#efefef;}#mermaid-svg-Op7TvzpSqzbCZIin .section-5 rect,#mermaid-svg-Op7TvzpSqzbCZIin .section-5 path,#mermaid-svg-Op7TvzpSqzbCZIin .section-5 circle,#mermaid-svg-Op7TvzpSqzbCZIin .section-5 polygon,#mermaid-svg-Op7TvzpSqzbCZIin .section-5 path{fill:hsl(0, 100%, 76.2745098039%);}#mermaid-svg-Op7TvzpSqzbCZIin .section-5 text{fill:black;}#mermaid-svg-Op7TvzpSqzbCZIin .node-icon-5{font-size:40px;color:black;}#mermaid-svg-Op7TvzpSqzbCZIin .section-edge-5{stroke:hsl(0, 100%, 76.2745098039%);}#mermaid-svg-Op7TvzpSqzbCZIin .edge-depth-5{stroke-width:-1;}#mermaid-svg-Op7TvzpSqzbCZIin .section-5 line{stroke:hsl(180, 100%, 86.2745098039%);stroke-width:3;}#mermaid-svg-Op7TvzpSqzbCZIin .disabled,#mermaid-svg-Op7TvzpSqzbCZIin .disabled circle,#mermaid-svg-Op7TvzpSqzbCZIin .disabled text{fill:lightgray;}#mermaid-svg-Op7TvzpSqzbCZIin .disabled text{fill:#efefef;}#mermaid-svg-Op7TvzpSqzbCZIin .section-6 rect,#mermaid-svg-Op7TvzpSqzbCZIin .section-6 path,#mermaid-svg-Op7TvzpSqzbCZIin .section-6 circle,#mermaid-svg-Op7TvzpSqzbCZIin .section-6 polygon,#mermaid-svg-Op7TvzpSqzbCZIin .section-6 path{fill:hsl(30, 100%, 76.2745098039%);}#mermaid-svg-Op7TvzpSqzbCZIin .section-6 text{fill:black;}#mermaid-svg-Op7TvzpSqzbCZIin .node-icon-6{font-size:40px;color:black;}#mermaid-svg-Op7TvzpSqzbCZIin .section-edge-6{stroke:hsl(30, 100%, 76.2745098039%);}#mermaid-svg-Op7TvzpSqzbCZIin .edge-depth-6{stroke-width:-4;}#mermaid-svg-Op7TvzpSqzbCZIin .section-6 line{stroke:hsl(210, 100%, 86.2745098039%);stroke-width:3;}#mermaid-svg-Op7TvzpSqzbCZIin .disabled,#mermaid-svg-Op7TvzpSqzbCZIin .disabled circle,#mermaid-svg-Op7TvzpSqzbCZIin .disabled text{fill:lightgray;}#mermaid-svg-Op7TvzpSqzbCZIin .disabled text{fill:#efefef;}#mermaid-svg-Op7TvzpSqzbCZIin .section-7 rect,#mermaid-svg-Op7TvzpSqzbCZIin .section-7 path,#mermaid-svg-Op7TvzpSqzbCZIin .section-7 circle,#mermaid-svg-Op7TvzpSqzbCZIin .section-7 polygon,#mermaid-svg-Op7TvzpSqzbCZIin .section-7 path{fill:hsl(90, 100%, 76.2745098039%);}#mermaid-svg-Op7TvzpSqzbCZIin .section-7 text{fill:black;}#mermaid-svg-Op7TvzpSqzbCZIin .node-icon-7{font-size:40px;color:black;}#mermaid-svg-Op7TvzpSqzbCZIin .section-edge-7{stroke:hsl(90, 100%, 76.2745098039%);}#mermaid-svg-Op7TvzpSqzbCZIin .edge-depth-7{stroke-width:-7;}#mermaid-svg-Op7TvzpSqzbCZIin .section-7 line{stroke:hsl(270, 100%, 86.2745098039%);stroke-width:3;}#mermaid-svg-Op7TvzpSqzbCZIin .disabled,#mermaid-svg-Op7TvzpSqzbCZIin .disabled circle,#mermaid-svg-Op7TvzpSqzbCZIin .disabled text{fill:lightgray;}#mermaid-svg-Op7TvzpSqzbCZIin .disabled text{fill:#efefef;}#mermaid-svg-Op7TvzpSqzbCZIin .section-8 rect,#mermaid-svg-Op7TvzpSqzbCZIin .section-8 path,#mermaid-svg-Op7TvzpSqzbCZIin .section-8 circle,#mermaid-svg-Op7TvzpSqzbCZIin .section-8 polygon,#mermaid-svg-Op7TvzpSqzbCZIin .section-8 path{fill:hsl(150, 100%, 76.2745098039%);}#mermaid-svg-Op7TvzpSqzbCZIin .section-8 text{fill:black;}#mermaid-svg-Op7TvzpSqzbCZIin .node-icon-8{font-size:40px;color:black;}#mermaid-svg-Op7TvzpSqzbCZIin .section-edge-8{stroke:hsl(150, 100%, 76.2745098039%);}#mermaid-svg-Op7TvzpSqzbCZIin .edge-depth-8{stroke-width:-10;}#mermaid-svg-Op7TvzpSqzbCZIin .section-8 line{stroke:hsl(330, 100%, 86.2745098039%);stroke-width:3;}#mermaid-svg-Op7TvzpSqzbCZIin .disabled,#mermaid-svg-Op7TvzpSqzbCZIin .disabled circle,#mermaid-svg-Op7TvzpSqzbCZIin .disabled text{fill:lightgray;}#mermaid-svg-Op7TvzpSqzbCZIin .disabled text{fill:#efefef;}#mermaid-svg-Op7TvzpSqzbCZIin .section-9 rect,#mermaid-svg-Op7TvzpSqzbCZIin .section-9 path,#mermaid-svg-Op7TvzpSqzbCZIin .section-9 circle,#mermaid-svg-Op7TvzpSqzbCZIin .section-9 polygon,#mermaid-svg-Op7TvzpSqzbCZIin .section-9 path{fill:hsl(180, 100%, 76.2745098039%);}#mermaid-svg-Op7TvzpSqzbCZIin .section-9 text{fill:black;}#mermaid-svg-Op7TvzpSqzbCZIin .node-icon-9{font-size:40px;color:black;}#mermaid-svg-Op7TvzpSqzbCZIin .section-edge-9{stroke:hsl(180, 100%, 76.2745098039%);}#mermaid-svg-Op7TvzpSqzbCZIin .edge-depth-9{stroke-width:-13;}#mermaid-svg-Op7TvzpSqzbCZIin .section-9 line{stroke:hsl(0, 100%, 86.2745098039%);stroke-width:3;}#mermaid-svg-Op7TvzpSqzbCZIin .disabled,#mermaid-svg-Op7TvzpSqzbCZIin .disabled circle,#mermaid-svg-Op7TvzpSqzbCZIin .disabled text{fill:lightgray;}#mermaid-svg-Op7TvzpSqzbCZIin .disabled text{fill:#efefef;}#mermaid-svg-Op7TvzpSqzbCZIin .section-10 rect,#mermaid-svg-Op7TvzpSqzbCZIin .section-10 path,#mermaid-svg-Op7TvzpSqzbCZIin .section-10 circle,#mermaid-svg-Op7TvzpSqzbCZIin .section-10 polygon,#mermaid-svg-Op7TvzpSqzbCZIin .section-10 path{fill:hsl(210, 100%, 76.2745098039%);}#mermaid-svg-Op7TvzpSqzbCZIin .section-10 text{fill:black;}#mermaid-svg-Op7TvzpSqzbCZIin .node-icon-10{font-size:40px;color:black;}#mermaid-svg-Op7TvzpSqzbCZIin .section-edge-10{stroke:hsl(210, 100%, 76.2745098039%);}#mermaid-svg-Op7TvzpSqzbCZIin .edge-depth-10{stroke-width:-16;}#mermaid-svg-Op7TvzpSqzbCZIin .section-10 line{stroke:hsl(30, 100%, 86.2745098039%);stroke-width:3;}#mermaid-svg-Op7TvzpSqzbCZIin .disabled,#mermaid-svg-Op7TvzpSqzbCZIin .disabled circle,#mermaid-svg-Op7TvzpSqzbCZIin .disabled text{fill:lightgray;}#mermaid-svg-Op7TvzpSqzbCZIin .disabled text{fill:#efefef;}#mermaid-svg-Op7TvzpSqzbCZIin .section-root rect,#mermaid-svg-Op7TvzpSqzbCZIin .section-root path,#mermaid-svg-Op7TvzpSqzbCZIin .section-root circle,#mermaid-svg-Op7TvzpSqzbCZIin .section-root polygon{fill:hsl(240, 100%, 46.2745098039%);}#mermaid-svg-Op7TvzpSqzbCZIin .section-root text{fill:#ffffff;}#mermaid-svg-Op7TvzpSqzbCZIin .section-root span{color:#ffffff;}#mermaid-svg-Op7TvzpSqzbCZIin .section-2 span{color:#ffffff;}#mermaid-svg-Op7TvzpSqzbCZIin .icon-container{height:100%;display:flex;justify-content:center;align-items:center;}#mermaid-svg-Op7TvzpSqzbCZIin .edge{fill:none;}#mermaid-svg-Op7TvzpSqzbCZIin .mindmap-node-label{dy:1em;alignment-baseline:middle;text-anchor:middle;dominant-baseline:middle;text-align:center;}#mermaid-svg-Op7TvzpSqzbCZIin :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} CVE-2026-46242

Bad Epoll
漏洞特征
Use-After-Free竞态条件
仅6条指令竞态窗口
本地提权到root
99%可靠利用成功率
潜伏近三年2023-2026
技术原理
ep_remove清file.f_ep后继续用file
并发__fput走快速路径跳过同步
eventpoll对象被提前kfree
hlist_del_rcu写入已释放kmalloc-192
SLAB_TYPESAFE_BY_RCU掩盖KASAN
影响范围
Linux 6.4+全系列
Android 6.6内核设备
Pixel 8的6.1内核不受影响
云多租户共享内核
Chrome渲染器沙箱可链式逃逸
修复方案
epi_fget钉住struct file
无运行时缓解必须打补丁
内核热补丁kpatch/livepatch
升级到6.18.33或7.0.10+
云环境滚动重启宿主机

2. 漏洞根因深度分析

2.1 epoll 子系统背景知识

epoll 是 Linux 内核提供的高性能 I/O 多路复用机制,自 Linux 2.5.44 引入以来,已成为 Nginx、Redis、Node.js、Python asyncio、几乎所有数据库引擎和容器运行时的事件驱动基石。其核心优势在于:事件通知采用回调驱动而非轮询,时间复杂度从 O(n) 降至 O(1),可高效管理数十万并发连接。

epoll 的三个核心系统调用构成完整生命周期:

  • epoll_create1(flags) :创建 epoll 实例,内核分配 struct eventpoll,返回文件描述符。该 fd 本身也是一个 struct file,因此 epoll 实例可以被另一个 epoll 实例监视(嵌套 epoll)。
  • epoll_ctl(epfd, op, fd, event) :向 epoll 实例添加/修改/删除被监视的 fd,核心操作是将 fd 与对应的 struct epitem 插入红黑树或从中移除。
  • epoll_wait(epfd, events, maxevents, timeout):阻塞等待事件就绪,内核检查就绪链表,事件到达时唤醒等待进程。

关键点 :epoll 实例本身是 struct file,可以被另一个 epoll 监视。这条"epoll 监视 epoll"的嵌套路径,正是 Bad Epoll 漏洞的利用通道。

epoll 子系统的核心实现在 fs/eventpoll.c 中。struct eventpoll 通过 kmem_cache 分配,属于 kmalloc-192 slab(取决于内核版本和编译配置)。struct file 则标记为 SLAB_TYPESAFE_BY_RCU------这个标记是后续 KASAN 失灵的关键。

2.2 ep_remove() UAF 根因分析

漏洞位于 ep_remove() 函数(通过 ep_remove_file() 调用)。问题代码的简化逻辑如下:

c 复制代码
// 漏洞版本简化示意 --- fs/eventpoll.c 中的 ep_remove()
static void ep_remove(struct eventpoll *ep, struct epitem *epi)
{
    struct file *file;

    ep_unregister_pollwait(ep, epi);

    // 步骤1:判断 dying 标志(无锁快速路径)
    if (unlikely(READ_ONCE(epi->dying)))
        return;

    // 步骤2:取 file 指针(⚠️ 未增加引用计数)
    file = epi->ffd.file;

    // 步骤3:加 file->f_lock 后清除 file->f_ep
    spin_lock(&file->f_lock);
    // 关键缺陷:清除 f_ep,相当于宣布"该 file 不再被 epoll 监视"
    if (ep_cmp_ffd(&epi->ffd, &ep->ffs))
        file->f_ep = NULL;  // ← 瞬态 NULL 出现

    // 步骤4:继续在临界区内使用 file(⚠️ 此时 file 可能已被并发 __fput 释放)
    hlist_del_rcu(&epi->fllink);  // ← 通过 epi->fllink.pprev 写入
    spin_unlock(&file->f_lock);

    // 步骤5:后续操作可能解引用已释放的 eventpoll
    // ...
}

问题链条的根因可以归纳为以下五步:

  1. ep_remove()file->f_lock 下清除 file->f_ep,相当于宣布"该 file 不再被 epoll 监视"。
  2. 但函数继续在临界区内通过 hlist_del_rcu()spin_unlock() 使用同一个 file 对象。
  3. 与此同时,另一个线程执行 __fput()(关闭文件描述符的内核路径)。
  4. __fput() 观察到 file->f_ep == NULL 这个瞬态值,认为该 file 不再被任何 epoll 监视,于是跳过 eventpoll_release_file() 的同步慢路径 ,直接走快速路径进入 f_op->release()file_free()
  5. 对于 epoll 监视 epoll 的嵌套场景,f_op->releaseep_eventpoll_release()ep_clear_and_put()ep_free(),会 kfree() 掉被监视的 struct eventpoll。而该 eventpoll 内嵌的 ->refs hlist_head 正是 epi->fllink.pprev 指向的位置------后续 hlist_del_rcu()*pprev = next 写操作,就写入了已释放的 kmalloc-192 内存

更严重的是,由于 struct file 标记为 SLAB_TYPESAFE_BY_RCU,该 slab 槽位可能在 ep_remove() 仍"持有" f_lock 期间被 alloc_empty_file() 回收并重新初始化(包括 f_lockf_ep)。最终结果是攻击者可控的 kmem_cache_free() 被导向错误的 slab cache------一个完整的 UAF 原语。

2.3 竞态窗口分析(6 条指令)

竞态窗口的"窄"是 Bad Epoll 最具迷惑性的特征。整个竞态区域仅约 6 条指令宽:

text 复制代码
CPU 0 (ep_remove 上下文)              CPU 1 (__fput 上下文)
─────────────────────────             ─────────────────────────
spin_lock(&file->f_lock)              
file->f_ep = NULL         ←──窗口──→  READ file->f_ep (观察到 NULL)
                                       跳过 eventpoll_release_file()
                                       f_op->release() → ep_free()
hlist_del_rcu(&epi->fllink)            kfree(eventpoll) ← 已释放
*pprev = next  ← 写入已释放内存        (slot 可能已被回收重用)
spin_unlock(&file->f_lock)            

为什么 KASAN 抓不到?

KASAN(Kernel Address Sanitizer)是检测 UAF 的常规武器,但这里失效了,原因有二:

  1. struct file 标记为 SLAB_TYPESAFE_BY_RCU,KASAN 默认不对其隔离 quarantine,slab 槽位可被合法回收重用,KASAN 无法识别为"已释放"。
  2. eventpollkfree() 后,其内嵌的 refs hlist_head 内存被回收,但 epi->fllink.pprev 仍指向该位置,写入时若 slot 已被新对象重用,KASAN 看到的是"活跃对象"而非"已释放对象"。

为什么 AI 审计错过了?

Anthropic 的 Mythos AI 模型在发现 CVE-2026-43074 后再次审计同一代码段,未能识别 Bad Epoll。综合公开分析,原因包括:

  • 竞态窗口太窄,AI 倾向于在显式锁顺序、明显空指针解引用等"静态信号"上识别问题。
  • 漏洞依赖 SLAB_TYPESAFE_BY_RCU 这种"看似安全"的标记来掩盖,AI 难以将 slab 标记与并发释放语义关联起来。
  • 运行时无 KASAN 告警、无崩溃日志,AI 在缺乏运行时证据时倾向于"代码看起来正确"。

Chung 通过人工逐行代码审查 ,结合对 __fput() 快速路径与 ep_remove() 临界区交叉语义的深度推演,才识别出这个 6 指令窗口。

3. 攻击链分析

3.1 攻击前置条件

条件 说明
本地代码执行 攻击者需在目标主机上拥有普通用户 shell(无 root 权限)
内核版本 Linux 6.4+ 未打补丁内核(含 Android 6.6 系列)
特殊权限 ❌ 无需任何特殊权限,普通用户即可
用户交互 ❌ 无需用户交互
网络要求 ❌ 纯本地漏洞,无需网络访问
云多租户场景 共享内核的云环境,任何租户获得本地 shell 即可尝试触达宿主机
容器场景 容器内普通用户即可触发,容器与宿主机共享内核

3.2 完整利用链

#mermaid-svg-kUeCooKhZlk6BFaz{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-kUeCooKhZlk6BFaz .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-kUeCooKhZlk6BFaz .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-kUeCooKhZlk6BFaz .error-icon{fill:#552222;}#mermaid-svg-kUeCooKhZlk6BFaz .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-kUeCooKhZlk6BFaz .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-kUeCooKhZlk6BFaz .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-kUeCooKhZlk6BFaz .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-kUeCooKhZlk6BFaz .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-kUeCooKhZlk6BFaz .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-kUeCooKhZlk6BFaz .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-kUeCooKhZlk6BFaz .marker{fill:#333333;stroke:#333333;}#mermaid-svg-kUeCooKhZlk6BFaz .marker.cross{stroke:#333333;}#mermaid-svg-kUeCooKhZlk6BFaz svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-kUeCooKhZlk6BFaz p{margin:0;}#mermaid-svg-kUeCooKhZlk6BFaz .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-kUeCooKhZlk6BFaz .cluster-label text{fill:#333;}#mermaid-svg-kUeCooKhZlk6BFaz .cluster-label span{color:#333;}#mermaid-svg-kUeCooKhZlk6BFaz .cluster-label span p{background-color:transparent;}#mermaid-svg-kUeCooKhZlk6BFaz .label text,#mermaid-svg-kUeCooKhZlk6BFaz span{fill:#333;color:#333;}#mermaid-svg-kUeCooKhZlk6BFaz .node rect,#mermaid-svg-kUeCooKhZlk6BFaz .node circle,#mermaid-svg-kUeCooKhZlk6BFaz .node ellipse,#mermaid-svg-kUeCooKhZlk6BFaz .node polygon,#mermaid-svg-kUeCooKhZlk6BFaz .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-kUeCooKhZlk6BFaz .rough-node .label text,#mermaid-svg-kUeCooKhZlk6BFaz .node .label text,#mermaid-svg-kUeCooKhZlk6BFaz .image-shape .label,#mermaid-svg-kUeCooKhZlk6BFaz .icon-shape .label{text-anchor:middle;}#mermaid-svg-kUeCooKhZlk6BFaz .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-kUeCooKhZlk6BFaz .rough-node .label,#mermaid-svg-kUeCooKhZlk6BFaz .node .label,#mermaid-svg-kUeCooKhZlk6BFaz .image-shape .label,#mermaid-svg-kUeCooKhZlk6BFaz .icon-shape .label{text-align:center;}#mermaid-svg-kUeCooKhZlk6BFaz .node.clickable{cursor:pointer;}#mermaid-svg-kUeCooKhZlk6BFaz .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-kUeCooKhZlk6BFaz .arrowheadPath{fill:#333333;}#mermaid-svg-kUeCooKhZlk6BFaz .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-kUeCooKhZlk6BFaz .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-kUeCooKhZlk6BFaz .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-kUeCooKhZlk6BFaz .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-kUeCooKhZlk6BFaz .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-kUeCooKhZlk6BFaz .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-kUeCooKhZlk6BFaz .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-kUeCooKhZlk6BFaz .cluster text{fill:#333;}#mermaid-svg-kUeCooKhZlk6BFaz .cluster span{color:#333;}#mermaid-svg-kUeCooKhZlk6BFaz div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-kUeCooKhZlk6BFaz .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-kUeCooKhZlk6BFaz rect.text{fill:none;stroke-width:0;}#mermaid-svg-kUeCooKhZlk6BFaz .icon-shape,#mermaid-svg-kUeCooKhZlk6BFaz .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-kUeCooKhZlk6BFaz .icon-shape p,#mermaid-svg-kUeCooKhZlk6BFaz .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-kUeCooKhZlk6BFaz .icon-shape .label rect,#mermaid-svg-kUeCooKhZlk6BFaz .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-kUeCooKhZlk6BFaz .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-kUeCooKhZlk6BFaz .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-kUeCooKhZlk6BFaz :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} 攻击者获得本地普通用户shell
创建4个epoll文件描述符

epfd0 → epfd1 → epfd2 → epfd3

形成嵌套监视链
利用prefetch侧信道

泄露KASLR基址
触发ep_remove竞态

通过精心构造的关闭顺序
竞态命中

eventpoll被kfree
Cross-Cache喷涂

用pipe缓冲区回收kmalloc-192 slot
通过/proc/self/fdinfo

读取任意内核内存
定位当前进程cred结构
构造ROP链

stack pivot到可控内存
覆盖cred->uid/gid为0

获得root权限
返回用户态

弹出root shell

公开 PoC 的核心技术亮点(基于原理分析与公开 writeup 整理):

1. KASLR 绕过(prefetch 侧信道)

text 复制代码
利用原理:
- epoll 嵌套监视会在内核侧形成 epitem 链表
- 通过 prefetch 指令探测内核地址是否映射
- 结合 /proc/self/fdinfo 暴露的内核指针
- 反推内核 .text 段基址,绕过 KASLR

2. 拓宽 6 指令竞态窗口

text 复制代码
竞态拓宽手法:
- 通过 CPU 亲和性绑定将两个线程钉在不同 CPU 核
- 利用 userfaultfd 或 FUSE 暂停一个线程
- 通过 cache 预取误导 CPU 流水线
- 将 6 指令窗口实际拓宽到可稳定命中

3. Race-Win Oracle(竞态命中判别)

公开 writeup 描述了一个巧妙的"竞态命中判别器"------通过观察 /proc/self/fdinfo 的输出变化判断竞态是否命中,避免盲目重试。这是将 99% 可靠性的关键工程突破。

4. Cross-Cache 喷涂与 pipe 回收

text 复制代码
内存回收原语:
- eventpoll 属于 kmalloc-192 slab
- 触发 kfree 后,立即用 pipe 缓冲区喷射同大小对象
- pipe_buffer 恰好可落入回收的 slot
- 通过 /proc/self/fdinfo 读取 pipe_buffer 内容 = 任意内核内存读

5. RIP 控制与 stack pivot

通过任意读定位当前进程 cred 结构后,构造 ROP 链覆盖 cred->uid/gid 为 0,完成提权。公开 PoC 报告在 kernelCTF lts-6.12.67 上约 99% 成功,在 COS 121-18867.294.100 上约 98% 成功。

3.3 云多租户横向移动风险

Bad Epoll 对云环境的威胁远超传统本地提权。在共享内核的云环境(如传统容器、某些 serverless 平台)中,最坏情况是任何租户获得 root 后可能触达宿主机
#mermaid-svg-7VAFIQp5hGY30Zyf{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-7VAFIQp5hGY30Zyf .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-7VAFIQp5hGY30Zyf .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-7VAFIQp5hGY30Zyf .error-icon{fill:#552222;}#mermaid-svg-7VAFIQp5hGY30Zyf .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-7VAFIQp5hGY30Zyf .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-7VAFIQp5hGY30Zyf .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-7VAFIQp5hGY30Zyf .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-7VAFIQp5hGY30Zyf .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-7VAFIQp5hGY30Zyf .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-7VAFIQp5hGY30Zyf .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-7VAFIQp5hGY30Zyf .marker{fill:#333333;stroke:#333333;}#mermaid-svg-7VAFIQp5hGY30Zyf .marker.cross{stroke:#333333;}#mermaid-svg-7VAFIQp5hGY30Zyf svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-7VAFIQp5hGY30Zyf p{margin:0;}#mermaid-svg-7VAFIQp5hGY30Zyf .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-7VAFIQp5hGY30Zyf .cluster-label text{fill:#333;}#mermaid-svg-7VAFIQp5hGY30Zyf .cluster-label span{color:#333;}#mermaid-svg-7VAFIQp5hGY30Zyf .cluster-label span p{background-color:transparent;}#mermaid-svg-7VAFIQp5hGY30Zyf .label text,#mermaid-svg-7VAFIQp5hGY30Zyf span{fill:#333;color:#333;}#mermaid-svg-7VAFIQp5hGY30Zyf .node rect,#mermaid-svg-7VAFIQp5hGY30Zyf .node circle,#mermaid-svg-7VAFIQp5hGY30Zyf .node ellipse,#mermaid-svg-7VAFIQp5hGY30Zyf .node polygon,#mermaid-svg-7VAFIQp5hGY30Zyf .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-7VAFIQp5hGY30Zyf .rough-node .label text,#mermaid-svg-7VAFIQp5hGY30Zyf .node .label text,#mermaid-svg-7VAFIQp5hGY30Zyf .image-shape .label,#mermaid-svg-7VAFIQp5hGY30Zyf .icon-shape .label{text-anchor:middle;}#mermaid-svg-7VAFIQp5hGY30Zyf .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-7VAFIQp5hGY30Zyf .rough-node .label,#mermaid-svg-7VAFIQp5hGY30Zyf .node .label,#mermaid-svg-7VAFIQp5hGY30Zyf .image-shape .label,#mermaid-svg-7VAFIQp5hGY30Zyf .icon-shape .label{text-align:center;}#mermaid-svg-7VAFIQp5hGY30Zyf .node.clickable{cursor:pointer;}#mermaid-svg-7VAFIQp5hGY30Zyf .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-7VAFIQp5hGY30Zyf .arrowheadPath{fill:#333333;}#mermaid-svg-7VAFIQp5hGY30Zyf .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-7VAFIQp5hGY30Zyf .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-7VAFIQp5hGY30Zyf .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-7VAFIQp5hGY30Zyf .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-7VAFIQp5hGY30Zyf .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-7VAFIQp5hGY30Zyf .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-7VAFIQp5hGY30Zyf .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-7VAFIQp5hGY30Zyf .cluster text{fill:#333;}#mermaid-svg-7VAFIQp5hGY30Zyf .cluster span{color:#333;}#mermaid-svg-7VAFIQp5hGY30Zyf div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-7VAFIQp5hGY30Zyf .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-7VAFIQp5hGY30Zyf rect.text{fill:none;stroke-width:0;}#mermaid-svg-7VAFIQp5hGY30Zyf .icon-shape,#mermaid-svg-7VAFIQp5hGY30Zyf .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-7VAFIQp5hGY30Zyf .icon-shape p,#mermaid-svg-7VAFIQp5hGY30Zyf .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-7VAFIQp5hGY30Zyf .icon-shape .label rect,#mermaid-svg-7VAFIQp5hGY30Zyf .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-7VAFIQp5hGY30Zyf .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-7VAFIQp5hGY30Zyf .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-7VAFIQp5hGY30Zyf :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} 云租户A

普通用户shell
利用Bad Epoll

容器内提权到root
容器root权限
利用其他内核漏洞

或容器逃逸技术
触达宿主机内核
宿主机root权限
横扫同宿主机所有租户
访问宿主机元数据服务

窃取云凭证
攻击云控制平面
云租户B

隔离被打破
云租户C

隔离被打破

关键风险点

  1. 共享内核 = 共享攻击面:传统容器(Docker、containerd 默认配置)与宿主机共享内核,内核漏洞等于全员漏洞。
  2. 沙箱逃逸跳板:Bad Epoll 把"容器内普通用户"提升到"容器内 root",这是后续容器逃逸(如 CVE-2024-21626 runc、CVE-2022-0185 filesystem context)的标准跳板。
  3. serverless 冷启动风险:某些 serverless 平台在共享内核上运行用户代码,攻击者可在冷启动窗口内尝试利用。
  4. CI/CD 流水线投毒:恶意 npm/PyPI/Maven 包在 CI runner 上获得本地 shell → Bad Epoll 提权 → 窃取 CI 凭证 → 投毒下游构建产物。

3.4 Chrome 渲染器沙箱逃逸角度

据公开报道,Bad Epoll 还可从 Chrome 渲染器沙箱内触发。Chrome 渲染器沙箱虽然限制了文件系统访问,但渲染器进程仍可调用 epoll 系统调用(用于网络事件循环)。攻击链如下:

text 复制代码
攻击链(基于原理分析):
1. 攻击者通过恶意网页触发 Chrome 渲染器漏洞(如 V8 类型混淆)
2. 在渲染器进程内获得代码执行(受沙箱限制)
3. 利用渲染器可访问的 epoll 系统调用触发 Bad Epoll
4. 从渲染器进程内提权到内核 root
5. 沙箱彻底失效,可访问用户数据、其他进程内存

这条路径使 Bad Epoll 与其他内核漏洞可以链式利用,从"打开恶意网页"一路到"完全控制用户系统",威胁等级显著上升。

4. 检测与诊断

4.1 受影响版本排查(uname -r)

Bad Epoll 的修复依赖于具体内核版本号,第一步必须盘点环境中所有 Linux 主机的内核版本。

bash 复制代码
# 检查当前内核版本
uname -r
# 预期输出(受影响示例): 6.8.0-45-generic
# 预期输出(已修复示例): 6.18.33-060118-generic

# 查看所有已安装内核(Debian/Ubuntu)
dpkg --list | grep -E "linux-image-[0-9]"
# 预期输出:
# ii  linux-image-6.8.0-45-generic  6.8.0-45.45~22.04.1  amd64  Linux kernel image for version 6.8.0 on 64 bit x86 SMP
# ii  linux-image-6.8.0-50-generic  6.8.0-50.50~22.04.1  amd64  Linux kernel image for version 6.8.0 on 64 bit x86 SMP

# 查看 RHEL/Rocky/AlmaLinux 已安装内核
rpm -qa | grep -E "^kernel-[0-9]"
# 预期输出:
# kernel-6.8.0-55.55.el9_4.x86_64

版本判定逻辑(基于公开 metadata 整理):

内核版本区间 状态
< 5.16(如 5.15.209) ✅ 不受影响
5.16 → 6.1.174 ✅ 不受影响(5.16 之前未引入)
6.1.175 → 6.1.x(部分 backport) ⚠️ 需查 vendor advisory
6.2 → 6.3.x ✅ 不受影响
6.4 → 6.18.32 🔴 受影响
6.18.33+ ✅ 已修复
6.19 → 7.0.9 🔴 受影响
7.0.10+ ✅ 已修复
7.1-rc1+ ✅ 已修复

4.2 各发行版补丁状态检查

发行版内核版本号与上游版本号不一致,必须以 vendor advisory 为准。

bash 复制代码
# Ubuntu 检查(含 HWE 内核)
ubuntu-security-status --unresolved
# 或更精确地查询 CVE 状态
pro security-status --cve CVE-2026-46242
# 预期输出(受影响):
# CVE-2026-46242: vulnerable (linux 6.8.0-45.45~22.04.1)
# 预期输出(已修复):
# CVE-2026-46242: not affected (linux 7.0.0-28.28)

# RHEL/Rocky/AlmaLinux 检查
yum updateinfo list --cves CVE-2026-46242
# 或
dnf updateinfo list --cves CVE-2026-46242
# 预期输出(有可用补丁):
# RHSA-2026:XXXX Important/Sec.    kernel-6.8.0-55.55.el9_4.x86_64

# SUSE/openSUSE 检查
zypper list-patches --cve CVE-2026-46242

# Debian 检查
apt-list --cve CVE-2026-46242 2>/dev/null || \
    grep CVE-2026-46242 /usr/share/debian-security-support/security-support-ended 2>/dev/null

主要发行版状态速查(截至 2026 年 7 月,基于 Ubuntu/Corgea 公开数据):

发行版 版本 状态
Ubuntu 26.04 LTS (resolute) linux 7.0.0-28.28 ✅ Fixed
Ubuntu 24.04 LTS (noble) linux ⚠️ Vulnerable, work in progress
Ubuntu 22.04 LTS (jammy) linux ✅ Not affected
Ubuntu 22.04 + HWE-6.8 linux-hwe-6.8 🔴 Vulnerable
Ubuntu 20.04 LTS (focal) linux ✅ Not affected
RHEL 9 / Rocky 9 / Alma 9 kernel 6.8.x ⚠️ 检查 RHSA
Android 6.6 系列 6.6.x 🔴 受影响(Pixel 8 的 6.1 不受影响)

4.3 异常 futex/epoll 系统调用检测

Bad Epoll 攻击会在短时间内产生大量 epoll_create/epoll_ctl/close 系统调用模式,可作为检测信号。

bash 复制代码
# 使用 perf 监控 epoll 系统调用异常
sudo perf stat -e 'syscalls:sys_enter_epoll_create*' \
                -e 'syscalls:sys_enter_epoll_ctl' \
                -e 'syscalls:sys_enter_close' \
                -a -- sleep 60

# 使用 bpftrace 检测高频 epoll 嵌套(可疑模式)
sudo bpftrace -e '
tracepoint:syscalls:sys_enter_epoll_ctl
/comm != "nginx" && comm != "redis-server" && comm != "node"/ {
    @[comm, pid] = count();
}
interval:s:60 { print(@); clear(@); }
'

# 检测 /proc/self/fdinfo 异常读取(PoC 利用特征)
sudo bpftrace -e '
tracepoint:syscalls:sys_enter_openat
/str(args->filename) == "/proc/self/fdinfo"/ {
    printf("suspicious fdinfo read by %s pid=%d\n", comm, pid);
}
'

注意:上述检测为"信号"而非"阻断"------Bad Epoll 利用窗口极短,运行时检测无法阻止提权,只能用于事后取证。真正的防护必须依赖补丁。

5. 修复方案

5.1 内核升级(各发行版)

升级到修复版本是最彻底的方案。Bad Epoll 无运行时缓解,补丁是唯一根治手段。

Ubuntu/Debian 升级

bash 复制代码
# 更新软件包索引
sudo apt update

# 安装修复版内核(以 Ubuntu 26.04 为例)
sudo apt install --only-upgrade linux-image-generic linux-headers-generic
# 预期输出:
# Setting up linux-image-7.0.0-28-generic (7.0.0-28.28) ...
# Setting up linux-headers-7.0.0-28-generic (7.0.0-28.28) ...

# 验证新内核已安装
ls /boot/vmlinuz-*
# 预期输出: /boot/vmlinuz-7.0.0-28-generic

# 重启生效(⚠️ 必须重启,无运行时缓解)
sudo reboot

# 重启后验证
uname -r
# 预期输出: 6.18.33-060118-generic 或更高

RHEL/Rocky/AlmaLinux 升级

bash 复制代码
# 更新内核到修复版本
sudo dnf update kernel kernel-core kernel-modules
# 预期输出:
# Upgrading:
#  kernel-core    x86_64  6.18.33-100.el9  rhel-9-baseos  45 M
#  kernel-modules x86_64  6.18.33-100.el9  rhel-9-baseos  12 M

# 重启生效
sudo reboot

# 验证
uname -r

Android 设备:等待设备厂商推送安全补丁。Pixel 8(6.1 内核)不受影响;Pixel 9/10 及其他搭载 6.6 内核的设备需关注厂商公告。

5.2 内核热补丁(kpatch / livepatch / kGraft)

对无法容忍重启的云宿主机、数据库节点、K8s control plane,内核热补丁是"无停机修复"的关键能力。Bad Epoll 漏洞函数 ep_remove() 调用路径相对独立,热补丁可行性较好。

Ubuntu Livepatch(Canonical Livepatch Service)

bash 复制代码
# 启用 Canonical Livepatch(需 Ubuntu Pro 订阅,个人用户免费)
sudo pro attach ${UBUNTU_PRO_TOKEN}
sudo pro enable livepatch

# 检查 livepatch 状态
canonical-livepatch status
# 预期输出:
# kernel: 6.8.0-45-generic
# fully-patched: true
# patches:
#   CVE-2026-46242 (Bad Epoll): applied

# 应用特定补丁
sudo canonical-livepatch refresh

RHEL Kernel Live Patching(kpatch)

bash 复制代码
# 安装 kpatch 工具
sudo dnf install kpatch kpatch-dnf

# 订阅并启用
sudo dnf copr enable @kernel/livepatch
sudo dnf install "kernel-livepatch-*"

# 查看已应用补丁
sudo kpatch list
# 预期输出:
# Loaded patch modules:
# livepatch_ep_remove_fix [enabled]

# 应用补丁
sudo kpatch load livepatch_ep_remove_fix.ko

# 验证补丁生效(无需重启)
sudo kpatch info livepatch_ep_remove_fix.ko

SUSE kGraft

bash 复制代码
# SUSE/openSUSE 热补丁
sudo zypper install kgraft
sudo zypper install kgraft-patch-*=CVE-2026-46242

# 查看已加载热补丁
sudo kgraft list

热补丁适用性判断

场景 是否推荐热补丁 说明
云宿主机(KVM hypervisor) ✅ 强烈推荐 避免影响所有租户 VM
K8s control plane 节点 ✅ 推荐 避免控制面抖动
数据库主节点 ✅ 推荐 避免连接中断
普通 Web 服务器 ⚠️ 可选 维护窗口重启更彻底
Android 设备 ❌ 不适用 等待厂商 OTA
已运行 PoC 的环境 ❌ 不适用 必须重启 + 全盘取证

重要约束:热补丁只是"临时止血",仍需在下一个维护窗口安排完整重启。建议热补丁 + 30 天内重启为标准流程。

5.3 云环境加固

云多租户场景下,Bad Epoll 的攻击半径从"单机提权"扩大到"宿主机沦陷 → 全租户沦陷"。加固必须从宿主机内核与租户隔离两层入手。

yaml 复制代码
# K8s Pod Security Standards 加固示例
apiVersion: v1
kind: Namespace
metadata:
  name: untrusted-tenant
  labels:
    # 强制 enforce restricted 模式
    pod-security.kubernetes.io/enforce: restricted
    pod-security.kubernetes.io/enforce-version: latest
    pod-security.kubernetes.io/audit: restricted
    pod-security.kubernetes.io/warn: restricted
---
apiVersion: v1
kind: Pod
metadata:
  name: hardened-app
  namespace: untrusted-tenant
spec:
  securityContext:
    # 必须以非 root 运行
    runAsNonRoot: true
    runAsUser: 1000
    fsGroup: 1000
    # 禁止特权提升
    seccompProfile:
      type: RuntimeDefault
  containers:
    - name: app
      image: ${APP_IMAGE}
      securityContext:
        allowPrivilegeEscalation: false
        readOnlyRootFilesystem: true
        capabilities:
          drop:
            - ALL
      resources:
        limits:
          memory: 512Mi
          cpu: 500m

gVisor / Kata Containers 隔离

bash 复制代码
# 对高敏感租户使用 gVisor(用户态内核,拦截 syscall)
# Containerd 配置 /etc/containerd/config.toml
[plugins."io.containerd.grpc.v1.cri".containerd.runtimes.gvisor]
  runtime_type = "io.containerd.runsc.v1"
  privileged_without_host_devices = false

# RuntimeClass
cat <<EOF | kubectl apply -f -
apiVersion: node.k8s.io/v1
kind: RuntimeClass
metadata:
  name: gvisor
handler: runsc
EOF

# Pod 指定使用 gvisor
# spec.runtimeClassName: gvisor

注意:gVisor 在用户态实现 syscall 拦截,可显著缩小内核攻击面(epoll 调用被 gVisor 拦截后不直接触达宿主机内核),但会带来性能开销。Kata Containers 用轻量 VM 隔离每个 Pod,对内核漏洞防护更强,适合高敏感场景。

5.4 安全加固检查清单

markdown 复制代码
□ 所有 Linux 主机内核是否已升级到 6.18.33+ 或 7.0.10+?
□ 关键宿主机是否已应用内核热补丁(livepatch/kpatch)?
□ 是否已安排 30 天内的完整重启窗口?
□ K8s 集群是否启用 Pod Security Standards restricted 模式?
□ 高敏感租户是否使用 gVisor / Kata Containers 隔离?
□ CI/CD runner 是否在补丁完成前限制外部依赖安装?
□ Android 设备是否已检查厂商安全公告并等待 OTA?
□ 是否部署 epoll 系统调用异常监控(bpftrace/perf)?
□ 是否盘点所有 Ubuntu 22.04 + HWE-6.8 内核(受影响)?
□ 是否建立内核漏洞应急响应流程(PoC 公开后 24h 内)?

6. 踩坑记录

序号 现象 根因分析 解决方案 效果
1 HWE 内核被忽视 主内核已升级,仍被 PoC 提权 Ubuntu 22.04 默认内核不受影响,但 HWE-6.8 内核受影响,运维只检查了主内核 全量盘点 linux-hwe-* 包,HWE 内核单独升级 漏洞真正闭合
2 livepatch 静默失败 状态显示 applied,但 PoC 仍成功 livepatch 模块加载失败但状态报告滞后,未实际钉住 ep_remove kpatch list 二次确认 + dmesg 检查加载日志 补丁确实生效
3 K8s 滚动升级卡死 升级节点内核后节点 NotReady 节点未 cordon/drain 直接重启,Pod 未能优雅迁移 kubectl cordon + kubectl drain 再重启 零中断升级
4 Android 设备漏报 厂商称"已修复",实际仍可利用 厂商 backport 了部分 patch 但漏掉 epi_fget() 钉住逻辑 与厂商确认补丁 commit hash 是否包含 a6dc643c6931 真正修复
5 容器内升级无效 apt upgrade 后 PoC 仍成功 容器与宿主机共享内核,容器内升级的内核包不生效 必须升级宿主机内核,容器内仅升级用户态工具 修复生效
6 gVisor 兼容性报错 切换 gVisor 后部分 Pod CrashLoopBackOff gVisor 不支持某些 syscall(如 inotify_add_watch 部分场景) 高敏感租户用 gVisor,普通租户用 runc + restricted PSA 兼容与安全平衡

坑 1 详解:HWE 内核被忽视

这是 Bad Epoll 修复中最常见的盲区。Ubuntu 22.04 LTS 默认内核 5.15 不受影响,但许多用户为获得新硬件支持或新特性启用了 HWE-6.8 内核。运维在自查时往往只检查 uname -r 看到的是 5.15,但实际运行的是 6.8(HWE),或反之。正确做法是同时检查 linux-image-genericlinux-image-hwe-* 两个包:

bash 复制代码
# 一次性列出所有已安装内核包
dpkg -l | grep -E "^ii\s+linux-image" | awk '{print $2, $3}'
# 预期输出示例:
# linux-image-5.15.0-125-generic 5.15.0-125.135
# linux-image-6.8.0-45-generic 6.8.0-45.45~22.04.1  ← HWE,受影响

坑 2 详解:livepatch 静默失败

内核热补丁在某些场景下会"声称已应用但实际未生效"。canonical-livepatch status 显示 applied,但 ep_remove() 仍是漏洞版本。原因可能是 livepatch 模块加载时 ep_remove 正被占用,patch 跳过了该函数。可靠验证方式:

bash 复制代码
# 检查 livepatch 实际钉住的函数
sudo cat /sys/kernel/livepatch/*/kallsyms 2>/dev/null | grep ep_remove
# 预期输出(已生效):
# ffffffff813a2b50 t ep_remove [livepatch_cve_2026_46242]

# 检查 dmesg 是否有 patch 失败警告
sudo dmesg | grep -i "livepatch.*fail\|livepatch.*skip"

坑 5 详解:容器内升级无效

容器与宿主机共享内核,这是常识,但在紧急响应中仍频繁踩坑。运维在容器内执行 apt upgrade linux-image-* 后,PoC 仍能成功------因为容器内的内核包根本不会被加载。正确流程:

text 复制代码
1. 在宿主机上升级内核(不是在容器内)
2. 重启宿主机(或热补丁)
3. 验证容器内 uname -r 与宿主机一致
4. 容器内仅升级用户态工具(如 openssl、curl)不影响内核

📊 运维监控与自动化保障

监控项

监控项 指标 告警阈值 检测意义
内核版本 node_uname_info < 6.18.33(6.4+ 分支) 受影响版本持续暴露
livepatch 状态 node_livepatch_applied 漏洞补丁未 applied 热补丁失效
epoll 系统调用速率 rate(sys_enter_epoll_ctl[5m]) 单进程 > 1000/s PoC 利用特征
fdinfo 读取频次 rate(sys_enter_openat["/proc/self/fdinfo"][5m]) 单进程 > 50/min PoC 任意读原语
进程 uid 异常跃迁 process_credentials{uid="0"} 非 sudo 进程 uid 突变 0 提权成功信号
内核 oops 计数 rate(node_kernel_oops_last[5m]) > 0 利用失败的副作用
K8s Pod 重启 kube_pod_container_status_restarts_total 非预期重启 > 3 容器逃逸尝试

Prometheus 告警规则

基于 Prometheus + node_exporter 的内核漏洞监控,可在大规模集群中自动发现受影响节点与可疑活动。

yaml 复制代码
# prometheus-rules-cve-2026-46242.yaml
groups:
  - name: cve-2026-46242-bad-epoll
    rules:
      # 告警1:受影响内核版本
      - alert: KernelVulnerableToBadEpoll
        expr: |
          count by (instance) (
            node_uname_info{release=~"6\.(4|5|6|7|8|9|1[0-8])\..*"}
            and on(instance)
            node_uname_info{release!~"6\.18\.(3[3-9]|[4-9][0-9])\..*"}
          ) > 0
        for: 10m
        labels:
          severity: critical
          cve: CVE-2026-46242
        annotations:
          summary: "节点内核受 Bad Epoll 漏洞影响"
          description: "节点 {{ $labels.instance }} 内核版本 {{ $value }} 受 CVE-2026-46242 影响,需立即升级到 6.18.33+。"

      # 告警2:livepatch 未应用
      - alert: LivepatchNotAppliedForBadEpoll
        expr: |
          node_livepatch_state{patch="cve_2026_46242"} != 1
        for: 5m
        labels:
          severity: warning
          cve: CVE-2026-46242
        annotations:
          summary: "Bad Epoll 热补丁未应用"
          description: "节点 {{ $labels.instance }} 的 CVE-2026-46242 热补丁未生效。"

      # 告警3:可疑 epoll 高频调用
      - alert: SuspiciousEpollActivity
        expr: |
          rate(node_system_calls_total{call="epoll_ctl"}[5m]) > 1000
        for: 2m
        labels:
          severity: warning
        annotations:
          summary: "检测到高频 epoll_ctl 调用"
          description: "节点 {{ $labels.instance }} epoll_ctl 速率 {{ $value }}/s,疑似 Bad Epoll 利用尝试。"

自动化巡检脚本(Python,跨发行版)

跨发行版巡检脚本可在异构环境中统一发现受影响主机,避免逐台手动检查。

python 复制代码
#!/usr/bin/env python3
# bad_epoll_audit.py --- CVE-2026-46242 跨发行版巡检脚本
# 用法: python3 bad_epoll_audit.py [--ssh-hosts hosts.txt]
# 依赖: 仅使用标准库,无第三方包

import subprocess
import re
import sys
import argparse
from dataclasses import dataclass
from typing import Optional


# 受影响的内核版本区间(基于公开 metadata 整理)
AFFECTED_RANGES = [
    # (起始, 结束, 说明)
    ("6.4.0", "6.18.32", "主线 6.4 - 6.18.32 受影响"),
    ("6.19.0", "7.0.9", "6.19 - 7.0.9 受影响"),
]


@dataclass
class KernelStatus:
    hostname: str
    kernel: str
    affected: bool
    fixed_version: Optional[str]
    livepatch_applied: bool
    detail: str


def parse_version(ver: str) -> tuple:
    """将版本字符串解析为可比较的元组"""
    parts = re.findall(r"\d+", ver.split("-")[0])
    return tuple(int(p) for p in parts[:3])


def is_affected(kernel: str) -> tuple:
    """判断内核是否受影响,返回 (受影响, 修复版本)"""
    try:
        v = parse_version(kernel)
    except Exception:
        return False, None

    for start, end, desc in AFFECTED_RANGES:
        s = parse_version(start)
        e = parse_version(end)
        if s <= v <= e:
            # 推荐修复版本
            if v < parse_version("6.19.0"):
                return True, "6.18.33"
            else:
                return True, "7.0.10"
    return False, None


def check_livepatch() -> bool:
    """检查 livepatch 是否已应用(Ubuntu Livepatch)"""
    try:
        result = subprocess.run(
            ["canonical-livepatch", "status"],
            capture_output=True, text=True, timeout=10
        )
        return "CVE-2026-46242" in result.stdout and "applied" in result.stdout
    except (FileNotFoundError, subprocess.TimeoutExpired):
        return False


def audit_local() -> KernelStatus:
    """审计本地主机"""
    hostname = subprocess.run(
        ["hostname"], capture_output=True, text=True
    ).stdout.strip()

    kernel = subprocess.run(
        ["uname", "-r"], capture_output=True, text=True
    ).stdout.strip()

    affected, fixed = is_affected(kernel)
    livepatch = check_livepatch() if affected else False

    if not affected:
        detail = "内核不受影响"
    elif livepatch:
        detail = f"受影响但已应用热补丁(仍建议升级到 {fixed})"
    else:
        detail = f"受影响,需升级到 {fixed}"

    return KernelStatus(
        hostname=hostname, kernel=kernel, affected=affected,
        fixed_version=fixed, livepatch_applied=livepatch, detail=detail
    )


def main():
    parser = argparse.ArgumentParser(description="CVE-2026-46242 Bad Epoll 巡检")
    parser.add_argument("--ssh-hosts", help="SSH 主机列表文件")
    args = parser.parse_args()

    print("=" * 70)
    print("CVE-2026-46242 Bad Epoll 漏洞巡检报告")
    print("=" * 70)

    if args.ssh_hosts:
        # 批量 SSH 巡检(示例:通过 ssh 执行 uname -r)
        try:
            with open(args.ssh_hosts) as f:
                hosts = [line.strip() for line in f if line.strip() and not line.startswith("#")]
        except FileNotFoundError:
            print(f"❌ 主机列表文件 {args.ssh_hosts} 不存在")
            sys.exit(1)

        for host in hosts:
            try:
                result = subprocess.run(
                    ["ssh", "-o", "ConnectTimeout=5", host, "uname -r"],
                    capture_output=True, text=True, timeout=10
                )
                kernel = result.stdout.strip()
                if not kernel:
                    print(f"❌ {host}: 无法获取内核版本")
                    continue
                affected, fixed = is_affected(kernel)
                status = "🔴 受影响" if affected else "🟢 不受影响"
                print(f"{status}  {host}  kernel={kernel}  fixed={fixed or 'N/A'}")
            except subprocess.TimeoutExpired:
                print(f"⚠️  {host}: SSH 连接超时")
            except Exception as e:
                print(f"❌ {host}: {e}")
    else:
        # 本地巡检
        status = audit_local()
        print(f"主机名: {status.hostname}")
        print(f"内核版本: {status.kernel}")
        print(f"是否受影响: {'🔴 是' if status.affected else '🟢 否'}")
        print(f"推荐修复版本: {status.fixed_version or 'N/A'}")
        print(f"热补丁状态: {'✅ 已应用' if status.livepatch_applied else '❌ 未应用'}")
        print(f"详情: {status.detail}")

    print("=" * 70)


if __name__ == "__main__":
    main()

Crontab 定时调度

cron 复制代码
# /etc/cron.d/bad-epoll-audit --- CVE-2026-46242 每日巡检
# 每天 03:00 执行,结果写入日志,受影响时发邮件告警

0 3 * * * root /opt/scripts/bad_epoll_audit.py --ssh-hosts /etc/hosts.txt \
    >> /var/log/bad-epoll-audit.log 2>&1; \
    grep -q "受影响" /var/log/bad-epoll-audit.log && \
    mail -s "[紧急] Bad Epoll 漏洞巡检发现受影响主机" ${OPS_MAIL} \
    < /var/log/bad-epoll-audit.log

预防措施

  1. 订阅内核安全公告:订阅 linux-kernel-announce、Ubuntu security-announce、RhSA 邮件列表,PoC 公开后 24h 内启动应急响应。
  2. 建立内核版本资产库:用 CMDB 维护所有主机内核版本,PoC 公开后可秒级筛选受影响范围。
  3. 常态化热补丁能力:所有生产主机预装 livepatch/kpatch,关键漏洞可在不重启情况下快速止血。
  4. 定期演练:每季度演练一次内核漏洞应急响应,从发现到全量补丁完成应在 72h 内。
  5. 多租户隔离升级:共享内核云环境优先部署 gVisor/Kata,将内核攻击面从租户侧屏蔽。

💰 成本核算与价值量化

开发成本

项目 工作量 单价 小计
漏洞情报跟踪与评估 0.5 人天 ¥2,000/人天 ¥1,000
内核升级方案设计(含回退) 1.0 人天 ¥2,000/人天 ¥2,000
内核热补丁验证(kpatch/livepatch) 1.5 人天 ¥2,500/人天 ¥3,750
跨发行版巡检脚本开发 1.0 人天 ¥2,000/人天 ¥2,000
Prometheus 监控规则 + 仪表板 1.0 人天 ¥2,000/人天 ¥2,000
K8s 滚动升级演练 1.0 人天 ¥2,000/人天 ¥2,000
应急响应文档与培训 0.5 人天 ¥2,000/人天 ¥1,000
开发成本合计 6.5 人天 --- ¥13,750

运行成本

项目 频次 单次成本 年度成本
内核热补丁订阅(Ubuntu Pro) 持续 --- ¥0(个人/小规模免费)
RHEL Livepatch 订阅 持续 --- ¥1,200/主机/年(按 50 主机计 ¥60,000)
巡检脚本运行(cron) 每日 ¥0.5 ¥182
Prometheus 监控存储 持续 --- ¥2,000
维护窗口重启(50 主机) 季度 ¥200/主机 ¥4,000
运行成本合计(首年,50 主机) --- --- ¥66,182

收益对比

维度 不修复的潜在损失 修复后收益
单台服务器被提权 数据泄露 + 横向移动,单次事件 ¥50 万+ 风险消除
云宿主机沦陷 全租户数据泄露,单次事件 ¥500 万+(含 SLA 赔付) 宿主机隔离稳固
合规罚款 等保 2.0 / GDPR 罚款 ¥100 万 - ¥1,000 万 合规风险消除
业务中断 内核 panic 导致服务不可用,每小时 ¥10 万 业务连续性保障
品牌声誉 安全事件舆情损失难以量化 信任度维护

ROI 计算

text 复制代码
年度成本 = 开发成本 + 运行成本 = ¥13,750 + ¥66,182 = ¥79,932
年度预期损失(50 主机规模,按 1% 概率被利用计):
  = 50 主机 × 1% × ¥500,000/台 = ¥250,000

ROI = (预期损失 - 年度成本) / 年度成本
    = (¥250,000 - ¥79,932) / ¥79,932
    = 212%

结论:投资回报率 212%,且未计入云宿主机沦陷与合规罚款的尾部风险。
对共享内核云服务商,ROI 应按宿主机口径计算,可达 1000%+。

8. 总结与行动清单

8.1 核心收获

  1. Bad Epoll 是 2026 年最严重的 Linux 内核漏洞之一------99% 可靠 root 提权,影响所有 Linux 6.4+ 内核,包括 Android 6.6 系列设备。
  2. 漏洞根因是 ep_remove()file->f_lock 下清 f_ep 后继续使用 file 对象 ------并发的 __fput() 观察到瞬态 NULL,跳过同步慢路径,导致 struct eventpoll 被提前 kfreehlist_del_rcu() 写入已释放内存。
  3. 竞态窗口仅约 6 条指令 ------KASAN 因 SLAB_TYPESAFE_BY_RCU 失灵,Mythos AI 也错过了,最终由人工代码审查发现。
  4. 无运行时缓解是最大运维痛点------epoll 是用户空间事件驱动基石,无法禁用,必须打补丁 + 重启或热补丁。
  5. 云多租户场景风险被显著放大------共享内核的容器/serverless 环境中,任何租户获得本地 shell 即可能提权到宿主机 root,进而横扫所有租户。
  6. 内核热补丁是关键止血手段------kpatch/livepatch/kGraft 可在不重启情况下应用补丁,适合云宿主机与无法容忍重启的关键节点。
  7. HWE 内核是常见盲区------Ubuntu 22.04 默认内核不受影响,但 HWE-6.8 受影响,运维必须全量盘点。
  8. gVisor/Kata Containers 是云环境纵深防御------用户态内核或轻量 VM 隔离可显著缩小内核攻击面。

8.2 立即行动清单

markdown 复制代码
□ **今天完成(PoC 已公开,窗口期极短)**:

- [ ] 全量盘点所有 Linux 主机内核版本(含 HWE 内核)
- [ ] 识别所有 Ubuntu 22.04 + HWE-6.8、24.04、26.04 主机
- [ ] 对云宿主机优先应用内核热补丁(livepatch/kpatch)
- [ ] 部署 epoll 异常监控(bpftrace/perf/Prometheus)

□ **本周完成**:

- [ ] 测试环境验证内核升级方案(6.18.33+ 或 7.0.10+)
- [ ] 制定 K8s 集群滚动升级计划(cordon + drain + 重启)
- [ ] 高敏感租户评估迁移到 gVisor/Kata Containers
- [ ] CI/CD runner 限制外部依赖安装(防供应链投毒链)

□ **本月完成**:

- [ ] 完成所有受影响主机的内核升级或热补丁 + 30 天内重启
- [ ] 验证 Android 设备厂商补丁状态(Pixel 9/10 等 6.6 内核)
- [ ] 建立内核漏洞应急响应流程(PoC 公开 → 24h 止血 → 72h 全量)
- [ ] 演练一次完整内核漏洞响应(从发现到全量补丁完成)

□ **持续运营**:

- [ ] 订阅内核安全公告(linux-kernel-announce / RHSA / Ubuntu)
- [ ] CMDB 维护内核版本资产库,PoC 公开后秒级筛选
- [ ] 季度演练内核漏洞应急响应
- [ ] 关键主机预装 livepatch/kpatch 工具链

参考链接

如果这篇内容对你有帮助,欢迎点赞收藏,有问题可以在评论区交流。

真实性声明:本文基于 CVE-2026-46242 的公开 NVD 描述、Ubuntu 安全公告、Linux 内核 commit message、Corgea / CyberSec Guru / 0xBlackash 等公开研究与 PoC 仓库整理撰写。漏洞根因、修复 commit、影响版本、CVSS 等核心信息均来自上述公开情报。利用链的工程细节(KASLR 绕过、竞态拓宽、Cross-Cache 喷涂)基于公开 writeup 的原理性描述,未包含可直接执行的漏洞利用代码。受限于公开情报的完整度,部分内核版本判定与厂商 backport 状态可能随时间变化,请以各发行版官方 advisory 为准。

相关推荐
平安的平安1 小时前
人在外地,怎样访问办公室里的电脑和内部资源?
运维·服务器·电脑
智体工坊1 小时前
从零搭建 AI 模型中转网关:部署、渠道、定价、装修全记录
运维·服务器·人工智能·搜索引擎·自动化
我命由我123451 小时前
Kotlin 面向对象 - Kotlin 类变量与类方法
java·服务器·后端·java-ee·kotlin·android jetpack·android runtime
信鸽爱好者1 小时前
一人多台电脑办公模式:windows 电脑A远程桌面操作ubuntu电脑B
linux·运维·ubuntu
木由里予1 小时前
TEE(Trusted Execution Environment)技术详解
java·linux·开发语言·网络·嵌入式硬件·android-studio
元岳数字人小元1 小时前
易部署易运维!AI数字人一体机实现场景长效运营
运维·人工智能·人机交互·交互·源代码管理
小比特-combat1 小时前
FreeRTOS任务通知
java·服务器·前端
深圳市益普科技有限公司2 小时前
半导体mes厂家有哪些?从自动检验与AOI集成看mes厂家的检验自动化水平
运维·自动化
开开心心_Every2 小时前
电脑文件搜索软件支持内容和拼音搜索
linux·服务器·人工智能·r语言·pdf·音视频·symfony