bpftrace报cannot open kprobe主因是yama.ptrace_scope限制非特权进程追踪内核符号;其值0-3逐级收紧权限,默认1仅允父子trace,而kprobe attach依赖perf_event_open等被yama拦截的机制。

为什么 bpftrace 报 cannot open kprobe 且跟 yama.ptrace_scope 有关
bpftrace 在 attach kprobe 时失败,核心原因是内核拒绝了对 kernel symbol 的动态追踪权限。这不是 bpftrace 自身 bug,而是 Yama LSM 模块通过 yama.ptrace_scope 限制了非特权进程对内核的 ptrace-style 访问——而 kprobe attach 底层依赖 ptrace(PTRACE_ATTACH) 或类似机制(如 perf_event_open 对 kernel text 的访问),会被该参数拦截。
yama.ptrace_scope 的四个取值和实际影响
该 sysctl 值控制谁可以 trace/attach 到其他进程或内核符号:
-
0:经典模式,任何用户可 ptrace 同用户进程;但 仍禁止 attach kprobe/kretprobe(因涉及 kernel text) -
1(默认值):仅允许父进程 trace 子进程;bpftrace启动后无法 attach 到任意 kernel function -
2:仅允许 CAP_SYS_PTRACE 权限的进程做 ptrace;普通用户运行bpftrace必然失败 -
3:完全禁用所有 ptrace(包括strace),kprobe 肯定不可用
注意:bpftrace 即使以 root 运行,在 ptrace_scope=1 下仍可能失败——因为它的 probe attach 不走传统 ptrace 流程,而是通过 perf_event_open + PROG_TYPE_KPROBE,而该路径在较新内核中也被 yama 拦截。
绕过限制的实操方式(按推荐顺序)
优先使用最小权限方案,避免全局降级安全策略:
- 临时放宽(调试用):
sudo sysctl -w kernel.yama.ptrace_scope=0 - 更安全的替代:用
sudo setcap cap_sys_ptrace+ep /usr/bin/bpftrace,再设ptrace_scope=1或2,部分内核版本可生效(取决于 perf_event 和 bpf 权限联动逻辑) - 检查是否已启用
CONFIG_SECURITY_YAMA:zcat /proc/config.gz | grep YAMA或查/boot/config-$(uname -r);若未启用,问题根源不在 yama - 确认 bpftrace 是否用了
--unsafe模式:bpftrace --unsafe -e 'kprobe:do_sys_open { printf("hit\n"); }';某些发行版默认禁用 unsafe 操作
容易被忽略的兼容性细节
不同内核版本对 yama 和 bpf 的交互处理不一致:
- Linux 5.8+ 引入了
bpf_kprobe_multi,部分绕过传统 kprobe 权限检查,但 bpftrace 默认不用它 - Ubuntu/Debian 默认启用了 yama,CentOS/RHEL 7/8 默认也启用,但 RHEL 9+ 改为 opt-in(
security=yama需显式加到 kernel cmdline) -
ptrace_scope=0并不能解决所有 kprobe 失败——如果内核编译时关了CONFIG_KPROBES或CONFIG_BPF_KPROBE_OVERRIDE,照样报错
真正要确认是否是 yama 导致的问题,最直接的方法是:sudo sysctl kernel.yama.ptrace_scope 查当前值,再配合 dmesg -T | tail -10 看是否有 yama_ptrace_access_check 拒绝日志。










