系统调用 openat 和 sys_enter_openat 有什么区别?

What is the difference between syscalls openat and sys_enter_openat?

我看到 python BCC implementation the syscall __x64_sys_openat is used to attach a kprobe, however in libbpf implementation 一个 kprobe 附加到 sys_enter_openat。似乎都捕获了 openat() 系统调用,我用 cat file.txt.

测试了它

它们有什么区别?还有哪个用起来比较靠谱?

__x64_sys_openat 内核 中某个函数的名称,BCC 将 kprobe 附加到该函数。

sys_enter_openata tracepoint in Linux 的名称,意味着这是一个(或多或少)稳定的接口,你可以挂钩用于跟踪,包括使用 eBPF 程序。您可以通过在 /sys/kernel/debug/tracing/events/ 下列出条目来查看系统上可用的跟踪点。我认为 BCC 也有一个名为 tplist 的实用程序来帮助它。

如果可以选择,我建议尽可能在跟踪点处挂钩,因为它们往往比内核内部结构更稳定:__x64_sys_openat 的参数或该函数的名称可能会在不同的内核之间发生变化例如内核版本;或者名称会在其他架构上发生变化,et cætera。但是,跟踪点不太可能更改。请注意,对于带有 CO-RE.

的 eBPF,内核内部的不稳定性有所缓解

然后并不总是可以挂钩到跟踪点:您只能使用内核中现有的跟踪点之一。如果你想挂钩到另一个不存在跟踪点的随机函数(并假设这个函数在编译时没有内联 - 通过在 /proc/kallsyms 中查找它来检查它),那么你想使用 kprobe.

有时候你还需要格外注意你hook的地方。例如,对于安全用例(即阻止系统调用),系统调用跟踪点(或相应的内核函数,显然)并不总是最好的挂钩点,因为它们可能会让您面临 TOCTOU 攻击。 LSM 挂钩可能是该用例的一个很好的解决方案。