如何扩展bcc的opensnoop.py的eBPF代码实现相对路径转完整绝对路径
实现opensnoop相对路径转绝对路径的修改方案
前置说明
请先确认运行环境内核版本 >= 4.15,bpf_d_path 辅助函数从该版本开始正式可用,同时需要调整data结构体中fname字段的长度,建议从默认的256字节调整为512字节,避免拼接路径后溢出。
eBPF代码修改(替换你的TODO部分)
// new code to handle relative paths: if (data.fname[0] != '/' && data.fname[0] != '\0') { struct task_struct *task; struct fs_struct *fs; struct path pwd_path; char pwd_buf[256] = {0}; long pwd_len; long fname_len; int i, j; // 获取当前进程的task_struct task = (struct task_struct *)bpf_get_current_task(); // 读取内核空间的fs指针,必须用bpf_probe_read_kernel bpf_probe_read_kernel(&fs, sizeof(fs), &task->fs); if (!fs) { goto submit; } // 读取fs下的pwd路径结构体 bpf_probe_read_kernel(&pwd_path, sizeof(pwd_path), &fs->pwd); // 调用bpf_d_path获取当前工作目录的绝对路径 pwd_len = bpf_d_path(&pwd_path, pwd_buf, sizeof(pwd_buf)); if (pwd_len < 0 || pwd_len >= sizeof(pwd_buf)) { goto submit; } // 计算原相对文件名长度,最多读取到fname末尾 for (fname_len = 0; fname_len < sizeof(data.fname); fname_len++) { if (data.fname[fname_len] == '\0') { break; } } // 检查拼接后总长度不超过data.fname的容量 if (pwd_len + 1 + fname_len >= sizeof(data.fname)) { goto submit; } // 把pwd路径写入data.fname开头 for (i = 0; i < pwd_len; i++) { data.fname[i] = pwd_buf[i]; } // 加路径分隔符 data.fname[i++] = '/'; // 拼接原相对文件名 for (j = 0; j < fname_len; j++) { data.fname[i + j] = data.fname[j]; } // 加字符串结束符 data.fname[i + j] = '\0'; } submit: events.perf_submit(ctx, &data, sizeof(data));
额外注意点
- 如果需要兼容
openat系统调用非AT_FDCWD的场景,需要额外获取openat的第一个参数dfd对应的路径,再基于该路径拼接相对文件名,逻辑和上述获取pwd的逻辑类似,仅需要将fs->pwd替换为dfd对应的struct file的f_path字段即可。 - 如果运行时出现无效内存访问报错,大概率是内核版本的结构体偏移不匹配,可以在eBPF代码开头引入
#include <linux/fs.h>#include <linux/sched.h>头文件自动适配偏移。 - Python侧解析输出的代码如果有做字段长度校验,需要同步调整为和eBPF侧
data.fname一致的长度。
内容的提问来源于stack exchange,提问作者Chris White
相关产品推荐
相关产品推荐

