最美情侣中文字幕电影,在线麻豆精品传媒,在线网站高清黄,久久黄色视频

歡迎光臨散文網(wǎng) 會(huì)員登陸 & 注冊

一文講解eBPF helper 函數(shù)的設(shè)計(jì)與實(shí)現(xiàn)

2023-11-21 15:44 作者:補(bǔ)給站Linux內(nèi)核  | 我要投稿

您是否想為內(nèi)核添加一個(gè)新的 eBPF 輔助(helper)函數(shù),但不知道從何入手?或者,您是否曾遇到過類似于?R2 type=ctx expected=fp, pkt, pkt_meta, map_value?的 eBPF verifier 報(bào)錯(cuò)?本文將從代碼層面對 eBPF 輔助函數(shù)在內(nèi)核中的設(shè)計(jì)與實(shí)現(xiàn)進(jìn)行深入淺出的分析。相信在閱讀本文后,您不僅能夠輕松應(yīng)對由于錯(cuò)誤調(diào)用輔助函數(shù)導(dǎo)致的 eBPF verifier 問題,還能了解如何實(shí)現(xiàn)一個(gè)新的 eBPF 輔助函數(shù)。

本文首先簡單介紹了 eBPF 輔助函數(shù)的概念,并探討了其在內(nèi)核中的設(shè)計(jì),包括哪些重要組成部分。隨后,結(jié)合輔助函數(shù)?bpf_perf_event_output?的實(shí)現(xiàn),幫助讀者了解實(shí)現(xiàn)一個(gè) eBPF 輔助函數(shù)所需的要素。最后,我們通過一段代碼分析了調(diào)用輔助函數(shù)時(shí)傳入不匹配的參數(shù)類型導(dǎo)致 eBPF verifier 報(bào)錯(cuò)的問題。

簡介

什么是 eBPF 輔助函數(shù)?eBPF 輔助函數(shù)是內(nèi)核提供給開發(fā)者的接口。

為什么要有 eBPF 輔助函數(shù)呢?為什么不能像驅(qū)動(dòng)一樣直接調(diào)用內(nèi)核函數(shù)呢?這主要是為了保證系統(tǒng)安全。由于 eBPF 程序運(yùn)行在內(nèi)核態(tài),為了防止不當(dāng)調(diào)用內(nèi)核函數(shù)導(dǎo)致系統(tǒng)崩潰或安全漏洞,eBPF 程序只能調(diào)用內(nèi)核提供的 eBPF 輔助函數(shù)。

截止目前內(nèi)核共提供了 210 多個(gè) eBPF 輔助函數(shù),具體詳細(xì)列表可見內(nèi)核源碼文件:include/uapi/linux/bpf.h

eBPF 輔助函數(shù)的設(shè)計(jì)

在內(nèi)核中,struct bpf_func_proto?描述了 eBPF 輔助函數(shù)的定義、入?yún)㈩愋?、返回值類型等重要信息。這些信息的指定主要是為了通過 eBPF verifier 的安全驗(yàn)證,確保傳入數(shù)據(jù)的可靠性,避免傳入錯(cuò)誤的參數(shù)導(dǎo)致系統(tǒng)崩潰。struct bpf_func_proto?的具體形式的代碼片段如下所示:

其中,func?表示該 eBPF 輔助函數(shù)的具體實(shí)現(xiàn),實(shí)現(xiàn)了特定的功能。bpf_return_type?描述該 eBPF 輔助函數(shù)的返回參數(shù)類型,而?argx_type?描述該函數(shù)的入?yún)㈩愋汀O旅鎸θ雲(yún)㈩愋秃头祷刂殿愋瓦M(jìn)行解析。

入?yún)㈩愋?/h1>

入?yún)㈩愋头譃榛绢愋秃蛿U(kuò)展類型。擴(kuò)展類型在基本類型的基礎(chǔ)上,添加了空指針類型,即允許入?yún)榭罩羔?。另外,?dāng)參數(shù)類型為?ARG_PTR_TO_BTF_ID?時(shí),則需要在?struct bpf_func_proto?的成員?argx_btf_id?指明具體的 btf 編號(hào)。

注:BTF 編號(hào)可以看成內(nèi)核數(shù)據(jù)類型的編號(hào),通過該編號(hào)可以確定數(shù)據(jù)類型。

基本類型

基本類型大致包含三類:

  1. 指針類型,指針類型又可以進(jìn)行細(xì)分:1)具體類型的指針類型,如?ARG_PTR_TO_SOCKET?表示?struct socket?指針;2)由 BTF 編號(hào)確定數(shù)據(jù)類型的指針類型,如?ARG_PTR_TO_BTF_ID?表示某一內(nèi)核數(shù)據(jù)類型指針,且該內(nèi)核數(shù)據(jù)類型由 BTF 編號(hào)指定;3)指向某一類型內(nèi)存的指針,如?ARG_PTR_TO_MAP_KEY?指向 eBPF 程序棧內(nèi)存的指針。

  2. 整數(shù)類型,如?ARG_CONST_SIZE?表示整數(shù),且該整數(shù)的值不能為 0;

  3. 任意類型,即?ARG_ANYTHING,其表示任意類型,但是需要初始化該值,否則 eBPF verifier 會(huì)報(bào)?未初始化?等相關(guān)錯(cuò)誤。

完整的基本類型如下表所示:


【文章福利】小編推薦自己的Linux內(nèi)核技術(shù)交流群:【749907784】整理了一些個(gè)人覺得比較好的學(xué)習(xí)書籍、視頻資料共享在群文件里面,有需要的可以自行添加哦?。。。ê曨l教程、電子書、實(shí)戰(zhàn)項(xiàng)目及代碼)? ? ?

零聲白金VIP體驗(yàn)卡(含基礎(chǔ)架構(gòu)/高性能存儲(chǔ)/golang/QT/音視頻/Linux內(nèi)核)課程:

擴(kuò)展類型

包含的擴(kuò)展類型如下表所示:

返回值類型

同參數(shù)類型類似,返回值類型也分為基本類型和擴(kuò)展類型。擴(kuò)展類型也是在基本類型的基礎(chǔ)添加了空指針類型。

基本類型

擴(kuò)展類型

擴(kuò)展類型是在基本類型的基礎(chǔ)上,添加了空指針類型,表示返回值可能是空指針,那么 eBPF verifier 需要考慮針對空指針進(jìn)行安全驗(yàn)證。

eBPF 輔助函數(shù)的實(shí)現(xiàn)

本小節(jié)以?bpf_perf_event_output?為例介紹 eBPF 輔助函數(shù)的實(shí)現(xiàn)。eBPF 輔助函數(shù)?bpf_perf_event_output?是應(yīng)用最廣泛的一個(gè),其主要功能是將數(shù)據(jù)通過 perf 緩沖區(qū)傳送給用戶態(tài)程序。實(shí)現(xiàn)?bpf_perf_event_output?需要完成以下三個(gè)步驟:

  1. 定義?struct bpf_func_proto?結(jié)構(gòu)體,為?bpf_perf_event_output?輔助函數(shù)指定功能函數(shù)、參數(shù)類型、返回值類型等;

  2. 為?bpf_perf_event_output?輔助函數(shù)分配唯一的編號(hào);

  3. 將?bpf_perf_event_output?與特定的 eBPF 程序類型綁定,以確保只有該類型的程序才能調(diào)用該輔助函數(shù)。

定義 struct bpf_func_proto

bpf_perf_event_output?的入?yún)㈩愋头謩e是:

  1. ARG_PTR_TO_CTX:?struct pt_regs?指針

  2. ARG_CONST_MAP_PTR:?struct bpf_map?指針

  3. ARG_ANYTHING:任意類型,且數(shù)值已初始化

  4. ARG_PTR_TO_MEM | MEM_RDONLY: 指向棧、報(bào)文或 eBPF map 元素值的指針

  5. ARG_CONST_SIZE_OR_ZERO: 整數(shù)且該整數(shù)值可為 0

返回值類型是整數(shù)類型:RET_INTEGER

添加編號(hào)

在完成?struct bpf_func_proto?的定義之后,需要為其分配一個(gè)唯一的編號(hào)。下面的代碼片段通過將其擴(kuò)展為?BPF_FUNC_perf_event_output?宏定義,并將該輔助函數(shù)的編號(hào)設(shè)置為 25,即?#define BPF_FUNC_perf_event_output 25

注:該代碼片段位于內(nèi)核源文件:include/uapi/linux/bpf.h

綁定 eBPF 程序類型

最后一步是要指定允許調(diào)用該輔助函數(shù)的 eBPF 程序類型。例如,下面的代碼片段中,允許?BPF_PROG_TYPE_KPROBE?類型的 eBPF 程序調(diào)用?bpf_perf_event_output?輔助函數(shù)。如果未指定允許調(diào)用該輔助函數(shù)的程序類型的 eBPF 程序調(diào)用了該輔助函數(shù),則在 eBPF 程序加載過程會(huì)出現(xiàn)類似于?unknown func bpf_perf_event_output#25?的 eBPF verifier 錯(cuò)誤提示。

小試牛刀

在理解了上述的理論知識(shí)后,我們可以來看看如何定位并解決開篇提到的問題:R2 type=ctx expected=fp, pkt, pkt_meta, map_value。下面是引起該錯(cuò)誤的代碼示例,讀者可以分析該代碼存在哪些問題以及如何解決這些問題。

問題解析

首先解釋一下錯(cuò)誤信息?R2 type=ctx expected=fp, pkt, pkt_meta, map_value?的含義。該錯(cuò)誤表示 R2 寄存器的數(shù)據(jù)類型應(yīng)該是指向棧內(nèi)存的指針、報(bào)文指針、或者 eBPF map 的元素值指針,但實(shí)際數(shù)據(jù)類型是 ctx,即指向?struct pt_regs?的指針。因此,該問題實(shí)際上是因?yàn)閿?shù)據(jù)類型不匹配引起的。

在調(diào)用?bpf_map_lookup_elem (&sockmap, &ctx->skaddr)?函數(shù)時(shí),我們傳遞的參數(shù)?&ctx->skaddr?是 ctx 類型參數(shù),而不是 fp 類型參數(shù)。那么為什么會(huì)有這個(gè)限制呢?

根據(jù)上文所述,eBPF 輔助函數(shù)的入?yún)㈩愋褪峭ㄟ^?struct bpf_func_proto?進(jìn)行定義的。我們可以參考?bpf_map_lookup_elem?輔助函數(shù)在內(nèi)核代碼中的實(shí)現(xiàn)來解釋這個(gè)問題。在該函數(shù)的代碼片段中,可以看到它的第二個(gè)入?yún)㈩愋蜑?ARG_PTR_TO_MAP_KEY,即指向 eBPF 程序棧內(nèi)存的指針,也就是 fp。

解決方案

針對這個(gè)問題,一般的解決方法是先定義一個(gè)棧變量,將?ctx->skaddr?的值存儲(chǔ)到棧上,例如?u64 skaddr = ctx->skaddr,然后在調(diào)用?bpf_map_lookup_elem?函數(shù)時(shí),將該棧變量的地址?&skaddr?作為函數(shù)的參數(shù)傳遞進(jìn)去。

總結(jié)

本文重點(diǎn)介紹了 eBPF 輔助函數(shù)在內(nèi)核中的設(shè)計(jì),并描述了參數(shù)類型、返回值類型等重要概念。以?bpf_perf_event_output?為例,介紹了實(shí)現(xiàn)一個(gè) eBPF 輔助函數(shù)的核心要素。eBPF 輔助函數(shù)在開發(fā) eBPF 程序中扮演著重要的角色,深入地了解 eBPF 輔助函數(shù)的設(shè)計(jì)和實(shí)現(xiàn)可以幫助解決開發(fā)過程中的許多相關(guān)問題。


原文作者:酷玩BPF


一文講解eBPF helper 函數(shù)的設(shè)計(jì)與實(shí)現(xiàn)的評論 (共 條)

使用qq登录你需要登录后才可以评论。
肇庆市| 乾安县| 儋州市| 西昌市| 玛曲县| 铜山县| 延川县| 临西县| 泰顺县| 龙井市| 宁城县| 鞍山市| 额尔古纳市| 区。| 新化县| 云梦县| 黄陵县| 越西县| 安仁县| 巴南区| 望谟县| 桐柏县| 南阳市| 新龙县| 剑河县| 霍邱县| 青铜峡市| 七台河市| 沅陵县| 伊金霍洛旗| 茌平县| 睢宁县| 绿春县| 丹棱县| 临沂市| 九江县| 建昌县| 称多县| 隆子县| 仁寿县| 克拉玛依市|