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
。
然后,可以在 BPF 程序中直接包含 vmlinux.h
,而无需定义类型。
可以使用 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
操作,或者更简单地使用 libbpf 助手 bpf_program__attach_lsm
,将 eBPF 程序作为 LSM 钩子附加。
可以使用 bpf_link__destroy
来销毁 bpf_program__attach_lsm
返回的 link
链接,从而将程序从 LSM 钩子中分离。
还可以使用 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 中找到相应的用户空间代码