使用PT_REGS_PARM3_CORE/PT_REGS_PARM3获取fchmodat参数遇错求助
x86_64内核5.15下eBPF获取fchmodat参数问题解决
问题1:PT_REGS_PARM3_CORE报错未声明'rsi'
PT_REGS_PARM3_CORE是BPF CO-RE架构下的寄存器访问宏,报错原因通常是CO-RE依赖的头文件或编译配置缺失,按以下步骤修复:
- 生成并引入正确的vmlinux.h:
用bpftool导出当前内核的BTF信息为C头文件:
在eBPF代码开头添加bpftool btf dump file /sys/kernel/btf/vmlinux format c > vmlinux.h#include "vmlinux.h"。 - 编译时开启CO-RE支持:
若使用Go的bpf2go工具,在go generate指令中加入--core参数,示例:
手动用clang编译时,需添加//go:generate bpf2go -cc clang -cflags "-O2 -g -Wall -Werror" --core chmod ./bpf/chmod.bpf.c-D__TARGET_ARCH_x86参数指定架构。 - 确认头文件完整性:检查vmlinux.h中是否包含
struct pt_regs的x86_64架构定义,确保rsi字段存在。
问题2:PT_REGS_PARM3导致内存访问无效
内存访问无效通常是系统调用参数判断错误或直接访问用户态内存导致,修复方案如下:
- 正确识别系统调用号:
raw_tracepoint/sys_enter中,系统调用号存储在orig_ax寄存器,而非PT_REGS_PARM1,需先过滤目标调用:__u32 syscall_nr = PT_REGS_ORIG_AX(regs); if (syscall_nr != __NR_fchmodat) return 0; - 对应正确的参数位置:
x86_64下fchmodat的参数与寄存器对应关系:- dirfd: PT_REGS_PARM1(regs)(rdi寄存器)
- pathname: PT_REGS_PARM2(regs)(rsi寄存器,用户态指针)
- mode: PT_REGS_PARM3(regs)(rdx寄存器,整数类型,可直接读取)
- flags: PT_REGS_PARM4(regs)(r10寄存器)
- 安全读取用户态内存:
pathname是用户态地址,eBPF程序不能直接解引用,需用bpf_probe_read_user_str读取:char path[256]; long ret = bpf_probe_read_user_str(path, sizeof(path), (const char *)PT_REGS_PARM2(regs)); if (ret < 0) return 0; - 确保程序权限:运行eBPF程序需root权限或具备
CAP_BPF、CAP_PERFMON等必要能力。
示例eBPF代码片段
#include "vmlinux.h" #include <bpf/bpf_helpers.h> #include <bpf/bpf_tracing.h> SEC("raw_tracepoint/sys_enter") int trace_sys_enter(struct pt_regs *regs) { __u32 syscall_nr = PT_REGS_ORIG_AX(regs); if (syscall_nr != __NR_fchmodat) { return 0; } int dirfd = PT_REGS_PARM1(regs); __u32 mode = PT_REGS_PARM3(regs); int flags = PT_REGS_PARM4(regs); char path[256]; long ret = bpf_probe_read_user_str(path, sizeof(path), (const char *)PT_REGS_PARM2(regs)); if (ret < 0) { return 0; } bpf_printk("fchmodat: dirfd=%d, path=%s, mode=%u, flags=%d", dirfd, path, mode, flags); return 0; } char _license[] SEC("license") = "GPL";
内容的提问来源于stack exchange,提问作者Kevin
相关产品推荐
相关产品推荐

