如何为自定义系统调用追踪器添加系统调用参数存储功能?
如何为系统调用追踪器添加参数存储功能?
要让你的系统调用追踪器存储参数,需要分两步修改代码:更新事件结构体以容纳参数,以及在追踪点中捕获并填充参数数据。
1. 更新事件结构体
x86_64架构下的系统调用最多包含6个参数,我们可以在data_t中添加一个u64类型的数组来存储这些参数(u64能兼容所有参数类型)。修改后的结构体如下:
struct data_t{ u32 pid; char p_comm[TASK_COMM_LEN]; char comm[TASK_COMM_LEN]; u32 syscall_id; u64 ts; u64 args[6]; // 存储最多6个系统调用参数 };
2. 修改追踪点代码
注意:你当前使用的raw_syscalls:sys_exit追踪点只能获取系统调用的返回值,无法直接拿到调用参数——参数需要在系统调用进入阶段捕获,也就是改用raw_syscalls:sys_enter追踪点。该追踪点的args结构体已经包含了系统调用ID和参数数组。修改后的代码如下:
TRACEPOINT_PROBE(raw_syscalls, sys_enter){ struct task_struct *task; u64 pid_tgid = bpf_get_current_pid_tgid(); u32 key = pid_tgid >> 32; task = (struct task_struct *)bpf_get_current_task(); struct data_t event = {}; bpf_probe_read_kernel_str(&event.p_comm, TASK_COMM_LEN, task->real_parent->comm); bpf_get_current_comm(&event.comm, sizeof(event.comm)); event.pid = key; event.syscall_id = args->id; // 复制系统调用参数到事件结构体 __builtin_memcpy(&event.args, args->args, sizeof(event.args)); // 记录时间戳 event.ts = bpf_ktime_get_ns(); syscalls.ringbuf_output(&event, sizeof(event), 0); return 0; }
额外注意事项
- 不同CPU架构的系统调用参数数量、传递方式可能不同,上述代码针对x86_64架构优化,其他架构需要调整参数数组的长度或类型。
- 如果需要同时记录参数和返回值,可以用BPF哈希表:在
sys_enter时将参数存入map(以PID+TGID或其他唯一标识为键),在sys_exit时取出参数,和返回值一起输出后再删除map中的条目。 - 确保结构体内存对齐符合BPF要求,避免程序加载失败;如果遇到对齐问题,可以给结构体添加
__attribute__((packed))属性。
内容的提问来源于stack exchange,提问作者Afonso Pinto
相关产品推荐
相关产品推荐

