03 - eBPF:核心可程式化的雲原生基石¶
這是整個學習計畫最進階的章節。閱讀本章前,請確認你已具備: - Linux 基礎(行程 (Process)、系統呼叫 (System Call)、檔案描述符 (File Descriptor)) - 容器 (Container) 基礎(命名空間 (Namespace)、控制群組 (cgroup)) - Kubernetes (K8s) 基礎(Pod、Service、網路策略 (NetworkPolicy)、CNI)
本章以建立觀念為主軸,但同時提供清晰的實作路徑,讓你能從「會用工具」一路走到「會寫程式」。
目錄¶
1. 為什麼需要 eBPF¶
1.1 傳統的困境:想在核心做事,代價很高¶
作業系統分成兩個世界:使用者空間 (User Space) 與 核心空間 (Kernel Space)。我們平常寫的程式(包含容器裡跑的應用程式)都活在使用者空間,看不到、也碰不到核心內部正在發生的事——封包怎麼轉送、行程怎麼排程、檔案怎麼開啟。
如果你想在核心 (Kernel) 層級做事(例如攔截每一個網路封包、監看每一次檔案開啟),傳統上你只有兩條路,而且都很痛:
| 做法 | 優點 | 致命缺點 |
|---|---|---|
| 寫核心模組 (Kernel Module) | 功能完整、效能高 | 一個 bug 就讓整台機器當機 (Kernel Panic);每次核心升級可能要重編譯;難維護、難審查 |
| 改核心原始碼後重新編譯 | 完全客製 | 要說服整個 Linux 社群接受你的修改,曠日廢時(常以「年」為單位) |
| 在使用者空間用既有介面 | 安全 | 資料要在核心與使用者空間之間反覆複製,效能差、且只能拿到核心「願意給」的有限資訊 |
簡單說:核心很強大,但傳統上「對外封閉」。 想擴充它的行為,要嘛冒著當機風險,要嘛慢得令人絕望。
1.2 eBPF 的破局:核心裡的沙箱¶
eBPF (extended Berkeley Packet Filter) 徹底改變了這個局面。它的核心理念是:
讓你在「不改核心原始碼、不裝核心模組」的前提下,安全地把自己的程式「注入」到核心內部執行。(官方定義見 ebpf.io:What is eBPF?)
1.3 最好的比喻:核心裡的 JavaScript¶
理解 eBPF 最快的方式,是拿瀏覽器與 JavaScript 來類比:
| 瀏覽器世界 | eBPF 世界 | 共通概念 |
|---|---|---|
| 瀏覽器引擎 (Browser Engine) | Linux 核心 (Kernel) | 龐大、不能隨便改的執行環境 |
| JavaScript | eBPF 程式 | 你寫的、可動態載入的小程式 |
| 網頁事件(點擊、載入) | 核心事件(收封包、開檔案、系統呼叫) | 事件觸發 (Event-driven) |
| JS 沙箱 (Sandbox) | eBPF 驗證器 (Verifier) + 沙箱 | 保證注入的程式不會搞垮宿主 |
就像你不需要為了讓網頁互動而「重新編譯瀏覽器」,你只要寫一段 JavaScript 掛上事件即可;eBPF 讓你不需要為了擴充核心行為而「重新編譯核心」,你只要寫一段 eBPF 程式掛上掛載點 (Hook Point) 即可。
而且 eBPF 程式是安全的:在它被允許執行前,核心裡的驗證器 (Verifier) 會嚴格審查它(下一節詳述),確保它不會無窮迴圈、不會存取非法記憶體、不會搞垮系統。這正是 eBPF 與傳統核心模組最大的差異——核心模組信任你,eBPF 不信任你,所以它先驗證你。(詳見核心官方文件 eBPF Verifier)
1.4 為什麼這在雲原生 (Cloud Native) 如此重要¶
雲原生環境的特徵是:高度動態、規模龐大、多租戶、強調可觀測性與零信任安全。
- 一台節點上可能跑著數十甚至上百個 Pod,網路連線瞬息萬變——傳統
iptables規則會膨脹到數萬條,效能崩潰。 - 安全團隊需要即時看到「哪個容器執行了什麼系統呼叫」,但又不能為了監控而拖垮應用程式。
- 平台團隊想要無侵入式 (Zero-instrumentation) 的可觀測性:不改一行應用程式碼,就能拿到 HTTP / gRPC / SQL 層級的指標。
eBPF 剛好同時滿足這三點:它在核心內運作,所以看得到一切;它是事件驅動且 JIT 編譯,所以夠快;它有驗證器把關,所以夠安全。 這就是為什麼 Cilium、Falco、Pixie、Tetragon 等雲原生明星專案,底層全都是 eBPF。
動手練習 1:用一句話向同事解釋「為什麼不直接寫核心模組就好」。提示:從「當機風險」與「維護成本」兩個角度切入。
2. eBPF 運作原理¶
2.1 全貌:從原始碼到核心內執行¶
flowchart TD
A["eBPF 原始碼<br/>(C 語言)"] -->|"clang/LLVM 編譯"| B["eBPF Bytecode<br/>(位元組碼)"]
B -->|"bpf() 系統呼叫載入"| C{"驗證器 (Verifier)<br/>安全檢查"}
C -->|"不通過 → 拒絕載入"| X["錯誤回傳"]
C -->|"通過"| D["JIT 編譯器<br/>(Just-In-Time)"]
D --> E["原生機器碼<br/>(Native Code)"]
E -->|"附掛到"| F["掛載點 (Hook Point)<br/>kprobe / tracepoint / XDP ..."]
F -->|"事件觸發時執行"| G["eBPF 程式運行"]
G <-->|"讀寫資料 / 與使用者空間溝通"| H["映射 (Maps)"]
H <--> I["使用者空間程式<br/>(loader / agent)"]
整個生命週期:寫 C → 編成位元組碼 → 經 bpf() 系統呼叫載入 → 驗證器審查 → JIT 編成原生機器碼 → 掛到掛載點 → 事件發生時執行 → 透過映射與使用者空間交換資料。 這個流程是 eBPF 子系統的官方總覽,完整定義可參見 Linux 核心 BPF 文件首頁。
2.2 程式類型 (Program Types)¶
eBPF 程式不是萬用的——你寫的程式必須宣告屬於哪一種類型,類型決定了:它能掛在哪種掛載點、能呼叫哪些輔助函式 (Helper Functions)、能拿到什麼樣的上下文 (Context)。完整的程式類型清單與其對應的掛載介面,可見 Linux 核心文件:Program Types and ELF Sections 與 eBPF Docs 的 Program Types 索引。
| 程式類型 | 典型用途 | 上下文 (Context) |
|---|---|---|
BPF_PROG_TYPE_KPROBE |
動態追蹤核心函式 | 暫存器狀態 (pt_regs) |
BPF_PROG_TYPE_TRACEPOINT |
追蹤核心靜態追蹤點 (Tracepoint) | 追蹤點專屬結構 |
BPF_PROG_TYPE_XDP |
最高速封包處理(網卡驅動層) | xdp_md(封包指標) |
BPF_PROG_TYPE_SCHED_CLS |
tc 流量控制 / 整形 | __sk_buff(socket buffer) |
BPF_PROG_TYPE_CGROUP_SKB |
cgroup 層級網路過濾 | __sk_buff |
BPF_PROG_TYPE_SOCKET_FILTER |
socket 層封包過濾 | __sk_buff |
BPF_PROG_TYPE_PERF_EVENT |
效能事件取樣(profiling) | 效能事件資料 |
2.3 映射 (Maps):eBPF 的記憶體與通訊管道¶
eBPF 程式本身是無狀態、短命的——每次事件觸發、跑完就結束。那狀態存哪裡?跨次事件如何累積資料?核心內的程式如何把結果送回使用者空間?
答案是 映射 (Maps)。映射是核心管理的鍵值資料結構 (Key-Value Store),同時被核心內的 eBPF 程式與使用者空間程式存取,扮演兩個世界之間的橋樑。
常見的映射類型(完整類型清單見 核心文件:BPF maps):
| 映射類型 | 用途 |
|---|---|
BPF_MAP_TYPE_HASH |
雜湊表,任意鍵值查找(如:依 PID 累計次數)。核心文件:HASH map |
BPF_MAP_TYPE_ARRAY |
陣列,索引固定 |
BPF_MAP_TYPE_PERCPU_HASH / PERCPU_ARRAY |
每 CPU 各自一份獨立的值,讀寫不需加鎖、避免跨 CPU 競爭,效能極高。核心文件:PERCPU_HASH、核心文件:PERCPU_ARRAY |
BPF_MAP_TYPE_PERF_EVENT_ARRAY |
把事件串流送往使用者空間(舊式,per-CPU 緩衝,可能有跨 CPU 事件順序錯亂與記憶體使用率較差的問題) |
BPF_MAP_TYPE_RINGBUF |
環形緩衝區 (Ring Buffer),核心 5.8 引入,多生產者單消費者 (MPSC),解決了 PERF_EVENT_ARRAY 的記憶體效率與跨 CPU 事件排序問題,是現代主流的事件串流方式。核心文件:BPF ring buffer |
BPF_MAP_TYPE_LRU_HASH |
雜湊表容量滿時自動淘汰最久未用 (Least Recently Used) 的項目。核心文件:HASH map(含 LRU 變體) |
2.4 驗證器 (Verifier):安全的守門員¶
這是 eBPF「安全」的關鍵。當你透過 bpf() 系統呼叫載入程式時,驗證器 (Verifier) 會在程式真正執行之前,以靜態分析窮舉所有可能的執行路徑,確保(詳細規則見核心官方文件 eBPF Verifier):
- 一定會結束:控制流程圖 (CFG) 不能含有迴圈,確保程式必定終止;核心 5.3 起放寬為允許有界迴圈 (Bounded Loops)——驗證器會展開模擬每一輪迭代的狀態,確認迴圈一定會在有限步驟內結束(LWN:Bounded loops in BPF for the 5.3 kernel)。
- 不會非法存取記憶體:每次解參考指標前,必須先檢查邊界(這就是為什麼你常被迫寫
if (ptr + 1 > data_end) return;)。 - 不會洩漏核心記憶體:在非特權模式下,不允許對指標做可能外洩核心位址的指標運算。
- 只用允許的輔助函式:依程式類型限制可呼叫的 helper,且若 helper 被標記為
gpl_only,程式的LICENSE必須宣告為 GPL 相容授權,否則載入會被拒絕(核心文件:BPF licensing)。 - 指令數量與複雜度受限:避免拖垮核心。核心 5.2 之前硬上限是 4096 條指令且複雜度上限 128K;5.2 之後的變更只放寬了特權 (root) 程式——複雜度上限改為單純的
BPF_COMPLEXITY_LIMIT_INSNS,約 100 萬條指令等級,此時純粹看驗證器能否在合理時間內窮舉完所有路徑。但非特權程式的 4096 條指令上限至今仍然存在,並未被移除(見 Linux 核心文件:BPF Design Q&A 中「BPF_MAXINSNS (4096)... the maximum number of instructions that the unprivileged bpf program can have」;變更歷史見 Linux 核心 commit:bpf: increase complexity limit and maximum program size)。
心法:驗證器不是你的敵人,是你的安全帶。 初學時被它擋下會很挫折,但它擋下的每一個錯誤,在傳統核心模組裡都可能是一次 Kernel Panic。
但安全帶也會有瑕疵:驗證器本身是複雜的靜態分析程式碼,一樣可能出錯。例如 CVE-2026-31413 就是驗證器對
BPF_OR常數運算元的純量分析錯誤(maybe_fork_scalars()誤用了BPF_AND的推導邏輯),導致驗證器認定的值與執行期實際值不一致,可被利用做越界的 map 存取(CVSS 7.8;CVE 官方記錄(NVD)、核心修補 commit)。這類問題通常需要載入非特權 eBPF 程式的能力才能觸發,也是許多 K8s 節點預設停用非特權 BPF(kernel.unprivileged_bpf_disabled=1,見 核心文件:BPF Design Q&A)或限制CAP_BPF授予對象的原因。
2.5 JIT 編譯:跑得跟原生一樣快¶
通過驗證後,JIT (Just-In-Time) 編譯器 會把與架構無關的 eBPF 位元組碼,翻譯成當下 CPU 的原生機器碼 (Native Machine Code)。eBPF 的暫存器與指令格式刻意設計成與現代 CPU(x86-64、ARM64 等)的暫存器/呼叫慣例相近,讓 JIT 多半能做到指令一對一映射,目前官方支援 x86-64/x86-32、arm64、arm32、ppc64/ppc32、s390x、mips64/mips32、sparc64、riscv64/riscv32、loongarch64、parisc(32/64 位元,核心 6.6 起新增)、arc(ARCv2)等架構——ppc32 與 mips32 也各自擁有獨立的 eBPF JIT 實作(而非僅有較舊的 classic BPF JIT),分別可見核心原始碼 arch/powerpc/net/bpf_jit_comp32.c、arch/mips/net/bpf_jit_comp32.c、arch/parisc/net/;arc 的 eBPF JIT 支援可見 arch/arc/net/ 及 Kconfig 中 select HAVE_EBPF_JIT if ISA_ARCV2,官方架構支援表見核心原始碼 Documentation/features/core/eBPF-JIT/arch-support.txt;相對地 sparc32 至今仍只有 classic BPF JIT、未支援 eBPF,故未列入。核心原始碼各架構下的 bpf_jit_comp*.c 為權威來源;概念說明見核心文件:Classic BPF vs eBPF。所以 eBPF 程式雖然是「動態載入的腳本」,執行效能卻接近原生編譯的核心程式碼,沒有直譯器的開銷。
2.6 掛載點 (Hook Points):程式掛在哪裡¶
eBPF 程式要「綁」到某個事件來源才能被觸發。常見掛載點:
| 掛載點 | 觸發時機 | 領域 |
|---|---|---|
| kprobe / kretprobe | 進入 / 離開任一核心函式時 | 追蹤(動態) |
| uprobe / uretprobe | 進入 / 離開使用者空間函式時(如追 libc、追 Go 函式) | 追蹤(動態) |
| tracepoint | 核心預先埋好的靜態追蹤點(穩定、跨版本) | 追蹤(靜態) |
| XDP (eXpress Data Path) | 封包經 DMA 進記憶體後、核心配置 sk_buff 與進入網路堆疊之前;只處理 ingress(進站)方向 |
網路(最高速) |
| tc (Traffic Control) | 核心網路堆疊的流量控制層,此時封包已有完整 sk_buff,可看到更豐富的協定中介資訊;支援 ingress 與 egress(出站)雙向 |
網路 |
| cgroup hooks | 某個 cgroup 的行程做網路 / socket 操作時 | 網路 / 安全 |
| LSM (Linux Security Module) | 核心安全決策點,程式回傳值可直接決定該操作被允許還是以 -EPERM 拒絕(核心 5.7 引入,需 CONFIG_BPF_LSM=y) |
安全 |
kprobe vs tracepoint 怎麼選? kprobe 能掛任何核心函式,彈性最大,但函式名稱可能隨核心版本改變(不穩定);tracepoint 是核心刻意提供的穩定介面,跨版本可靠,優先用 tracepoint,沒有合適的再退而用 kprobe。
XDP vs tc 怎麼選? XDP 掛在驅動層、早於
sk_buff配置,延遲最低、最適合「越早丟棄惡意/不需要的封包越好」的場景(如 DDoS 防護),但只能處理 ingress;tc 掛在網路堆疊內,雖然延遲略高,卻能看到完整封包中介資訊、可串接多個分類器、支援 egress,適合更複雜的策略控制。tc 的現代附掛方式:tcx。 傳統 tc BPF 程式要透過 netlink 掛在
clsactqdisc 上,多個程式共存時的執行順序與卸載時機不易管理。核心 6.6 引入的 tcx,提供以bpf_link為基礎的輕量多程式附掛機制:支援用BPF_F_BEFORE/BPF_F_AFTER明確指定執行順序、行程結束或 fd 關閉時自動卸載,不必再操作 qdisc。傳統tc/classifier/action附掛型態已被標示為過時,tcx 是目前建議的做法,Cilium 等專案已預設偵測核心支援後改用 tcx。詳見 eBPF Docs:BPF_PROG_TYPE_SCHED_CLS。動手練習 2:畫出「一個封包從網卡到應用程式」的路徑,並標出 XDP 與 tc 分別攔截在哪一段。思考:為什麼 DDoS 防護要用 XDP 而不是 tc?(提示:越早丟棄惡意封包,浪費的 CPU 越少。)
3. eBPF 的三大應用領域¶
eBPF 的應用千變萬化,但收斂起來就是三大支柱(這個分類方式也是 ebpf.io 官方對 eBPF 應用領域的劃分):
mindmap
root((eBPF))
可觀測性 Observability
無侵入式追蹤
效能分析 Profiling
指標 / Tracing
工具:bcc / bpftrace / Pixie
網路 Networking
高速封包處理 XDP
負載平衡
取代 kube-proxy
工具:Cilium / Katran
安全 Security
系統呼叫監控
執行期偵測
LSM 強制策略
工具:Falco / Tetragon
3.1 可觀測性 (Observability)¶
eBPF 最成熟、最容易上手的領域。因為程式直接跑在核心內,它能無侵入 (Zero-instrumentation) 地看到一切:每一次系統呼叫、每一個封包、每一次函式呼叫——完全不需要改應用程式碼。
- 抓出「誰在 fork 一堆短命行程」、「誰在狂開檔案」、「哪個連線延遲爆高」。
- 持續效能剖析 (Continuous Profiling):用極低開銷取樣 CPU 堆疊,找出熱點。
3.2 網路 (Networking)¶
eBPF 在網路領域是顛覆性的。透過 XDP 與 tc 掛載點,可以在封包處理的最早期就做轉送、過濾、負載平衡——速度遠超傳統 iptables。Cilium、Facebook 的 Katran(L4 負載平衡器)都建立在此之上(詳見第 5 節)。
3.3 安全 (Security)¶
eBPF 能即時觀察核心層的安全事件(誰執行了什麼程式、開了什麼檔、發了什麼連線),甚至透過 LSM hook 直接允許或拒絕某個操作。相較傳統稽核 (auditd),eBPF 的開銷低、可程式化、上下文更豐富。Falco、Tetragon 是代表作。
4. 學習路徑(由淺入深)¶
學 eBPF 最忌諱一開始就埋頭寫 C。正確的順序是:先當「使用者」用工具建立直覺 → 再當「開發者」寫程式。
flowchart LR
A["第 1 階段<br/>用 bpftrace 單行程式"] --> B["第 2 階段<br/>用 bcc 工具集"]
B --> C["第 3 階段<br/>libbpf + CO-RE 寫 C"]
C --> D["第 4 階段<br/>cilium/ebpf 寫 Go"]
style A fill:#d4f4dd
style B fill:#d4f4dd
style C fill:#fff3cd
style D fill:#fff3cd
4.1 第 1 階段:用 bpftrace 建立直覺¶
bpftrace 是一套高階追蹤語言(語法像 awk),讓你用一行就完成原本要寫一大段 C 的追蹤工作,內部以 LLVM 把腳本編譯成 eBPF 位元組碼。最適合探索與建立直覺。
# 安裝(以 Ubuntu/Debian 為例)
sudo apt-get update && sudo apt-get install -y bpftrace
# 範例 1:列出所有 tracepoint 與 kprobe(看看有哪些掛載點可用)
sudo bpftrace -l 'tracepoint:syscalls:*' | head
# 範例 2:統計每個行程觸發了幾次 execve(誰在狂開新程式?)
sudo bpftrace -e 'tracepoint:syscalls:sys_enter_execve { @[comm] = count(); }'
# 範例 3:每秒印出系統呼叫總數(觀察系統負載)
sudo bpftrace -e 'tracepoint:raw_syscalls:sys_enter { @ = count(); }
interval:s:1 { print(@); clear(@); }'
# 範例 4:畫出 read() 回傳大小的直方圖(資料分佈一目了然)
sudo bpftrace -e 'tracepoint:syscalls:sys_exit_read { @bytes = hist(args->ret); }'
動手練習 3:用 bpftrace 寫一行程式,統計每個指令名稱 (comm) 各自開啟了幾次檔案(提示:掛
tracepoint:syscalls:sys_enter_openat,用@[comm] = count())。
4.2 第 2 階段:用 bcc 工具集¶
bcc (BPF Compiler Collection) 內附數十支「即裝即用」的生產級工具。每支都是一個 eBPF 程式的完整範例,用法本身就是最好的教材。
# 安裝
sudo apt-get install -y bpfcc-tools linux-headers-$(uname -r)
# 工具通常以 -bpfcc 結尾(Ubuntu 套件命名)
sudo execsnoop-bpfcc # 即時顯示每一個被執行的新程式(含完整指令列)
sudo opensnoop-bpfcc # 即時顯示每一次檔案開啟(誰開了什麼檔)
sudo tcpconnect-bpfcc # 即時顯示每一個 TCP 主動連線(連到哪去了?)
sudo tcpaccept-bpfcc # 即時顯示每一個 TCP 被動接受的連線
sudo biolatency-bpfcc # 區塊裝置 I/O 延遲直方圖
sudo runqlat-bpfcc # 排程器執行佇列延遲(CPU 爭用程度)
這些工具的對應關係,正好涵蓋三大領域:
| 工具 | 看到什麼 | 領域 |
|---|---|---|
execsnoop |
誰執行了什麼程式 | 安全 / 觀測 |
opensnoop |
誰開了什麼檔 | 安全 / 觀測 |
tcpconnect |
誰連到哪裡 | 網路 / 安全 |
biolatency |
磁碟慢不慢 | 觀測 / 效能 |
動手練習 4:開兩個終端機。一個跑
sudo execsnoop-bpfcc,另一個隨意執行幾個指令(如ls、date)。觀察 execsnoop 即時捕捉到的輸出,理解「核心事件即時可見」的威力。
4.3 第 3 階段:寫程式 — libbpf + CO-RE(現代主流)¶
當工具滿足不了需求,就得自己寫。現代寫法的關鍵字是 CO-RE (Compile Once - Run Everywhere,一次編譯、到處執行)。
為什麼需要 CO-RE? 早期 bcc 的做法是在目標機器上即時編譯(把 C 原始碼字串內嵌進工具、執行期呼叫 Clang/LLVM)——所以每台機器都要裝完整編譯器工具鏈與核心標頭檔,部署笨重、編譯期耗資源、且編譯錯誤要到執行期才會發現。CO-RE 改變了這點(參考:Andrii Nakryiko, BPF CO-RE reference guide):
- 編譯時 Clang 會把「我要存取
task_struct的pid欄位」這類意圖記錄成 BTF (BPF Type Format) 重定位資訊,而非寫死欄位偏移量。BTF 本身由核心 4.18 引入(核心文件:BPF Type Format)。 - 載入時 libbpf 讀取目標機器當前核心的 BTF(
/sys/kernel/btf/vmlinux),比對並重新計算實際欄位偏移,在載入前動態調整存取位址——即使目標核心的結構體佈局與編譯時不同也能正確運作。 - 結果:一個編譯好的
.o檔,可以搬到不同核心版本的機器上直接跑,目標機器不需要編譯器、不需要核心標頭檔。
這就是今天 Cilium、Tetragon、Pixie 等主流專案採用的方式。
下面是一個最小可運行的 libbpf + CO-RE 骨架,功能:追蹤每一次 execve 並印出 PID 與指令名稱。
核心側程式 minimal.bpf.c(在核心內執行):
// minimal.bpf.c — 在核心空間執行的 eBPF 程式
#include "vmlinux.h" // 由 BTF 產生,含所有核心型別定義
#include <bpf/bpf_helpers.h>
char LICENSE[] SEC("license") = "GPL"; // 必須宣告授權,否則無法用 GPL helper
// 定義一個環形緩衝區 (Ring Buffer) 映射,用來把事件送回使用者空間
struct {
__uint(type, BPF_MAP_TYPE_RINGBUF);
__uint(max_entries, 256 * 1024); // 緩衝區大小:256 KB
} events SEC(".maps");
// 事件資料結構
struct event {
int pid;
char comm[16];
};
// 掛到 execve 系統呼叫的進入點 (tracepoint)
SEC("tracepoint/syscalls/sys_enter_execve")
int handle_execve(void *ctx)
{
// 從環形緩衝區預留一塊空間
struct event *e = bpf_ringbuf_reserve(&events, sizeof(*e), 0);
if (!e)
return 0; // 預留失敗就放棄(緩衝區滿了)
// bpf_get_current_pid_tgid() 回傳 64 位元值:高 32 位是 TGID(即一般認知的 PID),低 32 位是個別執行緒 ID
// 參考:https://docs.ebpf.io/linux/helper-function/bpf_get_current_pid_tgid/
e->pid = bpf_get_current_pid_tgid() >> 32;
bpf_get_current_comm(&e->comm, sizeof(e->comm));
bpf_ringbuf_submit(e, 0); // 提交事件給使用者空間
return 0;
}
使用者側載入器(概念流程,以 libbpf 為例):
// minimal.c — 使用者空間載入器(關鍵步驟)
// 1. minimal_bpf__open() 開啟編譯好的 eBPF 物件
// 2. minimal_bpf__load() 載入核心(此時驗證器會審查)
// 3. minimal_bpf__attach() 附掛到 tracepoint
// 4. ring_buffer__poll() 輪詢環形緩衝區、處理事件
// (實務上 .bpf.c 會用 bpftool 產生 skeleton 標頭檔,大幅簡化以上樣板)
典型建置流程(完整流程說明見 核心文件:libbpf Overview):
# 1. 產生 vmlinux.h(從當前核心的 BTF 萃取所有型別)
bpftool btf dump file /sys/kernel/btf/vmlinux format c > vmlinux.h
# 2. 用 clang 把 .bpf.c 編成 eBPF 物件檔(注意 -target bpf)
clang -O2 -g -target bpf -c minimal.bpf.c -o minimal.bpf.o
# 3. 產生 skeleton 標頭(讓使用者側程式好寫)
bpftool gen skeleton minimal.bpf.o > minimal.skel.h
# 4. 編譯使用者側並連結 libbpf,即可執行
強烈建議直接從官方範本起步:libbpf/libbpf-bootstrap 把上面所有樣板都準備好了。
4.4 第 4 階段:用 Go 寫 — cilium/ebpf¶
如果你的世界是雲原生(K8s 控制器、Operator、agent 多半用 Go),那麼 cilium/ebpf(官方文件站 ebpf-go.dev)是純 Go 實作、無 CGO 依賴的主流函式庫,由 Cilium 與 Cloudflare 共同維護,Cilium 本身的 Go 程式碼也使用它來載入與附掛 eBPF 程式。
// main.go — 用 cilium/ebpf 載入並附掛 eBPF 程式(精簡骨架)
package main
import (
"log"
"os"
"os/signal"
"github.com/cilium/ebpf/link"
"github.com/cilium/ebpf/ringbuf"
"github.com/cilium/ebpf/rlimit"
)
// 用 go:generate 搭配 bpf2go,把 minimal.bpf.c 編譯並產生 Go 綁定
//go:generate go run github.com/cilium/ebpf/cmd/bpf2go bpf minimal.bpf.c
func main() {
// 移除 MEMLOCK 上限(舊核心 < 5.11 需要;5.11+ 已改用 cgroup 記憶體核算,此呼叫會是 no-op)
// 參考:https://ebpf-go.dev/concepts/rlimit/
if err := rlimit.RemoveMemlock(); err != nil {
log.Fatal(err)
}
// 載入 bpf2go 產生的 eBPF 物件(objs 含 program 與 map)
objs := bpfObjects{}
if err := loadBpfObjects(&objs, nil); err != nil {
log.Fatalf("載入 eBPF 物件失敗: %v", err)
}
defer objs.Close()
// 把 eBPF 程式附掛到 execve tracepoint
tp, err := link.Tracepoint("syscalls", "sys_enter_execve", objs.HandleExecve, nil)
if err != nil {
log.Fatalf("附掛 tracepoint 失敗: %v", err)
}
defer tp.Close()
// 開啟環形緩衝區讀取器,從核心讀回事件
rd, err := ringbuf.NewReader(objs.Events)
if err != nil {
log.Fatalf("開啟 ringbuf 失敗: %v", err)
}
defer rd.Close()
// 收到 Ctrl-C 時優雅結束
stop := make(chan os.Signal, 1)
signal.Notify(stop, os.Interrupt)
log.Println("開始監聽 execve 事件... (按 Ctrl-C 結束)")
go func() {
for {
record, err := rd.Read() // 阻塞讀取下一筆事件
if err != nil {
return
}
log.Printf("收到事件,長度 %d bytes", len(record.RawSample))
// 實務上會把 record.RawSample 解析成事件結構
}
}()
<-stop
log.Println("收到結束訊號,清理中...")
}
動手練習 5:clone
libbpf/libbpf-bootstrap,建置並執行其中的minimal範例。觀察它如何只用幾十行就完成載入、附掛、讀取事件。接著嘗試把追蹤目標從execve改成openat。
5. eBPF 與 Kubernetes¶
這是本章與你雲原生學習主線最關鍵的交會點。
5.1 核心痛點:iptables 撐不住雲原生規模¶
傳統 K8s 預設用 kube-proxy + iptables 模式來實作 Service 的負載平衡與轉送。問題在於:
- iptables 規則是線性比對的鏈結,封包路由的複雜度是
O(N)(N 為規則數)。每新增一個 Service / Endpoint,規則就增加。 - 大型叢集動輒數千個 Service、數萬條規則——實務上規模來到約 5000 個 Service(對應數萬條規則)時效能就會明顯惡化,封包每次轉送都要從頭掃這串長鏈,延遲與 CPU 隨規模線性惡化。
- 規則更新需要整批重載 (atomic replace),在高變動環境下成本高昂。
現況補充:K8s 社群也意識到此問題。
kube-proxy的 nftables 模式已於 1.33 版 GA,用近似O(1)的映射結構解決了同樣的效能問題(Kubernetes 官方部落格:NFTables mode for kube-proxy);不過 iptables 目前仍是上游預設模式。- IPVS 模式的棄用走多版本漸進式時程,依照官方 KEP-5495:1.35 起印出棄用警告(功能仍完整可用)、1.37 引入
KubeProxyIPVSfeature gate(預設true)、1.40 預設翻成false、1.43 才真正移除程式碼(pkg/proxy/ipvs)、1.46 清掉 feature gate。社群建議及早改用 nftables 以避免屆時被迫遷移。Kubernetes v1.37(代號 Garhwal)已於 2026-08-26 正式發布(官方發布公告),上述KubeProxyIPVSfeature gate 現已隨此版本實際生效,而非僅是規劃中的時程。留意 AWS 的 EKS 1.35 版本說明截至目前(2026-07)仍寫著「will be removed in Kubernetes 1.36」,而 1.36 已於 2026-04 發布且並未移除 IPVS,此說法已被實際發布時程證偽,與上游 KEP-5495(程式碼要到 1.43 才移除)也不一致——實際時程請一律以上游 KEP-5495 追蹤進度為準,而非 AWS 文件的這句敘述。- 但 nftables/IPVS 都只解決了「Service 轉送」這一項問題,並未涵蓋 eBPF 在身分型網路策略、L7 可視性、無侵入式可觀測性上的能力——這正是 Cilium 等 eBPF 方案除了取代 kube-proxy 之外仍有價值的原因。
flowchart TD
subgraph 傳統["傳統:kube-proxy + iptables"]
P1["封包進入"] --> R["線性掃描<br/>數萬條 iptables 規則 O(n)"] --> T1["轉送到 Pod"]
end
subgraph eBPF["eBPF:Cilium"]
P2["封包進入"] --> H["eBPF 雜湊表查找<br/>O(1)"] --> T2["轉送到 Pod"]
end
eBPF 用雜湊表 (Hash Map) 做查找,複雜度從 O(n) 降到接近 O(1),且更新單一條目不需重載整體。這就是 eBPF 取代 iptables 的根本優勢。
5.2 Cilium:eBPF 在 K8s 的旗艦專案¶
Cilium 已於 2023 年 10 月畢業成為 CNCF Graduated 專案,用 eBPF 全面重寫了 Kubernetes 的網路、安全與可觀測性層。CNCF 官方公告當時稱其為「僅次於 Kubernetes、CNCF commit 數第二活躍的專案」(CNCF 公告)——這是畢業當下(2023 年)的排名快照,非持續更新的即時數據:
| Cilium 能力 | eBPF 怎麼做到 | 取代了什麼 |
|---|---|---|
| CNI(容器網路) | 用 eBPF 在核心內處理 Pod 間封包轉送 | 傳統 bridge/overlay |
| 取代 kube-proxy | 用 eBPF cgroup hook 在 socket 層(connect/sendmsg 等)做服務轉譯,搭配 tc 層的封包級負載平衡 |
kube-proxy + iptables。詳見 Cilium 官方文件:Kubernetes Without kube-proxy |
| 網路策略 (NetworkPolicy) | 在 eBPF 層依身分 (Identity)(由 label 推導出的數值 ID)而非 IP 強制策略,查表方式做策略判斷 | iptables 規則。詳見 Cilium 官方文件:eBPF Datapath 介紹 |
| L7 感知策略 | eBPF 解析 HTTP / gRPC / Kafka,做應用層管控 | 須額外 sidecar |
| 可觀測性 (Hubble) | eBPF 觀測所有網路流並彙整 | 須額外監控堆疊 |
Hubble 是 Cilium 的可觀測性元件,讓你即時看到「哪個 Pod 跟哪個 Pod 講話、用什麼協定、有沒有被策略擋下」——服務地圖一目了然。
版本現況:Cilium 1.20.0 已於 2026 年 7 月發布(超過 2,660 個 commit),Gateway API 支援由 v1.4 提升到 v1.6.1(對應本教材第 1 章 5.3 節談到的 TCPRoute/UDPRoute GA),並支援 Kubernetes v1.36。升級前請注意官方列出的重大變更項目(legacy Mutual Authentication、Envoy Go extensions、
cilium.io/v2alpha1 CiliumNodeConfig等)。目前最新修補版為 Cilium 1.20.4(2026-10-23 發布的 out-of-band 安全修補版,僅修補 Go 標準函式庫 CVE-2026-111943〔crypto/x509拒絕信任已遭竊取私鑰的 eMudhra 中繼憑證〕,編譯用 Go 版本升級到 1.26.10,並附帶數項 bug fix,如 wildcard CIDR selector 搭配--policy-cidr-match-mode=nodes、NAT46x64 gateway prefix 轉換的 panic、IPv6 ClusterIP reverse NAT checksum 在舊版核心〔< 6.12〕下的錯誤等;與 BPF/kernel 子系統本身無關)。前一個功能性修補版為 Cilium 1.20.3(2026-10-15 發布;前一個修補版 1.20.2 於 2026-09-15 發布,本次除了 BPF/網路、ENI IPAM、cluster-mesh、identity/policy 等多項修正外,還新增一項 Gateway API 小功能:啟用hostNetwork模式時可用節點標籤選擇器 (label selector) 限制 Envoy listener 只部署到符合標籤的節點,而非預設部署到所有節點),本次 1.20.3 將 Gateway API 規格支援從 v1.6.1 升到 v1.6.3(並把 Gateway 驗證邏輯集中化),其餘修正包含 conntrack GC 誤刪仍在使用中的連線追蹤項目、ICMP 處理改用內層封包前 576 bytes 避免 checksum 計算錯誤等 BPF datapath 細節;Kubernetes 版本支援範圍未變。
# 用 Helm 安裝 Cilium 並啟用「取代 kube-proxy」模式(概念示意)
helm install cilium cilium/cilium --namespace kube-system \
--set kubeProxyReplacement=true \
--set hubble.relay.enabled=true \
--set hubble.ui.enabled=true
# 檢查 Cilium 狀態
cilium status
# 觀察即時網路流(需先 cilium hubble enable)
hubble observe --follow
5.3 其他重要的雲原生 eBPF 專案¶
| 專案 | 領域 | 一句話說明 |
|---|---|---|
| Cilium | 網路 / 安全 / 觀測 | eBPF 版的 CNI 與服務網格,kube-proxy 替代品 |
| Tetragon | 安全 | Cilium 旗下,執行期安全觀測與強制執行 (Enforcement) |
| Falco | 安全 | CNCF 執行期威脅偵測,可用 eBPF 作為事件來源 |
| Pixie | 可觀測性 | 用 eBPF 自動抓 K8s 應用層遙測,免改程式碼 |
| Parca / Pyroscope | 可觀測性 | eBPF 持續效能剖析 (Continuous Profiling) |
動手練習 6:用
kind或minikube建一個本地叢集,安裝 Cilium 並啟用 Hubble UI。部署兩個有互相通訊的 Pod,在 Hubble UI 觀察它們之間的網路流。接著套用一條CiliumNetworkPolicy阻擋其中一個方向,觀察流被擋下的事件。
6. 環境需求¶
6.1 核心版本¶
eBPF 的功能與核心版本強相關。各功能登場的大致里程碑(詳見各功能對應的核心官方文件):
| 核心版本 | 重要里程碑 |
|---|---|
| 3.18 (2014) | eBPF 首次併入主線 |
| 4.x 系列 | kprobe、tracepoint、XDP、Maps 等陸續成熟 |
| 4.18 | BTF 引入,CO-RE 的基礎 |
| 5.2 | 特權程式的指令/複雜度上限放寬至約 100 萬條等級;非特權程式維持 4096 條上限(詳見 2.4 節驗證器規則 5) |
| 5.3 | 有界迴圈 (Bounded Loops) 開放 |
| 5.7 | BPF LSM 引入 |
| 5.8 | CAP_BPF / CAP_PERFMON 權限拆分、Ring Buffer 映射 引入 |
實務建議:做 CO-RE 與現代開發,以核心 5.4+(理想 5.8+)且啟用 BTF(CONFIG_DEBUG_INFO_BTF=y)為基準。(截至 2026 年 10 月,主線核心已進入 7.x 系列——Linux 7.0 於 2026 年 4 月發布,其後 7.1 接續,7.2 已於 2026-08-16 發布(Phoronix 報導),穩定分支已滾動到 7.2.9(2026-10-03 發布,LinuxCompatible 報導);主線 (mainline) 版本 7.3 已如期於 2026-10-18 正式定案發布(未再加開 rc8,Linux 核心原始碼 v7.3 標籤),主線開發現已進入 7.4 的合併窗口 (merge window) 階段;上述 5.4+/5.8+ 只是「CO-RE 可用」的最低基準,新專案沒有理由不用更新的 LTS 核心。)
近期已知的 eBPF 相關核心安全公告(提醒:eBPF 的攻擊面包含驗證器、maps、helper 三處,以下各對應一處): - CVE-2026-63830(CVSS 9.4,Critical,2026-07-19 揭露):
sk_msg的sg.copybitmap 是 scatterlist entry 的「所有權狀態」標記,但 sockmap/TLS 的 transform 路徑在 move、copy、split、compactmsg->sg.data[]entries 時,沒有同步搬動對應的sg.copybit,導致外部(page cache)所擁有的記憶體頁被誤判為可由 BPF 修改,可寫入原本唯讀的 page cache 內容。屬於本節分類中的 maps/helper 攻擊面;修補見核心 commit406e8a651a7b。(註:CVSS 9.4 曾是本清單一度最高分,但下面 2026-08-22 揭露的 CVE-2026-74612 以 CVSS 10.0 超越,詳見下方該筆說明。) - CVE-2026-63926(CVSS 8.4,Ubuntu priority High,2026-07-20 揭露):同屬 sockmap 攻擊面,錯誤發生在bpf_msg_push_data()把插入點落在 scatterlist 某個 entry「中間」時的分割 (split) 邏輯——插入點會把原本的 entry 拆成左右兩段,右段(rsge)的offset欄位語意是「page-local」偏移量,但程式碼卻用訊息全域(message-global)的插入位置start直接加總(rsge.offset += start),而非只加上該 entry 內的局部差值(start - offset)。當插入點落在非第一個 SG entry(offset != 0)時,這個誤用會讓右段的 page offset 被多加了一截,使分割後的 scatterlist 版面錯位,後續以此欄位走訪、複製資料時可能存取到錯誤的 page 位置,造成記憶體毀損或資訊外洩。修補把rsge.offset += start改成rsge.offset += start - offset。修補見核心 commitf72eed9b84fb("bpf: sockmap: fix tail fragment offset in bpf_msg_push_data")。與下面 CVE-2026-64548 同屬bpf_msg_push_data()這個 helper 出錯的案例,只是這次錯在分割後偏移量算錯了基準值(message-global vs fragment-local),而非整數溢位;也與上面 CVE-2026-63830 同屬 sockmap scatterlist 處理機制出錯的類型。 - CVE-2026-64548(CVSS 8.4,2026-07-27 揭露):同樣是 sockmap 攻擊面,bpf_msg_push_data()在 scatterlist ring 空間不足、走進 copy-fallback 配置路徑時,以copy + len計算配置大小——但len是 BPF 程式可完全控制的ARG_ANYTHING參數,且兩者皆為 u32,未做溢位檢查就相加,可構造len使總和整數溢位成一個很小的值,造成配置的緩衝區過小,後續memcpy寫入超出邊界,導致 heap 記憶體毀損。修補是在配置前加一行溢位檢查if (unlikely(copy + len < copy)) return -EINVAL;(核心 commit0c0a8ed85349,"bpf, sockmap: reject overflowing copy + len in bpf_msg_push_data()")。與上面 CVE-2026-63830 同屬 sockmap/scatterlist 機制出錯的案例,只是這次錯在整數溢位而非 bit 同步。 - CVE-2025-39913(CVSS 7.8,2025-10 揭露):同屬 sockmap 攻擊面,比上面兩筆 2026 年案例早了約九個月。tcp_bpf_send_verdict()在為訊息「corking」(透過bpf_msg_cork_bytes()觸發)配置psock->cork失敗時(例如以 fault injection 模擬記憶體不足),沒有呼叫sk_msg_free()回復先前sk_msg_alloc()對sk->sk_forward_alloc所做的變更,導致該sk_msg物件的參照計數與記憶體追蹤狀態不一致,形成 Use-After-Free,可能被本地攻擊者用於權限提升或核心資訊洩漏。與上面 CVE-2026-63830、CVE-2026-64548 同屬 sockmap/cork 生命週期管理出錯的類型,只是這次錯在配置失敗後的清理路徑,而非 scatterlist 的搬移或溢位計算。 - CVE-2026-23359(CVSS 7.8,2026-03-25 揭露):BPF_MAP_TYPE_DEVMAP的 XDP 廣播轉送路徑中,get_upper_ifindexes()在收集裝置的「上層 (upper)」介面索引時未做邊界檢查,呼叫端原本假設上層裝置數量不超過MAX_NEST_DEV(8)並依此配置陣列空間——但當一張裝置疊了超過 8 個上層裝置(例如疊了大量 macvlan 介面)、且掛上帶BPF_F_BROADCAST | BPF_F_EXCLUDE_INGRESSflag 的 XDP 程式時,收到封包觸發轉送就會寫出堆疊陣列邊界,造成 stack out-of-bounds write。修補為get_upper_ifindexes()加上max容量參數,超出時回傳-EOVERFLOW並中止轉送。與下面 CVE-2026-64545 同屬 XDP 導向 (redirect) 路徑出錯的案例,只是這次錯在邊界檢查而非 NULL 檢查(且觸發需要CAP_BPF+CAP_NET_ADMIN,一般僅 root 可達,風險相對較低)。 - CVE-2026-31525(CVSS 7.8,2026-04-22 揭露):BPF 直譯器 (interpreter) 處理有號 32 位元除法/取餘 (sdiv/smod) 指令時,對運算元呼叫abs()巨集——但當運算元為S32_MIN(0x80000000)時,abs()的行為屬於未定義行為 (undefined behavior),導致直譯器實際算出的結果,與驗證器scalar32_min_max_sdiv()靜態推導出的範圍不一致,可構造出讓驗證器誤判為安全、實際卻越界的 map value 存取。修補新增abs_s32(),先轉型為u32再取負以避免有號溢位。與 2.4 節的 CVE-2026-31413 同屬「驗證器推導與執行期實際行為不一致」的類型,只是這次錯在直譯器對abs()的誤用,而非純量推導邏輯本身。 - CVE-2026-43030(CVSS 7.8,2026-05-01 揭露):驗證器的regsafe()在比對指向封包 (packet) 的指標狀態時,當舊狀態rold->reg->range == BEYOND_PKT_END而目前狀態rcur->reg->range == N時可能誤判為安全,導致某些其實帶有有效封包範圍、理應被探索的狀態被跳過驗證。屬於驗證器的狀態剪枝 (state pruning) 邏輯出錯。 - CVE-2026-43009(CVSS 7.8,Ubuntu priority High,2026-05-01 揭露,與上面 CVE-2026-43030 同批公告):backtrack_insn()在回溯精確度追蹤 (precision tracking) 時,遇到帶BPF_ATOMIC | BPF_FETCH的BPF_STX指令(例如BPF_CMPXCHG)未特殊處理——這類指令的src暫存器(BPF_CMPXCHG則是r0)其實同時也是「目的」,會被寫入記憶體讀出的舊值,但既有邏輯仍把它當成一般 store、只當作輸入處理,導致精確度沒有正確回傳給對應的堆疊 (stack) 位置、該位置未被標記為 precise。後續驗證器的路徑剪枝 (path pruning) 可能因此誤判兩條實際堆疊狀態不同的分支為等價而剪掉不該剪的分支。修補讓backtrack_insn()的BPF_LDX處理邏輯透過新增的is_atomic_fetch_insn()判斷式,一併涵蓋 atomic fetch 指令。屬於驗證器的狀態剪枝邏輯出錯,與上面 CVE-2026-43030 同屬一類但錯在不同的暫存器精確度追蹤路徑。 - CVE-2026-43070(CVSS 7.8,2026-05-05 揭露):BPF_END(位元組序轉換)指令會就地改變暫存器的純量值,但驗證器沒有同步重置該暫存器的id,導致後續以 ID 為基礎的邊界追蹤 (range tracking) 誤把兩個暫存器視為同源,可能被利用構造越界記憶體存取。屬於驗證器純量追蹤出錯的案例。 - CVE-2026-43321(CVSS 7.8,2026-05-08 揭露):compute_insn_live_regs()在計算 live register 時,漏掉標記gotox rX(間接跳躍)指令實際用到的暫存器rX,導致驗證器對該暫存器的存活分析不完整。屬於驗證器的存活分析 (liveness analysis) 出錯。 - CVE-2026-43306(CVSS 5.5,Ubuntu priority Medium,2026-05-08 揭露,與上面 CVE-2026-43321 同日公告,2026-10-15 複查時發現先前遺漏、補上):啟用CONFIG_CFI(Control Flow Integrity)的核心要求間接函式呼叫的指標型別必須與目標函式完全匹配——BPF crypto 子系統執行自我測試 (self-test) 時,bpf_crypto_ctx_release()被以不匹配的函式指標型別註冊為 destructor kfunc,觸發 CFI type mismatch 失敗。原函式本身因同時也被一般 BPF 程式呼叫(其void *引數型別會讓驗證器處理上出問題),不能直接改型別,修補改為另外新增一個型別正確的 stub function,專門用來註冊為 destructor。修補見核心 commit4e3e57dbf46d等 4 筆對應穩定分支修補。屬於驗證器/核心介接層對 BPF kfunc 型別檢查出錯的案例,與下面 CVE-2026-53099(kCFI 設定名稱過期導致保護失效)、CVE-2026-92486(BPF callback ABI 與 kCFI 型別不一致)同屬 kCFI/CFI 相關的同類問題家族。Ubuntu 在 24.04/22.04/20.04/18.04/16.04 上標示為 Vulnerable,26.04 LTS 標示為 Not affected。 - CVE-2026-45838(CVSS 5.5,2026-05-27 揭露):cgroup_storage_get_next_key()用list_next_entry()判斷是否走到 list 尾端,但該巨集在最後一個元素時並不會回傳NULL,而是透過container_of()繞回 list head,導致原本的NULL檢查永遠不會命中,使函式把 list head 誤當成合法的 map entry 讀取,將核心內部的struct欄位(而非真正的storage->key)外洩給使用者空間。屬於本節分類中的 maps/helper 攻擊面。 - CVE-2026-45967(CVSS 5.5,Ubuntu priority Medium,2026-05-27 揭露,與上面 CVE-2026-45838 同日公告,2026-10-15 複查時發現先前遺漏、補上):instruction array map(BPF_MAP_TYPE_INSN_ARRAY)的map_direct_value_addr()在計算某個非零偏移量 (offset) 對應的位址時,自己先把 offset 加上去一次——但呼叫端resolve_pseudo_ldimm64()緊接著又會把同一個 offset 再加一次,導致對非零偏移量的查詢得到錯誤(偏移量被重複計算)的位址。修補讓map_direct_value_addr()直接回傳基底位址,offset 的計算完全交給呼叫端處理一次就好。修補見核心 commit73ef43202a37、e3bd7bdf5ffe。屬於本節分類中的 maps/helper(instruction array map 位址解析)攻擊面。Ubuntu 所有受支援版本均標示為 Not affected。 - CVE-2026-45971(CVSS 5.5,Ubuntu priority Medium,2026-05-27 揭露,與上面 CVE-2026-45967 同日公告,2026-10-15 複查時發現先前遺漏、補上):BPF 程式簽章 (program signature) 機制原本沒有限制使用者可宣告的簽章大小——但實務上合理的簽章遠小於KMALLOC_MAX_CACHE_SIZE,允許任意大小讓攻擊者能構造超大簽章,強迫核心走向昂貴的kmalloc_large()/vmalloc()配置路徑,可被用於資源耗盡型的阻斷服務。修補("bpf: Limit bpf program signature size")為簽章大小加上合理上限。修補見核心 commit5835a077c6f5等 3 筆對應穩定分支修補。屬於本節分類中的 maps/helper(程式簽章配置)攻擊面。Ubuntu 所有受支援版本均標示為 Not affected。 - CVE-2026-45933(CVSS 7.8,2026-05-27 揭露,與上面 CVE-2026-45971 同日公告,2026-10-16 複查時發現先前遺漏、補上):驗證器sync_linked_regs()把邊界資訊從known_reg同步給「連動 (linked)」暫存器reg時,連同known_reg的id一起複製了過去——若known_reg原本帶有BPF_ADD_CONST標記的基底 id,這個 id 就被誤用沿用到reg上;一旦之後又對reg做一次賦值(例如another_reg = reg),reg會被指派一個全新的 id,原本與known_reg之間的連動關係就此斷裂,後續對known_reg推導出的邊界收斂(例如排除某個除以零的分支)不會再傳播給reg,可構造出驗證器誤判為「除數不可能為零」、實際執行期卻真的除零的情境。修補改為同步時保留原本的id(與既有對off、subreg_def欄位的保留方式一致)。修補見核心 commitaf9e89d8dd39("bpf: Preserve id of register in sync_linked_regs()"),修正對象為更早的 commit98d7ca374ba4("bpf: Track delta between \"linked\" registers.")。屬於驗證器(scalar/連動暫存器 id 追蹤)層級的問題,與下面 CVE-2026-53092(rX += rX時 delta 算錯)、CVE-2026-93127(窄讀取正負號擴展與 id 共用衝突)同屬sync_linked_regs()連動暫存器同步機制反覆出錯的同類問題家族。 - CVE-2026-45903(NVD CVSS 0.0,2026-05-27 揭露,與上面 CVE-2026-45933 同日公告,2026-10-16 複查時發現先前遺漏、補上):自從驗證器改用MEM_RDONLY/MEM_WRITE旗標判斷 helper 是否會寫入其ARG_PTR_TO_MEM緩衝區引數(核心 commit37cce22dbd51,"bpf: verifier: Refactor helper access type tracking")之後,多個既有 helper 的bpf_func_proto宣告忘了同步補上正確旗標——其中bpf_get_stack_proto_raw_tp甚至被標成唯讀MEM_RDONLY,但它實際上會把呼叫結果寫入使用者提供的緩衝區。驗證器因此可能誤判緩衝區在 helper 呼叫後「內容不變」,把呼叫前快取的舊值直接拿來用、省略本應重新讀取的操作,讓追蹤/觀測類 BPF 程式讀到過期(stale)資料而非 helper 實際寫入的值。修補除了把bpf_get_stack_proto_raw_tp改成ARG_PTR_TO_UNINIT_MEM,也為bpf_snprintf、bpf_snprintf_btf、bpf_read_branch_records、bpf_xdp_fib_lookup、bpf_skb_fib_lookup、bpf_tcp_raw_gen_syncookie_ipv4/ipv6、bpf_tcp_raw_check_syncookie_ipv4/ipv6等多個 helper 的 prototype 補上對應的MEM_WRITE/MEM_RDONLY旗標。修補見核心 commit802eef5afb18("bpf: Fix memory access flags in helper prototypes")。屬於本節分類中的 maps/helper(helper prototype 存取旗標標記)類別,但性質上屬於正確性修正而非可被利用的記憶體安全漏洞——NVD 評為 CVSS 0.0,與本節其他著重記憶體越界/UAF/資訊外洩的條目不同,風險主要是觀測資料失準而非安全邊界被突破。 - CVE-2026-45927(CVSS 未公布,2026-05-27 揭露,與上面 CVE-2026-45903 同日公告,2026-10-18 複查時發現先前遺漏、補上):bpf_map_get_info_by_fd()計算並快取 map 的內容雜湊(hash)時,沒有檢查該 map 是否已經 freeze(凍結,凍結後 map 內容不可再變更)——使用者空間可以先對仍可寫入的 map 取得雜湊、快取下來,接著修改 map 內容後才呼叫 freeze,讓依賴這份雜湊比對內容是否遭竄改的 signed loader(簽章載入器)誤以為目前(已被動過手腳)的內容與快取的舊雜湊一致,形成 Time-of-Check-to-Time-of-Use(TOCTOU)漏洞。修補讓對尚未 freeze 的 map 要求計算雜湊時直接回傳-EPERM,僅在 map 真正凍結、內容不會再變之後才允許產生雜湊。修補見核心 commit7752d3634386、f415e114b58f、a2c86aa621c2。屬於本節分類中的 maps/helper(map 雜湊計算時序)攻擊面,與下面 CVE-2026-80675(libbpf signed loader 在 SHA 驗證前未檢查 map 獨佔性)同屬「map 雜湊比對流程可被競態繞過」的同類問題家族,只是這次錯在核心本身計算雜湊的時機,而非使用者空間 loader 的比對邏輯。 - CVE-2026-52910(CVSS 6.4,2026-06-19 揭露):SO_REUSEPORT的 classic BPF(cBPF)選核程式與 eBPF 選核程式,在移除路徑上被同一份程式碼處理,但兩者生命週期管理方式不同——eBPF prog 透過bpf_prog_put()走參照計數、於 RCU grace period 後才真正釋放,cBPF prog 卻在sk_reuseport_prog_free()中被立即釋放。當另一顆 CPU 正在reuseport_select_sock()內、於 RCU read section 中讀取同一份 cBPF 程式做封包選核時,程式已被釋放,形成 Use-After-Free(fuzzing 以 KASAN 抓到 vmalloc-out-of-bounds 讀取)。修補改為 cBPF prog 比照 eBPF 走法,等 RCU grace period 後才釋放。屬於本節分類中的 maps/helper 生命週期管理類型,與上面 CVE-2025-39913 同屬 reuseport/cork 物件釋放時機出錯的案例。 - CVE-2026-52938(CVSS 5.5,Ubuntu priority Medium,2026-06-24 揭露,2026-10-15 複查時發現先前遺漏、補上):BPF socket local storage 的bpf_selem_unlink_nofail()在把 selem 從儲存串列移除之前,先把它的smap指標清成 NULL——但若此時另一顆 CPU 正透過bpf_sk_storage_clone()(例如 TCP SYN 收包時複製 socket 觸發)在 RCU read-side critical section 中走訪同一份串列,就可能讀到這個smap已被清空、卻還留在串列上的 selem,解參考 NULL 指標造成核心崩潰(KASAN 回報 null-ptr-deref)。修補在bpf_sk_storage_clone()與bpf_sk_storage_diag_put_all()都補上smap的 NULL 檢查,並重構diag_get()改以參數傳入smap(bpf_sk_storage_diag_put()路徑的smap本就受參照計數保護,直接傳入即可)。修補見核心 commit16af24fea29c、375e4e33c18d。屬於本節分類中的 maps/helper(socket local storage 生命週期)攻擊面,與上面 CVE-2026-52910(SO_REUSEPORTcBPF 程式釋放時機與 RCU 寬限期不同步)同屬 BPF 相關物件釋放時機與並發讀取之間競態的同類問題。Ubuntu 僅 26.04 LTS 標示為受影響並已修補(7.0.0-31.31),其他版本標示為 Not affected 或 Not in release。 - CVE-2026-53031(CVSS 7.8,2026-06-24 揭露):BPF arena(BPF_MAP_TYPE_ARENA,核心 6.9 引入的一種 BPF 程式與使用者空間共享的稀疏記憶體區域,可 mmap 給雙方以指標直接互通,常用於零複製建構鏈結串列、樹狀結構等複雜資料型態;參考核心 commit317460317a02("bpf: Introduce bpf_arena"))的arena_alloc_pages()直接收下一個未經檢查的純int node_id,並沿整條記憶體配置鏈往下傳遞,完全沒有邊界檢查。屬於本節分類中的 maps/helper 攻擊面。 - CVE-2026-53033(CVSS 6.4,Ubuntu priority High,2026-06-24 揭露):unix_stream_bpf_update_proto()中,sockmap 附掛在 AF_UNIX socket 上的 iterator 程式所讀取的peer指標,在該 socket 從TCP_ESTABLISHED轉換到TCP_CLOSE的過程中可能變成過期指標,形成 Use-After-Free。屬於 maps/helper 攻擊面,與前述 sockmap 系列問題(CVE-2026-63830、CVE-2026-64548)同屬 sockmap 生命週期管理類型。 - CVE-2026-53034(CVSS 5.5,Ubuntu priority Medium,2026-06-24 揭露):與上一筆 CVE-2026-53033 是同一個函式unix_stream_bpf_update_proto()、同一段程式碼競態的姊妹漏洞,但發生的時間點更早、後果也不同。unix_stream_connect()會先用WRITE_ONCE(sk->sk_state, TCP_ESTABLISHED)把狀態改成已連線,之後才指派unix_peer(sk) = newsk;而sock_map_sk_state_allowed()只檢查sk_state == TCP_ESTABLISHED就認定這個 socket 已經設置完整(隱含 peer 也已就緒)。若 sockmap 更新剛好落在這兩個步驟之間的窗口,unix_stream_bpf_update_proto()讀到的unix_peer(sk)便仍是NULL,直接解參考造成 NULL pointer dereference(核心崩潰、阻斷服務)。修補在讀出sk_pair後立即檢查:if (unlikely(!sk_pair)) return -EINVAL;。修補見核心 commit041eb6348d73("bpf, sockmap: Fix af_unix null-ptr-deref in proto update")——該 commit message 也明白指出,這個 NULL 檢查雖然擋下了 connect() 競態,但不足以防禦另一種「close()競態」下的 use-after-free,那正是上一筆 CVE-2026-53033 所修補的問題。屬於 maps/helper 攻擊面,與 CVE-2026-53033 同屬 AF_UNIX sockmap 生命週期管理系列的一體兩面:53034 是連線建立初期的 NULL 競態,53033 是連線關閉時的 UAF 競態。 - CVE-2026-53035(CVSS 5.5,Ubuntu priority Low,2026-06-24 揭露):同樣是 AF_UNIX 版本 sockmap iterator 的問題,但錯在鎖而非指標生命週期——bpf_iter_unix_seq_show()走訪 socket 時若lock_sock_fast()走進 fast path 取得了 socket 鎖,此時若 iterator 程式接著呼叫bpf_sock_map_update()更新 sockmap,sock_map_update_elem()內部會對同一顆 socket 再呼叫一次bh_lock_sock(),形成同一把鎖(slock-AF_UNIX)的遞迴鎖定 (recursive locking),導致執行緒自旋死鎖(阻斷服務)。觸發需要CAP_PERFMON或 init user namespace 下的CAP_SYS_ADMIN(用於載入 iterator 所需的BPF_PROG_TYPE_TRACING程式),故 Ubuntu 將其標為 Low priority。屬於 maps/helper(iterator)攻擊面,與上面 CVE-2026-53033、CVE-2026-53034 同屬 af_unix sockmap 併發/生命週期管理出錯的系列問題,只是這次錯在鎖的遞迴取用而非參照或 NULL 檢查。 - CVE-2026-53036(CVSS 7.8,2026-06-24 揭露):arm64 平台的 BPF JIT 編譯器,check_imm巨集用來驗證分支位移 (branch displacement) 是否落在合法的有號 N 位元範圍內時有差一 (off-by-one) 錯誤,可能讓超出範圍的值通過檢查,經由位元遮罩效應把原本的前向分支 (forward branch) 變成後向分支 (backward branch),影響B.cond、CBZ/CBNZ等指令的編碼正確性。屬於 JIT 編譯器層級的邊界檢查出錯,不同於前述多屬驗證器或 maps/helper 的案例。 - CVE-2026-53081(CVSS 6.4,Ubuntu priority High,2026-06-24 揭露):驗證器的狀態剪枝機制在比對兩個帶有BPF_ADD_CONST標記的純量暫存器時,沒有確認雙方的 base id 是否一致——例如舊狀態的R3 = R2 + 10(base id A)與目前狀態的R3 = R4 + 10(base id C)彼此無關,卻可能被誤判為等價狀態而剪枝放行。屬於驗證器狀態剪枝出錯,與前述 CVE-2026-43030 同屬此類但錯在不同暫存器追蹤機制。 - CVE-2026-53085(CVSS 6.4,Ubuntu priority High,2026-06-24 揭露):開放編碼 (open-coded) 的task_vmaiterator 在讀取任務的記憶體映射前,沒有正確取得mm_struct的參照計數(該結構未標記SLAB_TYPESAFE_BY_RCU),當任務並發結束 (exit) 時可能被提前釋放,形成 Use-After-Free。屬於 maps/helper(iterator)攻擊面。 - CVE-2026-53090(CVSS 6.4,Ubuntu priority High,2026-06-24 揭露):驗證器對 subprogram 內的ld_abs/ld_ind(直接讀取封包資料)指令,只模擬了成功路徑,沒有同時模擬封包資料讀取失敗時、程式會直接回傳 0 給呼叫端的失敗路徑,導致該路徑的狀態分析不完整。屬於驗證器路徑分析出錯。2026-09-22 審查後補充:交叉比對 Ubuntu Security Notices 逐一 CVE 編號後發現,2026-06-24 這批公告實際收錄的 BPF 相關 CVE 遠不只上面 8 筆,以下 15 筆先前遺漏,一併補上(其中 CVE-2026-53037/53093/53097 等鄰近編號經查證為同日公告但非 BPF 子系統問題——分別是 HID
usbhid、brcmfmacWiFi 驅動、mt76WiFi 驅動——故不收錄於此):
- CVE-2026-53032(CVSS 5.5,Ubuntu priority Medium,2026-06-24 揭露):
map_kptr_match_type()原本的檢查順序是先判斷btf_is_kernel(reg->btf)才檢查base_type(reg->type),但一個被存入 kptr 欄位的純量暫存器根本沒有btf(其reg->btf為 NULL),導致btf_is_kernel()對 NULL 解參考崩潰。問題由重構bpf_kptr_xchg()本地 kptr 邏輯的 commitab6c637ad027引入。修補把「base_type(reg->type) != PTR_TO_BTF_ID就直接判定不符」的檢查提到任何reg->btf存取之前。屬於驗證器對暫存器型別檢查順序出錯的案例,與上面 CVE-2026-53095(kprobe/freplace 附掛檢查)同屬驗證器檢查邏輯出錯但情境不同的問題。- CVE-2026-53069(CVSS 7.5,2026-06-24 揭露,syzkaller 回報):
xdp_master_redirect()呼叫 bonding 驅動的bond_xdp_get_xmit_slave()→bond_xdp_xmit_roundrobin_slave_get()→bond_rr_gen_slave_id(),而後者會解參考bond->rr_tx_counter——這個 per-CPU 計數器只有在bond_open()(即介面被IFF_UP)時才會配置。但bpf_master_redirect_enabled_key是全域的 static key,只要系統上任一顆 bond 裝置掛了原生 XDP,這條XDP_TX → xdp_master_redirect()的攔截路徑就會對所有 bond slave 全域生效——即使某顆從未ifup的 bond 裝置,只要收到 XDP_TX 流量就會走進這條路徑,對還沒配置的rr_tx_counterNULL 解參考,造成核心崩潰。修補在呼叫 master 的->ndo_xdp_get_xmit_slave()前先檢查IFF_UP,不符就以XDP_ABORTED直接丟棄封包。屬於本節分類中的 maps/helper(XDP 導向路徑)攻擊面,與下面 6.1 節已列的 CVE-2026-64545(同一函式xdp_master_redirect()另一種 NULL 檢查缺漏)同屬一類問題;此案 CVSS 向量為AV:N(可由網路上收到的 XDP 流量觸發,不需要本機權限),是本節少見的「遠端可觸發」BPF 相關 CVE。- CVE-2026-53074(CVSS 5.5,2026-06-24 揭露):
bpf_prog_test_run_skb()(供BPF_PROG_TEST_RUN系統呼叫測試 skb 型程式用)先呼叫eth_type_trans()判斷協定,再依skb->protocol存取ip_hdr(skb)/ipv6_hdr(skb)來初始化測試用的 socket family/address 欄位——但若呼叫端只提供了一個 Ethernet header、EtherType 宣稱是 IPv4/IPv6 卻沒有附上實際的 L3 header,就會讀到 skb 資料緩衝區之外的記憶體。修補把 IPv4/IPv6 的最小長度檢查併入既有的協定 switch,長度不足就提早以-EINVAL拒絕,不再存取網路層 header。屬於本節分類中的 maps/helper(BPF_PROG_TEST_RUN測試基礎設施)攻擊面。- CVE-2026-53076(CVSS 7.1,2026-06-24 揭露):
pcpu_init_value()在把資料從一個 map 複製到 per-CPU map 時,假設所有來源 value 都已被核心向上取整到 8 bytes,因此直接呼叫copy_map_value_long()做整段複製——但BPF_MAP_TYPE_CGROUP_STORAGE等來源 map 的value_size若未對齊 8 bytes(例如剛好 4 bytes),驗證器允許的存取範圍就是精確的 4 bytes,而非核取整後的 8 bytes。當這樣的 4-byte 來源被複製進一個value_size同為 4 bytes 的 per-CPU map 時,pcpu_init_value()仍依 8-byte 假設去讀,造成越界讀取(OOB read)。屬於本節分類中的 maps/helper 攻擊面,與上面 CVE-2026-93174(per-CPU map value 複製長度未對齊)同屬「per-CPU map 複製路徑對齊/長度假設出錯」的同類問題家族,只是這次是讀入而非寫出的方向。- CVE-2026-53078(CVSS 7.8,2026-06-24 揭露):BPF
sock_ops程式存取 ctx 欄位時,若dst_reg == src_reg(同一暫存器既是目的也是來源),SOCK_OPS_GET_SK()/SOCK_OPS_GET_FIELD()這兩個 codegen 巨集會借用一個暫存暫存器去檢查is_fullsock/is_locked_tcp_sock,檢查結果為否(例如 socket 處於TCP_NEW_SYN_RECV、還只是個request_sock)時,理應把dst_reg清零,但漏了這一步,讓它殘留原本的 ctx 指標值。SOCK_OPS_GET_SK情境下,這個殘留值會被誤判為合法的PTR_TO_SOCKET_OR_NULL,可被當成偽造的 socket 指標傳給bpf_skc_to_tcp6_sock()等 helper,造成 stack out-of-bounds 存取;SOCK_OPS_GET_FIELD情境下,驗證器則會把這個殘留的核心指標誤判為SCALAR_VALUE洩漏給使用者空間。修補在!fullsock/!locked_tcp_sock路徑補上BPF_MOV64_IMM(dst_reg, 0)。屬於本節分類中的 maps/helper(ctx 欄位存取 codegen)攻擊面,是少見的「同暫存器 dst/src」邊界情況被漏掉的案例。- CVE-2026-53083(CVSS 5.5,2026-06-24 揭露):
bpf_fd_array_map_clear()清空PROG_ARRAYmap 時,對每個 entry 都呼叫一次可能很昂貴的prog_array_map_poke_run(),但迴圈中沒有cond_resched()。當 map 的 entry 數量很大時,這個長迴圈會長時間佔用 CPU 不釋放,導致 RCU 寬限期遲遲無法結束,在高負載下觸發 RCU stall(核心回報rcu: INFO: rcu_sched detected stalls),使系統回呼與 workqueue 大幅延遲,形同阻斷服務。修補在迴圈中補上cond_resched()。屬於本節分類中的 maps/helper(map 生命週期)攻擊面。- CVE-2026-53084(CVSS 5.5,2026-06-24 揭露):與下一筆 CVE-2026-53085 同屬
task_vmaiterator 系列問題,但錯在鎖順序而非參照計數。iterator 原本在整個 BPF 程式主體執行期間持有 per-VMA 鎖(vm_lock),但若程式呼叫的 helper 內部又需要取得依賴mmap_lock的鎖(鎖順序為vm_lock → i_rwsem → mmap_lock → vm_lock),就會形成鎖順序反轉,可能導致死鎖。修補改為在_next()內、仍持有 per-VMA 鎖時就用memcpy()把 VMA 資料快照下來,再釋放鎖後才把快照交給 BPF 程式本體使用(驗證器只信任快照中的vm_mm/vm_file指標,vm_file另外用get_file()額外取得參照、於下次迭代或_destroy()以fput()釋放)。修補見核心 commit4cbee026db54("bpf: return VMA snapshot from task_vma iterator")。屬於本節分類中的 maps/helper(iterator)攻擊面。- CVE-2026-53089(CVSS 7.8,2026-06-24 揭露):查詢已 offload 到硬體的 BPF map/程式資訊時,
bpf_map_offload_info_fill_ns()/bpf_prog_offload_info_fill_ns()用get_net(dev_net(offmap->netdev))取得對應的 network namespace 參照——rtnl_lock/bpf_devs_lock確保netdev指標本身有效,但無法阻止該 netns 的參照計數在同一時間因 netns 銷毀而歸零。一旦get_net()在參照計數已經是 0 的情況下仍執行遞增,就會觸發refcount_t: addition on 0,屬於 Use-After-Free 的一種形式。修補改用maybe_get_net()(內部用refcount_inc_not_zero()),計數已歸零時回傳NULL,讓呼叫端改以-ENOENT正常失敗而非毀損記憶體。修補見核心 commita0c584fc1805。屬於本節分類中的 maps/helper(BPF offload)攻擊面。- CVE-2026-53092(CVSS 7.8,Ubuntu priority Low,2026-06-24 揭露):驗證器
adjust_reg_min_max_vals()處理rX += rX(即src_reg、dst_reg指向同一個bpf_reg_state)這種邊界情況時,函式先就地修改了dst_reg的值,但後續計算 delta(用於sync_linked_regs()把邊界變化同步給其他「連動 (linked)」暫存器)時,讀取src_reg拿到的卻是修改後的值而非原始來源值,導致算出錯誤的 delta,被sync_linked_regs()錯誤傳播到其他連動暫存器上,形成驗證器推導與執行期實際值不一致。修補直接跳過src_reg == dst_reg這個特例。修補見核心 commitcc86a8b0a1c5("bpf: Fix linked reg delta tracking when src_reg == dst_reg")。屬於驗證器(scalar/連動暫存器追蹤)層級的問題,與上面 CVE-2026-45933(sync_linked_regs()同步時誤複製 id)、CVE-2026-93127(窄讀取正負號擴展與 id 共用衝突)、CVE-2026-53081(BPF_ADD_CONST誤用基底 id)同屬驗證器對純量追蹤處理出錯的同類問題家族。- CVE-2026-53094(CVSS 7.8,Ubuntu priority Low,2026-06-24 揭露):
BPF_F_XDP_DEV_BOUND_ONLY(裝置綁定 (dev-bound-only) XDP 程式,offload 給網卡硬體)在啟用常數混淆 (constant blinding)(bpf_jit_harden >= 2)做 JIT 編譯時,bpf_jit_blind_constants()會複製 (clone) 出一份新程式,原始程式隨後在bpf_jit_prog_release_other()中被釋放——這個函式會更新aux->prog指向存活下來的複製品,但漏了同步更新offload->prog,讓它繼續指向已被釋放的原始程式。之後 network namespace 被銷毀、觸發bpf_dev_bound_netdev_unregister()走訪這個懸空的offload->prog時,即形成 Use-After-Free。修補讓bpf_jit_prog_release_other()同步更新offload->prog。屬於本節分類中的 maps/helper(BPF offload/JIT 常數混淆)攻擊面。- CVE-2026-53096(CVSS 7.8,Ubuntu priority Low,2026-06-24 揭露):
dev_map_redirect_multi()(BPF_MAP_TYPE_DEVMAP_HASH的多播轉送路徑,由 softirq context 的xdp_do_generic_redirect_map()呼叫、跑在 RCU read-side critical section 內)走訪 hash bucket 時用了hlist_for_each_entry_safe(),而非 RCU-safe 的hlist_for_each_entry_rcu();但併發的寫入端(__dev_map_hash_update_elem()、dev_map_hash_delete_elem())是用hlist_add_head_rcu()/hlist_del_rcu()等 RCU 原語修改同一份 list。hlist_for_each_entry_safe()做的是一般的指標解參考,缺少與寫入端配對所需的 acquire barrier,可能讀到修改中、不一致的 list 結構,造成記憶體毀損或崩潰。屬於本節分類中的 maps/helper(devmap XDP 多播轉送)攻擊面,與上面 CVE-2026-53069、6.1 節 CVE-2026-64545 同屬 XDP 導向 (redirect) 路徑出錯的系列問題,只是這次錯在 RCU 走訪方式而非 NULL 檢查。- CVE-2026-53099(CVSS 5.5,Ubuntu priority Low,2026-06-24 揭露):較早的重構把編譯選項
CONFIG_CFI_CLANG改名為編譯器無關的CONFIG_CFI(commit23ef9d439769),但 BPF 子系統中用來保護btf_dtor_kfunc_t(BTF 解構子 kfunc 指標)的 kCFI(Control Flow Integrity,比對函式指標實際型別與呼叫端預期型別)相關程式碼,仍沿用舊的CONFIG_CFI_CLANG名稱做條件編譯——名稱對不上,導致這段原本該啟用的 CFI 保護程式碼實際上被編譯器整段排除,btf_dtor_kfunc_t的型別混淆 (type confusion) 攻擊面因此失去 kCFI 保護。屬於驗證器/核心介接層對 BPF callback 型別檢查失效的案例,與上面 CVE-2026-92486(BPF callback ABI 與 kCFI 型別不一致觸發 Panic)同屬 kCFI 相關的同類問題,但這次是保護機制本身因設定名稱過期而失效,而非型別本身不一致。- CVE-2026-53106(CVSS 5.5,2026-06-24 揭露):BPF local storage(
bpf_xxx_storage_delete()系列 helper)刪除 selem 時,可能透過kfree_rcu()、call_rcu()或call_rcu_tasks_trace()延遲釋放——但這些延遲釋放路徑在 NMI 或可重入 (reentrant) context 下呼叫可能造成死鎖。修補先針對「在 NMI 中呼叫」這個明確可辨識的情境,讓bpf_xxx_storage_delete()系列 helper 直接回傳錯誤而不嘗試刪除(commit message 也坦言:可重入情境下的死鎖尚未完全解決,是長期待解的問題)。屬於本節分類中的 maps/helper(local storage)攻擊面。- CVE-2026-53110(CVSS 7.8,Ubuntu priority Low,2026-06-24 揭露):s390x ABI 規定呼叫端必須把無號引數做零擴展 (zero-extend)、有號引數做正負號擴展 (sign-extend),被呼叫端(callee)對回傳值也要遵守同樣規則——但 s390 的 BPF JIT 編譯器只實作了正負號擴展,漏了零擴展這一半。這讓 BPF 程式的回傳值或 kfunc 引數在暫存器高位殘留未定義的舊資料,可能被後續程式碼誤讀成錯誤的數值,影響控制流或記憶體存取正確性。修補為 s390 JIT 補上零擴展邏輯。修補見核心 commit
202e42e4aa89("s390/bpf: Zero-extend bpf prog return values and kfunc arguments")。屬於 JIT 編譯器層級的 ABI 合規性出錯,與上面 CVE-2026-89581(x86 JIT REX prefix 誤用)、CVE-2026-93147(s390 JIT 誤用ly而非llgf)同屬架構特定的 JIT 編譯器錯誤,這次是 s390 上零擴展規則整個被遺漏,而非單一指令選錯。- CVE-2026-53111(CVSS 5.5,2026-06-24 揭露):
bpf_lwt_xmit_push_encap()這個 helper 需要讀取skb_dst(skb)->dev來計算封裝所需的 headroom,但透過bpf_prog_test_run_skb()(BPF_PROG_TEST_RUN)建構的測試用 skb,其_skb_refdst欄位可能根本沒有被初始化,導致skb_dst(skb)回傳的 dst entry 為 NULL,對->dev解參考時觸發 NULL pointer dereference、核心崩潰。屬於本節分類中的 maps/helper(BPF_PROG_TEST_RUN測試基礎設施)攻擊面,與上面 CVE-2026-53074(同樣是bpf_prog_test_run_skb測試路徑對輸入假設不足)同屬測試基礎設施對輸入前提檢查不足的同類問題。 上述 CVE-2026-53031/53032/53033/53034/53035/53036/53069/53074/53076/53078/53081/53083/53084/53085/53089/53090/53092/53094/53096/53099/53106/53110/53111 與下面的 CVE-2026-53095 合計 24 筆,同屬 2026-06-24 同一批公告的核心 BPF 修補,是本清單收錄數量最多的單一批次,建議一併留意。- CVE-2026-53215(CVSS 9.8 Critical,Ubuntu priority Critical,2026-06-25 揭露):Marvell
mvpp2網卡驅動的 RX error path 發生錯誤時,會把目前描述符的緩衝區歸還給硬體 BM(Buffer Manager)pool——但這個動作只有在驅動仍持有該緩衝區時才合法。若mvpp2_rx_refill()在緩衝區已交給 XDP(可能已被mvpp2_run_xdp()recycle、redirect 或送入XDP_TX)或已附掛到 skb 之後才失敗,驅動仍會把這個「已經不屬於自己」的緩衝區送回 BM pool,讓硬體 DMA 寫入一段已轉交給 XDP/網路堆疊、驅動已不再擁有的記憶體。修補改為在把目前緩衝區交給 XDP 或 skb 之前,先重新填補 BM pool;若重新填補失敗則直接丟棄封包並保留目前緩衝區歸還,避免緩衝池計數失衡。修補見核心 commit5e8e2a9624df("net: mvpp2: refill RX buffers before XDP or skb use")。屬於網卡驅動層與 XDP 資料路徑整合出錯的案例,與上面 CVE-2026-74317(ixgbe XPS/XDP 佇列)、CVE-2026-74476(veth XDP frag)同屬「驅動層對 XDP 緩衝區生命週期管理出錯」的類型;此則直到 2026-09-02 才隨 Ubuntu 核心安全公告 USN-8661-4 補上 CVSS 評分與優先度資訊,是這份清單目前 CVSS 分數最高(9.8 Critical)的案例之一。- CVE-2026-53184(CVSS 7.5,Ubuntu priority Medium,2026-06-25 揭露,與上面 CVE-2026-53215 同日公告):UDP socket 被接上帶
SK_SKBverdict 程式的 sockmap 後,核心在 UDP 收包路徑上會把skb->dev欄位挪作內部快取用途(dev_scratch,一段整數值而非真正的裝置指標);此時若 verdict 程式呼叫bpf_sk_lookup_tcp()/bpf_skc_lookup_tcp()等 socket 查找 helper,這些 helper 內部的bpf_skc_lookup()只檢查skb->dev是否非空,便直接把它當struct net_device *解參考,對著這段偽裝成指標的整數值做記憶體存取,在 softirq context 中觸發 general protection fault(非規範位址)。修補改為在執行 sockmap verdict 之前先清空skb->dev,讓 helper 改回退到sock_net(skb->sk)取得正確的 network namespace。修補見核心 commit1b585673a224("udp: clear skb->dev before running a sockmap verdict")。屬於 maps/helper(sockmap UDP 收包路徑)攻擊面,與下面的 CVE-2026-68386(UDP sockmap 參照計數洩漏)同屬 sockmap 對 UDP socket 特殊欄位處理不當的系列問題,只是這次錯在skb->dev欄位重用而非參照計數。- CVE-2026-64036(CVSS 7.8):
css_rstat_updated()這個 BPF kfunc 沒有驗證呼叫端傳入的 CPU 編號合法性,持有CAP_BPF+CAP_PERFMON即可觸發越界的 per-CPU 記憶體存取;已在 6.18.34 / 7.0.11 / 7.1 等版本修補。這正是 6.2 節「CAP_BPF拆分權限」立意雖好,但拆出的能力組合仍可能被濫用的實例。- CVE-2026-64192:在
CONFIG_BPF_LSM=y但 BPF LSM 未於開機時初始化的系統上,建立BPF_MAP_TYPE_INODE_STORAGEmap 會讓 inode 安全 blob 的偏移量停留在錯誤的預設值,導致記憶體別名進而破壞 RCU 回呼指標,清理階段觸發 Kernel Panic;修補後改為在建立當下直接拒絕該 map 類型(影響 5.10 至 7.1.4,修補見 7.2-rc2 起)。- CVE-2026-63809(CVSS 7.8,Ubuntu priority High,2026-07-19 揭露):這筆錯誤不在驗證器或 sockmap,而在 cgroup sysctl 過濾(
BPF_CGROUP_SYSCTL)hook 的宿主端記憶體管理。proc_sys_call_handler()(一般/proc/sys寫入路徑)以kvzalloc()配置暫存的 sysctl 寫入緩衝區——這個配置器在請求容量夠大時會退回使用vmalloc()——再把這段緩衝區傳給__cgroup_bpf_run_filter_sysctl(),讓附掛的 BPF 程式檢視、甚至替換其內容。當 BPF 程式選擇替換緩衝區內容時,舊緩衝區會被釋放,但釋放時呼叫的是kfree()而非對應kvzalloc()語意的kvfree();一旦當初的配置確實落到vmalloc()分支,kfree()對這種記憶體的處理方式是未定義的,會直接毀損核心記憶體(fault injection 重現得到kfree()內的 page fault)。修補把該處的kfree()換成kvfree()。修補見核心 commit4c21b5927d43("bpf: use kvfree() for replaced sysctl write buffer")。屬於本節分類中的 maps/helper 攻擊面,與 2026-06-19 揭露的 CVE-2026-52910(cBPF/eBPF reuseport 程式釋放路徑生命週期不一致)同屬「BPF hook 前後,兩段程式碼對同一塊記憶體的管理慣例(配置器種類或釋放時機)沒有對齊」的類型,只是這次錯在配置器種類(該用kvfree()卻用了kfree()),而非 RCU 釋放時機。- CVE-2026-64545(CVSS 7.5,2026-07-27 揭露):XDP 導向函式
xdp_master_redirect()(net/core/filter.c)在接收裝置沒有 upper-master adjacency 時缺少 NULL 檢查,當 bond slave 裝置在釋放過程中收到XDP_TX流量,就可能觸發 NULL pointer dereference 造成 Kernel Panic(阻斷服務);與 2.6 節、3.2 節討論的 XDP 高速封包處理路徑直接相關。修補見核心 commite82d8cc4321c。- CVE-2026-63864(CVSS 8.4,2026-07-20 揭露):驗證器的
visit_tailcall_insn()忽略了自己的錯誤回傳值,導致 tail call 指令的堆疊存活性(stack liveness)分析可能出錯,讓驗證器誤判為安全而放行本應拒絕的程式;持有CAP_BPF(或系統允許非特權 BPF)即可觸發。修補見核心 commit6bd96e40f31d與945816e63c86。與上面 CVE-2026-31413(見 2.4 節)同屬「驗證器邏輯本身出錯」的類型,只是這次錯在 tail call 而非純量運算。- CVE-2026-64354(CVSS 7.8 High,Ubuntu priority Medium,2026-07-25 揭露,2026-09-25 系統性複查時發現先前遺漏、補上):
BPF_BTF_LOAD載入使用者提供的 BTF 資料時,btf_parse_struct_metas()用btf_repeat_fields()以u32運算計算展開後的欄位數量——構造過的惡意 BTF 可讓這個計算整數溢位繞回一個很小的值,使原本該擋下「展開欄位數超出暫存陣列容量」的檢查誤判通過,後續memcpy()便對一段核心堆疊上、大小固定為BTF_FIELDS_MAX的暫存陣列寫入超出邊界的資料,造成 stack buffer overflow。修補在複製欄位前加上溢位檢查,拒絕不合理的欄位數量。修補見核心 commitc5ff816d5f13。屬於本節分類中的 maps/helper(BTF 載入)攻擊面,與上面 CVE-2026-64548(sockmapcopy + lenu32 溢位)、CVE-2026-53076(per-CPU 對齊假設導致越界)同屬「邊界檢查用的整數運算本身可被溢位繞過」的同類問題。- CVE-2026-64507(CVSS 未公布,Ubuntu priority Medium;Amazon Linux 另給出 5.6,2026-07-25 揭露,2026-10-11 複查時發現先前遺漏、補上):x86 架構的加固措施——當 BPF JIT 配置的可執行記憶體頁被釋放、重新配置給另一支程式使用時,發出一次 IBPB(Indirect Branch Predictor Barrier)flush,清空分支預測器裡殘留的舊項目;若 BPF dispatcher 本身已採用 retpoline 定序,則略過此次 flush。此為因應下方「Branch Target Reuse(BTR)」側通道攻擊研究而新增的緩解措施,由
CONFIG_BPF_JIT控制。修補見核心 commita3af84b0fa00("x86/bugs: Enable IBPB flush on BPF JIT allocation")。與下一筆 CVE-2026-64508 同屬一套緩解措施,但這次是 x86 架構專屬的 flush 實作。屬於 2.5 節 JIT 編譯器攻擊面的新分類——不是程式碼生成邏輯出錯(如上面 arm64 的 CVE-2026-53036、下面 x86 的 CVE-2026-89581),而是 CPU 推測執行側通道:攻擊者可利用 CPU 在 JIT 記憶體頁重複使用後仍殘留的分支預測器狀態,外洩先前佔用同一塊記憶體的程式資料。- CVE-2026-64508(CVSS 約 7.0 High(Oracle/TuxCare 評分,NVD 尚未定案),Ubuntu priority Medium,2026-07-25 揭露,2026-10-11 複查時發現先前遺漏、補上):與上一筆同屬 BTR 緩解套件,這是架構無關的通用加固支援:新增
bpf_arch_pred_flushstatic call,讓各架構能在 BPF JIT 記憶體的「封包 (pack)」被回收重用前插入分支預測器清空動作;預設為 no-op(不插入任何指令),須搭配各架構自己的實作(如上一筆 CVE-2026-64507 的 x86 IBPB flush)才會真正生效。已知限制:大於單一 pack 的配置不在此次 flush 的覆蓋範圍內(程式假設非特權 cBPF 程式的配置大小遠小於 pack 大小,違反此假設時核心會發出警告)。修補主線標題為 "bpf: Support for hardening against JIT spraying"。上面這兩筆是因應 2026-09-29 由 VUSec(阿姆斯特丹自由大學)與 Scuola Superiore Sant'Anna 研究團隊公開揭露的「Branch Target Reuse(BTR)」 Spectre-v2 新變種攻擊而新增的核心緩解措施:研究者示範用非特權 classic BPF(cBPF)程式,在 Intel CPU(Raptor Cove、Lion Cove 微架構)上於約 3~5 分鐘內還原出另一個行程(
su)記憶體中的 root 密碼雜湊,手法是利用 CPU 在 JIT 程式碼記憶體頁被釋放、重新配置給另一段程式碼後,仍殘留先前程式碼留下的分支預測項目(stale branch-predictor entries)。研究同時證實 Intel、AMD、Arm 處理器都存在這種行為,也在 Firefox SpiderMonkey(透過 WebAssembly,未做出完整瀏覽器層級的 exploit)與 Oracle GraalVM 上示範了類似手法。Intel 官方立場是這不構成需要 Intel 專屬新緩解措施的硬體漏洞(Intel 安全公告,2026-10-01);Linux 核心選擇的緩解方式就是上述兩筆 CVE 的 IBPB flush 機制。與本節其他案例性質不同——CVE-2026-64507/64508 不是 eBPF 子系統自身的程式邏輯錯誤,而是利用「BPF JIT 是少數非特權使用者就能觸發、且會動態配置/釋放可執行記憶體的核心機制」這個特性,去打 CPU 微架構層級的側通道,再次提醒 BPF JIT 本身值得被當成獨立的攻擊面類別關注。研究論文與技術細節見 VUSec 專案頁:Branch Target Reuse 與報導 Phoronix。 - CVE-2026-53095(CVSS 5.5,2026-06-24 揭露):uprobe類型的程式被允許修改struct pt_regs,但uprobe底層實際的程式類型其實與kprobe共用(都是BPF_PROG_TYPE_KPROBE),導致freplace程式可以附掛到監控核心函式的kprobe程式上,間接繼承本該只屬於uprobe的pt_regs寫入權限,在核心函式執行期間竄改其參數。修補方式是在freplace附掛時比對雙方的kprobe_write_ctx是否一致,不一致就拒絕附掛(核心 commit611fe4b79af7,"bpf: Fix abuse of kprobe_write_ctx via freplace")。屬於驗證器/附掛檢查邏輯出錯的另一個案例,與 CVE-2026-31413、CVE-2026-63864 同屬一類,只是這次錯在「附掛檢查」而非純量分析或堆疊分析。 - CVE-2026-68386(CVSS 未公布,Ubuntu priority Medium,2026-08-10 揭露):UDP socket 一旦被(自動)綁定,核心就會為它設上SOCK_RCU_FREE,使其參照計數語意從「一般 refcount、sk_is_refcounted()為真」切換成「交由 RCU 管理、sk_is_refcounted()為假」;但先前一次改動(commit0c48eefae712,"sock_map: Lift socket state restriction for datagram sockets")讓 sockmap 可以接受尚未綁定的 UDP socket。BPF 程式對這個仍是「一般 refcount」狀態的 socket 做 sockmap 查詢時會取得一次參照;若該 socket 之後才完成綁定、切換成 RCU 管理模式,BPF 程式後續呼叫bpf_sk_release()釋放時,釋放路徑是依 socket當下(已綁定)的參照計數模式判斷是否要遞減,於是原本在「未綁定」階段取得的那次參照就再也沒被遞減,形成永久的參照計數洩漏(KASAN unreferenced-object 可重現)。修補改為在 sockmap update 當下直接拒絕未雜湊(unhashed,即尚未綁定)的 UDP socket,BPF 程式因此無法在一個「參照計數語意可能中途改變」的 socket 上取得查詢用的參照。修補見核心 commit66efd3368ae1("bpf, sockmap: Reject unhashed UDP sockets on sockmap update")。屬於本節分類中的 maps/helper(sockmap socket 參照計數生命週期)攻擊面,與 CVE-2025-39913、CVE-2026-52910 同屬「BPF 相關 socket 物件的參照計數或釋放語意,在不同執行狀態間切換時未保持一致」的類型,但方向相反:39913/52910 錯在物件被提前釋放形成 UAF,68386 則是參照永遠沒被釋放形成資源洩漏;也與上面 CVE-2026-53033/53034(AF_UNIX peer 生命週期問題)同屬 sockmap 對不同協定家族(AF_UNIX vs UDP)socket 狀態假設與實際生命週期不一致的系列問題。 - CVE-2026-68284(CVSS 7.8 High(v3.1)/7.1(v4.0),Ubuntu priority High,2026-08-10 揭露,與上面 CVE-2026-68386 同日公告):tcp_bpf_sendmsg()在等待 socket 傳送緩衝區(呼叫sk_stream_wait_memory())期間會釋放又重新取得 socket 鎖,但函式把當下的msg_tx(指向psock->cork,即正在 corking 累積中的訊息)存成區域變數繼續沿用;若另一執行緒在這段鎖釋放的空窗期,也對同一個 socket 送出資料並釋放了同一個 cork 訊息,原本那個msg_tx就變成懸空指標,後續程式碼卻誤把它當成僅供本次呼叫使用的區域訊息 (local message) 而再釋放一次,形成 double-free 型的 Use-After-Free(KASAN 可重現)。修補見核心 commit2d66a033864e("bpf, sockmap: Fix cork use-after-free in tcp_bpf_sendmsg()")。屬於 maps/helper 攻擊面,與上面已列的 CVE-2026-63830、CVE-2026-64548、CVE-2025-39913 同屬 sockmap cork/生命週期管理出錯的系列問題,只是這次錯在鎖釋放期間 cork 指標未重新確認,而非 scatterlist 搬移或整數溢位。 - CVE-2026-74364(CVSS 7.1,2026-08-15 揭露):BPF 的「獨佔 (exclusive) map」機制原本保證某些 map 只能被單一程式存取,但這類 map 可以被當成 inner map 塞進一個非獨佔的 map-in-map 外層 map,執行期經由外層 map 存取時,原本的相容性/獨佔性檢查完全沒被檢查到,形同繞過。修補見核心 commit9a3c3c49c333。屬於本節分類中的 maps/helper 攻擊面,與下一筆 CVE-2026-74360 同屬「map 獨佔保證被繞過」的同類問題,只是繞過的入口不同(map-in-map vs. iterator)。 - CVE-2026-74360(CVSS 未公布,Ubuntu priority Medium,2026-08-15 揭露):bpf_map_elemiterator 在bpf_iter_attach_map()「附掛當下」就直接綁定目標 map,而非透過程式本身去參照,導致上一筆提到的獨佔性檢查完全沒有機會被執行——且此 iterator 還把 map value 以可寫緩衝區的形式暴露給使用者。修補見核心 commit3c56ee343f94。與上一筆同屬 maps/helper 的獨佔保證繞過類型。 - CVE-2026-74371(CVSS 7.8,2026-08-15 揭露):BPF_PROG_QUERY(含 cgroup BPF query)在處理較舊、較小的bpf_attr結構(相容舊版 userspace)時,核心仍無條件把query.revision寫回使用者提供的緩衝區,若呼叫端傳入的緩衝區不夠大,就會造成越界寫入。修補見核心 commit21c4b99b27f3。屬於本節分類中的 maps/helper(BPF syscall query 介面)攻擊面。 - CVE-2026-74363(CVSS 7.8,2026-08-15 揭露):bpffs(BPF 檔案系統)的 use-after-free——併發的unlinkat()釋放掉一個 inode 的最後一個參照後,destroy_inode()立即釋放該 inode,但另一個 task 可能仍在 RCU read mode 下走訪同一條路徑,形成 UAF(此問題源自先前為了避免 RCU context 警告所做的修改)。修補把清理邏輯拆成兩段:bpf_destroy_inode()保留可阻塞的操作,新增bpf_free_inode()專門做 RCU-safe 的延遲釋放。修補見核心 commitb93c55b4932d。是這份清單中少數涉及 bpffs 檔案系統層(而非驗證器/maps/helper 三分類本身)的案例。 - CVE-2026-74400(CVSS 未公布,Ubuntu priority Medium,2026-08-15 揭露):bpf_set_dentry_xattr()/bpf_remove_dentry_xattr()這兩個 helper 在收到 negative dentry(例如來自security_inode_create()的呼叫路徑)時,d_inode(dentry)會回傳NULL,但程式碼沒檢查就直接inode_lock(inode),造成 NULL pointer dereference;相關權限檢查函式中原本用WARN_ON處理同一情況,在啟用panic_on_warn的系統上等於也能被觸發成阻斷服務。修補改為對 NULL inode 直接回傳-EINVAL。修補見核心 commit07410646f6ff。 - CVE-2026-74258(CVSS 7.8 High,Ubuntu priority Medium,2026-08-15 揭露):uprobe_multi(BPF_LINK_TYPE_UPROBE_MULTI,一次附掛大量 uprobe 的機制)的建立路徑,負責把使用者空間傳入的uoffsets/uref_ctr_offsets/ucookies陣列複製進核心時,一樣是用__get_user()逐一讀取陣列元素,卻沒有在讀取前對整段使用者指標陣列先呼叫access_ok()驗證其可存取性,形成對未經檢查的使用者空間指標直接解參考的漏洞。修補見核心 commit4d87a251d45b("bpf: Guard __get_user access with access_ok for uprobe_multi data")。與下面 6.3 節的 CVE-2026-80865(kprobe_multi版本、晚約三週於 2026-09-04 才揭露)幾乎是同一類漏洞的姊妹案例——兩者都是「附掛時 (attach-time) 系統呼叫參數缺少access_ok()檢查」,只差在uprobe_multi與kprobe_multi各自的建立路徑。 - CVE-2026-74382(CVSS 未公布,Ubuntu priority Medium,2026-08-15 揭露):這筆不在驗證器/maps/helper 三分類內,而是 TC(traffic control)子系統的cls_bpf——cls_bpf_offload_cmd()在 offload rollback 失敗時,會用相同參數遞迴呼叫自己;若 rollback 本身持續失敗(不限 netdevsim 測試驅動,任何tc_setup_cb_replace()連續失敗兩次的網卡驅動都可能觸發),就會無窮遞迴耗盡核心堆疊,造成 stack overflow / 阻斷服務。修補改為只允許一次 rollback,失敗就直接回傳原始錯誤,不再遞迴。修補見核心 commit27db54b90bcc。提醒:這說明 eBPF 的攻擊面不只驗證器/maps/helper 三處,tc(cls_bpf)這類與 eBPF 整合的核心子系統本身的控制流程,也可能是問題來源。 - CVE-2026-72111(CVSS 8.4 High(v3.1,Scope Changed)/8.8(v4.0),Ubuntu priority High,2026-08-15 揭露,同批公告):驗證器check_mem_access()在讀取 LSM hook 回傳值這類 context 欄位時,會呼叫__mark_reg_s32_range()依 hook 的合法範圍收斂暫存器邊界——但該函式是把新範圍與暫存器既有邊界做交集(max_t()/min_t()),而非直接取代。若暫存器帶有前一條指令殘留的邊界(例如剛被BPF_MOV64_IMM設過值),交集結果會比實際情況更窄,造成驗證器推導與執行期不一致,可被利用繞過 BPF 記憶體安全檢查。修補讓此路徑改用既有else分支已在用的mark_reg_unknown()直接重置。屬於驗證器純量追蹤出錯,與 2.4 節的 CVE-2026-31413、上面的 CVE-2026-63864 同屬一類。修補見核心 commit5e0b273e0a62。 - CVE-2026-68462(CVSS 7.8,Ubuntu priority Low,2026-08-15 揭露):較早一次改動把指標的常數偏移量從reg->off改記錄到reg->var_off,但 buffer access 的邊界檢查函式(涉及可寫入的 raw tracepoint 存取路徑)仍只檢查reg->off(instruction offset),導致驗證器可能誤放行帶有負值常數偏移量的 buffer 指標存取,造成越界記憶體存取;觸發需要CAP_BPF與CAP_PERFMON,故 Ubuntu 將其標為 Low priority。修補見核心 commitfd4cfa8c8f9a(問題最初由 commit022ac0750883引入)。屬於驗證器指標偏移追蹤出錯的案例,與上面的 CVE-2026-72111、下面的 CVE-2026-74338 同屬「驗證器該擋卻沒擋」的類型。 - CVE-2026-72423(CVSS 8.8 High,2026-08-15 揭露,同批公告):BPF conntrack 的__bpf_nf_ct_lookup()/__bpf_nf_ct_alloc_entry()這類 kfunc 收下呼叫端提供的opts結構與其大小opts__sz,驗證器只檢查opts__sz範圍內的記憶體是否合法——但底層 wrapper 函式在查詢或配置失敗時,會無條件寫入opts->error欄位,若呼叫端傳入的opts__sz小到不含error欄位偏移量,這次寫入就落在驗證器沒檢查過的範圍外,造成越界寫入。修補見核心 commit6f6183a39533。屬於本節分類中的 maps/helper(conntrack kfunc)攻擊面,與下面 2026-08-22 批次的 CVE-2026-74715 同屬 conntrack kfunc 對opts結構處理不夠嚴謹的同類問題,只是這次錯在越界寫入而非參照計數失衡。 - CVE-2026-74338(CVSS 7.8 High,2026-08-15 揭露):BPF_LSM_CGROUP這類附掛在 cgroup shim 上的 LSM 程式,執行環境是rcu_read_lock_dont_migrate()——這個環境不允許阻塞,因此帶有BPF_F_SLEEPABLE旗標的可睡眠 (sleepable) 程式理論上不該被允許附掛到這個 hook,但驗證器先前並未在載入時擋下這個組合,直到程式執行期呼叫可能睡眠的操作(例如存取 extended attribute)才會觸發核心崩潰。修補讓驗證器在載入階段就直接拒絕這個組合。修補見核心 commit5b038319be44。屬於驗證器附掛檢查邏輯出錯的案例,與 2.4 節 CVE-2026-31413、上面 CVE-2026-72111、CVE-2026-63864 同屬「驗證器該擋卻沒擋」的類型。 - CVE-2026-72400(CVSS 7.8 High,Ubuntu priority Medium,2026-08-15 揭露):IPv6 Segment Routing Header 的seg6_validate_srh()在檢查長度是否足以涵蓋struct ipv6_sr_hdr之前,就先讀取srh->type、srh->hdrlen等固定欄位;而bpf_lwt_push_encap()、bpf_push_seg6_encap()(SEG6-local 的END_B6/END_B6_ENCAPaction)會把 BPF 程式提供的指標與長度一路傳進來,未設最小長度下限——只給 2 bytes 的 SEG6 header 就會讓驗證函式讀到 offset 2 處的欄位,造成越界讀取。修補改為先驗證長度、再讀欄位。屬於本節分類中的 maps/helper(BPF helper 呼叫路徑)攻擊面。修補見核心 commita75d99f46bf2。 - CVE-2026-72402(CVSS 5.5 Medium,Ubuntu priority Medium,2026-08-15 揭露,同批公告,2026-09-22 審查後補充):print_bpf_insn()在驗證器記錄檔(verifier log)中列印ldimm64指令時,會遮蔽 (mask) 帶有指標的偽來源 (pseudo source) 立即值,避免核心指標位址外洩到記錄檔——但原本的遮蔽邏輯只涵蓋BPF_PSEUDO_MAP_FD、BPF_PSEUDO_MAP_VALUE這兩種偽來源型別,漏掉了同樣會在列印前被解析成核心指標值的BPF_PSEUDO_MAP_IDX、BPF_PSEUDO_MAP_IDX_VALUE、BPF_PSEUDO_BTF_ID。持有可讀取驗證器記錄檔權限(例如透過BPF_PROG_LOAD的log_buf或核心記錄)的本機使用者,可藉此取得原本應被遮蔽的核心指標位址,作為繞過 KASLR 等後續攻擊的線索(CWE-117,Improper Logging)。修補把這三種偽來源型別一併納入遮蔽邏輯的判斷式,讓記錄檔統一印出0x0。修補見核心 commit72a85e9464a5("bpf: Mask pseudo pointer values in verifier logs when pointer leak is not allowed")。屬於驗證器記錄檔資訊外洩的案例,與上面 6.1 節 CVE-2026-52910、CVE-2026-92520(未清零的核心堆疊內容外洩給使用者空間)同屬「核心內部資訊(指標位址、未初始化記憶體)不當外洩」的同類問題,但這次外洩管道是驗證器 debug 記錄檔,而非 map value 或 socket 選核結果。 - CVE-2026-74256(CVSS 8.4 High,Ubuntu priority Medium,2026-08-15 揭露):sockmap 的bpf_msg_pop_data()邊界檢查start + len以u32相加後才轉型為u64判斷,相加本身已在 32 位元下溢位,讓原本應被拒絕的越界start/len組合通過檢查;後續 pop 迴圈因此跑出 scatterlist 尾端,sk_msg_shift_left()對空 slot 呼叫put_page(),造成 GPF/記憶體毀損。修補把加法運算的其中一個運算元先轉型為u64再相加,避免 32 位元溢位。屬於 maps/helper 攻擊面,與 6.1 節已列的 CVE-2026-63830、CVE-2026-64548 同屬 sockmap 系列問題,只是這次錯在整數寬度而非 scatterlist 搬移或 cork 生命週期。修補見核心 commita48802fb2cd2。 - CVE-2026-74257(CVSS 7.8 High,Ubuntu priority Medium,2026-08-15 揭露):sk_msg_recvmsg()從psock->ingress_msg取出sk_msg時是在鎖保護下窺視 (peek),但後續處理卻是無鎖的,需要呼叫端自行序列化(TCP 路徑用lock_sock()、AF_UNIX 用iolock)。udp_bpf_recvmsg()先前的一個修改移除了它原本持有的lock_sock(),導致併發存取形成 Use-After-Free(syzbot 發現)。修補是把該鎖加回來。屬於 maps/helper 攻擊面,與上面 CVE-2026-74256 同屬 2026-08-15 這批公告中的 sockmap 問題,只是這次錯在缺乏鎖保護而非邊界計算。修補見核心 commitc010995b29c8。 - CVE-2026-74317(CVSS 7.8 High(v3.1)/7.1(v4.0),Ubuntu priority High,2026-08-15 揭露):Intelixgbe驅動(涵蓋 E610 晶片)對 XDP Tx 佇列誤呼叫了netif_set_xps_queue()——但 XDP 專用佇列並未對 netdev 曝露,不該被設定 XPS。在 CPU 數 ≥ 64 的機器上,MSI-X 限制讓最大佇列對數被限制在 63,但 XDP 設定路徑仍會產生 64 條 XDP 佇列,對最後一條佇列呼叫 XPS 設定時觸發 WARNING 與 KASAN 回報的記憶體毀損。此問題源頭可追溯到 2017 年 ixgbe 最初加入XDP_TX支援的實作(33fdc82f0883),直到現代高核心數機器搭配 E610 晶片才浮現。屬於網卡驅動層與 XDP 佇列設定整合出錯的案例,觸發時機是載入 XDP 程式而非執行期封包處理。修補見核心 commit7bd4355272de。 - CVE-2026-74335(CVSS 未公布,Ubuntu priority Medium,2026-08-15 揭露):bpf_task_from_vpid()呼叫鏈find_task_by_vpid()→find_task_by_pid_ns(vpid, task_active_pid_ns(current))→find_pid_ns()。cgroup_skb類程式在 softirq 中執行,可能中斷正在do_exit()途中的任務;一旦該任務走過exit_notify()→release_task()→__unhash_process(),其thread_pid會被清空,導致task_active_pid_ns(current)回傳NULL,find_pid_ns()對NULL->idr解參考,造成 NULL pointer dereference。修補是在current沒有 pid namespace 時直接提前返回。屬於本節分類中的 maps/helper(kfunc)攻擊面。修補見核心 commit50dff0061552。 - CVE-2026-74476(CVSS 9.1 Critical(v3.1)/6.8(v4.0),Ubuntu priority Medium,2026-08-15 揭露):veth驅動收到data_len非零但nr_frags為零的 frag_list skb 時,veth_convert_skb_to_xdp_buff()沒有先把它轉換成一般分片 (frags) 形式,卻仍用skb_is_nonlinear()判斷是否要對外宣告XDP_FLAGS_HAS_FRAGS/xdp_frags_size——等於告訴 XDP 程式「資料在frags[]裡」,但實際frags[]是空的。AF_XDP 的 copy 模式相信這份錯誤中介資訊,在__xsk_rcv()內memcpy()時就會越界崩潰。修補改為先用skb_pp_cow_data()把非線性 skb 攤平再轉換。屬於網路驅動(veth)/ XDP 資料路徑整合出錯,與 2.6 節討論的 XDP 高速封包處理路徑直接相關。修補見核心 commitd0d641596304。 - CVE-2026-74558(CVSS 未公布,Ubuntu priority Medium,2026-08-15 揭露):AF_XDP 零複製 (zero-copy) 批次解析在遇到無效描述符時中止解析,若前面已有 continuation 描述符,Tx consumer 會直接跳過這些片段,既沒送進驅動、也沒歸還到 completion ring(封包片段數超過xdp_zc_max_segs時同樣有此問題)。修補改為按「封包」為單位解析批次,把有效封包的描述符送進驅動、其餘僅需歸還的描述符送回 completion queue。與下面 CVE-2026-74559、CVE-2026-74560 同屬 2026-08-15 同批修補的 AF_XDP 多緩衝 (multi-buffer) 路徑緩衝區生命週期問題。修補見核心 commit72f2b4516faf。 - CVE-2026-74559(CVSS 未公布,Ubuntu priority Medium,2026-08-15 揭露):一般 (generic) xmit 路徑的 AF_XDP 多緩衝邏輯在描述符數超過MAX_SKB_FRAGS,或片段中途出現無效描述符時,xsk_build_skb()沒有把後續已配置但未使用的 continuation 描述符歸還,造成緩衝區遺失。修補新增xdp_sock::drain_cont旗標,確保後續描述符被歸還到 completion queue。與上面 CVE-2026-74558 同屬 AF_XDP 多緩衝路徑問題。修補見核心 commitbd44a6dcd424。 - CVE-2026-74560(CVSS 未公布,Ubuntu priority Medium,2026-08-15 揭露):xsk_build_skb()的-EOVERFLOW路徑、__xsk_generic_xmit()迴圈後清理、xsk_release()三處在丟棄部分完成的多緩衝 skb 時呼叫xsk_drop_skb(),其內部經xsk_consume_skb()透過xsk_cq_cancel_locked()取消 completion queue 的預留——但此時對應的 Tx 描述符其實已被消耗、completion queue 位置也已預留,取消動作讓緩衝區位址永遠送不回 completion queue,使用者空間因此永久遺失這些緩衝區。修補改走既有的xsk_destruct_skb解構子路徑歸還。與上面 CVE-2026-74558、CVE-2026-74559 同屬同一天修補的 AF_XDP 多緩衝路徑問題,建議一併留意升級。修補見核心 commita3c8382ebce4。 - CVE-2026-74612(CVSS 10.0 Critical,2026-08-22 揭露,本節目前最高分的一筆):veth驅動處理 XDP 對非線性 skb 做 fragment 調整時,只更新了skb->data_len,卻沒有同步更新skb->len,造成skb_headlen()回傳的「線性區大小」比實際線性區還大。後續(例如 UDP 收包路徑)把資料複製到使用者空間時,就會把skb_shared_info結構與其後的核心指標、記憶體中繼資料,當成一般封包資料一併外洩給使用者空間——實測顯示每次外洩約 1024 bytes 的核心資訊。修補同步skb->len/skb->data_len,並把__skb_put()換成正確處理非線性 skb 的skb_set_tail_pointer()。屬於網路驅動(veth)/XDP 資料路徑整合出錯的案例,與 2.6 節、3.2 節的 XDP 高速封包處理路徑直接相關,也與下面 CVE-2026-74665 同屬同一類 skb 長度欄位失同步的問題。修補見核心 commitcb6379feaaff。 - CVE-2026-74665(CVSS 9.1 Critical,2026-08-22 揭露):與上面 CVE-2026-74612 同一類問題,只是發生在通用 (generic) XDP 路徑而非 veth 驅動——XDP 程式調整非線性 skb 的分片後,同樣只更新skb->data_len未同步skb->len,造成線性區大小失真,後續讀取觸發越界讀取,外洩skb_shared_info與核心指標等內部結構給使用者空間。修補見核心 commit33f2b2eb33d6。屬於 maps/helper(XDP 資料路徑)攻擊面。 - CVE-2026-74616(CVSS 9.8 Critical,2026-08-22 揭露):xdpf_clone()在把一個 XDP frame 廣播複製 (broadcast clone) 到同一個 page 上的多份副本時,只檢查來源 frame 本身的大小是否合法,沒有確認複製後的每一份副本是否仍有足夠的 tailroom 容納skb_shared_info結構——當來源 frame 背後的配置空間較大時,即使通過既有檢查,複製出的副本仍可能一路延伸進本該留給skb_shared_info的區域。轉回 skb 時build_skb_around()因此把 metadata 結構直接蓋在還在使用中的封包資料上,可能竄改 XDP 的 return metadata。修補見核心 commite48e8edbef2e。屬於本節分類中的 maps/helper(XDP 廣播轉送路徑)攻擊面,與 3.2 節已列的 CVE-2026-23359 同屬 XDP 廣播轉送(BPF_MAP_TYPE_DEVMAP)路徑出錯的案例。 - CVE-2026-74710(CVSS 7.8 High,2026-08-22 揭露):AF_XDP 允許使用者空間附上一段 TX metadata,但核心原本只檢查 metadata 存在、沒有規定最小長度——只要開啟了 flag,任何請求的 metadata 欄位組合至少都需要 8 bytes,若使用者空間提供的緩衝區小於這個組合所需的最小長度,核心就會讀到註冊記憶體區域之外。修補把最小長度提高到 16 bytes。修補見核心 commit1bb30b181d9f。屬於 maps/helper(AF_XDP)攻擊面,與上面 CVE-2026-74558/74559/74560 同屬 AF_XDP 子系統,但這次錯在 TX metadata 長度下限而非緩衝區生命週期。 - CVE-2026-74589(CVSS 8.4 High,2026-08-22 揭露):sockmap 的tcp_bpf_send_verdict()在處理 redirect 判決時,把目標 socket 指標(sk_redir)複製出來使用,但複製當下沒有先取得參照就釋放了來源 socket 的鎖——若另一執行緒此時也在處理同一個 redirect 並釋放了它手上的參照,原本那個未受保護的指標就可能指向已釋放的記憶體,形成 Use-After-Free。修補改為在來源鎖仍保護 redirect 指標時,先取一個暫時參照,操作完成後才釋放。修補見核心 commita76624733730。屬於 maps/helper 攻擊面,與上面已列的 CVE-2026-63830、CVE-2026-64548、CVE-2025-39913 同屬 sockmap 系列生命週期管理出錯的案例。 - CVE-2026-74714(CVSS 7.8 High,2026-08-22 揭露):bpf_iter_tcp_established_batch()走訪 TCP 連線時,對TCP_NEW_SYN_RECV狀態的 request socket 直接呼叫sock_hold()累加參照計數——但這類 socket 在被公開到 ehash chain、釋放 bucket lock 之後,要再過一段時間才會把rsk_refcnt設成正式值(3),iterator 若剛好在這段空窗期讀到它,等於對一個參照計數還沒穩定(甚至可能已歸零)的物件加參照,可能導致該物件被提前釋放而 iterator 仍持有懸空指標,形成 Use-After-Free。修補見核心 commite5fd3f514e27。屬於 maps/helper(iterator)攻擊面,與上面 CVE-2026-53085(task_vmaiterator UAF)同屬 iterator 類型的生命週期管理出錯。 - CVE-2026-74715(CVSS 7.8 High,2026-08-22 揭露):BPF conntrack kfunc__bpf_nf_ct_lookup()/__bpf_nf_ct_alloc_entry()在取得與歸還 network namespace 參照時,分別各自讀了一次呼叫端傳入的opts->netns_id——若這個opts指向的是可被併發修改的共享 map value,兩次讀到的值可能不一致,導致「取用」與「歸還」對應到不同的 netns,參照計數因此失衡,可能造成使用中的 netns 被提前銷毀,引發核心崩潰。修補改用READ_ONCE()在進入函式時就把所有輸入欄位快照下來,確保 get/put 用的是同一份數值。修補見核心 commitfdeba03fea78。屬於 maps/helper(conntrack kfunc)攻擊面,與上面 2026-08-15 批次的 CVE-2026-72423 同屬「conntrack kfunc 對opts結構處理不夠嚴謹」的同類問題,只是這次錯在參照計數失衡而非越界寫入。 - CVE-2026-74720(CVSS 7.8 High,2026-08-22 揭露):驗證器處理scalar += pointer(純量與指標相加,結果仍是指標)這類運算時,adjust_ptr_min_max_vals()只挑著複製部分暫存器狀態欄位到目的暫存器,而非完整複製指標狀態——這種選擇性複製遺漏了棧指標所需的 frame number、以及以 ID 追蹤的 parent 一致性等欄位,導致驗證器對指標來源 (provenance) 的追蹤出現落差,可能被利用構造出驗證器誤判為安全的越界存取。修補改用呼叫端既有的暫時 offset 暫存器,完整保留指標狀態而非選擇性複製欄位。修補見核心 commita4c6f804b44c。屬於驗證器指標追蹤出錯的案例,與 CVE-2026-43070(暫存器id未同步重置)同屬指標/純量狀態追蹤不完整的類型。 - CVE-2026-74700(CVSS 7.8 High,2026-08-22 揭露):這筆嚴格來說不是 eBPF 專屬漏洞,而是 TC(traffic control)子系統cls_api的通用競態問題:當兩個執行緒在同一條 chain 上同時建立不同類型的分類器(例如u32與flower)時,tcf_proto_destroy()沒有全程持有rtnl_lock,可能讓一個分類器提前釋放另一個分類器仍在使用的資源,形成 Use-After-Free(KASAN 回報slab-use-after-free in u32_init)。修補改為在銷毀路徑上補齊rtnl_lock保護。收錄這筆的原因與上面 CVE-2026-74382 相同:cls_bpf是受影響的分類器類型之一(核心目前有 8 種分類器在銷毀路徑上未遵守rtnl_held),但此次觸發場景是u32/flower競態,並非cls_bpf專屬——再次提醒 eBPF 的攻擊面延伸至與它共用框架的核心子系統控制流程。修補見核心 commita347304b2ca1。 - CVE-2026-74590(CVSS 7.8 High,2026-08-22 揭露):BPF helperbpf_get_fsverity_digest()(透過 dynptr 讀取檔案 fsverity 摘要值)原本假設呼叫端傳入的arg->digest_size在函式執行期間不會改變——但若這個大小值實際指向可被併發修改的共享記憶體(例如 map value),中途變動的長度會讓函式依錯誤大小存取雜湊演算法回傳的緩衝區,可能造成記憶體毀損。修補改用雜湊演算法本身固定的hash_alg->digest_size取代呼叫端可控的arg->digest_size,並把相關變數從u32加寬為u64以符合__bpf_dynptr_size()的回傳型別。修補見核心 commit3e8ec7c03872("fsverity: Fix bpf_get_fsverity_digest() dynptr assumptions")。屬於本節分類中的 maps/helper(fsverity digest helper)攻擊面,是這批(2026-08-22)公告中唯一涉及 fsverity 整合的案例。上述 CVE-2026-74612/74616/74665/74589/74710/74714/74715/74720/74700/74590 為 2026-08-22 公告的同一批修補,加上上面 2026-08-15 那批,兩批合計已超過 25 筆——反映 sockmap、XDP/AF_XDP 資料路徑、conntrack kfunc、驗證器指標追蹤仍是目前這條攻擊面被最頻繁回報問題的幾個區塊。 - CVE-2026-80612(CVSS 9.8 Critical,2026-08-28 揭露,本節目前最高分之一):被轉送、帶有 XDP metadata 的封包若進入 LWT(Lightweight Tunnel)封裝路徑,核心在封裝前沒有先清除這段 metadata——非 BPF 的 LWT 封裝(MPLS、Seg6、IOAM6)會在 push/pull skb headroom 時,直接把還留在原處的 metadata 悄悄覆寫掉;而 BPF LWT xmit(即
bpf_skb_change_head()等 helper 所在的路徑)則因為 IP output 路徑是先執行 LWT xmit、之後才由 neighbour output 建立外層 L2 header,兩者對 metadata 該放哪裡的假設不一致,觸發警告並清空 metadata。修補在進入 LWT 封裝前統一清除 skb 上的 XDP metadata。與 2.6 節、3.2 節討論的 XDP 高速封包處理路徑、以及上面 CVE-2026-74710(AF_XDP TX metadata 長度檢查)同屬「XDP metadata 在核心不同子系統間傳遞時處理不一致」的類型,只是這次錯在 LWT 封裝路徑忘記清除,而非長度檢查不足。修補見核心 commitc00320b0e355。 - CVE-2026-80675(CVSS 7.1 High,Ubuntu priority Medium,2026-08-28 揭露):libbpf 的 signed loader(簽章載入器)機制會在載入時比對map->sha——也就是對已 freeze 的 map 呼叫BPF_OBJ_GET_INFO_BY_FD算出的雜湊值,是否與載入器指令中內嵌的 metadata 雜湊一致。但 signed loader 本身在做這項比對前,沒有確認該 map 是否具備獨佔 (exclusive) 屬性——若主機省略了獨佔設定,另一個持有 map 存取權的 BPF 程式就能在雜湊算出之後、比對完成之前竄改 map 內容,使檢查通過的其實是已被動過手腳的資料。修補讓 signed loader 在繼續 SHA 驗證前,先強制檢查 map 獨佔性設定是否正確。屬於本節分類中的 maps/helper 攻擊面,與上面 CVE-2026-74364、CVE-2026-74360 同屬「map 獨佔保證被繞過」的同類問題,只是這次繞過的是使用者空間 signed loader 的驗證時序,而非核心內的 map-in-map 或 iterator 路徑。修補見核心 commit0fb6c9ed6493。 - CVE-2026-80669(CVSS 未公布,Ubuntu priority Medium,2026-08-28 揭露):BPF LSM 程式原本可以附掛到xfrm_decode_session()這個 hook 上,該 hook 設計上可以回傳錯誤值——但呼叫端security_skb_classify_flow()是從一條void傳回型別的路徑呼叫它,一旦收到非零錯誤就會觸發BUG_ON(),等於讓一個惡意或有 bug 的 BPF LSM 程式,把原本單純的封包分類 (packet classification) 操作變成核心整個 panic。修補直接停用 BPF 附掛到這個 hook 的能力。屬於驗證器/附掛檢查邏輯出錯的另一案例,與上面 CVE-2026-74338(BPF_LSM_CGROUP允許附掛不相容的 sleepable 程式)、CVE-2026-53095(freplace繞過kprobe_write_ctx檢查)同屬「驗證器該擋卻沒擋」的類型,只是這次錯在完全沒有限制某個 hook 的可附掛性,而非附掛時的相容性比對不完整。修補見核心 commit12091470c6b4。上述 CVE-2026-80612/80675/80669 為 2026-08-28 公告的同一批修補。 - CVE-2026-80738(CVSS 7.3 High(v3.1),Ubuntu priority Medium,2026-09-03 揭露):BPF TCP syncookie 輔助函式
bpf_tcp_gen_syncookie()/bpf_tcp_check_syncookie()(常見於 XDP/tc 層做 SYN flood 防禦,讓 BPF 程式直接產生或驗證 TCP SYN cookie)接受的引數型別是ARG_PTR_TO_BTF_ID_SOCK_COMMON——只保證傳入的是廣義的sock_common指標,可能是完整 socket,也可能是request_sock/timewait 這類只共用sock_common前段版面配置的「迷你 socket (mini-socket)」。但這兩個 helper 內部卻直接存取sk->sk_protocol,而這個欄位只存在完整 socket 的結構定義裡——對 mini-socket 讀取等於讀到結構外的記憶體,形成越界讀取。修補在存取sk->sk_protocol前先檢查sk->sk_state != TCP_LISTEN(mini-socket 永遠不會處於TCP_LISTEN狀態,以此區分兩種指標)。屬於本節分類中的 helper 攻擊面,是「helper 引數的型別檢查不夠精確,把窄型別當成寬型別存取」的案例。修補見核心 commit31a420a822ff。 - CVE-2026-80865(CVSS 未公布,Ubuntu priority Medium,2026-09-04 揭露):kprobe_multi(BPF_LINK_TYPE_KPROBE_MULTI,一次附掛大量 kprobe 的機制)的建立路徑中,負責把使用者空間傳入的符號名稱陣列複製進核心的copy_user_syms()(位於kernel/trace/bpf_trace.c)用__get_user()逐一讀取陣列元素,卻沒有在讀取前對整段使用者指標陣列先呼叫access_ok()驗證其可存取性,形成對未經檢查的使用者空間指標直接解參考的漏洞。修補補上這段陣列範圍的access_ok()檢查,並簡化了原本失敗路徑的錯誤處理(配置失敗時直接回傳-ENOMEM)。這筆與本節談的執行期 verifier/maps/helper 攻擊面不同,問題出在載入/附掛時(attach-time)的系統呼叫參數驗證——建立 kprobe-multi link 通常需要較高權限(CAP_PERFMON/CAP_SYS_ADMIN),但也再次提醒:eBPF 的攻擊面不只在程式執行邏輯本身,連「使用者空間怎麼把設定傳進核心」這類資料搬移路徑,一樣可能漏掉基本的指標驗證。修補見核心 commitd5dc200c3a3f("bpf: Add missing access_ok call to copy_user_syms",Fixes:0236fec"bpf: Resolve symbols with ftrace_lookup_symbols for kprobe multi link")。上面 6.1 節的 CVE-2026-74258 是同一類漏洞早三週(2026-08-15)被揭露的姊妹案例(uprobe_multi版本)。 - CVE-2026-80735(CVSS 7.3 High,Ubuntu priority Medium,2026-09-03 揭露,與上面 CVE-2026-80738 同批公告):核心ovpn(OpenVPN in-kernel)子系統在解參考sk->sk_user_data前,沒有先確認該 socket 的所有權——問題在於其他子系統(公告原文明確點名 BPF SOCKMAP)也會把自己的資料指標寫進同一個sk_user_data欄位,但不會同時設定ovpn期待的encap_type標記。當一個 socket 已被 BPF sockmap 接管、其sk_user_data實際指向 sockmap 自己的結構時,若ovpn路徑仍把它當成自己的資料解參考,就會把 sockmap 的資料錯讀成ovpn的結構,造成越界讀取。與上面 CVE-2026-63830、CVE-2026-64548、CVE-2025-39913、CVE-2026-74589 同屬 sockmap 攻擊面,但這次的根因是 socket 所有權標記在多個子系統間共用欄位卻互不相容,而非 sockmap 自身的邊界或生命週期管理。修補見核心 commit59aed1eb60d7(問題由f6226ae7a0cd引入)。上述 CVE-2026-80738/80735/80865 為 2026-09-03~04 公告(其中 80738 與 80735 同批)。 - CVE-2026-89564(CVSS 7.8 High,2026-09-11 揭露):IPv4/IPv6 對非本機遞送的 multicast 封包做轉送前,沒有先解除由
bpf_sk_assign()(常見於 XDP/tc 層的連線導向負載平衡,把封包直接指派給特定 socket 處理)所建立的skb->sk關聯(orphan)。當這個被預取 (prefetch) 的 socket 在轉送過程中被釋放後,ip_mr_input()/IPv6 對應的 multicast 轉送路徑仍持有對它的參照,後續釋放 skb 時解參考到已釋放的 socket,形成 Use-After-Free。修補在進入非本機 multicast 轉送路徑前,先呼叫既有的 orphan 機制解除 skb 上的 socket 關聯。修補見核心 commite36ce6e78fe3("ip: orphan prefetched skbs before multicast forwarding")。屬於本節分類中的 maps/helper(bpf_sk_assign()相關的 IP multicast 轉送路徑)攻擊面。 - CVE-2026-89516(CVSS 未公布,Ubuntu priority Medium,2026-09-11 揭露,與上面一筆同日公告):sched_extdispatch 路徑上的process_deferred_reenq_users()在處理延遲重新排入佇列(deferred reenqueue)請求時,若對應的 DSQ(Dispatch Sequence Queue)在scx_bpf_dsq_reenq()佇列請求送出後、run_deferred()真正執行前就已被銷毀,函式會直接對這個已銷毀的 DSQ 執行BUG_ON()斷言,造成核心崩潰(阻斷服務)。修補改用READ_ONCE()讀取 DSQ 狀態,發現已銷毀就跳過該筆延遲請求,而不是斷言崩潰。修補見核心 commit8d8dd8ae89ea("sched_ext: Don't BUG_ON a destroyed DSQ in process_deferred_reenq_users")。屬於本節分類中的 maps/helper(sched_ext kfunc)攻擊面,與下面同批(2026-09-11)公告的 CVE-2026-89518 同屬sched_ext/BPF_PROG_TYPE_STRUCT_OPS可插拔排程器 dispatch 路徑出錯的姊妹案例,錯在 DSQ 銷毀時機競態,而非 rq 誤判;主流 Ubuntu LTS 版本目前均標示「Not affected」。上述 CVE-2026-89564/89516 為 2026-09-11 公告的同一批修補。 - CVE-2026-89579(CVSS 7.8 High,Ubuntu priority Medium,2026-09-11 揭露):BPF bloom filter map(
BPF_MAP_TYPE_BLOOM_FILTER)在32 位元核心上的bloom_map_alloc(),計算所需 bitset 大小時呼叫BITS_TO_BYTES(U32_MAX)——這段用的是 32 位元運算,DIV_ROUND_UP內部的加法在數值逼近U32_MAX時發生整數溢位而回捲,實際配置到的記憶體只有一個固定大小的 bloom filter 物件,但用來檢查存取範圍的bitset_mask欄位卻仍被設成溢位前的U32_MAX,兩者完全對不上。更麻煩的是雜湊值算出來是u32,但核心的set_bit()接受的是帶正負號的long偏移量——在 32 位元系統上,只要雜湊值落在0x80000000到U32_MAX之間就會被當成負偏移量,直接對配置範圍外的記憶體讀寫。持有CAP_BPF的本機使用者可藉由觸發這個「配置不足 + 負偏移量」的組合,在 32 位元 x86 核心上做到本機權限提升。修補改為把雜湊值拆成「字組指標」與「字組內位元編號」兩部分後再分別呼叫 bit 操作函式,確保偏移量永遠落在合法範圍內。修補見核心 commit11c1e83。屬於本節分類中的 maps/helper(bloom filter map,僅影響 32 位元核心)攻擊面,是少見的「架構特定 (32-bit only)」本機權限提升案例。 - CVE-2026-89580(CVSS 7.8 High,Ubuntu priority Medium,2026-09-11 揭露):get_perf_callchain()(供bpf_get_stack()/bpf_get_stackid()等 helper 使用)會回傳一段 per-CPU 的perf_callchain_entry緩衝區,並在回傳之前就先透過put_callchain_entry()釋放它的遞迴保護槽——等於在__bpf_get_stack()真正把資料複製出來之前,已經沒有任何機制保住這段緩衝區不被其他執行緒搶走。在可搶佔 (preemptible) 的核心組態下(例如掛在非睡眠 raw tracepoint 上、僅靠migrate_disable()而非preempt_disable()保護的 BPF 程式),「取得緩衝區」與「複製資料」之間的空窗可能被搶佔,同一顆 CPU 上另一個任務重用同一塊 per-CPU 緩衝區並覆寫trace->nr,造成後續memcpy()依這個失真的長度值寫出緩衝區邊界(out-of-bounds write)。修補改為在取得緩衝區、複製資料的整段期間關閉搶佔,可能觸發 page fault 的 build-id 解析則延後到重新開啟搶佔之後、只對私有副本操作。問題可追溯至 2018 年引入bpf_get_stackhelper 的 commitc195651e565a,修補見核心 commit15f1bd857466("bpf: Disable preemption in bpf_get_stackid")。屬於本節分類中的 maps/helper(棧回溯 stack-unwinding helper)攻擊面。 - CVE-2026-89581(CVSS 7.8 High,Ubuntu priority Medium,2026-09-11 揭露):x86 BPF JIT 編譯器在組譯存取 per-CPU 變數位址的指令時,目的暫存器是編碼在ModRM.reg、需要REX.R位元才能定址到擴充暫存器(R8-R15),但組譯 REX prefix 時誤用了add_1mod()(只會設定REX.B,用於定址ModRM.rm/SIB.base)而非正確的add_2mod();由於這段指令定址模式是「disp32且無 base 暫存器」,REX.B在此完全不起作用,導致高位暫存器位元直接遺失。實際效應是所有is_ereg()判定為擴充暫存器的目的位址,都會解析成「共用相同低三位元」的錯誤暫存器(例如 R5→RAX、R7→RBP、R8→RSI、R9→RDI),使 BPF 程式讀寫 per-CPU 變數時,實際存取到完全不相干的暫存器內容,可能造成記憶體毀損或核心 Panic。此問題自 6.10 引入(commit7bdbf7446305)後長期潛伏——用 Clang 編譯的 BPF 程式因為每次存取前都會重新載入位址,不會踩到這個路徑,直到 GCC 編譯的 BPF 程式(會讓多個 per-CPU 位址同時存活於暫存器中)在test_progs-bpf_gcc測試中促發才被發現。修補把add_1mod()改為add_2mod(),已於穩定版 6.12.109 / 6.18.50 / 7.2.4 / 7.3-rc1 修補,此處連結為 6.12 穩定分支的對應修補 commit638bc3aada8e。屬於 JIT 編譯器層級的指令編碼出錯,與上面 6.1 節 arm64 的 CVE-2026-53036(分支位移邊界檢查出錯)同屬 JIT 編譯器出錯的案例,但這次錯在暫存器編碼而非邊界檢查。 - CVE-2026-89518(CVSS 未公布,Ubuntu priority Medium,2026-09-11 揭露,與上面三筆同批公告):sched_ext(以BPF_PROG_TYPE_STRUCT_OPS實作、可用 BPF 程式客製化排程邏輯的可插拔排程器類別)dispatch 路徑上的多個 kfunc——scx_dsq_move()、scx_bpf_sub_dispatch()、finish_dispatch()、scx_bpf_dsq_reenq()、scx_bpf_dsq_nr_queued()——原本都假設「目前執行的 CPU」與「被 dispatch 目標的 run queue (rq)」永遠相同;但在核心排程 (core scheduling) 下,dispatch 可能於 core-wide pick 過程中對兄弟 (sibling) rq 執行,使this_rq()與實際 dispatch 目標不一致——scx_dsq_move()可能因此誤判鎖狀態,對已持有鎖的目標 rq 重複上鎖而死鎖;finish_dispatch()/scx_bpf_dsq_reenq()/scx_bpf_dsq_nr_queued()則可能把SCX_DSQ_LOCAL解析成執行緒目前所在 CPU 的本地 DSQ,而非真正被 dispatch 的 rq 所屬 DSQ。修補改為統一使用scx_locked_rq()(在 ops 呼叫期間指向真正被 dispatch 的 rq,非持鎖情境下為NULL)取代this_rq()。修補見核心 commit3dd52416e44a。屬於本節分類中的 maps/helper(sched_ext kfunc)攻擊面,是本節收錄清單中少見的、與BPF_PROG_TYPE_STRUCT_OPS/sched_ext可插拔排程器相關而非傳統網路/追蹤路徑的案例,提醒 BPF 的攻擊面也涵蓋以 struct_ops 形式暴露給 BPF 程式的核心子系統;與上面 2026-09-11 揭露的 CVE-2026-89516 同屬sched_extdispatch 路徑出錯的姊妹案例,只是這次錯在 rq 誤判而非 DSQ 銷毀時機競態。上述 CVE-2026-89579/89580/89581/89518 為 2026-09-11 公告的同一批修補,與上面的 CVE-2026-89564/89516 同日但分開兩批公告。 - CVE-2026-90001(CVSS 7.8 High,2026-09-17 揭露):HID-BPF(讓 BPF 程式客製化 HID(Human Interface Device,如滑鼠、鍵盤、觸控板)裝置行為的框架,自核心 6.10 起改以
BPF_PROG_TYPE_STRUCT_OPS實作,見 commitebc0d80「HID: bpf: implement HID-BPF through bpf_struct_ops」)的 struct_ops 銷毀路徑中,裝置移除路徑__hid_bpf_ops_destroy_device()與 BPF link 釋放路徑hid_bpf_unreg()分別在不同的鎖定範圍下,各自用「ops->hdev是否為 NULL」判斷該不該由自己釋放裝置參照——但hid_bpf_unreg()可能先讀到ops->hdev非 NULL、卡在鎖上等待時,銷毀路徑已先把它清空並釋放參照,導致兩條路徑對同一筆裝置參照各自 double-put,提前釋放struct hid_device造成 Use-After-Free。修補統一在prog_list_lock底下做「該不該清空/釋放」的判斷:銷毀路徑改為持鎖期間先計數、鬆鎖後才真正釋放參照;unreg 路徑則在鎖內重新檢查ops->hdev,若已被清空就直接提早返回。修補見核心 commit9cdc7e6("HID: bpf: serialize device reference release in struct_ops destroy path")。屬於本節分類中的 maps/helper(BPF_PROG_TYPE_STRUCT_OPS)攻擊面,與上面 2026-09-11 揭露的 CVE-2026-89518、CVE-2026-89516 同屬 struct_ops 生命週期/併發管理出錯的同類問題,只是這次錯在 HID-BPF 裝置銷毀路徑的參照計數競態,而非 sched_ext 排程 dispatch 路徑。 - CVE-2026-93043(CVSS 未公布,尚未列入 Ubuntu Security Notices,2026-09-17 揭露):BPF 直譯器 (interpreter) 不認得insn_arraymap(間接跳躍/「gotox」機制)所用的BPF_JMP|BPF_JA|BPF_X指令——若程式因故(例如核心關閉 JIT,或退回直譯器執行)不走 JIT 而改由直譯器執行,___bpf_prog_run()踩到這個指令會直接觸發BUG_ON(),造成核心 Panic(本機阻斷服務)。修補在驗證階段就檢查程式是否使用了insn_arraymap,若有就設定prog->jit_required = true,強制要求 JIT、不允許直譯器 fallback,而不是等到執行期才 Panic。修補見核心 commit17da80d0c7b5、905f716362e1。屬於本節分類中的 maps/helper(insn_array/gotox)攻擊面,與下面 CVE-2026-93044、CVE-2026-93135 同屬「直譯器不支援某指令卻仍允許 fallback」這一類問題,同批(2026-09-17)公告;截至撰文時 Ubuntu Security Notices 尚未收錄此案,故連結至官方 CVE Program 的原始記錄。 - CVE-2026-93044(CVSS 未公布,尚未列入 Ubuntu Security Notices,2026-09-17 揭露):與上一筆同批修補,問題模式相同但換成 BPF arena(BPF_MAP_TYPE_ARENA)——直譯器同樣不支援 arena 相關的 ST/LDX/STX 指令,若使用 arena 的程式退回直譯器執行,會在__bpf_prog_select_runtime()之後踩到「未知 opcode」的核心 BUG。修補同樣是在驗證階段對使用 arena map 的程式設定jit_required = true。修補見核心 commit408b6d3bc19c、34746b5a84ec。屬於本節分類中的 maps/helper(arena)攻擊面,與上面 CVE-2026-53031(arena 配置時node_id未驗證)同屬 arena 相關的姊妹問題,但這次錯在直譯器 fallback,而非邊界檢查。 - CVE-2026-93045(CVSS 7.8 High,2026-09-17 揭露):bpf_arena_free_pages()從 BPF 程式接收一個純量的 arena 位址,先截斷成低 32 位元、再加上 arena base 還原成完整的使用者空間位址——但若這個純量值低於 arena base 的低 32 位元,還原出來的full_uaddr會落在user_vm_start之下,而既有的邊界裁切只檢查了上界、沒檢查下界,讓這個越界位址被當成合法偏移量寫入 arena 的釋放樹 (free-tree)。後續配置若重用到這筆錯誤的偏移量,就可能回傳 arena 實際映射範圍之外的頁面,造成攻擊者可影響、映射範圍外的記憶體被讀寫。修補在計算偏移量之前,先擋下位址低於user_vm_start的釋放請求。修補見核心 commit90453eaf8f14等 4 筆對應穩定分支修補(6.12.110/6.18.52/7.2.6/7.3-rc1)。屬於本節分類中的 maps/helper(arena)攻擊面,與上面 CVE-2026-53031 同屬 arena 邊界檢查問題,但這次錯在釋放路徑漏了下界檢查,而非配置路徑的node_id。 - CVE-2026-93135(CVSS 未公布,尚未列入 Ubuntu Security Notices,2026-09-17 揭露):部分架構(核心原始說明點名 LoongArch、ARM64、RISC-V)的 JIT 會把 helper 呼叫直接內嵌 (inline) 進編譯後的指令、並改寫呼叫的位移量——但若當下 JIT 被關閉、或 JIT 編譯本身失敗而動態退回直譯器執行,直譯器執行到的會是這段「已改寫成內嵌位移量、但直譯器根本不懂得怎麼解讀」的指令,可能造成核心 Panic。修補在程式使用了這類 helper 內嵌功能、但 JIT 不可用時直接拒絕載入,而不是讓它退回直譯器。修補見核心 commit21c644536679、f1c27922576e。屬於本節分類中的 maps/helper(helper call inlining)攻擊面,與上面 CVE-2026-93043、CVE-2026-93044 同屬「直譯器不支援某種 JIT-only 最佳化,卻仍允許 fallback」這一類問題,只是這次觸發條件是 helper 呼叫內嵌而非 gotox/arena。 - CVE-2026-93138(CVSS 7.8 High,2026-09-17 揭露):核心用來快取 vmlinux BTF(對應核心自身型別資訊)的全域指標,在bpf_get_btf_vmlinux()中用一般的變數賦值「發布」出去,之後其他執行緒也只是用一般的無鎖讀取去檢查這個指標是否已設定——兩邊都沒有對應的記憶體屏障,在弱記憶體排序架構上,讀取端可能先看到指標已非 NULL,卻還沒看到指標所指向的 BTF 物件完成初始化的內容,等於用到尚未初始化完整的核心記憶體。修補改用smp_store_release()發布指標、smp_load_acquire()讀取,確保「看到指標非 NULL」時,其指向的內容也保證已初始化完成。修補見核心 commit92863e678070(問題由8580ac9引入)。屬於驗證器(vmlinux BTF 初始化)層級的記憶體排序 (memory ordering) 問題,是本節少見的「發布/讀取端缺屏障」類型案例。 - CVE-2026-90313(CVSS 未公布,尚未列入 Ubuntu Security Notices,2026-09-17 揭露):替換 (replace) cgroup BPF 程式的路徑(__cgroup_bpf_attach)在替換過程失敗、需要復原成原本程式時,沒有正確還原原本的old_pl_flags/old_storage/old_flags,導致原本(未被替換掉)的程式繼續執行、呼叫bpf_get_local_storage()時,拿到的是已經失效的儲存指標,形成類似 Use-After-Free 的無效記憶體存取。修補改為在嘗試替換之前先保存這些欄位,失敗時完整復原。修補見核心 commite26db0d636e4等對應穩定分支修補(6.6.157/6.12.110/6.18.52/7.2.6/7.3-rc1)。屬於本節分類中的 maps/helper(cgroup local storage)攻擊面,是少見的「附掛/替換失敗路徑清理不完整」導致 UAF 的案例。上述 CVE-2026-93043/93044/93045/93135/93138/90313 為 2026-09-17 公告的一批修補,與上面同日的 CVE-2026-90001 合計本批共 7 筆。
- CVE-2026-93144(CVSS 未公布,Ubuntu priority Medium,2026-09-18 揭露):驗證器
check_ptr_to_btf_access()讓依程式類型客製化的btf_struct_accesscallback,在核心預設的唯讀存取檢查介入之前就先自行判斷該不該允許寫入——這使得原本應該完全唯讀的PTR_UNTRUSTEDBTF 指標(例如透過bpf_rdonly_cast()取得的指標)得以被寫入,讓 BPF 程式能經由這類指標寫入任意核心記憶體。修補在共同進入點就先擋下對PTR_UNTRUSTED指標的非讀取操作,不再讓個別 callback 有機會繞過。問題源自bpf_obj_new()/allocated objects 支援引入時的 commit282de14。修補見核心 commitac65c710cc64("bpf: Reject writes through untrusted BTF pointers")。屬於驗證器對 BTF 指標唯讀性檢查不足的案例,與下面 CVE-2026-93148(同批公告、同屬 MEM_ALLOC/BTF 物件邊界檢查)屬於同一天揭露的姊妹問題。- CVE-2026-93147(CVSS 未公布,Ubuntu priority Medium,2026-09-18 揭露):s390 BPF JIT 編譯器把 32 位元值(
cpu_nr)載入 64 位元 BPF 暫存器時,誤用了不會零擴展(zero-extend)高位的ly指令,而非正確應使用的llgf,導致暫存器高 32 位殘留舊資料。修補把ly換成llgf。問題源自 commit9012cf2。修補見核心 commit5f6cc299938b("s390/bpf: Replace ly instruction with llgf")。屬於 JIT 編譯器指令編碼出錯的案例,與上面 CVE-2026-89581(x86 JIT REX prefix 誤用add_1mod())同屬「JIT 組譯階段選錯指令/prefix 導致暫存器內容失真」的同類問題,只是這次是架構特定於 s390。- CVE-2026-93148(CVSS 未公布,Ubuntu priority Medium,2026-09-18 揭露):
PTR_TO_BTF_ID | MEM_ALLOC物件(來自bpf_obj_new()或 percpu kptr)是以固定的 BTF struct 大小配置,但驗證器對 BTF struct walk 原本設計給一般 BTF 型別走訪用的「trailing flexible array 邊界放寬」規則,卻沒有排除這類固定大小配置的物件——導致存取範圍在套用這項放寬之前就先繞過了本該有的 struct-size 邊界檢查,可能讓存取跨出實際配置的物件邊界。修補在對 MEM_ALLOC 物件做 BTF walk 時,先擋下超出 struct 大小的存取範圍,再套用 flexible-array 放寬規則,並把同一套規則同步套用到 struct ID 比對(避免 kfunc/kptr 型別檢查一樣繞過物件邊界)。問題源自bpf_obj_new()引入的 commit958cf2e,以及 percpu kptr 的 alloc/xchg/direct_access 支援 commit36d8bdf。修補見核心 commit9c9ee0324c77("bpf: Reject MEM_ALLOC BTF accesses past object bounds")。屬於驗證器對 allocated objects 邊界檢查不足的案例,與上面 CVE-2026-93144 同屬本批(2026-09-18)公告中的 BTF/allocated objects 驗證器問題。- CVE-2026-93173(CVSS 未公布,Ubuntu priority Medium,2026-09-18 揭露):
__bpf_prog_put_rcu()在 softirq context 呼叫security_bpf_prog_free()觸發 LSM hook——但若有 sleepable BPF LSM 程式掛在這個 hook 上,might_fault()便會偵測到「在不允許睡眠的情境呼叫可能睡眠的函式」,觸發BUG: sleeping function called from invalid context。修補把bpf_prog_free從sleepable_lsm_hooks清單移除,讓核心不再允許在此 hook 掛 sleepable 程式(非睡眠版本的 observer 仍可正常掛載),真正需要延遲的清理工作已經由既有的 RCU 寬限期保護,不受此限制影響。問題源自重構bpf_prog_alloc/bpf_prog_freeLSM hook 的 commit1b67772。修補見核心 commit2ce3f548cfc6("bpf,lsm: Drop bpf_prog_free from sleepable_lsm_hooks")。屬於驗證器/附掛檢查邏輯允許不相容的 hook 附掛組合的案例,與上面 CVE-2026-80669(BPF LSM 附掛到void傳回路徑的 hook 觸發BUG_ON())同屬「hook 該限制卻沒限制附掛相容性」的同類問題。- CVE-2026-90159(CVSS 未公布,Ubuntu priority Medium,2026-09-18 揭露):cgroup BPF 的
BPF_CGROUP_UNIX_GETPEERNAME/BPF_CGROUP_UNIX_GETSOCKNAMEhook 執行時不持有 socket lock,但掛在這兩個 hook 上的程式仍可呼叫bpf_setsockopt()/bpf_getsockopt(),而這兩個 helper 內部會呼叫sock_owned_by_me()斷言目前執行緒持有該 socket 的鎖,於是觸發核心警告(WARN,非記憶體毀損,但代表 helper 在不該被呼叫的情境下被呼叫)。修補直接禁止在這兩個 hook 型別呼叫這兩個 sockopt helper。修補見核心 commit84473a7e1813。屬於驗證器/附掛檢查邏輯允許不相容 hook 組合的案例,與上面 CVE-2026-93173、CVE-2026-80669 同屬「hook 該限制卻沒限制附掛相容性」的同類問題。- CVE-2026-90210(CVSS 7.8 High,2026-09-18 揭露):
bpf_trampoline_update()若在modify_fentry_multi()/unregister_fentry_multi()執行之前就失敗,此時cur_image其實還等於old_image(尚未真的切換),但失敗處理路徑仍照常釋放old_image——而 ftrace 仍持續呼叫進這塊已被釋放的 trampoline 映像,形成 Use-After-Free。修補見核心 commit0253073fb7d7("bpf: Fix UAF in bpf_trampoline_multi_attach_free on update failure")。屬於本節分類中的 maps/helper(BPF trampoline/多重附掛)攻擊面,與上面 CVE-2026-89518/89516(sched_ext struct_ops 生命週期管理出錯)同屬「附掛/更新失敗路徑清理不完整」導致 UAF 的同類問題。- CVE-2026-92486(CVSS 未公布,Ubuntu priority Medium,2026-09-18 揭露):BPF 子程式呼叫遵循
bpf_callback_t(3 個參數)的 ABI 慣例,但核心的 task work 整合機制卻用一般的函式指標型別去呼叫這個 callback——在啟用 kCFI(kernel Control Flow Integrity,比對函式指標實際型別與呼叫端預期型別是否一致)的組態下,這種型別不一致會被 kCFI 判定為可疑的控制流轉移,直接觸發核心 Panic。修補見核心 commit2805abd08957。屬於驗證器/核心介接層對 BPF callback ABI 型別檢查不足的案例,是本節少見的 kCFI 相關問題。- CVE-2026-92520(CVSS 未公布,Ubuntu priority Medium,2026-09-18 揭露):BPF queue/stack map 的
pop/peekhelper 在 map 為空時會把呼叫端的輸出緩衝區清零後才回傳錯誤,但另一條「取鎖失敗」(-EBUSY)的錯誤路徑卻沒有同樣清零就直接回傳,讓 BPF 程式能讀到這段未初始化的核心堆疊內容(資訊外洩)。修補見核心 commit7ac6e1ae41a0。屬於本節分類中的 maps/helper(queue/stack map)攻擊面,與上面 CVE-2026-93174 同屬本批未初始化記憶體外洩的姊妹問題。- CVE-2026-93111(CVSS 7.8 High,2026-09-18 揭露):建立
tracing_multilink 時沒有設定ftrace_managed標記,導致之後若在同一批函式上再附掛一個fentrylink,原本的tracing_multilink 在釋放時可能無法被正確釋放。修補見核心 commit30bdd6d1384d。屬於本節分類中的 maps/helper(BPF trampoline/ftrace 多重附掛)攻擊面,與上面 CVE-2026-90210 同屬本批 trampoline/多重附掛路徑出錯的姊妹問題。- CVE-2026-93112(CVSS 7.1 High,Ubuntu priority Medium,2026-09-18 揭露):
bpf_cpumask_populate()這個 kfunc 原本設計是把資料寫入一個可寫的struct bpf_cpumask *,但函式簽章實際接受的是唯讀的struct cpumask *——而其他唯讀 kfunc(例如取得目前線上 CPU 遮罩的介面)也會回傳這個唯讀型別,使得 BPF 程式能把一個借來的、本應唯讀的 cpumask 傳給bpf_cpumask_populate()當成可寫目的地,寫入不屬於自己的記憶體。修補收緊函式簽章,要求傳入真正可寫、由bpf_cpumask_create()配置的struct bpf_cpumask *。修補見核心 commit8740156ad33b。屬於本節分類中的 maps/helper(cpumask kfunc)攻擊面,是本節少見的「kfunc 參數型別可寫性檢查不足」案例。- CVE-2026-93127(CVSS 7.8 High,2026-09-18 揭露):
check_stack_read_fixed_off()把堆疊上的純量重新讀回暫存器時,若讀取指令是帶正負號擴展的窄讀取(BPF_MEMSX),會沿用原本純量的id,但實際數值卻已被coerce_reg_to_size_sx()做了正負號擴展——如果同一個堆疊槽位同時也被一般的零擴展讀取(BPF_MEM)讀過,兩個暫存器會共用同一個id、卻代表不同的執行期數值。之後只要對零擴展那個暫存器做if reg == const比較,驗證器的sync_linked_regs()就會誤用這個共用id,把正負號擴展暫存器的值「精煉」成一個它在執行期根本不會有的數值,可被利用來讓驗證器誤判邊界、造成越界存取。修補見核心 commit2cb5f4ca695e("bpf: Drop scalar id on sign-extending narrowing stack fills")。屬於驗證器(scalar/id 追蹤)層級的問題,與上面 CVE-2026-43070(BPF_END未重置 id)、CVE-2026-45933(sync_linked_regs()同步時誤複製 id)、CVE-2026-53081(BPF_ADD_CONST誤用基底 id)同屬驗證器對純量id追蹤處理出錯的同類問題家族,這次錯在窄讀取的正負號擴展與 id 共用互相衝突。- CVE-2026-93174(CVSS 未公布,Ubuntu priority Medium,2026-09-18 揭露):
copy_map_value_long()在複製含特殊欄位(如 spin lock、kptr)的 per-CPU map value 時,傳給bpf_obj_memcpy()的長度是原始的map->value_size,而非核心配置記憶體時實際使用、向上對齊到 8 位元組的round_up(map->value_size, 8)——導致 value 結尾到對齊邊界之間的 padding bytes 永遠不會被複製、初始化;而lookup_elem(及其變體)用來回傳給使用者空間的暫存緩衝區又沒有以__GFP_ZERO配置,使這段殘留的核心堆積內容(padding)可被 BPF 程式讀到、外洩給使用者空間。修補見核心 commit7cf9cd98cf6f。屬於本節分類中的 maps/helper(per-CPU map value 複製路徑)攻擊面,與上面 CVE-2026-45838 同屬未初始化記憶體外洩的同類問題,只是這次錯在複製長度未對齊,而非欄位本身忘記清零。- CVE-2026-90143(CVSS 7.8 High,2026-09-18 揭露):KCM(Kernel Connection Multiplexor)的
kcm_parse_func_strparser()呼叫bpf_prog_run_pin_on_cpu()執行 BPF parser 程式時,雖然阻止了 CPU 遷移,卻沒有一併建立 RCU read-side critical section——導致這段 BPF 程式若呼叫 map 操作,會觸發WARN_ON_ONCE(!bpf_rcu_lock_held())警告,代表 map 操作是在缺乏 RCU 保護的情況下執行,存在潛在的釋放後使用風險。修補在執行程式前明確持有 RCU read lock。修補見核心 commitb0346dd64e49("net: kcm: Hold RCU read lock while running BPF parser")。屬於本節分類中的 maps/helper(KCM/BPF 附掛情境缺少 RCU 保護)攻擊面。- CVE-2026-90146(CVSS 7.8 High,2026-09-18 揭露):
bpf_xdp_link_update()直接呼叫dev_xdp_install(),跳過了dev_xdp_attach(),使得原本應該在附掛/更新時一併檢查的項目(程式是否已被硬體卸載、是否已綁定其他裝置、native/generic 模式是否相符、DEVMAP/CPUMAP 限制等)完全沒有執行——使用者可以先用一般程式建立 XDP link,再透過BPF_LINK_UPDATE把它換成一個硬體卸載 (offloaded) 或裝置綁定的程式,讓它繞過檢查、被當成一般軟體路徑程式執行。修補把這些檢查搬進dev_xdp_install()這個三條路徑(ip link set xdp、BPF_LINK_CREATE、BPF_LINK_UPDATE)共同會走到的入口,dev_xdp_attach()只保留與它自身相關的 netlink flag 檢查。修補見核心 commitad27ed7d2309("bpf, xdp: move offload check into dev_xdp_install()")。屬於驗證器/附掛檢查邏輯允許不相容組合的案例,與上面 CVE-2026-80669、CVE-2026-90159、CVE-2026-93173 同屬「附掛/更新路徑該擋卻沒擋」的同類問題,這次錯在BPF_LINK_UPDATE繞過了 XDP 附掛應有的相容性檢查。- CVE-2026-90211(CVSS 未公布,Ubuntu priority Medium,2026-09-18 揭露):s390 BPF JIT 對 arena 指標做帶
BPF_FETCH的原子讀改寫 (RMW) 運算時,會轉成BPF_PROBE_ATOMIC並註冊例外表項目——但bpf_jit_probe_atomic_pre()只填入了 arena base 與 probe offset,卻沒有填入需要在錯誤發生時被清零的「fetch 目的暫存器」欄位(維持在初始化時的 -1),導致ex_handler_bpf()誤判成「沒有暫存器需要清零」。這對純寫入的BPF_{ADD,AND,OR,XOR}沒有影響,但帶BPF_FETCH的 RMW(以及BPF_XCHG/BPF_CMPXCHG)會把舊值讀進暫存器——一旦存取未映射的 arena 分頁觸發錯誤,程式恢復執行時,該暫存器殘留的會是錯誤發生前的舊值,而非其他架構上一致保證的 0。修補改用bpf_atomic_load_reg()正確填入這個欄位。修補見核心 commitcc3e12330599。屬於 JIT 編譯器層級的 arena 例外處理出錯案例,與上面 CVE-2026-93045(arena 釋放路徑下界檢查缺失)同屬 arena 相關問題,但這次是架構特定(s390)的錯誤處理疏漏,而非邊界檢查。- CVE-2026-90217(CVSS 7.8 High,2026-09-18 揭露):驗證器對堆疊上的
STACK_ITER(iterator)槽位做狀態剪枝 (state pruning) 比對時,沒有比較指標型別本身——一個 iterator 槽位可能是MEM_RCU(有 RCU 保護)或PTR_UNTRUSTED(不受信任),這兩種型別在安全性上完全不同,但驗證器卻把它們視為等價狀態,可能把一條實際不安全的執行路徑,誤判成與先前已驗證過的安全路徑等價而直接剪枝略過。修補在比對STACK_ITER槽位時,一併比較指標型別是否相符。修補見核心 commit83608e303b95("bpf: Compare iterator types during state pruning")。屬於驗證器(狀態剪枝)層級的問題,與上面 CVE-2026-93127(narrow read 正負號擴展與 id 共用衝突)同屬「剪枝時遺漏了某個應該比較的狀態欄位」的同類問題家族。- CVE-2026-90250(CVSS 未公布,Ubuntu priority Medium,2026-09-18 揭露):
__cgroup_bpf_replace用link_update把一個 cgroup 上原本掛載的空程式替換成使用BPF_MAP_TYPE_PERCPU_CGROUP_STORAGE、且會呼叫bpf_get_local_storage()的新程式時,沒有為這個新程式配置並指派所需的 cgroup storage——導致新程式繼承了一段未初始化的儲存指標,執行到bpf_get_local_storage()時直接對 NULL 指標解參考,造成核心 Panic。修補改為在 link update 時,若新舊程式的 cgroup storage 需求不相容就直接拒絕替換。修補見核心 commit3f562c537e9e。屬於本節分類中的 maps/helper(cgroup local storage)攻擊面,與上面 CVE-2026-90313(cgroup 替換失敗路徑復原不完整)同屬 cgroup BPF 程式替換路徑處理不周全的同類問題。- CVE-2026-90269(CVSS 未公布,Ubuntu priority Medium,2026-09-18 揭露):一般的
BPF_LDX讀取若來源是可能出錯的指標型別(裸PTR_TO_BTF_ID、PTR_TO_BTF_ID | PTR_UNTRUSTED、PTR_TO_BTF_ID | MEM_ALLOC | PTR_UNTRUSTED、PTR_TO_MEM | MEM_RDONLY | PTR_UNTRUSTED),驗證器會經由bpf_convert_ctx_accesses()把它改寫成帶例外表保護的BPF_PROBE_MEM;但語意相同、只是多了 acquire 語意的BPF_LOAD_ACQ(load-acquire)卻沒有走這條改寫路徑,JIT 因此對它產生一段沒有例外表項目的一般載入指令——一旦對這類指標(例如從受信任的task_struct讀出、對核心執行緒而言可能為 NULL 的next->mm)做 load-acquire 觸發錯誤,就不是安全地跳到例外處理常式,而是直接核心 Panic。修補讓驗證器對BPF_LOAD_ACQ比照BPF_LDX拒絕這些來源指標型別。修補見核心 commit7db0a00445f1("bpf: Reject load-acquire from pointers requiring fault protection")。屬於驗證器/JIT 對新指令(load-acquire)未比照既有指令套用相同保護規則的案例。- CVE-2026-90299(CVSS 未公布,Ubuntu priority Medium,2026-09-18 揭露):當核心關閉
CONFIG_FUNCTION_ERROR_INJECTION時,驗證器允許 sleepable tracing/LSM 程式附掛到名稱帶有__x64_等架構前綴的符號上,卻沒有先確認這個符號實際對應的是不是一個真正的核心函式——因此一個 sleepable fentry 程式可以附掛到另一個名稱恰好帶有__x64_前綴的 BPF 程式(而非核心函式)上,例如附掛到__x64_sys_nop這個 XDP 程式,並在其中呼叫bpf_copy_from_user()。由於 XDP 程式執行環境不允許睡眠,一旦掛上的 XDP 程式被觸發(如ping一次即可),就會觸發BUG: sleeping function called from invalid context。修補規定:只要附掛目標的 BTF 不是核心自身的 BTF,一律禁止 sleepable 程式附掛。修補見核心 commit00244bdaa423("bpf: Fix sleepable check for tracing/lsm prog")。屬於驗證器/附掛檢查邏輯的案例,與上面 CVE-2026-90146、CVE-2026-90159、CVE-2026-93173 同屬「附掛相容性檢查不足」的同類問題家族,這次錯在把 BPF 程式誤判成核心函式。- CVE-2026-90300(CVSS 未公布,尚未列入 Ubuntu Security Notices,2026-09-17 公布,CVE Program 保留日期 2026-09-11;2026-10-17 複查補入,屬同批次先前遺漏項目):
__bpf_get_task_stack()(支撐bpf_get_task_stack()/bpf_get_task_stack_sleepable()這兩個 helper)在走訪task_struct失敗的多條錯誤路徑上,直接回傳錯誤碼,卻沒有清空呼叫端傳入、標記為ARG_PTR_TO_UNINIT_MEM的輸出緩衝區——導致 BPF 程式在呼叫失敗後,讀到的是緩衝區裡殘留的核心堆疊舊內容(資訊外洩);若程式把這段緩衝區直接當成 map key 使用,殘留的未初始化位元組還會讓同一筆邏輯 key 在不同次呼叫間產生不一致的雜湊結果。修補在這些失敗路徑統一補上memset(),確保緩衝區內容在任何回傳路徑下都是確定的。修補見核心 commitf5d242825ca417b("bpf: Clear buf on error in __bpf_get_task_stack"),已隨 Linux 7.3-rc1 併入主線。屬於本節分類中的 maps/helper(task stack dump helper)攻擊面,與上面 CVE-2026-90317(同一個__bpf_get_task_stack()函式,但錯在 RCU 指標失效時機而非緩衝區清零)是同一函式的姊妹案例,也與 CVE-2026-92520、CVE-2026-93174 同屬「特定錯誤路徑忘記清零輸出緩衝區」的未初始化記憶體外洩同類問題家族。- CVE-2026-90312(CVSS 7.8 High,2026-09-18 揭露):
check_atomic_load()在驗證 load-acquire 指令時,先呼叫check_load_mem()才呼叫atomic_ptr_type_ok()——當指令的來源與目的是同一個暫存器(dst_reg == src_reg)時,check_load_mem()會先把這個暫存器的型別覆寫成「載入後的值型別」,導致隨後執行的atomic_ptr_type_ok()已經讀不到原本的來源指標型別,無法正確拒絕ctx、pkt、flow_keys、sock等不該做 load-acquire 的來源型別。由於bpf_convert_ctx_accesses()不會改寫 atomic load,驗證器沒擋下的存取會直接對底層核心物件做未轉換的存取,實際讀到的是原始核心記憶體位元組,卻被驗證器當成別的型別(如PTR_TO_SOCK_COMMON_OR_NULL)追蹤,形成型別混淆 (type confusion),而不只是單純的資料外洩。修補比照check_atomic_rmw(),在做 load 之前先用check_reg_arg()/atomic_ptr_type_ok()驗證來源指標型別。修補見核心 commitb87803391baa("bpf: Check load-acquire src ptr type before the load")。屬於驗證器對新指令(load-acquire)驗證順序出錯的案例,與上面 CVE-2026-90269 同屬 load-acquire 指令保護不完整的同批姊妹問題。- CVE-2026-90317(CVSS 7.8 High,2026-09-18 揭露):在 sleepable BPF 程式中,spin lock 有時是保護一個 kptr 唯一的 RCU 機制——但驗證器在程式呼叫最後一次
bpf_spin_unlock()、實際結束這段 RCU 保護之後,仍繼續把該指標視為有效,沒有讓它失效。這讓另一個 CPU 有機會搶先釋放這個物件,原程式後續若仍使用這個指標就會造成 Use-After-Free;文中提到一個受能力限制的執行期概念驗證,已實際在__bpf_get_task_stack()觸發了task_struct的 UAF。修補改為在解鎖前記錄程式當下是否仍處於 RCU 保護情境,只有在這次解鎖確實結束了最後一段 RCU 保護時,才讓相關指標失效(非 sleepable 程式與位於明確 RCU read-side 區段內的情況則不受影響)。修補見核心 commit180c7000712d("bpf: Invalidate RCU pointers after final spin unlock")。屬於驗證器/RCU 對指標存活期追蹤不完整的案例,是「解鎖」與「RCU 保護結束」兩件事在驗證器眼中被錯誤視為無關的少見類型。- CVE-2026-90392(CVSS 7.8 High,2026-09-18 揭露):
bpf_link_show_fdinfo()(/proc/<pid>/fdinfo讀取 BPF link 資訊)與bpf_link_get_info_by_fd()(BPF_OBJ_GET_INFO_BY_FD)在讀取link->prog時完全沒有持有任何鎖——若此時另一執行緒透過bpf_link_update()把這個 link 換成別的程式,原本的舊程式可能被釋放,讓這兩個讀取路徑手上拿到的是已釋放記憶體的指標,形成 Use-After-Free。修補改為在 RCU 保護下讀取link->prog,確保讀取期間該指標指向的物件仍然存活。修補見核心 commit863f3ddd0b8a("bpf: Fix potential UAF when reading bpf link info")。屬於本節分類中的 maps/helper(BPF link 生命週期)攻擊面,與上面 CVE-2026-90210(trampoline 更新失敗路徑 UAF)同屬「link/trampoline 併發更新時舊物件保護不足」的同類問題。- CVE-2026-93137(CVSS 7.8 High,2026-09-18 揭露):
bpf_find_vma()讀取目標(可能是另一個)task 的task->mm,沒有先取得參照就直接呼叫mmap_read_trylock(mm)——由於mm_struct不是SLAB_TYPESAFE_BY_RCU,若目標 task 在這段「讀取指標」與「嘗試上鎖」之間剛好執行exit_mm()並釋放了這個mm_struct,mmap_read_trylock()操作到的就是已釋放的記憶體,形成 Use-After-Free。修補針對「非目前執行緒自己」的 task,改在task->alloc_lock保護下用spin_trylock()(避免在 BPF 情境下阻塞)取得mm的參照,操作完成後以mmput_async()釋放;目前執行緒自身的task->mm則因為本來就穩定而維持原邏輯,中斷關閉情境與!CONFIG_MMU則直接拒絕這條路徑。修補見核心 commit47b079e2117a("bpf: Fix use-after-free on mm_struct in bpf_find_vma()")。屬於本節分類中的 maps/helper(task/mm iterator 相關 helper)攻擊面,與上面 CVE-2026-53084/53085(task_vmaiterator 鎖順序/參照計數問題)、CVE-2026-74714(iterator UAF)同屬「iterator/helper 對目標 task 生命週期物件保護不足」的同類問題家族。上述 CVE-2026-93144/93147/93148/93173/90159/90210/92486/92520/93111/93112/93127/93174 及本次系統性複查追加的 CVE-2026-90143/90146/90211/90217/90250/90269/90299/90312/90317/90392/93137 合計 23 筆(2026-10-17 複查另補入 CVE-2026-90300,詳見上方該筆說明,故本批實際合計 24 筆),均屬同一批公告(CVE Program 原始記錄時間戳記多為 2026-09-17,Ubuntu Security Notices 揭露日期則統一為 2026-09-18,一天落差為公告流程正常延遲)。
2026-09-25 審查後補充:上一輪複查(2026-09-23)誤判 2026-09-19 之後沒有新揭露的 BPF CVE——重新交叉比對 Ubuntu Security Notices、CVE Program 官方記錄(
CVEProject/cvelistV5)後,發現 2026-09-24 與 2026-09-25 兩批公告其實新增了至少 14 筆 BPF 相關 CVE,一併補上:
- CVE-2026-93270(CVSS 未公布,Ubuntu priority Medium,2026-09-24 揭露):BPF 直譯器處理
BPF_MOV64_PERCPU_REG(把 per-CPU base offset 加進暫存器)這個特殊指令時,ALU64_MOV_X這個 label 底下的直譯邏輯忽略了指令的off欄位——而這個off正是用來標記「這是一筆 percpu 暫存器搬移、需要另外加上 base offset」的旗標。JIT 有正確處理這個 offset,但直譯器沒有,導致當 JIT 被關閉、或程式退回直譯器執行時,percpu 暫存器實際拿到的是未加上 base offset 的原始值,後續解參考時直接觸發 page fault、核心 Panic。修補讓含有這類 percpu 定址指令的程式強制要求jit_required = true,不再允許退回直譯器執行。修補見核心 commit57cf929a33cb、7a0855e73757。與上面 CVE-2026-93043/93044/93135 同屬「直譯器不支援某種 JIT-only 構造、卻仍允許 fallback」的同類問題,這次的構造是 percpu 暫存器搬移而非 gotox/arena/helper 內嵌。- CVE-2026-97944(CVSS 未公布,Ubuntu priority Medium,2026-09-25 揭露):x86 FineIBT 的函式前導碼(preamble)曾把用來存放 CFI hash 的指令從
subl $hash, %r10d改成subl $hash, %eax,連帶把 hash 立即值在指令中的位元組偏移量從第 7 個位元組搬到第 5 個位元組——但cfi_get_func_hash()(BPF JIT 建立 struct_ops trampoline 時,用來取得被取代之樁函式 (stub) CFI hash 的函式)仍照舊從偏移量 7 讀取,读到錯誤的資料。在啟用 kCFI + FineIBT 的核心上,這會讓 struct_ops trampoline(例如 sched_ext、HID-BPF 等場景)攜帶錯誤的 CFI hash,导致核心到 BPF 的間接呼叫(如 TCP 壅塞控制初始化)在 CFI 驗證階段失敗,觸發核心 Panic。修補見核心 commitcd9b4595d628、67cf94c30a8b、5a5d26f2cfe1。與上面 CVE-2026-92486(task work 以一般函式指標型別呼叫bpf_callback_t,觸發 kCFI Panic)同屬「BPF 與 kCFI/FineIBT 介接處型別或偏移量對不齊」的同類問題。- CVE-2026-98019(CVSS 未公布,Ubuntu priority Medium,2026-09-25 揭露):
check_func_arg()允許把一個可為 NULL 的 helper/kfunc 參數視為「已做過 NULL 檢查」時,沒有同步把底層的純量暫存器標記為 precise;check_helper_call()對bpf_get_local_storage()第二個參數必須為零的檢查也有同樣問題。兩者都會讓驗證器的精確度傳播 (precision propagation) 鏈斷裂,導致狀態剪枝 (checkpoint pruning) 時做出錯誤判斷。修補見核心 commit1a3a10b030c9。屬於驗證器(純量 precise 標記/精確度傳播)層級的問題,與下面 CVE-2026-98132(zero spill 精確度傳播斷裂)同屬本批精確度追蹤缺陷。- CVE-2026-98041(CVSS 未公布,Ubuntu priority Medium,2026-09-25 揭露):驗證器的
is_branch_taken()靜態預測條件分支結果時,沒有區分BPF_JMP(64 位元比較)與BPF_JMP32(32 位元比較)——對一筆指標與零值比較的BPF_JMP32指令,is_branch_taken()卻依整個 64 位元純量值去預判分支走向,而非只看低 32 位元,導致驗證器誤剪枝、放行本應拒絕的路徑。修補見核心 commitd16f0eafcaa6等 4 筆對應穩定分支修補。與上面 CVE-2026-43030(regsafe()封包範圍比對誤判)、CVE-2026-53081(狀態剪枝時未比對 base id)同屬「驗證器狀態剪枝/分支預測遺漏應比對欄位」的同類問題家族。- CVE-2026-98043(CVSS 未公布,Ubuntu priority Medium,2026-09-25 揭露):驗證器的
reg_not_null()只要指標型別的「基底」保證非 NULL,就判定該指標非 NULL——但若指標帶有未限定範圍的偏移量,執行期實際的偏移量仍可能讓最終位址算出來剛好是 NULL,reg_not_null()卻沒有把這種情況排除。修補要求偏移量必須落在±BPF_MAX_VAR_OFF範圍內才能套用這項非 NULL 推斷。修補見核心 commitcb6642048739。與下面 CVE-2026-98134 同屬「驗證器對指標非 NULL 的推斷過於寬鬆」的同批姊妹問題。- CVE-2026-98049(CVSS 未公布,Ubuntu priority Medium,2026-09-25 揭露):BPF arena 指標的 32 位元
cmpxchg(帶BPF_FETCH、經bpf_convert_ctx_accesses()轉成BPF_PROBE_ATOMIC)運算結果,沒有依 BPF 語意「32 位元暫存器運算後應零擴展高 32 位元」的規則做零擴展——原因是is_cmpxchg_insn()只認得一般的BPF_ATOMIC模式,沒有把BPF_PROBE_ATOMIC也算進去,導致這條零擴展的最佳化路徑漏掉了 arena 版本。修補讓is_cmpxchg_insn()同時比對BPF_ATOMIC與BPF_PROBE_ATOMIC。修補見核心 commit1c1b476d43a8。屬於本節分類中的 maps/helper(arena atomic)攻擊面,與上面 CVE-2026-90211(s390 arena RMW 例外處理未清零 fetch 目的暫存器)同屬 arena atomic 運算處理不完整的同類問題。- CVE-2026-98063(CVSS 未公布,Ubuntu priority Medium,2026-09-25 揭露):
btf_var_show()無條件呼叫btf_type_id_resolve(),但這個函式會解參考btf->resolved_ids——對 vmlinux BTF 這類「base BTF」而言,這個欄位在解析階段本來就不會被填,永遠是 NULL。當 BPF 程式把一個來自 vmlinux BTF 的BTF_KIND_VAR型別 ID 傳給bpf_snprintf_btf()時,就會觸發這個 NULL pointer dereference。姊妹函式btf_modifier_show()早就有對應的 NULL 防呆,唯獨btf_var_show()沒加。修補比照加上同樣的防呆。修補見核心 commite472ae0d9786。與下面 CVE-2026-98064 同屬本批bpf_snprintf_btf()/BTF show 路徑對特殊 BTF 型別(base BTF、void)處理不完整的姊妹問題。- CVE-2026-98064(CVSS 未公布,Ubuntu priority Medium,2026-09-25 揭露):
btf_modifier_show()解析完修飾詞 (modifier) 後,會無條件呼叫btf_type_ops(t)->show()——但void型別根本沒有對應的show操作實作,若 BPF 程式經由bpf_snprintf_btf()傳入一個最終解析為const void的型別 ID,就會呼叫到不存在的函式指標,觸發 NULL pointer dereference。修補為找不到對應show實作的型別種類補上btf_df_show()這個預設(no-op)實作。修補見核心 commit717abdfd1d55。與上面 CVE-2026-98063 同屬同批 BTF show 路徑防呆不足的姊妹問題。- CVE-2026-98075(CVSS 未公布,Ubuntu priority Medium,2026-09-25 揭露):
jit_subprogs()(位於fixups.c)會把BPF_PSEUDO_FUNC型別的載入指令,改寫成指向真正函式位址的指令——但驗證器沒有拒絕「BPF_PSEUDO_FUNC指向主程式本身(而非某個子程式)」這種情形。若搭配bpf_timer_set_callback()這類會把這個「函式參照」當成回呼(callback)登記並在之後呼叫的 helper,核心就可能對著一個從未被正確改寫成真實函式位址的值執行「呼叫」動作。修補讓驗證器直接拒絕這種指向主程式自身的BPF_PSEUDO_FUNC參照。修補見核心 commit118212417ba0。屬於驗證器邏輯本身出錯的案例,與上面 CVE-2026-31413、CVE-2026-63864 同屬一類,這次錯在漏掉了對BPF_PSEUDO_FUNC參照目標的合法性檢查。- CVE-2026-98084(CVSS 未公布,Ubuntu priority Medium,2026-09-25 揭露):驗證器對
bpf_loop()這類回呼型 helper 做精確度回溯 (precision backtracking) 分析時,R1(回呼的第一個參數,對bpf_loop()而言是目前的迭代次數)理應在多次驗證迭代間持續維持 precise 標記——但當bpf_loop()呼叫是在第二次驗證迭代中才被驗證到時,這段回溯邏輯會不小心把R1的 precise 標記重置掉,导致驗證器可能誤判、放行本應拒絕的程式。修補見核心 commite3e4f66cc4b7。與上面 CVE-2026-98019 同屬本批精確度傳播/追蹤缺陷的姊妹問題,也與 CVE-2026-43009(atomic-fetch 精確度追蹤)同屬同一大類。- CVE-2026-98132(CVSS 未公布,Ubuntu priority Medium,2026-09-25 揭露):
__clean_func_state()在堆疊槽位上某 4 個位元組已經「半死」(half-dead,即該範圍內的資料不再被後續程式使用)時,會把該處純量零值的堆疊寫入 (spill) 降級標記成STACK_ZERO——但這個降級動作會弄斷原本依附在這個純量識別碼 (id) 上的精確度傳播鏈,讓驗證器對後續使用同一識別碼的暫存器做出錯誤推斷。修補避免把純量零值的堆疊寫入降級為STACK_ZERO。修補見核心 commit2f3536bff882。與上面 CVE-2026-98019、CVE-2026-98084 同屬本批精確度傳播鏈斷裂的同類問題,也與 CVE-2026-93127(narrow read 正負號擴展與 id 共用衝突)同屬純量 id 追蹤處理出錯的大家族。- CVE-2026-98134(CVSS 未公布,Ubuntu priority Medium,2026-09-25 揭露):
check_cond_jmp_op()比較兩個指標時,只要其中一個指標的型別沒有帶PTR_MAYBE_NULL旗標,就直接推斷它在執行期一定非 NULL——但某些型別(例如PTR_TO_MEM)即使沒帶這個旗標,執行期實際上仍可能是 NULL。修補不再用「有沒有PTR_MAYBE_NULL旗標」(type_may_be_null())當判斷依據,改用明確列出「哪些型別真的保證非 NULL」的白名單函式reg_not_null()。修補見核心 commitb55c9f019e16。與上面 CVE-2026-98043 同屬本批「驗證器對指標非 NULL 的推斷過於寬鬆」的姊妹問題。- CVE-2026-98149(CVSS 未公布,Ubuntu priority Medium,2026-09-25 揭露):per-CPU array/hash/cgroup-storage map 在沒有帶
BPF_F_CPU/BPF_F_ALL_CPUS旗標的一般更新 (update) 路徑上,是用邏輯 (logical) CPU 編號去換算來源緩衝區裡對應該 CPU 資料的偏移量——但緩衝區裡的 per-CPU 資料實際上是依「目前系統上實際存在的 CPU (possible CPU)」緊密排列,而非依邏輯編號排列。當 CPU 編號不連續(例如只有 CPU 0、2、3 存在)時,這個換算方式會對錯位置讀寫,導致寫入錯誤的 per-CPU 數值,也造成對更新緩衝區的越界讀取。既有的查詢 (lookup) 路徑本來就是依 possible-CPU 順序正確走訪,只有這個更新路徑算錯。修補讓更新路徑比照查詢路徑,改用 possible-CPU 的緊密偏移量。修補見核心 commit75b0a6db4300。屬於本節分類中的 maps/helper(per-CPU map 緩衝區配置慣例)攻擊面,與上面 CVE-2026-53076/93174(per-CPU map value 長度/對齊算錯)同屬「per-CPU map 對緩衝區排列方式的假設出錯」的同類問題,但這次錯在稀疏 CPU 拓樸下的索引換算,而非長度對齊。- CVE-2026-98150(CVSS 未公布,Ubuntu priority Medium,2026-09-25 揭露,與上面 CVE-2026-98149 同日公告、同屬稀疏 CPU 拓樸主題,但錯在不同函式):
bpf_map_check_op_flags()驗證呼叫端搭配BPF_F_CPU旗標傳入的 CPU 編號是否合法時,比對的基準是num_possible_cpus()——這是一個數量(有幾個 CPU),而非「哪些 CPU 編號實際存在」的集合(nr_cpu_ids/cpu_possible()mask)。在 CPU 編號不連續(有「編號空洞」)的系統上,這個誤用會同時導致部分合法 CPU 編號被誤判拒絕、部分不存在的 CPU 編號卻被誤判放行,後者可能導致對BPF_MAP_TYPE_PERCPU_ARRAY之類的 map 操作觸發 page fault、核心崩潰。修補改為對照nr_cpu_ids與cpu_possible()mask 驗證。修補見核心 commited54bf564ac5。與上面 CVE-2026-98149 同屬本批稀疏 CPU 拓樸問題的姊妹案例。- CVE-2026-98151(CVSS 未公布,Ubuntu priority Medium,2026-09-25 揭露):驗證器內部有一項一致性自我檢查(觸發時會回報 "REG INVARIANTS VIOLATION"),用來確保暫存器的變數偏移量 (
var_off) 追蹤與其 32 位元子暫存器邊界彼此一致——但在處理推測執行 (speculative execution) 路徑(Spectre 緩解機制用來複製、分別驗證的分支路徑)時,驗證器對暫存器狀態拍照存檔 (snapshot) 的時間點,恰好落在「dst_reg的var_off仍是原本的常數偏移量」與「32 位元子暫存器邊界已被清空成全範圍」這兩個步驟之間,導致存檔下來的狀態本身就自相矛盾。修補調整操作順序,確保存檔前兩者已同步更新完畢。修補見核心 commit150aeba624e8等 4 筆對應穩定分支修補。屬於驗證器(推測執行路徑的暫存器狀態追蹤)層級的問題,是本節少見的「Spectre 緩解機制本身與一般狀態追蹤邏輯沒對齊」類型案例。上述 CVE-2026-93270(2026-09-24 公告)與 CVE-2026-97944/98019/98041/98043/98049/98063/98064/98075/98084/98132/98134/98149/98150/98151(2026-09-25 公告)合計 14 筆,加上前述系統性複查追加的 CVE-2026-64354(2026-07-25 揭露,先前遺漏)共 15 筆,均已逐一以 Ubuntu Security Notices 個別 CVE 頁面核實(而非僅憑搜尋摘要)。經抽樣複查 CVE-2026-98xxx 鄰近編號範圍(約 20 筆),另有相當比例屬於非 BPF 子系統(如 stmmac、NTFS、nvme)問題,不排除同一批公告中仍有其他 BPF 相關 CVE 尚未逐一核實,下次複查應對 2026-09-25 這批做完整的系統性複查(參照 2026-06-24、2026-09-17/18 兩批的做法)。CVE-2026-74612(CVSS 10.0)至今仍是本節收錄清單中嚴重度最高的一筆——本批新增案例中,若計入未公布 CVSS 的個案(均為 Ubuntu priority Medium),已知數值最高者僅 CVE-2026-64354 的 CVSS 7.8,故排序無須調整。
2026-09-26 複查完成:上一輪(2026-09-25)自承尚未對 CVE-2026-98xxx 範圍做完整系統性複查——本次改用 Ubuntu 官方 CVE 追蹤器資料介面,對 2026-09-24~25 兩批公告逐一比對修補所在的檔案路徑,確認先前遺漏了以下 23 筆核心 BPF 子系統(
kernel/bpf/*、include/linux/bpf*.h)CVE,另有 2 筆修補檔案雖不在kernel/bpf/、net/bpf/本身、但問題直接關乎 BPF 攻擊面(XDP 程式生命週期、sockmap 安全邊界),依本節既有慣例(如 CVE-2026-64545 之於net/core/filter.c、CVE-2026-74665 之於 generic XDP 路徑)一併收錄,合計 25 筆:
- CVE-2026-97420(CVSS 未公布,Ubuntu priority Medium,2026-09-24 揭露):
bpf_sysctl_set_new_value()(cgroup BPF sysctl hook 用來覆寫使用者透過 sysctl 寫入的待生效值)在替換緩衝區時沒有補上結尾的 NUL 字元,導致後續依賴「以 NUL 結尾字串」語意解析該值的 sysctl 處理路徑讀出緩衝區外的記憶體;可透過對/proc/sys/net/core/flow_limit_cpu_bitmap之類的 sysctl 寫入觸發,KASAN 會回報 slab-out-of-bounds read。修補見核心 commita66e3b5bacf3("bpf: NUL-terminate replaced sysctl value")。屬於本節分類中的 maps/helper(cgroup sysctl hook)攻擊面。- CVE-2026-98007(CVSS 未公布,Ubuntu priority Medium,2026-09-25 揭露):
bpf_loop()的迴圈次數參數nr_loops原本宣告為ARG_ANYTHING,意味著特權載入者理論上可以傳入指標值而非純量;當這類指標值流入精確度回溯 (precision backtracking) 邏輯時會觸發驗證器內部WARN()(若系統開啟panic_on_warn甚至直接 Kernel Panic)。修補新增ARG_SCALAR引數型別,要求nr_loops必須是純量。修補見核心 commitc3fd8e5fd100("bpf: Reject non-scalar bpf_loop iteration counts")。屬於驗證器對 helper 引數型別檢查不足的案例。- CVE-2026-98033(CVSS 未公布,Ubuntu priority Medium,2026-09-25 揭露):
__mark_reg_known_zero()在清空一個回呼(callback)堆疊幀的暫存器狀態時,連帶清掉了map_uid這個欄位——但map_uid正是驗證器用來區分「共用同一個 map-in-map 樣板、但實際指向不同 inner map」的唯一依據。清空後,timer / workqueue / task work 這類會登記回呼的 helper,可能把原本屬於不同 inner map 的計時器互相配對錨定,構成潛在的 Use-After-Free 攻擊面。修補讓清空動作保留map_uid。修補見核心 commitb90c5d770dad("bpf: Preserve inner map identity in callback frames")。屬於 maps/helper(map-in-map / 回呼)攻擊面。- CVE-2026-98034(CVSS 未公布,Ubuntu priority Medium,2026-09-25 揭露):
check_map_kptr_access()允許把一個「已知為零」的暫存器寫入 kptr 欄位,卻沒有呼叫mark_chain_precision()讓這次寫入的來源保持精確追蹤——導致狀態剪枝 (state pruning) 可能誤判:一條「寫入零值」的路徑與另一條「寫入攻擊者可控的非零值」的路徑被視為等價而剪枝放行。修補讓這類 NULL kptr 寫入強制標記為 precise。修補見核心 commitecdc504379("bpf: Mark NULL kptr stores precise")。屬於驗證器精確度傳播不足的案例。- CVE-2026-98035(CVSS 未公布,Ubuntu priority Medium,2026-09-25 揭露):
rhtab_delete_elem()與rhtab_map_update_existing()在回收 (recycle) hash map 元素時,用bpf_obj_free_fields()去清理該元素上的特殊欄位(timer、workqueue、kptr 等)——但這個函式在 NMI context 下呼叫並不安全。修補改用bpf_obj_cancel_fields():立即取消尚未觸發的非同步欄位,kptr 的實際釋放則延後交給配置器的解構路徑處理。修補見核心 commit28fde1356dbc("bpf: Cancel special fields when recycling rhtab elements")。屬於 maps/helper(hash map 回收路徑)攻擊面。- CVE-2026-98036(CVSS 未公布,Ubuntu priority Medium,2026-09-25 揭露):元素插入邏輯會對一個「已被回收、但尚未完成解構」的 rhtab 插槽重新執行
check_and_init_map_value(),把插槽上殘留的特殊欄位(例如仍處於武裝狀態的計時器指標)直接清零——但此時可能還有 BPF 程式持有對該計時器的參照,清理順序被打亂。修補讓「回收但尚未解構」的元素不再被重複初始化。修補見核心 commit6a5266b82882("bpf: Preserve special fields in recycled rhtab elements")。與上一筆(CVE-2026-98035)同屬 rhtab 回收路徑對特殊欄位生命週期管理不足的姊妹問題。- CVE-2026-98037(CVSS 未公布,Ubuntu priority Medium,2026-09-25 揭露):
type_is_ptr_alloc_obj()用來判斷一個指標是否指向「BPF 配置的物件」,卻沒有排除PTR_UNTRUSTED旗標——導致一個原本合法的 local kptr,在其 RCU 保護窗口結束、被降級為不可信 (untrusted) 之後,仍能通過這項檢查,進而被像bpf_refcount_acquire()這類 kfunc 接受。修補讓帶有PTR_UNTRUSTED的指標明確被排除。修補見核心 commit7441ee827664("bpf: Reject untrusted allocated-object pointers")。屬於驗證器指標可信度檢查不足的案例。- CVE-2026-98038(CVSS 未公布,Ubuntu priority Medium,2026-09-25 揭露):
bpf_refcount_acquire()原本只要看到一個經 RCU 讀取、屬於「借用而非圖節點自身持有」的 local kptr,就直接當成擁有型參照 (owning reference) 對待,讓驗證器跳過原本針對這類參照所要求的 NULL 檢查。修補讓這種借用的 RCU kptr 在通過bpf_refcount_acquire()後仍維持可為 NULL,強制呼叫端做 NULL 檢查。修補見核心 commitdc36739e5cc9("bpf: Keep refcount_acquire nullable for borrowed RCU kptrs")。- CVE-2026-98039(CVSS 未公布,Ubuntu priority Medium,2026-09-25 揭露):對
BPF_KPTR_PERCPU欄位做寫入時,驗證器沒有要求來源暫存器必須同時帶有MEM_PERCPU旗標才能匹配目的欄位——型別不比對的結果,是 per-CPU 指標與一般指標可能被混淆使用 (type confusion),存在被利用做任意核心記憶體讀寫的風險。修補要求寫入 per-CPU kptr 欄位時來源暫存器必須帶有MEM_PERCPU。修補見核心 commit048029ba1c79("bpf: Require MEM_PERCPU for percpu kptr stores")。- CVE-2026-98040(CVSS 未公布,Ubuntu priority Medium,2026-09-25 揭露):以暫存器對暫存器的形式做 NULL 檢查(例如
if (r0 == r6),而非與立即值 0 比較)時,驗證器沒有把被比較的那個「已知為零」的暫存器標記為 precise——導致狀態剪枝可能誤判,放行一段實際上會對bpf_map_lookup_elem()失敗回傳值(未經檢查的 NULL)做解參考的程式。修補讓這種暫存器形式的 NULL 檢查也把比較用的零值暫存器標記為 precise。修補見核心 commitddca9a3b8833("bpf: Mark the zero register precise for a register-form NULL check")。- CVE-2026-98042(CVSS 未公布,Ubuntu priority Medium,2026-09-25 揭露):
check_cond_jmp_op()中,collect_linked_regs()(收集彼此關聯的純量識別碼)是在暫存器狀態快照被拍下之後才執行——導致原本應該被清除的純量 id,在快照還原時又被「復活」。修補把collect_linked_regs()的呼叫時機提前到快照之前。修補見核心 commit73a98f96811e("bpf: Don't resurrect a scalar id dropped by collect_linked_regs()")。- CVE-2026-98044(CVSS 未公布,Ubuntu priority Medium,2026-09-25 揭露):舊式的
BPF_LD_ABS/BPF_LD_IND封包讀取指令,在回呼 (callback) 函式內部沒有被明確拒絕——這類指令本就會讓精確度回溯邏輯出現額外的問題(見下面 CVE-2026-98085),放進 callback 更是雪上加霜,可觸發驗證器WARN()或載入失敗。修補直接拒絕在 callback 內使用這兩個舊式指令。修補見核心 commitbc489c0c9b8c("bpf: Reject legacy packet loads from callbacks")。- CVE-2026-98045(CVSS 未公布,Ubuntu priority Medium,2026-09-25 揭露):
bpf_get_stack()/bpf_get_task_stack()有一種「可能發生 page fault (faultable)」的變體,用來解析使用者空間堆疊的 build ID,過程中可能觸發阻塞式的檔案系統讀取——但這兩個 helper 沒有被標記為 sleepable,理論上可以從非睡眠、甚至 atomic context 呼叫,踩到「在 atomic context 中睡眠」的核心大忌。修補為這兩個變體加上.might_sleep = true。修補見核心 commit9d02927fdf4e("bpf: Mark faultable stack helpers as sleepable")。- CVE-2026-98046(CVSS 未公布,Ubuntu priority Medium,2026-09-25 揭露):
bpf_btf_find_by_name_kind()內部會經__btf_new_fd()呼叫anon_inode_getfd()配置檔案描述符,這個過程可能因為 fd table 配置而睡眠——但這個 helper 本身沒有被標記為 sleepable,理論上可以在 timer callback 之類的非睡眠情境下被呼叫。修補將其標記為 sleepable。修補見核心 commit17f54a8f2b97("bpf: Mark bpf_btf_find_by_name_kind() as sleepable")。與上一筆(CVE-2026-98045)同屬本批「helper 實際會睡眠卻沒宣告 sleepable」的姊妹問題家族。- CVE-2026-98047(CVSS 未公布,Ubuntu priority Medium,2026-09-25 揭露):
in_rbtree_lock_required_cb()只檢查驗證器目前最內層的堆疊幀,漏掉了「在持有 rbtree spin lock 期間,巢狀呼叫一個靜態子程式(該子程式壓入的堆疊幀沒有設定in_callback_fn),子程式內又解鎖並重新上鎖同一個 rbtree」的情形——這段空窗期讓其他 CPU 有機會釋放正在被比較的節點,導致原生 rbtree 插入邏輯操作到已釋放記憶體。修補讓這項檢查改為往上走訪所有目前活躍的堆疊幀。修補見核心 commit369f4ce73457("bpf: Check ancestor frames for rbtree callbacks")。- CVE-2026-98048(CVSS 未公布,Ubuntu priority Medium,2026-09-25 揭露):
mark_fastcall_pattern_for_call()負責識別並改寫bpf_fastcall慣用的暫存器溢寫 (spill) / 填回 (fill) 指令序列,但沒有考慮到這段序列可能被一個跳躍/分支目標從中間切入進入——如果真的被切入,改寫邏輯可能誤判、產生錯誤的機器碼。修補借助控制流程圖 (CFG) 分析新增jump_target旗標,遇到任何屬於跳躍目標的指令就停止繼續延伸這個 pattern。修補見核心 commit24adbc2c3bbe("bpf: don't rewrite bpf_fastcall patterns entered by a jump")。- CVE-2026-98058(CVSS 未公布,Ubuntu priority Medium,2026-09-25 揭露):
bpf_sys_bpf()(在核心內完整重跑一次bpf(2)系統呼叫本體,可能取用 mutex、做GFP_KERNEL配置、等待 RCU 寬限期結束)與bpf_sys_close()都沒有被標記為 sleepable,理論上能從 hrtimer callback 之類的情境呼叫,觸發「在 atomic context 中排程」的核心錯誤。修補把這兩個系統呼叫類 helper 標記為 sleepable。修補見核心 commitd05524794240("bpf: Mark syscall helpers as sleepable")。- CVE-2026-98059(CVSS 未公布,Ubuntu priority Medium,2026-09-25 揭露):
sched_process_wait這個 raw tracepoint 的引數在某些呼叫路徑(例如wait4(-1)或waitid(P_ALL)經由do_wait())實際上可能是 NULL,但驗證器原本把這個引數當成「一律可信、絕不為 NULL」的指標對待,讓掛在這個 tracepoint 上、JIT 編譯後的 BPF 程式有機會直接解參考 NULL。修補把它加進raw_tp_null_args[],標記為可為 NULL。修補見核心 commit3c03a1b8ded8("bpf: Mark sched_process_wait argument as nullable")。- CVE-2026-98060(CVSS 未公布,Ubuntu priority Medium,2026-09-25 揭露):驗證器原本已經會拒絕在 rbtree 比較回呼內呼叫一般的 spin-lock helper,但沒有把「韌性鎖」(resilient lock,
res_spin_lock/res_spin_unlock)kfunc 一併納入這項限制——而__bpf_rbtree_add()要求整個回呼走訪過程中都持有樹根鎖,若在回呼內意外解開鎖,其他 CPU 就可能在走訪中途釋放節點。修補把韌性鎖操作也一併納入 rbtree 回呼內的禁止清單。修補見核心 commit7b7b8b596010("bpf: Reject resilient lock operations in rbtree callbacks")。與上面 CVE-2026-98047 同屬本批 rbtree 回呼鎖定保證被繞過的同類問題。- CVE-2026-98061(CVSS 未公布,Ubuntu priority Medium,2026-09-25 揭露):直接在回呼 (callback) 堆疊幀內發出 tail call,驗證器會把這個行為建模成一種「返回」——但如果這個回呼幀本身是同步回呼 (synchronous callback),這樣建模可能構造出不合法的返回狀態,在
BPF_PROG_LOAD階段觸發驗證器WARN()並回傳-EFAULT。持有CAP_BPF的一般行程即可觸發。修補直接拒絕從 callback 幀內部發出的 tail call。修補見核心 commit617c8266e49f("bpf: Reject tail calls directly from callback frames")。- CVE-2026-98062(CVSS 未公布,Ubuntu priority Medium,2026-09-25 揭露):
signal_generate/signal_deliver這兩個 raw tracepoint,在某些呼叫路徑下傳入的「siginfo」引數其實是像SEND_SIG_NOINFO/SEND_SIG_PRIV這類特殊哨兵值,而非真正指向siginfo結構的指標——但驗證器原本把它當成合法指標對待,讓掛載的 BPF 程式有機會解參考這個假指標;由於訊號產生有可能發生在計時器中斷情境下,這會直接導致核心 Panic。修補把這兩個 tracepoint 的該引數標記為純量,不再視為指標。修補見核心 commitd2eaea3599bc("bpf: Mark signal tracepoint siginfo arguments as scalar")。與上面 CVE-2026-98059 同屬本批 raw tracepoint 引數型別/可為 NULL 標記不準確的姊妹問題家族。- CVE-2026-98065(CVSS 未公布,Ubuntu priority Medium,2026-09-25 揭露):hash map(htab / rhtab)為了支援欄位解構器 (field destructor) 而新增了
map_check_btf回呼之後,一個「無鍵」(key-less,btf_key_type_id == 0)的 BTF 描述仍然可能通過驗證;之後透過 bpffs 讀取這個 map 時,btf_type_show()會嘗試顯示這個對應到void型別的鍵,卻沒有對這種特殊型別做防呆,直接解參考 NULL 造成核心崩潰。修補讓 hash map 的map_check_btf直接拒絕無鍵的 BTF。修補見核心 commit7ca2312528("bpf: Reject key-less BTF for hash maps")。- CVE-2026-98085(CVSS 未公布,Ubuntu priority Medium,2026-09-25 揭露):
backtrack_insn()在為精確度回溯建模BPF_LD_ABS/BPF_LD_IND這兩個指令時,認定它們同時具有「順序執行」與「隱含跳到子程式結尾」兩條邊——但沒有在後面那條「子程式結尾」邊上呼叫bt_subprog_enter(),導致回溯邏輯在檢視被呼叫端 (callee) 幀的指令時,卻誤在呼叫端 (caller) 的幀上操作精確度標記,可能造成 segfault 或不健全的狀態剪枝。修補補上這條邊上缺漏的bt_subprog_enter()呼叫。修補見核心 commit671b7b9a660e("bpf: backtrack_insn(): Handle ld_{abs,ind} subprog exit edge")。以下 2 筆修補檔案不在
kernel/bpf//net/bpf/本身,但問題直接關乎 BPF/XDP 攻擊面,依本節慣例一併收錄:
- CVE-2026-97955(CVSS 未公布,Ubuntu priority Medium,2026-09-25 揭露,檔案為
drivers/net/ethernet/microsoft/mana/mana_bpf.c):Azure 網卡驅動(mana)的mana_xdp_set()會先把新的 XDP 程式指標寫入apc->bpf_prog(因為後續mana_pre_alloc_rxbufs()需要依它決定 RX buffer 大小),才進行記憶體配置;若配置失敗,函式直接回傳錯誤、跳過原本負責還原舊程式指標的err_dealloc_rxbuffs清理路徑。BPF 核心此時認定這次附掛失敗,會釋放它對這個新程式的參照,程式可能被釋放——但apc->bpf_prog卻仍指向它,下一次mana_xdp_get()的呼叫端對著這個懸空指標呼叫bpf_prog_add(),形成 Use-After-Free。一般使用者透過ip link set dev ethX xdp obj ...在 RX buffer 預先配置失敗時就可能觸發。修補見核心 commit4c46beb807ef("net: mana: restore the XDP program pointer when pre-allocation fails")。屬於 maps/helper(XDP 程式生命週期)攻擊面,收錄理由與本節 6.3 節「eBPF 是節點層級」的討論相呼應——驅動層對 XDP 程式指標的生命週期管理疏漏,同樣是 BPF 資料路徑整體攻擊面的一部分。- CVE-2026-93824(CVSS 未公布,Ubuntu priority Medium,2026-09-24 揭露,檔案為
net/tls/tls_main.c):核心原本允許同一個 socket 同時掛上核心 TLS (kTLS) 卸載與 sockmap(供 sockmap iterator / redirect 之類的 BPF 程式讀寫該 socket 的資料),但這兩者對sk->sk_prot、收送資料路徑的假設彼此衝突,組合使用會讓大量既有但未被觸發的 bug 浮現。修補直接讓核心拒絕 TLS 與 sockmap 同時掛在同一個 socket 上的組合,而非嘗試讓兩者相容。修補見核心 commit(標題)"tls: reject the combination of TLS and sockmap"。與本節前述多筆 sockmap 生命週期問題(CVE-2026-63830、CVE-2026-64548、CVE-2026-53033)同屬 sockmap 攻擊面,但這次是從「禁止危險組合」直接堵死問題,而非修補既有程式碼路徑的邏輯錯誤。上述 25 筆(CVE-2026-97420、97955、93824 共 3 筆屬 2026-09-24 揭露;其餘 22 筆 CVE-2026-98xxx〔98007/98033/98034/98035/98036/98037/98038/98039/98040/98042/98044/98045/98046/98047/98048/98058/98059/98060/98061/98062/98065/98085〕屬 2026-09-25 揭露)均已逐一以 Ubuntu Security Notices 個別 CVE 頁面核實,且比對修補 commit 確認改動確實落在所描述的函式與檔案。經此次系統性複查,2026-09-25 這批公告目前已無已知遺漏。所有個案 CVSS 均未公布(Ubuntu priority 均為 Medium),故排序上 CVE-2026-74612(CVSS 10.0)仍是本節收錄清單中嚴重度最高的一筆,無需調整。這批案例又以「helper 未標記 sleepable」(CVE-2026-98045/98046/98058)、「精確度回溯/傳播鏈斷裂」(CVE-2026-98034/98040/98042/98044/98085)、「rbtree 回呼鎖定保證被繞過」(CVE-2026-98047/98060)三種模式最為集中,顯示這幾類問題在驗證器程式碼庫中屬於反覆出現的結構性弱點,而非單一個案。
這幾個案例的教育意義:eBPF 的「安全」是核心持續攻防的動態結果,不是一次性保證——生產環境務必訂閱 Linux 核心官方 CVE 公告(linux-cve-announce 郵件論壇) 或發行版的安全公告,並優先選用仍在收到安全更新的 LTS 核心。
2026-09-30 複查:對 2026-09-26 之後到本次複查為止新公告的個案,以及先前幾批「自承尚未逐一複查」的範圍做二次系統性複查,確認先前遺漏以下 2 筆核心 BPF 子系統 CVE(其中一筆屬 2026-09-25 批、一筆回頭補上 2026-09-17 批的漏網之魚,不影響上方「合計本批共 7 筆」處原本 7 筆各自的核實結果,僅為補齊該批總數):
- CVE-2026-100074(CVSS 未公布,Ubuntu priority Medium,2026-09-25 揭露):BTF 在描述 map value 內的特殊欄位(如
bpf_spin_lock、bpf_timer)時,部分欄位型別被定義為「同一個結構內只能出現一次」的唯一 (unique) 欄位——但BPF_REFCOUNT(struct bpf_refcount,用來對 local kptr 配置物件做參照計數)先前並未被標記為 unique,理論上允許在同一個結構裡宣告多個 refcount 欄位,違反參照計數機制「一個配置物件對應唯一一份計數」的不變量。修補把BPF_REFCOUNT加入 BTF 的 unique 欄位判斷清單。修補見核心 commit61e6553("bpf: Mark bpf_refcount field as unique"),問題由 6.4 版引入的 commitd54730b所致,已回溯修補至 6.18.52、7.2.6 等穩定分支。屬於本節分類中的 maps/helper(BTF 特殊欄位/local kptr 參照計數)攻擊面,與上面 CVE-2026-98038(同樣圍繞bpf_refcount_acquire()參照計數正確性)出自同一波 "bpf: Fix refcount_acquire" 修補系列,但這筆修的是欄位唯一性檢查,而非借用 RCU kptr 的可為 NULL 語意。公開資料目前未詳述此欄位唯一性缺陷的具體利用路徑,此處描述以官方 commit 訊息與 Ubuntu CVE 頁面為準,未做超出已核實範圍的臆測。- CVE-2026-92518(CVSS 7.8 High,2026-09-17 揭露,先前系統性複查遺漏):RISC-V 架構的 BPF JIT 在
CONFIG_CFI_CLANG(Clang Control Flow Integrity)開啟時,prog->bpf_func進入點本身已跳過開頭的 kcfi(Kernel CFI)指令——但 tail call 的跳躍位移量計算卻把這段已跳過的 kcfi 指令長度重複計入一次,導致實際跳躍位置多跳了 4 bytes,跳過了原本用來調整堆疊指標的指令,造成核心堆疊損毀 (kernel stack corruption)。持有CAP_BPF、可在 RISC-V +CONFIG_CFI_CLANG核心上載入並串接 tail call 的攻擊者,有機會藉損毀的堆疊進一步破壞核心記憶體,構成權限提升或阻斷服務風險。修補見核心 commit34b1bb3、52fb175、a6e11a8("riscv, bpf: Fix kernel stack corruption in tailcall")。屬於 JIT(僅 RISC-V +CONFIG_CFI_CLANG組合)攻擊面,是本節目前唯一一筆專屬 RISC-V 架構的 BPF CVE;僅影響同時符合「RISC-V 架構」與「啟用CONFIG_CFI_CLANG」兩項條件的核心組態,一般 x86_64/ARM64 節點不受影響。上述 2 筆均已以 Ubuntu 官方 CVE 頁面核實。CVE-2026-92518(CVSS 7.8)不影響排序——CVE-2026-74612(CVSS 10.0)仍是本節收錄清單中嚴重度最高的一筆。另有 CVE-2026-98158("ppp_async: drop the errored frame instead of resetting its headroom",2026-09-25 揭露)經檢視後判定不屬於 BPF 子系統本身的缺陷(問題出在 PPP 收包路徑處理錯誤訊框的方式,僅是該路徑上可能掛有 classic BPF 封包過濾器作為情境描述,修補本身完全在
drivers/net/ppp/ppp_async.c),依本節既有收錄標準(修補須落在 BPF/XDP/sockmap 本身的攻擊面)不予收錄。
- CVE-2026-98219(CVSS 未公布,Ubuntu priority Medium,2026-10-06 揭露):
sched_ext的scx_alloc_and_add_sched()在發佈ops->priv與狀態切換為SCX_ENABLING之間存在一段競態 (race) 空窗;若一個透過scx_bpf_error_bstr()(由已附掛的 BPF 程式呼叫)在這段空窗期提出的錯誤宣告,被 disable 路徑上的「尚未啟用捷徑 (pre-enable shortcut)」吃下,就會跳過原本該做的清理——排程器因此卡在「永遠無法被 disable」的狀態,而bpf_scx_unreg()卻已經釋放了仍在使用中的物件,形成 Use-After-Free。修補關閉這段「尚未啟用」期間的錯誤宣告捷徑,讓它一律走正常的 teardown 流程。修補見核心 commitc7a1c6e8004a("sched_ext: Close the pre-enable ops error claim window"),已回溯至穩定分支 commit959c66dc4a91,問題由 commit105dcd005be2引入。屬於本節分類中的 maps/helper(sched_ext kfunc)攻擊面,與上面 2026-09-11 揭露的 CVE-2026-89516/89518 同屬sched_ext/BPF_PROG_TYPE_STRUCT_OPS可插拔排程器生命週期管理出錯的同類問題,這次是貨真價實的 UAF,而非單純的斷言崩潰或鎖誤判。Ubuntu 目前把所有受支援 LTS 版本都標示為「Not affected」。CVE-2026-98220(CVSS 未公布;Amazon Linux 另給出 CVSS 3.1 4.4,Ubuntu priority Medium,2026-10-06 揭露,與上面一筆同日公告):
sched_ext的相容層 kfunc 包裝函式scx_bpf_select_cpu_and()/scx_bpf_dsq_insert_vtime(),在根排程器掛有子排程器 (sub-scheduler) 的情境下,會拒絕某些呼叫並把錯誤回報到「呼叫端任務目前所屬的排程器」上——但若呼叫端任務此時已經退出sched_ext(例如已 exit 但尚未被 reap 的任務),它的排程器指標就是 NULL,錯誤回報路徑直接解參考這個 NULL 指標,造成核心崩潰。可透過BPF_PROG_TYPE_SYSCALL程式在有子排程器掛載時觸發。修補見核心 commit0a85182723b6("sched_ext: Fix NULL sched deref in kfunc sub-sched error paths")。屬於本節分類中的 maps/helper(sched_ext kfunc)攻擊面,與上面 CVE-2026-98219 同日公告、同屬 sched_ext 子排程器錯誤處理路徑出錯的姊妹案例,但這次錯在 NULL 指標而非生命週期管理。CVE-2026-98273(CVSS 未公布,Ubuntu priority Medium,2026-10-06 揭露):x86 kprobes 核心的
int3_emulate_call()在模擬單步執行被 kprobe 取代的CALL指令時,假設該指令永遠是 5 bytes 長——但帶 CS (segment override) 前綴的call變體實際上是 6 bytes。若用 eBPF 掛載的 kprobe(例如透過BPF_PROG_TYPE_KPROBE/kprobe_multi)精確附掛在這種 6-byte CS CALL 指令的位置,模擬執行算出的返回位址會少算 1 byte,導致 CPU 從指令中間恢復執行、把後續不相關的機器碼當指令解碼,造成核心崩潰。修補改用指令解碼器實際算出的指令長度,取代原本寫死的 5 bytes。修補見核心 commita5f7a5bb3b7f("x86/kprobes: Fix crash when probing CS CALL instructions"),問題由 commit6256e66引入,已回溯至穩定分支 commitcfc1af3d054a等。嚴格來說這筆漏洞本身不在kernel/bpf/底下(修補落在arch/x86/kernel/kprobes/core.c,屬於 kprobes 核心機制而非 BPF 子系統),收錄理由與上面 6.1 節 CVE-2026-74700(TCcls_api競態)相同:Ubuntu 官方 CVE 描述明確以「用 eBPF 掛載 kprobe 觸發」為情境(eBPF 的kprobe/kprobe_multi附掛機制讓一般使用者能以較低權限〔CAP_PERFMON〕在函式內任意位元組位置掛探針,是這個漏洞最容易被觸發的途徑之一),再次提醒 eBPF 的攻擊面延伸至它所依附的核心子系統(kprobes)本身。與上面 CVE-2026-80865(kprobe_multi的copy_user_syms()缺少access_ok())同屬 kprobe 附掛機制相關的案例,但這次是指令長度假設錯誤而非指標驗證缺失。Ubuntu 在 22.04/24.04/26.04 LTS 上均標示為「Vulnerable」(尚待各核心套件更新),與上面多筆「Not affected」的 sched_ext/verifier 案例不同。上述 CVE-2026-98219/98220/98273 皆為 2026-10-06 公告、已以 Ubuntu 官方 CVE 頁面核實,確認無 2026-09-25 之後、2026-10-06 之前的遺漏批次。CVE-2026-74612(CVSS 10.0)仍是本節收錄清單中嚴重度最高的一筆。
2026-10-09 批次(2026-10-13 初次收錄時,Ubuntu CVE 追蹤系統尚未建立對應頁面,故改以 Linux 核心官方 CVE 記錄〔CNA: Linux,CVE.org 官方資料,經 CVEProject/cvelistV5 鏡像逐筆核實〕與 git.kernel.org 修補 commit 作為查核依據;2026-10-14 複查更新:逐一重新查詢 ubuntu.com/security/CVE-2026-9837x 等,Ubuntu 現已為本批全部 7 筆建立頁面〔標示 Published 2026-10-09/13,Last updated 2026-10-14〕,但 CVSS 評分欄位仍全部空白,Ubuntu priority 均為 Medium;同時本次複查也在原本記錄的 5 筆之外,發現同一批公告中另有 CVE-2026-98377、98381 兩筆先前遺漏、同屬 kernel/bpf 相關攻擊面的項目,一併補齊如下,故本批合計筆數由 5 筆更正為 7 筆。另外已核對 2026-10-12 公告的 CVE-2026-98385〔
sched/cache的 CFS cache-aware 分組與mm_struct生命週期脫鉤,僅因命名含 "sched" 而需排除,與sched_ext/BPF_PROG_TYPE_STRUCT_OPS無關〕與 2026-10-14 公告的 CVE-2026-98386~98431〔共 46 筆,涵蓋 SCSI/s390/amdgpu/Bluetooth/SMB/wifi 等子系統〕,逐筆確認均與 kernel/bpf、net/bpf 或 BPF 掛載路徑(kprobe/XDP/verifier/helper)無關,不需收錄):
- CVE-2026-98376(CVSS 未公布,Ubuntu priority Medium,2026-10-09 公布):
percpu_array_map_ops.map_meta_equal原本指向通用的bpf_map_meta_equal(),這個通用版本不會比較max_entries。當一個 percpu array 被當成 map-in-map 的 inner map 使用時,執行期可以把它替換成一個max_entries更小的 percpu array 卻通過相容性檢查——但percpu_array_map_gen_lookup()在 JIT 階段已把原本樣板 map 的index_mask內嵌成立即值,用替換後較小的 map 做查找時,就會對pptrs[]做越界存取。修補讓percpu_array_map_ops.map_meta_equal改指向已經會檢查max_entries的array_map_meta_equal()。修補見核心 commit593980175389("bpf: Use array_map_meta_equal for percpu array inner map replacement")。屬於本節分類中的 maps/helper(map-in-map 相容性檢查)攻擊面,與 2.3 節討論的 map-in-map 機制直接相關。- CVE-2026-98377(CVSS 未公布,Ubuntu priority Medium,2026-10-09 公布;2026-10-14 複查補入,屬同批次先前遺漏項目):VLAN 標籤插入函式
__vlan_insert_inner_tag()(include/linux/if_vlan.h)只透過skb_cow_head()確保寫入端有足夠 headroom,卻從未驗證 skb 內是否真的存在mac_lenbytes 的 MAC header 資料。它的兩個ETH_HLEN包裝函式——skb_vlan_push()底下的__vlan_insert_tag(),以及一般傳送路徑validate_xmit_vlan()底下的vlan_insert_tag()——都會無條件重寫skb->data開頭 16 bytes(一次 12-byte memmove 加兩次 2-byte 寫入,位移 +12 與 +14),卻沒有任何呼叫端替它做邊界檢查(相對地,「彈出 (pop)」方向的輔助函式則正確使用了skb_ensure_writable()/pskb_may_pull())。IFF_TUN裝置的hard_header_len為 0,讓packet_snd()可以送出僅 1 byte 的 AF_PACKET/SOCK_RAW 原始封包;第一次 vlan push 只會設定硬體加速 (hwaccel) 標籤,不動資料,但第二次 push——無論是走 clsact 的action vlan push,還是直接由掛載的 eBPF/TC 程式呼叫bpf_skb_vlan_push()這個 helper——都會在skb->len仍只有 1 的狀態下進入該函式。由於 skb 的 head buffer 來自不帶__GFP_ZERO的skbuff_small_headslab,每次 push 都會把skb->tail之後尚未初始化的 slab 記憶體一併拖進封包內容;連續三次 push 後,原本只送出 1 byte 的封包,離開核心時變成 13 bytes,其餘 11 bytes 全是未初始化的核心 slab 殘留資料(含疑似 linear-map 核心位址的高位 bits)外洩給網路對端,可能用於繞過 KASLR。修補要求該函式重寫的 MAC header 範圍必須確實存在,否則直接丟棄這個畸形封包。修補見核心 commitab888242fce4("vlan: require the MAC header to be present in __vlan_insert_inner_tag()"),已回溯至多個穩定分支(含40a5cc4b7251〔6.12.112〕、f42562dd027d〔6.18.55〕、59af43ccece4〔7.2.9〕)。官方記錄中此問題的「引入版本」標記為 git 歷史最早的基準 commit,意味著這個缺陷早於 git 歷史追蹤範圍、從 VLAN 子系統誕生起便存在。屬於本節分類中的 helper 攻擊面(bpf_skb_vlan_push()),這次是未初始化記憶體外洩而非越界讀取。- CVE-2026-98378(CVSS 未公布,Ubuntu priority Medium,2026-10-09 公布):
bpf_link_prime()會先把新建立的 link 插入link_idr(此時 ID 暫為 0,代表「尚未定案 (unsettled)」),之後才由anon_inode_getfile()配置對應的匿名檔案、bpf_link_settle()正式發佈真正的 ID。bpf_link_by_id()原本就懂得跳過這種 ID 為 0 的過渡態 link,但 link iterator(透過bpffs的bpf_link_seq_next()逐一走訪所有 link)卻沒有同樣的判斷,會直接對這個過渡態 link 取參照。若此時anon_inode_getfile()剛好配置失敗,建立端會把這個仍是私有狀態的 link 直接釋放——iterator 手上留著的參照就變成懸空指標,下一次bpf_link_put()存取到已釋放記憶體(KASAN slab-use-after-free)。修補讓bpf_link_get_curr_or_next()比照bpf_link_by_id()的做法,跳過 ID 為 0 的過渡態 link。修補見核心 commit50e80e2bb5e2("bpf: Skip unsettled links in link iterator"),已回溯至多個穩定分支(含68930f8d40ab等 6 個分支版本)。屬於本節分類中的 maps/helper(bpf_link生命週期)攻擊面。- CVE-2026-98381(CVSS 未公布,Ubuntu priority Medium,2026-10-09 公布;2026-10-14 複查補入,屬同批次先前遺漏項目):
veth驅動的veth_set_channels()(對應ethtool -L調整 RX/TX 佇列數)在縮減佇列數時,會替被移除的 RX 佇列拆除 XDP 相關資源(NAPI 等),卻忘了把這些佇列的rq->xdp_prog指標清空。如果這之後使用者透過ip link set xdp off或替換成另一支程式來卸載/替換該 XDP 程式,這些已被縮減、但指標未清空的佇列,手上留著的仍是舊程式的指標——而舊程式在bpf_prog_put()參照計數歸零後已被釋放。日後若再次把佇列數調大、重新啟用這些佇列的 NAPI,送達的流量會經veth_poll()→veth_xdp_rcv()→veth_xdp_rcv_skb()(drivers/net/veth.c)解參考這個指向已釋放記憶體的rq->xdp_prog,形成 Use-After-Free,導致核心 Oops 與 panic(官方描述附上的 KASAN 崩潰堆疊確認崩潰點正是veth_xdp_rcv_skb,呼叫鏈經veth_xdp_rcv→veth_poll→__napi_poll→net_rx_action)。觸發條件是對同一張 veth 裝置依序操作「縮減通道數 → 卸載/替換 XDP 程式 → 增加通道數」。veth pair 正是絕大多數 CNI 外掛(包括 Kubernetes Pod 網路)用來連接容器與主機網路的基礎設施,只要容器端(或任何在該 netns 下具備CAP_NET_ADMIN/CAP_BPF的一方)能操作ethtool/ip link調整自己這端 veth 的通道數與 XDP 掛載,就有機會觸發這條路徑——是這份清單中少見「與 Kubernetes 節點網路基礎設施(veth pair)直接相關」的 BPF/XDP 攻擊面案例。修補見核心 commit7104a3707143("veth: manage XDP program pointers during channel resize"),已回溯至 6 個穩定分支(7a8e143109ff〔5.15.222〕、1a5c5b9c64ba〔6.1.189〕、f0e8dba8c224〔6.6.158〕、3c10a5dd0d38〔6.12.112〕、25bb7c362252〔6.18.55〕、43f6b647f209〔7.2.9〕)。屬於本節分類中的 maps/helper(XDP 程式生命週期)攻擊面,與上面 CVE-2026-74612/74476(veth 驅動 XDP 資料路徑 skb 長度欄位失同步)同屬 veth/XDP 驅動整合出錯的系列問題,這次錯在通道數變更時機下的指標清理,而非 skb 欄位同步或錯誤處理路徑。- CVE-2026-98382(CVSS 未公布,Ubuntu priority Medium,2026-10-09 公布):
__bpf_offload_dev_match()在比對裝置是否相符時,若精確的 netdev 比對失敗,會退而比較兩者的offdev(offload 裝置)指標是否相同——但一般「裝置綁定、非真正 offload (dev-bound-only)」的程式,其offdev原本就是 NULL,理論上不該用這種退而求其次的比較方式。若此類程式剛好掛在一個已註冊 offload 的網卡上,就會意外繼承一個非 NULL 的真實offdev,進而與另一張無關的 sibling 網卡「比對相符」。持有CAP_BPF與CAP_NET_ADMIN的攻擊者可用bpf(BPF_LINK_CREATE)指定不同的目標 ifindex,讓一支原本綁定 veth 裝置、使用veth_xdp_buff特化欄位的程式,實際在 tun 裝置單純的xdp_buff上執行,讀取到該欄位範圍外的記憶體,造成一般保護錯誤 (general protection fault) 或 NULL 解參考當機。修補讓非 offload 程式只接受精確的 netdev 比對,offdev退而比較的邏輯只保留給真正的多埠 offload 程式使用。修補見核心 commite57f04194361("bpf: Reject dev-bound-only programs on other devices"),已回溯至多個穩定分支。屬於本節分類中的 maps/helper(BPF offload 裝置綁定)攻擊面,與上面 CVE-2026-53094(offload->prog 懸空指標)同屬 offload 裝置綁定機制出錯的同類問題,但這次錯在裝置匹配邏輯而非指標同步。- CVE-2026-98383(CVSS 未公布,Ubuntu priority Medium,2026-10-09 公布):
LWT_SEG6LOCAL類型的程式可以先用bpf_lwt_seg6_adjust_srh()讓快取的 SRH(Segment Routing Header)指標失效,接著呼叫bpf_skb_pull_data()——但後者可能導致skb->head被重新配置(realloc),使原本每 CPU 快取的 SRH 指標變成懸空指標;程式結束後,核心對 SRH 做收尾驗證時仍透過這個懸空指標寫入,形成 Use-After-Free。修補讓驗證器直接拒絕LWT_SEG6LOCAL程式使用bpf_skb_pull_data()這個 helper 組合,其餘 LWT 程式類型不受影響、仍可正常使用該 helper。修補見核心 commit0f38472a2aa8("bpf: Disallow bpf_skb_pull_data() for LWT_SEG6LOCAL"),已回溯至 4.18 以來的多個穩定分支。屬於驗證器對特定程式類型與 helper 組合檢查不足的案例,與本節前述 CVE-2026-98007(bpf_loop()引數型別)、CVE-2026-98085(backtrack_insn精確度回溯)同屬驗證器對 helper 使用前提檢查不足的同類問題家族。- CVE-2026-98384(CVSS 未公布,Ubuntu priority Medium,2026-10-09 公布):
sk_protocol欄位定義在struct sock裡,並不屬於較小的struct sock_common。但 TCP socket iterator(iter_tcp4_timewait/iter_tcp6_timewait等)可能把一個 TIME_WAIT 或 request socket(兩者都只有sock_common大小,不是完整的struct sock)交給bpf_sock_destroy(),而該 helper 原本無條件讀取sk->sk_protocol來決定後續處理方式,對著這兩種較小物件讀取就等於讀到物件外的記憶體(KASAN slab-out-of-bounds read)。修補讓sk_protocol檢查只套用在完整的struct sock上,TIME_WAIT 與NEW_SYN_RECVsocket 則交由既有的tcp_abort()邏輯正確處理。修補見核心 commit5b4eb82475ae("bpf: Fix out-of-bounds read of sk_protocol in bpf_sock_destroy()"),已回溯至多個穩定分支。屬於本節分類中的 maps/helper(bpf_sock_destroy/ socket iterator)攻擊面。上述 CVE-2026-98376/98377/98378/98381/98382/98383/98384 共 7 筆,皆於 2026-10-09 隨 Linux 核心官方 CVE 批次公告公布(CNA: Linux),核心描述、受影響版本與修補 commit 均已對照 CVE.org 官方記錄(經 CVEProject/cvelistV5 鏡像)與(98376/98378/98382/98383/98384 五筆)Ubuntu 官方頁面逐筆核實,commit hash 取自官方記錄的
references欄位,未假設或臆測。CVE-2026-74612(CVSS 10.0)仍是本節收錄清單中嚴重度最高的一筆,不受影響。已複查至 2026-10-14,確認 2026-10-12(CVE-2026-98385)與 2026-10-14(CVE-2026-98386~98431,共 46 筆)兩批公告均與 kernel/bpf 無關,無遺漏。2026-10-15 複查:確認無新批公告(Ubuntu Security Notices 與 CVEProject/cvelistV5 均無 2026-10-15 之後的新 kernel/bpf CVE),Linux 7.3 仍停在 rc7(尚未定案)。同時對先前幾批「自承可能有遺漏」的舊批次(2026-05-01、2026-05-08、2026-05-27、2026-06-19/24)做回頭複查,確認先前遺漏以下 4 筆核心 BPF 子系統 CVE,已補齊如上:CVE-2026-43306(2026-05-08,bpf crypto destructor kfunc 的 CFI 型別不匹配)、CVE-2026-45967(2026-05-27,instruction array map 偏移量重複計算)、CVE-2026-45971(2026-05-27,BPF 程式簽章大小未設上限)、CVE-2026-52938(2026-06-24,
bpf_sk_storage_clone()的 NULL pointer dereference)。以上 4 筆均已逐一核對 Ubuntu Security Notices 個別 CVE 頁面與 git.kernel.org 修補 commit(CVE-2026-43306/45967/45971 另以 CVEProject/cvelistV5 官方 JSON 記錄核實)。CVE-2026-74612(CVSS 10.0)仍是本節收錄清單中嚴重度最高的一筆,不受影響;本次新增案例 CVSS 均為 5.5(Medium),排序無需調整。2026-10-17 複查:確認 Ubuntu Security Notices 與 CVEProject/cvelistV5 均無 2026-10-15 之後的新 kernel/bpf CVE 批次公告,Linux 7.3 已於 2026-10-11 發出 rc7(Linus Torvalds 於公告中表示若無新問題,預計 2026-10-18 正式發布,目前仍未定案)。同時對 2026-09-17/18 這批「系統性複查」過的舊批次再次回頭複查,發現先前仍遺漏 CVE-2026-90300(
__bpf_get_task_stack()失敗路徑未清空輸出緩衝區,2026-09-17 公布,CVE Program 保留日期 2026-09-11),已補齊如上,該批次合計筆數由 23 筆更正為 24 筆。CVE-2026-74612(CVSS 10.0)仍是本節收錄清單中嚴重度最高的一筆,不受影響。
- CVE-2026-98589(CVSS 未公布,2026-10-18 公布):驗證器原本允許把指向封包記憶體(
PTR_TO_PACKET)的指標當作一般引數傳給子程式(subprogram)呼叫——但若該子程式內部會呼叫pskb_*系列 helper 改動封包的 linear data(例如觸發skb重新配置),傳入時驗證器核對過的那個封包指標,呼叫結束後可能已經失效,外層程式卻仍把它當成合法指標繼續使用,形成懸空指標存取。修補讓驗證器直接拒絕把可能失效的封包指標傳給任何「會修改封包」的子程式。修補見核心 commit0b6b2bb9b90a、a6c1edfbe240("bpf: Reject BPF programs passing mutable packet pointers to subprograms")。屬於驗證器對跨子程式呼叫的指標存活性檢查不足的案例。- CVE-2026-98590(CVSS 未公布,2026-10-18 公布):
bpf_sockcontext 存取rx_queue_mapping欄位時,程式碼生成邏輯誤用了需要符號擴展(sign-extend)的 64 位元MOV指令,而非驗證器原本預期、對應正確目的大小的 32 位元搬移;導致程式實際讀到的數值,可能與驗證器靜態推導出的範圍不一致,讓 BPF 程式讀到理論上不該存在的rx_queue_mapping數值。修補改為正確生成 32 位元搬移指令,並回報正確的 4-byte 目的大小。修補見核心 commite3ddcf4aeb34("bpf: Fix bpf_sock context code generation")等多筆對應穩定分支修補。屬於驗證器(context access 程式碼生成)層級的問題,與 2.4 節 CVE-2026-31413、本節 CVE-2026-31525 同屬「驗證器靜態推導與執行期實際行為不一致」的同類問題家族。- CVE-2026-98628(CVSS 未公布,2026-10-18 公布):程式通過驗證後,核心還會做一輪又一輪的「後驗證指令改寫(post-verification instruction rewrite)」(例如常數混淆 constant blinding、重寫特定 helper 呼叫),這些改寫輔助函式一次只處理/搬移一條指令,複雜度隨程式長度呈平方成長——但改寫過程完全沒有檢查是否有待處理的訊號、也不會主動讓出 CPU(reschedule)。持有載入權限的使用者可以故意提交一支含有大量無條件跳躍指令的超長程式,讓這段改寫耗時暴增,此時連
SIGKILL都無法立即中止該行程,形成本地阻斷服務(無法被殺掉的行程持續佔用 CPU)。修補讓這些改寫輔助函式變成可被取消與可重新排程的點,若常數混淆過程被中斷則回傳-EINTR(但並未解決改寫本身平方成長的時間複雜度)。修補見核心 commit56dc616d7a1f、261b61d3735b("bpf: Make post-verification instruction rewrites killable")。屬於本節分類中的 maps/helper(程式載入後改寫流程)攻擊面,性質上是可用性(DoS)問題而非記憶體安全漏洞。- CVE-2026-98641(CVSS 未公布,2026-10-18 公布):arm64 的 BPF JIT 編譯器在例外回呼(exception callback,配合
bpf_throw()/例外處理機制使用)路徑上,從未正確設定帶框指標(frame pointer)——導致這條路徑可能沿用一個已經結束、對應子程式早已離開的舊堆疊訊框(stack frame),讓例外回呼誤判自己的呼叫關係,進而可能毀損記憶體或讓核心當機。修補補上例外回呼路徑的 frame pointer 設定。修補見核心 commitecdd770a9fc3("bpf, arm64: set up the frame pointer for the exception callback")等多筆對應穩定分支修補。屬於JIT(僅限 arm64 架構)層級的問題,與 2.5 節所述各架構 JIT 實作差異相呼應——這類因單一架構 JIT 實作疏漏導致的錯誤,不影響 x86-64 等其他已支援架構。- CVE-2026-98644(CVSS 未公布,2026-10-18 公布):
__htab_map_lookup_and_delete_batch()(BPF_MAP_LOOKUP_BATCH搭配刪除的批次操作,作用於BPF_MAP_TYPE_HASH等雜湊表映射)在走訪大型雜湊表的每個 bucket 時,全程沒有任何讓出 CPU 的時機點(reschedule point)——對一個項目數極多的雜湊表發出批次查詢並刪除,會讓這個系統呼叫長時間佔用 CPU 不釋放,觸發 RCU 停滯或 soft lockup(核心偵測到某 CPU 長時間未進入排程而發出警告甚至 panic)。修補在走訪過程中加入週期性讓出 CPU 的邏輯,並從儲存的 bucket 游標(cursor)位置繼續,不影響查詢結果正確性。修補見核心 commit5c8b1869cb99("bpf: Avoid soft lockup in __htab_map_lookup_and_delete_batch()")等多筆對應穩定分支修補。屬於本節分類中的 maps/helper(雜湊表批次操作)攻擊面,性質上是可用性(DoS)問題。- CVE-2026-98799(CVSS 未公布,2026-10-18 公布):BPF 程式可以透過 trampoline(用來攔截核心函式呼叫、轉而先執行附掛的 BPF 程式的進入點機制)掛接到核心函式上;當程式被 detach(卸載)後,其所在的 trampoline image 理論上應該被釋放——但若當下正好有另一顆 CPU 的行程還執行在這個(已經 detach、記憶體即將釋放)的 trampoline image 內部,仍可能繼續跑到已釋放的程式碼,形成 Use-After-Free。修補讓 JIT 在每個呼叫點前插入可被動態修補的 nop,一旦程式被 detach 就把這個 nop 改寫成跳躍指令、直接跳過該程式,並同時調降 x86/arm64/powerpc 架構下單個 trampoline 可附掛的最大程式數量上限。修補見核心 commit
967566ad325b、17637e1a581a("bpf: Skip detached progs in trampoline images that are still in use")。屬於核心介接層(trampoline 附掛/卸載機制)的生命週期管理問題,性質與併發釋放類的 Use-After-Free 一致。- CVE-2026-98860(CVSS 未公布,2026-10-18 公布):HID-BPF 驅動層的
hid_bpf_hw_request()在檢查底層傳輸層(transport driver)回傳值時,把帶正負號的ssize_t回傳值直接與不帶正負號的size_t比較——當傳輸層回傳負數錯誤碼(例如-EPIPE)時,會被隱性提升(implicit promotion)成一個巨大的正數size_t,使原本應視為失敗的呼叫被誤判為成功,進而把未被修改的緩衝區內容當成有效資料回傳給呼叫端。修補把size轉型為ssize_t再比較,讓真正的負數錯誤碼能被正確回傳。修補見核心 commit8b85ef0f5610("HID: bpf: cast size into ssize_t to return the actual negative error code")等多筆對應穩定分支修補。屬於本節分類中的 maps/helper(HID-BPF 驅動層)攻擊面,與上面 CVE-2026-90001(HID-BPF struct_ops 銷毀路徑的 Use-After-Free)同屬 HID-BPF 框架內的問題,但這次錯在單純的有號/無號比較疏漏,而非併發生命週期管理。- CVE-2026-98800(CVSS 未公布,Ubuntu priority High,2026-10-19 公布;2026-10-21 複查補入,屬同批次先前遺漏項目):BPF 程式從 trampoline 卸載(detach)後,其專屬的 trampoline image 要等一個 RCU grace period(sleepable 程式則等 RCU tasks trace grace period)才釋放,理論上足以涵蓋所有正在執行該程式的 task——但在可被搶占 (preemptible) 的核心上,若一個 task 剛好在進入 trampoline 的「進入輔助函式 (enter helper)」之前就被搶占,此時它尚未持有對應的讀取鎖,等它被排程回來繼續執行時,呼叫的可能已是已經釋放的程式碼,形成 Use-After-Free(官方 KASAN 報告顯示崩潰點在
__bpf_prog_enter_recur())。修補讓釋放流程在既有等待之外,額外多等一個 RCU tasks grace period——因為 RCU tasks grace period 必須等到所有曾被搶占的 task 都重新執行過一次才算結束,恰好能涵蓋這個搶占時間窗。修補見核心 commit40955f6512a0、0fb5751a6e41("bpf: Wait for an RCU tasks grace period before freeing trampoline progs")。屬於核心介接層(trampoline 生命週期)問題,與上面 CVE-2026-98799(trampoline detach 後的另一條 Use-After-Free 路徑,錯在缺少可修補的 nop 跳板)同屬同一輪 trampoline 生命週期管理修補,這次錯在搶占情境下的 grace period 覆蓋範圍不足,而非缺少跳板機制。- CVE-2026-98813(CVSS 未公布,Ubuntu priority High,2026-10-19 公布;2026-10-21 複查補入,屬同批次先前遺漏項目):
bpf_ma_set_dtor()會複製一份 map 的btf_record,讓bpf_mem_alloc的解構子(destructor)之後能替 hash/rhash map 的元素釋放特殊欄位(kptr、list_head、rb_root等)——但btf_record_dup()複製時只對核心 (kernel) BTF 與模組 (module) BTF 取得參照,對指向使用者 map 自身 BTF(map->btf)的欄位(例如指向本地型別的 kptr,或list_head/rb_root攜帶的value_rec)卻完全沒有取得參照。當這份複製品的生命週期拉長——例如bpf_mem_alloc_destroy()把收尾工作交給背景 workqueue 延後執行——而 map 本身已經被bpf_map_free()釋放、連帶釋放了map->btf的參照,之後若載入該 BTF 的程式也已退出,map->btf就被真正釋放;背景 worker 透過這份複製品呼叫btf_is_kernel()、btf_find_struct_meta()時,存取到的就是已釋放記憶體(KASAN slab-use-after-free)。修補讓btf_record_dup()複製時也替 map BTF 多取一份參照,確保複製品存活期間 map BTF 不會被釋放。修補見核心 commitb506f5699e14、ab39974240a0("bpf: Hold map BTF for the memory allocator destructor record")。屬於本節分類中的 maps/helper(map BTF 參照計數)攻擊面,與 2.3 節討論的 map-in-map/BTF 機制有關,是本節另一筆因「複製 BTF 相依結構卻漏取參照」導致的生命週期管理缺陷。- CVE-2026-98816(CVSS 未公布,Ubuntu priority Medium,2026-10-19 公布;2026-10-21 複查補入,屬同批次先前遺漏項目):啟用
bpf_jit_harden=2(對所有程式、含特權程式做常數混淆)時,bpf_jit_blind_insn()會把if rX op imm goto off這類帶立即值的條件跳躍,改寫成「先用隨機數 XOR 還原立即值,再跳躍」的三段指令;若原跳躍是往回跳(backward jump),改寫邏輯會把off多減 2 以補償指令數量變化——但off是16 位元有號數,當原始off剛好是-32767或-32768時,減 2 會整數下溢(underflow)繞回,讓實際跳躍位移變成一個遠在程式結尾之後、約 32767 條指令遠的正值;又因為這個跳躍是改寫動作「新插入」的指令,既有的bpf_adj_branches()跳躍範圍檢查並不會檢查它,使這個越界跳躍得以蒙混過關,程式一執行就讓核心當機。修補讓bpf_jit_blind_insn()(以及呼叫它的bpf_jit_blind_constants())在偵測到跳躍改寫後的位移會溢位時直接回傳-ERANGE,拒絕載入。修補見核心 commit443328237113、ad139384ecdd("bpf: Fix overflow of jump offset in constant blinding")。屬於JIT(常數混淆 constant blinding)層級的問題,性質上是可用性(DoS)問題,且只在額外開啟bpf_jit_harden=2這個較少見的強化模式時才會觸發。- CVE-2026-98861(CVSS 未公布,Ubuntu priority High,2026-10-19 公布;2026-10-21 複查補入,屬同批次先前遺漏項目):fprobe(BPF kprobe-multi 機制底層依賴的追蹤設施)的
unregister_fprobe()/unregister_fprobe_async()原本倚賴標準 RCU grace period(synchronize_rcu()/call_rcu())確保所有「正在執行中的 fprobe handler」都跑完才釋放對應資源——但若 handler 剛好在RCU 未在監看(RCU not watching)的情境下執行(例如 CPU 進入 idle loop、或nohz_full的延伸靜止狀態),標準 RCU 並不會追蹤這類關閉搶占的區段,導致synchronize_rcu()根本沒等到這些執行完成,一旦 fprobe 緊接著被釋放,就形成 Use-After-Free。修補讓fprobe_ftrace_entry()、fprobe_fgraph_entry()、fprobe_return()改用新定義的guard(rcu_sched_notrace)(),並在!rcu_is_watching()時提早退出,確保這段執行一定會被涵蓋在等待範圍內(附帶好處是同時避開了原本rcu_read_lock()在CONFIG_PROVE_LOCKING下每次進入都觸發 lockdep 檢查的額外負擔)。修補見核心 commita85d0f00671b、dd4a0d4993633、e0a624919040("fprobe: Use guard(rcu_sched_notrace) and check rcu_is_watching()")。屬於核心介接層(fprobe/kprobe-multi 追蹤機制)的生命週期管理問題,與上面 CVE-2026-98800(trampoline 搶占情境下的 grace period 覆蓋範圍不足)同屬同一類「RCU 等待範圍未涵蓋特殊排程情境」的問題家族,只是這次發生在 fprobe 而非 trampoline。- CVE-2026-98865(CVSS 未公布,Ubuntu priority Low,2026-10-19 公布;2026-10-21 複查補入,屬同批次先前遺漏項目):sched_ext(以
BPF_PROG_TYPE_STRUCT_OPS掛載、可用 BPF 程式自訂 CPU 排程策略的機制)的ops.dequeue()callback,在scx_consume_dispatch_q()(consume 路徑)與move_task_between_dsqs()(move 路徑)這兩條路徑上,是在仍持有來源 DSQ(排程佇列)鎖的狀態下被呼叫的。若一個 BPF 排程器在自己的ops.dequeue()實作裡,又去走訪(iterate,例如透過bpf_iter_scx_dsq)同一個來源 DSQ 並試圖再次上鎖,就會自我死鎖(self-deadlock);即使不是同一個 DSQ,由於所有 DSQ 鎖共用同一個 lockdep 鎖類別(lock class),也會觸發 lockdep 的遞迴鎖檢查而跳出警告,實務後果是排程被卡死、系統失去回應。修補把這三條路徑上ops.dequeue()的呼叫時機,都移到 DSQ 解鎖之後執行。修補見核心 commitfe499ae9da46、cb86607ada73("sched_ext: Don't run ops.dequeue() with a DSQ lock held")。屬於本節分類中的 maps/helper(BPF_PROG_TYPE_STRUCT_OPS/sched_ext 掛載機制)攻擊面,性質上是可用性(DoS)問題;Ubuntu 將其標為 Low,原因是載入自訂 sched_ext 排程器需要在初始使用者命名空間(init userns)持有CAP_BPF,非特權使用者即使搭配CLONE_NEWUSER也無法取得這項權限。上述 CVE-2026-98589/98590/98628/98641/98644/98799/98860 原列 7 筆,加上 2026-10-21 複查補入的 CVE-2026-98800/98813/98816/98861/98865 共 5 筆,本批合計 12 筆,均於 2026-10-18 隨 Linux 核心官方 CVE 批次公告公布(CNA: Linux),核心描述、受影響版本與修補 commit 均已對照官方 CVE Program 記錄(經 CVEProject/cvelistV5 鏡像)逐筆核實,commit hash 取自官方記錄的 references 欄位,未假設或臆測。新補入的 5 筆現已可在 Ubuntu Security Notices 查到個別頁面(Ubuntu priority 分別為 High/High/Medium/High/Low,CVSS 分數欄位仍空白);其餘 7 筆因公布時間極新,Ubuntu Security Notices 尚未個別收錄,仍以 CVEProject/cvelistV5 官方記錄頁面作為連結來源。CVE-2026-74612(CVSS 10.0)仍是本節收錄清單中嚴重度最高的一筆,不受影響;本批全部案例均未見官方公布 CVSS 分數,排序無需調整。
2026-10-18 複查:新增上述 2026-10-18 公布的 CVE。同時對 2026-05-27 批次再次回頭複查,發現先前仍遺漏 CVE-2026-45927(
bpf_map_get_info_by_fd()未要求 map 已 freeze 即可計算雜湊,形成 TOCTOU),已補齊如上。CVE-2026-74612(CVSS 10.0)仍是本節收錄清單中嚴重度最高的一筆,不受影響。2026-10-19 複查:確認 Ubuntu Security Notices 與 CVEProject/cvelistV5 均無 2026-10-18 之後的新 kernel/bpf CVE 批次公告。上一輪(2026-10-17)記錄 Linux 7.3 停在 rc7、「正式發布時程仍未定案」——現已核實 Linus Torvalds 已於 2026-10-18 正式標記
v7.3發布(如期在 rc7 公告的預定日發布,未再加開 rc8),詳見 Linux 核心原始碼v7.3標籤。CVE-2026-74612(CVSS 10.0)仍是本節收錄清單中嚴重度最高的一筆,不受影響。2026-10-21 複查:確認 Ubuntu Security Notices 與 CVEProject/cvelistV5 均無 2026-10-18 之後的新 kernel/bpf CVE 批次公告;但回頭複查 2026-10-18 這批官方公告的完整清單後,發現當時遺漏了同一批次裡另外 5 筆同屬 kernel/bpf 攻擊面的項目——CVE-2026-98800、98813、98816、98861、98865——已核實並補齊如上。另外發現 CVE-2026-98869(2026-10-21 公布,屬今天才公布的全新案例,非 2026-10-18 批次遺漏項目),詳見下方獨立說明。CVE-2026-74612(CVSS 10.0)仍是本節收錄清單中嚴重度最高的一筆,不受影響。
- CVE-2026-98869(CVSS 未公布,2026-10-21 公布;因公布時間極新,Ubuntu Security Notices 尚未收錄,故以 CVEProject/cvelistV5 官方記錄頁面作為連結來源):s390 架構的 JIT 仰賴驗證器在特定時機明確插入「零擴展(zero extension)」指令,才能讓 32 位元運算(例如
w1 += 1)正確地把目的暫存器上半的 32 位元清零——這是 BPF 語意要求的行為。驗證器原本靠追蹤「暫存器上半部是否曾被讀取」(subreg_def欄位)來判斷該不該插入這段零擴展,但在改用「靜態存活性分析(static liveness analysis)」取代舊有「暫存器鏈(register-chain)存活性」追蹤方式的那次改動(核心 commit107e16979905)之後,這項追蹤邏輯未同步更新,導致兩個純量值相同、但 ALU32 定義不同的驗證器狀態,在狀態比對時被誤判為等價——其中一個狀態原本需要的零擴展,另一個卻可能因此被跳過。這是一筆驗證器與 s390 JIT 之間行為不一致的問題,與 2.4 節所述「驗證器靜態推導與執行期實際行為不一致」是同一類風險(與本節前述 CVE-2026-98590 的 context access 程式碼生成問題同屬一個問題家族),這次具體發生在跨架構(s390)零擴展追蹤邏輯上,可能讓攻擊者控制的純量暫存器上半 32 位元殘留值滲入後續的核心記憶體存取。修補改為讓bpf_compute_live_registers()直接靠靜態的暫存器存活性分析推導zext_dst,不再依賴已經與新追蹤機制脫節的subreg_def。修補見核心 commit7ce090afbf72("bpf: Infer zext_dst based on static register liveness analysis")。屬於驗證器層級的問題,僅影響 s390 架構。2026-10-23 複查:確認 Ubuntu Security Notices 與 CVEProject/cvelistV5 均無 2026-10-21 之後的新 kernel/bpf CVE 公告。CVE-2026-74612(CVSS 10.0)仍是本節收錄清單中嚴重度最高的一筆,不受影響。另確認 Cilium 於 2026-10-23 發布 1.20.4(與 1.19.10、1.18.16 同步發布的 out-of-band 安全修補版),已反映於下方「版本現況」。該版本本身不是 BPF/kernel 漏洞,而是 Go 標準函式庫 CVE-2026-111943(
crypto/x509新增拒絕清單,拒絕信任已遭竊取私鑰的 eMudhra 中繼憑證,CNA: Go)——Cilium 隨之把編譯用的 Go 版本升級到 1.26.10 以修補此問題,與本節聚焦的核心 BPF 子系統漏洞屬不同攻擊面,僅作版本追蹤記錄,不計入上方 CVE 清單。
# 檢查核心版本
uname -r
# 檢查是否啟用 BTF(CO-RE 的前提);存在此檔代表有 BTF
ls -l /sys/kernel/btf/vmlinux
# 檢查核心設定中與 eBPF 相關的選項
grep -E 'CONFIG_BPF|CONFIG_DEBUG_INFO_BTF' /boot/config-$(uname -r)
6.2 權限:從 root 走向 CAP_BPF¶
早期載入 eBPF 程式幾乎都需要 root(或 CAP_SYS_ADMIN)——權限太大,不符合最小權限原則。
核心 5.8 起引入了專屬能力 CAP_BPF,把原本綁在 CAP_SYS_ADMIN 上的 eBPF 權限拆出來,可搭配(參考:Linux capabilities(7) man page):
CAP_BPF:基本的 eBPF 操作(建立 map、做大部分bpf()系統呼叫)。注意單獨持有CAP_BPF仍無法載入大多數類型的程式。CAP_PERFMON:載入追蹤類程式(kprobe、tracepoint、perf event)所需,需與CAP_BPF搭配使用。CAP_NET_ADMIN:載入網路類(XDP / tc)程式所需,同樣需與CAP_BPF搭配。
這讓你能給一個 agent 剛好夠用的權限組合,而不是整個 root。
6.3 在容器 / Kubernetes 裡跑 eBPF 的注意事項¶
在 K8s 中部署 eBPF agent(如 Cilium、Falco、Tetragon),通常以 DaemonSet(每個節點一份)形式運行,並需注意:
- 特權或精細能力:Pod 通常需要
CAP_BPF/CAP_PERFMON/CAP_NET_ADMIN,或在受控下使用privileged: true。以 Cilium agent 為例,其預設能力清單包含NET_ADMIN、SYS_ADMIN、SYS_RESOURCE、IPC_LOCK等多項能力(完整清單見 Cilium 原始碼install/kubernetes/cilium/values.yaml中securityContext.capabilities.ciliumAgent段落所列出的預設值,額外還包含NET_RAW、SYS_MODULE、DAC_OVERRIDE、FOWNER、SETGID、SETUID、SYSLOG、CHOWN、KILL)。 - 掛載核心檔案系統:常需把宿主的
/sys/kernel/debug(debugfs)、/sys/fs/bpf(bpffs)掛進容器——eBPF 程式與 map 可以「釘選 (Pin)」到 bpffs 路徑,讓多個行程或重啟後仍能找到、複用同一份物件(eBPF Docs:Pinning)。 - eBPF 是節點層級、非命名空間化的:容器的隔離靠的是命名空間 (Namespace)、cgroup 等核心機制,但所有容器共用同一個核心;eBPF 程式作用於整個核心,而非單一容器的命名空間。意即一個節點上的 eBPF agent 看得到該節點上所有容器——這是它強大(全域可觀測)也需謹慎(權限邊界、最小權限原則更重要)之處。
- 託管叢集 (EKS/GKE/AKS) 的核心限制:你無法自選節點核心版本,得確認雲商提供的核心已啟用 BTF 並支援你需要的功能。這對前一章
02-eks學到的 AWS 環境尤其相關——選用節點 AMI 時要留意核心版本。
動手練習 7:檢視 Cilium 或 Falco 的官方 DaemonSet manifest,找出它宣告了哪些
securityContext.capabilities與volumeMounts(尤其是bpf-maps、sys-kernel-debug),對照本節說明,理解「為什麼它需要這些」。
7. 學習資源¶
| 資源 | 類型 | 說明 |
|---|---|---|
| ebpf.io | 官方入口 | eBPF 基金會官網,概念、生態系、文件總匯,最佳起點 |
| 《Learning eBPF》— Liz Rice | 書籍 | 由淺入深的入門經典,O'Reilly 出版(2023 年 3 月) |
| Cilium 官方文件 | 文件 | K8s 上實戰 eBPF 網路 / 安全 / Hubble 的權威來源 |
| libbpf-bootstrap | 範本 | libbpf + CO-RE 的官方起手範本,寫 C 必看 |
| cilium/ebpf | 函式庫 | Go 開發者寫 eBPF 的主流函式庫,含豐富範例 |
| bcc / bpftrace | 工具 | 觀測階段的必備工具集與單行追蹤語言 |
| Brendan Gregg 的網站與著作 | 進階 | 效能分析與 eBPF 追蹤的大師級資源 |
建議學習順序:ebpf.io 建立全貌 → 《Learning eBPF》系統性打底 → bpftrace/bcc 動手玩 → libbpf-bootstrap 或 cilium/ebpf 寫第一支程式 → Cilium 文件落地到 K8s。
8. 本章檢核點 (Checklist)¶
完成本章後,你應該能勾選以下每一項:
觀念理解 - [ ] 能說明「為什麼不直接寫核心模組」,並從當機風險與維護成本說明 eBPF 的優勢 - [ ] 能用「核心裡的 JavaScript」比喻向他人解釋 eBPF - [ ] 能說明驗證器 (Verifier) 的角色,以及它如何保證 eBPF 程式的安全 - [ ] 能解釋 JIT 編譯為何讓 eBPF 兼具「動態載入」與「原生效能」 - [ ] 能說出映射 (Maps) 的用途,以及它如何連接核心與使用者空間
掛載點與類型 - [ ] 能區分 kprobe、uprobe、tracepoint、XDP、tc、cgroup、LSM 各自的觸發時機 - [ ] 知道何時該優先選 tracepoint 而非 kprobe(穩定性) - [ ] 能說明 eBPF 三大應用領域:可觀測性、網路、安全
動手實作 - [ ] 已用 bpftrace 跑過至少 3 個單行程式 - [ ] 已用 bcc 工具(execsnoop / opensnoop / tcpconnect)實際觀測過系統 - [ ] 理解 CO-RE (Compile Once - Run Everywhere) 解決了什麼問題,以及 BTF 的角色 - [ ] 已建置並執行 libbpf-bootstrap 的 minimal 範例(或 cilium/ebpf 範例)
Kubernetes 整合 - [ ] 能說明為什麼 iptables 在大規模叢集會成為瓶頸,以及 eBPF 如何改善 - [ ] 知道 Cilium 用 eBPF 實作了哪些能力(CNI、取代 kube-proxy、NetworkPolicy、Hubble) - [ ] 認識 Tetragon、Falco、Pixie 各屬於哪個應用領域 - [ ] (進階)已在本地叢集安裝 Cilium 並用 Hubble 觀察過網路流
環境與部署 - [ ] 能檢查自己機器的核心版本與 BTF 是否啟用 - [ ] 知道 CAP_BPF 相較於 root 的意義(最小權限) - [ ] 理解在容器 / K8s 裡跑 eBPF 的注意事項(DaemonSet、能力、掛載 bpffs/debugfs、非命名空間化、託管叢集核心限制)
下一步:把本章學到的 eBPF 觀念,連回
01-kubernetes的網路策略與02-eks的節點選型——當你在 EKS 上選擇 Cilium 作為 CNI 時,你會清楚知道底層每一個封包,正由一段你能理解的 eBPF 程式在核心內處理。這就是雲原生最深的一層。