BPF_PROG_TYPE_CGROUP_SYSCTL

本文件描述了 BPF_PROG_TYPE_CGROUP_SYSCTL 程式型別,該型別為 sysctl 提供 cgroup-bpf 鉤子。

該鉤子必須附加到 cgroup,並且每當該 cgroup 中的程序嘗試從 proc 中的 sysctl 旋鈕讀取或寫入時都會被呼叫。

1. 附加型別

必須使用 BPF_CGROUP_SYSCTL 附加型別將 BPF_PROG_TYPE_CGROUP_SYSCTL 程式附加到 cgroup。

2. 上下文

BPF_PROG_TYPE_CGROUP_SYSCTL 提供從 BPF 程式訪問以下上下文的功能:

struct bpf_sysctl {
    __u32 write;
    __u32 file_pos;
};
  • write 指示 sysctl 值是正在讀取 (0) 還是正在寫入 (1)。此欄位是隻讀的。

  • file_pos 指示訪問 sysctl 時的檔案位置(讀取或寫入)。此欄位是讀寫的。寫入此欄位會設定 sysctl proc 檔案中 read(2) 將從中讀取或 write(2) 將寫入的起始位置。例如,即使使用者空間在 file_pos > 0 時呼叫 write(2),將零寫入此欄位也可用於透過 bpf_sysctl_set_new_value() 覆蓋整個 sysctl 值。將非零值寫入此欄位可用於從指定的 file_pos 開始訪問 sysctl 值的一部分。並非所有 sysctl 都支援在 file_pos != 0 時進行訪問,例如,對數字 sysctl 條目的寫入必須始終在檔案位置 0。另請參閱 kernel.sysctl_writes_strict sysctl。

有關如何訪問上下文欄位的更多詳細資訊,請參閱 linux/bpf.h

3. 返回碼

BPF_PROG_TYPE_CGROUP_SYSCTL 程式必須返回以下返回碼之一:

  • 0 表示“拒絕訪問 sysctl”;

  • 1 表示“繼續訪問”。

如果程式返回 0,使用者空間將從 read(2)write(2) 獲得 -1,並且 errno 將設定為 EPERM

4. 輔助函式

由於 sysctl 旋鈕由名稱和值表示,sysctl 特定的 BPF 輔助函式專注於提供對這些屬性的訪問:

  • bpf_sysctl_get_name():將 /proc/sys 中可見的 sysctl 名稱獲取到 BPF 程式提供的緩衝區中;

  • bpf_sysctl_get_current_value():將 sysctl 當前持有的字串值獲取到 BPF 程式提供的緩衝區中。此輔助函式在從 sysctl read(2) 和向 sysctl write(2) 時都可用;

  • bpf_sysctl_get_new_value():在實際寫入發生之前,獲取當前正在寫入 sysctl 的新字串值。此輔助函式只能在 ctx->write == 1 時使用;

  • bpf_sysctl_set_new_value():在實際寫入發生之前,覆蓋當前正在寫入 sysctl 的新字串值。sysctl 值將從當前的 ctx->file_pos 開始被覆蓋。如果整個值需要被覆蓋,BPF 程式可以在呼叫此輔助函式之前將 file_pos 設定為零。此輔助函式只能在 ctx->write == 1 時使用。透過此輔助函式設定的新字串值,核心會像處理使用者空間傳入的等效字串一樣進行處理和驗證。

BPF 程式以與使用者空間在 proc 檔案系統中相同的方式(即作為字串)看待 sysctl 值。由於許多 sysctl 值表示一個整數或一個整數向量,因此可以使用以下輔助函式從字串中獲取數值:

  • bpf_strtol():將字串的初始部分轉換為長整數,類似於使用者空間的 strtol(3)

  • bpf_strtoul():將字串的初始部分轉換為無符號長整數,類似於使用者空間的 strtoul(3)

有關此處描述的輔助函式的更多詳細資訊,請參閱 linux/bpf.h

5. 示例

有關用 C 語言編寫的 BPF 程式示例,該程式訪問 sysctl 名稱和值,解析字串值以獲取整數向量,並使用結果決定是否允許或拒絕訪問 sysctl,請參閱 test_sysctl_prog.c

6. 注意事項

BPF_PROG_TYPE_CGROUP_SYSCTL 旨在用於受信任的根環境,例如監控 sysctl 使用情況或捕獲在單獨 cgroup 中以 root 身份執行的應用程式嘗試設定的不合理值。

由於 task_dfl_cgroup(current)sys_read / sys_write 時被呼叫,它可能返回與 sys_open 時不同的結果,即在 proc 檔案系統中開啟 sysctl 檔案的程序可能與嘗試從中讀取/寫入的程序不同,並且這兩個程序可能在不同的 cgroup 中執行,這意味著 BPF_PROG_TYPE_CGROUP_SYSCTL 不應作為限制 sysctl 使用的安全機制。

與任何 cgroup-bpf 程式一樣,如果執行在 cgroup 中的應用程式以 root 身份執行,並且不應允許其分離/替換管理員附加的 BPF 程式,則應格外小心。