探索aarch64架构上使用ftrace的BPF LSM

探索aarch64架构上使用ftrace的BPF LSM

💡 原文中文,约32500字,阅读约需78分钟。
📝

内容提要

本文探讨了在ARM64架构上使用ftrace的BPF LSM的差异,并介绍了作者在MacBook M2上开发eBPF程序时遇到的问题。作者通过使用bpftrace和trace-cmd工具来调查问题,并发现在Linux 5.15和6.1内核上加载BPF LSM程序时出现了错误。经过分析,作者发现这是因为缺少对aarch64架构的支持。然而,作者指出这个问题将在下一个6.4版本的Linux内核中得到修复。

🔎

延伸解读

问题根源:aarch64 缺少 ftrace 直接调用支持

文章通过 ftrace 跟踪发现,在 aarch64 上加载 BPF LSM 程序失败的根本原因是内核缺少 CONFIG_DYNAMIC_FTRACE_WITH_DIRECT_CALLS 支持。在 5.15 内核中,arch_prepare_bpf_trampoline 返回 -ENOTSUPP;在 6.1 内核中,虽然该函数已实现,但 register_fentry 中因 tr->fops 未初始化而再次返回 -ENOTSUPP。这导致依赖 ftrace 直接调用的 BPF LSM 程序无法附加。

排查方法:利用 ftrace 和 bpftrace 定位内核缺失功能

作者使用 trace-cmd 记录函数调用图,并结合 bpftrace 捕获关键函数的返回值,从而定位到错误发生在 arch_prepare_bpf_trampoline 和 register_fentry 等函数。这种方法对于分析内核中“不存在”的功能特别有效,因为它能揭示错误返回的路径。读者在遇到类似内核功能缺失问题时,可以借鉴这种从系统调用入口开始、逐步缩小范围的调试思路。

版本差异:5.15 与 6.1 内核的表现及修复预期

在 Linux 5.15 上,aarch64 的 arch_prepare_bpf_trampoline 是弱符号占位实现,直接返回 -ENOTSUPP。到了 6.1,该函数已实现,但 register_fentry 中仍因缺少 ftrace 直接调用支持而失败。文章指出,相关补丁已合并到主线,预计在 6.4 内核中启用 aarch64 的 BPF LSM 支持。因此,在 6.4 之前,aarch64 用户需依赖 Kprobes 等替代方案。

❓

Q&A

为什么在aarch64架构上加载BPF LSM程序会失败?

在aarch64架构上,由于缺少ftrace直接调用(CONFIG_DYNAMIC_FTRACE_WITH_DIRECT_CALLS)功能,导致BPF LSM程序加载失败。具体来说,在Linux 5.15和6.1内核上,当尝试加载BPF LSM程序时,会返回错误代码ENOTSUPP(524)。

在aarch64上,BPF LSM和Kprobes有什么区别?

在x86_64上,BPF LSM可以直接使用;而在aarch64上,由于缺乏对BPF LSM的支持,通常依赖于Kprobes来实现类似功能。BPF LSM提供了更直接的安全钩子,而Kprobes则是动态跟踪机制。

如何调查aarch64上BPF LSM加载失败的问题?

可以使用bpftrace和trace-cmd工具进行调查。通过bpftrace捕获内核函数的返回值,例如使用kretprobe:arch_prepare_bpf_trampoline来检查错误代码;使用trace-cmd记录函数调用图,分析内核执行路径,从而定位问题。

在Linux 5.15和6.1内核上,BPF LSM加载失败的具体表现是什么?

在Linux 5.15和6.1内核上,尝试加载BPF LSM程序(如path_mknod钩子)时,会返回错误代码524(ENOTSUPP)。在5.15上,arch_prepare_bpf_trampoline函数返回-524;在6.1上,虽然该函数不再返回错误,但register_fentry函数因tr->fops未初始化而返回-ENOTSUPP。

aarch64上BPF LSM支持缺失的具体内核机制是什么?

缺失的机制是CONFIG_DYNAMIC_FTRACE_WITH_DIRECT_CALLS,该配置依赖于HAVE_CONFIG_DYNAMIC_FTRACE_WITH_DIRECT_CALLS,而aarch64架构未实现此功能。这导致在bpf_trampoline_lookup中,tr->fops字段未被初始化,进而使register_fentry返回-ENOTSUPP。

这个问题在哪个Linux内核版本中得到修复?

该问题预计在Linux 6.4内核版本中得到修复。一个补丁已经合并到mainline分支,该补丁将在aarch64上启用LSMs(以及其他功能),从而支持BPF LSM。

🏷️

标签

➡️

继续阅读