<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          eBPF 介紹

          共 3648字,需瀏覽 8分鐘

           ·

          2022-02-17 15:53

          eBPF 是一項(xiàng)革命性的技術(shù),它能在操作系統(tǒng)內(nèi)核中運(yùn)行沙箱程序。被用于安全并有效地?cái)U(kuò)展內(nèi)核的能力而無需修改內(nèi)核代碼或者加載內(nèi)核模塊。

          從古至今,由于內(nèi)核有監(jiān)視和控制整個系統(tǒng)的特權(quán),操作系統(tǒng)一直都是實(shí)現(xiàn)可觀察性、安全性和網(wǎng)絡(luò)功能的理想場所。同時,操作系統(tǒng)內(nèi)核也很難進(jìn)化,因?yàn)樗暮诵慕巧约皩Ψ€(wěn)定和安全的高度要求。因此,操作系統(tǒng)級別的創(chuàng)新相比操作系統(tǒng)之外實(shí)現(xiàn)的功能較少。

          eBPF 從根本上改變了這個定律。通過允許在操作系統(tǒng)內(nèi)運(yùn)行沙箱程序,應(yīng)用開發(fā)者能夠運(yùn)行 eBPF 程序在運(yùn)行時為操作系統(tǒng)增加額外的功能。然后操作系統(tǒng)保證安全和執(zhí)行效率,就像借助即時編譯器(JIT compiler)和驗(yàn)證引擎在本地編譯那樣。這引發(fā)了一波基于 eBPF 的項(xiàng)目,涵蓋了一系列廣泛的使用案例,包括下一代網(wǎng)絡(luò)、可觀察性和安全功能。

          現(xiàn)在,eBPF 被廣泛用于:在現(xiàn)代數(shù)據(jù)中心和云原生環(huán)境中提供高性能網(wǎng)絡(luò)和負(fù)載均衡;以低開銷提取細(xì)粒度的安全可觀察性數(shù)據(jù);幫助應(yīng)用開發(fā)者追蹤應(yīng)用程序;洞悉性能問題和加強(qiáng)容器運(yùn)行時的安全性等等。一切皆有可能,而 eBPF 釋放的創(chuàng)新才剛剛開始。

          介紹

          如果你想要深入了解 eBPF,查看?eBPF & XDP Reference Guide。無論你是一個想要構(gòu)建 eBPF 程序的開發(fā)者還是對使用 eBPF 技術(shù)的解決方案感興趣,都有必要了解一下基本概念和架構(gòu)。

          鉤子(Hook)

          eBPF 程序是事件驅(qū)動的,當(dāng)內(nèi)核或應(yīng)用程序通過某個錨點(diǎn)時就會運(yùn)行。預(yù)定義的鉤子包括系統(tǒng)調(diào)用、函數(shù)進(jìn)入/退出、內(nèi)核追蹤點(diǎn)、網(wǎng)絡(luò)事件等等。

          如果預(yù)定義的鉤子不存在,可以創(chuàng)建一個內(nèi)核探針(kprobe)或用戶探針(uprobe)來將 eBPF 程序附加至內(nèi)核或用戶應(yīng)用程序的任何地方。

          怎么寫 eBPF 程序?

          在很多情況下,并不直接使用 eBPF,而是通過 Cilium、bcc 或 bpftrace 等項(xiàng)目間接使用,它們在 eBPF 之上提供了一層抽象,無需直接編寫程序而是提供了一些能力,由 eBPF 來實(shí)現(xiàn)。

          要是沒有上層抽象的話,就要直接編寫程序了。Linux 內(nèi)核期望 ePBF 程序以字節(jié)碼的形式加載。直接編寫字節(jié)碼不太可能,實(shí)際開發(fā)中更常見的是使用 LLVM 等編譯器套件將偽 C 代碼編譯成 eBPF 字節(jié)碼。

          Loader & Verification 架構(gòu)

          當(dāng)所需的鉤子被確定后,可以使用?bpf 系統(tǒng)調(diào)用?將 eBPF 程序加載至 Linux 內(nèi)核。通常使用 eBPF 庫完成,下節(jié)將介紹可用的開發(fā)工具鏈。

          當(dāng)程序被加載至 Linux 內(nèi)核時,在被連接到所請求的鉤子之前要經(jīng)過兩個步驟:

          驗(yàn)證

          驗(yàn)證步驟確保 eBPF 程序可以安全運(yùn)行,將檢查程序是否符合以下條件:

          • 加載 eBPF 程序的進(jìn)程的權(quán)限。除非啟用非特權(quán) eBPF,否則只有特權(quán)(privileged)進(jìn)程可以加載 eBPF 程序。

          • 程序不會崩潰或損害系統(tǒng)。

          • 程序是會運(yùn)行完成的(不會處于循環(huán)狀態(tài),這樣會耽誤進(jìn)一步處理)。

          JIT 編譯

          JIT(Just-In-Time)編譯步驟將程序的通用字節(jié)碼翻譯成機(jī)器特定的指令集來優(yōu)化程序的執(zhí)行速度。這使得 eBPF 程序可以像本地編譯的內(nèi)核代碼或作為內(nèi)核模塊加載的代碼一樣高效運(yùn)行。

          Maps

          共享收集的信息和存儲狀態(tài)的能力對 eBPF 程序來說至關(guān)重要。為此,eBPF 程序可以利用 eBPF maps 的概念來存儲和檢索數(shù)據(jù)。eBPF maps 可被 eBPF 程序以及用戶空間的應(yīng)用程序通過系統(tǒng)調(diào)用來訪問。

          map 類型支持多種數(shù)據(jù)結(jié)構(gòu):

          • 哈希表、數(shù)組

          • LRU(Least Recently Used)

          • 環(huán)形緩沖區(qū)(Ring Buffer)

          • LPM(Longest Prefix match)

          輔助調(diào)用

          eBPF 程序不能隨意調(diào)用內(nèi)核函數(shù)。這樣做的話需要使 eBPF 程序與特定的內(nèi)核版本綁定,并使程序的兼容性變得復(fù)雜。相反,eBPF 程序調(diào)用輔助函數(shù),這是內(nèi)核提供的一個穩(wěn)定的 API。

          輔助調(diào)用的集合還在持續(xù)擴(kuò)充中,以下是可用的輔助調(diào)用:

          • 生成隨機(jī)數(shù)

          • 獲取當(dāng)前時間和日期

          • eBPF map 訪問

          • 獲取進(jìn)程/cgroup 上下文

          • 操控網(wǎng)絡(luò)包和轉(zhuǎn)發(fā)邏輯

          尾部調(diào)用和函數(shù)調(diào)用

          eBPF 程序可與尾部 & 函數(shù)調(diào)用的概念相結(jié)合。函數(shù)調(diào)用允許在 eBPF 程序中定義和調(diào)用函數(shù)。尾部調(diào)用能夠調(diào)用和執(zhí)行另一個 eBPF 程序并替換執(zhí)行上下文,類似于常規(guī)進(jìn)程進(jìn)行 execve() 系統(tǒng)調(diào)用。

          eBPF 安全性

          能力越大責(zé)任越大。

          eBPF 是一項(xiàng)非常強(qiáng)大的技術(shù),目前運(yùn)行在許多關(guān)鍵軟件基礎(chǔ)設(shè)施組件的核心。在 eBPF 的開發(fā)中,當(dāng) eBPF 被考慮納入 Linux 內(nèi)核時,eBPF 的安全性是最關(guān)鍵的方面。eBPF 的安全性通過幾個層面得到保證:

          所需的權(quán)限

          除非非特權(quán)的 eBPF 被啟用,否則所有打算將 eBPF 加載到 Linux 內(nèi)核的進(jìn)程必須以特權(quán)模式(root 權(quán)限)運(yùn)行或需要 CAP_BPF 能力。這就意味著不受信任的程序無法加載 eBPF 程序。

          如果啟用了非特權(quán) eBPF,非特權(quán)進(jìn)程可以加載特定的 eBPF 程序,但功能被閹割,對內(nèi)核的訪問也受限制。

          驗(yàn)證器

          如果一個進(jìn)程被允許加載 eBPF 程序,所有程序仍會通過 eBPF 驗(yàn)證器。eBPF 驗(yàn)證器確保程序本身的安全性。例如:

          • eBPF 程序會被驗(yàn)證它們總是可以執(zhí)行完成,永不被阻塞或死循環(huán)。只有當(dāng)驗(yàn)證器能夠確保循環(huán)包含了退出條件并保證為真時,程序才會被接受。

          • 程序不得使用任何未初始化的變量或越界訪問內(nèi)存。

          • 程序不能太大,不可能加載任意大的 eBPF 程序。

          • 程序的復(fù)雜度必須有限。驗(yàn)證器將評估所有可能的執(zhí)行路徑,并且必須能夠在有限時間內(nèi)完成分析。

          加固

          在驗(yàn)證成功后,eBPF 程序會根據(jù)是從特權(quán)還是非特權(quán)進(jìn)程加載的來運(yùn)行一個“加固進(jìn)程”:

          • 程序執(zhí)行保護(hù):持有 eBPF 程序的內(nèi)核內(nèi)存被保護(hù)且只讀。出于任何原因,不論是內(nèi)核 bug 還是惡意操作,如果 eBPF 程序被試圖修改,內(nèi)核將崩潰而不是允許它繼續(xù)執(zhí)行被破壞/篡改的程序。

          • 針對 Spectre 的緩解措施:CPU 可能會預(yù)測錯分支,并留下可觀察的副作用,這些副作用可以通過旁路被提取出來。舉幾個例子:eBPF 程序屏蔽了內(nèi)存訪問來將瞬時指令下的訪問重定向到受控區(qū)域,驗(yàn)證器也會遵循只有在投機(jī)執(zhí)行下才能訪問的程序執(zhí)行路徑,JIT 編譯器在尾調(diào)用不能轉(zhuǎn)換為直接調(diào)用的情況下發(fā)出 Retpolines。

          • 常量盲化:代碼中的所有常量都被屏蔽以防止 JIT 噴涂攻擊(JIT spraying)。這可以防止攻擊者將可執(zhí)行代碼作為常量注入,存在另一個內(nèi)核 bug 的情況下,會允許攻擊者跳入 eBPF 程序的內(nèi)存段執(zhí)行代碼。

          抽象的運(yùn)行時上下文

          eBPF 程序不能隨意直接訪問內(nèi)核內(nèi)存,要想訪問程序上下文之外的數(shù)據(jù)和數(shù)據(jù)結(jié)果必須通過 eBPF 輔助工具(eBPF helper)來完成,如此保證了數(shù)據(jù)訪問的一致性并限制了 eBPF 程序的訪問權(quán)限。舉個栗子,如果確保安全的情況下,一個正在運(yùn)行的 eBPF 程序就被允許修改某些數(shù)據(jù),但不能隨機(jī)修改內(nèi)核中的數(shù)據(jù)。

          開發(fā)工具鏈

          開發(fā)者可以根據(jù)不同的需求選擇合適的工具來開發(fā)和管理 eBPF 項(xiàng)目:

          bcc

          BCC 是一個使用戶能夠編寫嵌入 eBPF 程序的 Python 腳本的框架,主要用于追蹤和剖析應(yīng)用程序和系統(tǒng),利用 eBPF 程序來在用戶空間收集統(tǒng)計(jì)數(shù)據(jù)或生成事件,并以對人類友好的形式展示。運(yùn)行 Python 程序會生成 eBPF 字節(jié)碼并將其加載進(jìn)內(nèi)核。

          bpftrace

          bpftrace 是一種 Linux eBPF 的高級追蹤語言,在 4.x 版本的內(nèi)核中可用。bpftrace 使用 LLVM 作為后端來將腳本編譯為 eBPF 字節(jié)碼,利用 BCC 和 Linux eBPF 子系統(tǒng)以及已有的 Linux 追蹤功能進(jìn)行交互:內(nèi)核動態(tài)追蹤(kprobes)、用戶級動態(tài)追蹤(uprobes)和追蹤點(diǎn)(tracepoint)。bpftrace 語言的靈感來自于 awk、C 和 Dtrace 還有 SystemTap 這樣的老一輩追蹤器。

          eBPF Go 庫

          gobpf?是一個通用的 eBPF Go 庫,將獲取 eBPF 字節(jié)碼的過程和加載/管理程序解耦。eBPF 程序通常由高級編程語言編寫,然后使用 clang/LLVM 編譯器來編譯成字節(jié)碼。

          libbpf C/C++ 庫

          libbpf?是一個基于 C/C++ 的通用 eBPF 庫,幫助將由 clang/LLVM 編譯器生成的 eBPF 對象文件和加載至內(nèi)核解耦,提供易用的 API 來抽象與 BPF 系統(tǒng)調(diào)用的交互。


          瀏覽 755
          點(diǎn)贊
          評論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          評論
          圖片
          表情
          推薦
          點(diǎn)贊
          評論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  天天爽天天日天天射天天舔天天操天天射天天搞 | 一级爱ai高清免费在线视频 | 午夜肏逼| 麻豆映画视频在线打桩机 | 玖玖视频二区 |