LSM BPF 程式¶
這些 BPF 程式允許特權使用者執行時檢測 LSM 鉤子,以使用 eBPF 實現系統範圍的 MAC(強制訪問控制)和審計策略。
結構¶
該示例顯示了一個可以附加到 file_mprotect LSM 鉤子的 eBPF 程式
-
int file_mprotect(struct vm_area_struct *vma, unsigned long reqprot, unsigned long prot);¶
可以在 security/security.c 中找到可以被檢測的其他 LSM 鉤子。
使用 BPF 型別格式 (BTF) 的 eBPF 程式不需要包含核心標頭檔案來訪問附加的 eBPF 程式的上下文資訊。它們可以簡單地在 eBPF 程式中宣告結構體,並僅指定需要訪問的欄位。
struct mm_struct {
unsigned long start_brk, brk, start_stack;
} __attribute__((preserve_access_index));
struct vm_area_struct {
unsigned long start_brk, brk, start_stack;
unsigned long vm_start, vm_end;
struct mm_struct *vm_mm;
} __attribute__((preserve_access_index));
注意
欄位的順序無關緊要。
如果可以在構建時訪問 BTF 資訊,則可以透過生成 vmlinux.h 來進一步簡化此操作
# bpftool btf dump file <path-to-btf-vmlinux> format c > vmlinux.h
注意
如果構建環境與部署 BPF 程式的環境匹配,則 path-to-btf-vmlinux 可以是 /sys/kernel/btf/vmlinux。
然後可以將 vmlinux.h 簡單地包含在 BPF 程式中,而無需定義型別。
可以使用 tools/lib/bpf/bpf_tracing.h 中定義的 ``BPF_PROG`` 宏來宣告 eBPF 程式。在此示例中
"lsm/file_mprotect"指示程式必須附加到的 LSM 鉤子
mprotect_audit是 eBPF 程式的名稱
SEC("lsm/file_mprotect")
int BPF_PROG(mprotect_audit, struct vm_area_struct *vma,
unsigned long reqprot, unsigned long prot, int ret)
{
/* ret is the return value from the previous BPF program
* or 0 if it's the first hook.
*/
if (ret != 0)
return ret;
int is_heap;
is_heap = (vma->vm_start >= vma->vm_mm->start_brk &&
vma->vm_end <= vma->vm_mm->brk);
/* Return an -EPERM or write information to the perf events buffer
* for auditing
*/
if (is_heap)
return -EPERM;
}
__attribute__((preserve_access_index)) 是一個 clang 特性,允許 BPF 驗證器使用 BPF 型別格式 (BTF) 資訊在執行時更新訪問的偏移量。由於 BPF 驗證器知道型別,因此它還會驗證對 eBPF 程式中各種型別的所有訪問。
載入¶
可以使用 bpf(2) 系統呼叫的 BPF_PROG_LOAD 操作載入 eBPF 程式
struct bpf_object *obj;
obj = bpf_object__open("./my_prog.o");
bpf_object__load(obj);
這可以透過使用 bpftool 生成的骨架標頭檔案來簡化
# bpftool gen skeleton my_prog.o > my_prog.skel.h
然後可以透過包含 my_prog.skel.h 並使用生成的幫助程式 my_prog__open_and_load 來載入程式。
附加到 LSM 鉤子¶
LSM 允許使用 bpf(2) 系統呼叫的 BPF_RAW_TRACEPOINT_OPEN 操作將 eBPF 程式附加為 LSM 鉤子,或者更簡單地使用 libbpf 幫助程式 bpf_program__attach_lsm。
可以透過銷燬 bpf_program__attach_lsm 返回的 link 連結來從 LSM 鉤子中分離程式,使用 bpf_link__destroy。
也可以使用 my_prog.skel.h 中生成的幫助程式,即 my_prog__attach 用於附加,my_prog__destroy 用於清理。
示例¶
可以在 tools/testing/selftests/bpf/progs/lsm.c 中找到示例 eBPF 程式,並在 tools/testing/selftests/bpf/prog_tests/test_lsm.c 中找到相應的使用者空間程式碼