openEuler 2203 中利用ebpf实现文件变更实时监控


在利用ebpf监控文件变更操作中,记录一些内核参数获取的过程。
1.环境信息 

 openeuler 2203

2.常用的修改文件的方式或者命令
1).直接使用文件系统的操作接口,比如write等;
2.)系统命令,比如vim/vi,sed,echo,cp,mv
涉及到的系统调用主要有:

sys_enter_write
sys_enter_renameat2
sys_enter_rename
sys_enter_copy_file_range
sys_enter_unlinkat


3.监控中参数获取遇到问题
1).根据fd获取文件的名称

在ebpf中函数sys_enter_write函数的参数,可以通过命令bpftrace:

#  bpftrace -vl tracepoint:syscalls:sys_enter_write
tracepoint:syscalls:sys_enter_write
    int __syscall_nr
    unsigned int fd
    const char * buf
    size_t count

如果需要在sys_entrer_write中获取fd对应文件名称,通过以下方式:

    unsigned int fd;
    struct task_struct* t;
    struct task_struct* p;
    struct files_struct* f;
    struct fdtable* fdt;
    struct file** fdd;
    struct file* file;
    struct path path;
    struct dentry* dentry;
    struct inode* inode;
    struct qstr pathname;
    umode_t mode;
    unsigned long i_ino;
    char filename[128];

    fd =args->fd;
    t = (struct task_struct*)bpf_get_current_task();
    bpf_probe_read(&f, sizeof(f), &(t->files));
    bpf_probe_read(&fdt, sizeof(fdt), (void*)&f->fdt);
    int ret = bpf_probe_read(&fdd, sizeof(fdd), (void*)&fdt->fd); 
    bpf_probe_read(&file, sizeof(file), (void*)&fdd[fd]);
    //可以获取到文件的inode
    bpf_probe_read(&inode, sizeof(inode), &file->f_inode);
    bpf_probe_read(&e.i_ino, sizeof(i_ino), &inode->i_ino);
    bpf_probe_read(&mode, sizeof(mode), &inode->i_mode);
   //可以对文件的类型过滤
    if(!S_ISREG(mode)){
        return 0;
    }

    //获取文件的名称
    bpf_probe_read(&path, sizeof(path), (const void*)&file->f_path);
    bpf_probe_read(&dentry, sizeof(dentry), (const void*)&path.dentry);
    bpf_probe_read(&pathname, sizeof(pathname), (const void*)&dentry->d_name);


2).文件绝对路径获取
操作文件的时候,传入参数文件路径可以是相对路径或者是绝对路径,如果是相对路径可能需要在获取文件的完成路径。
在ebpf安全保护机制下,不可控循环可能不让操作,所以这边固定了循环次数,也就是固定目录的深度,这个地方举例是4级目录结构。

struct dentry* d_parent;
#pragma unroll
for (int i = 0; i < MAX_DEPTH; i++) {
    bpf_probe_read(&d_parent, sizeof(d_parent), (const void*)&dentry->d_parent);
    if (d_parent == dentry) {
        break;
    }
    if(i == 0){
        bpf_probe_read(&e.dir1, sizeof(d_parent->d_iname), (const void*)&d_parent->d_iname);
    }else if(i == 1){ 
         bpf_probe_read(&e.dir2, sizeof(d_parent->d_iname), (const void*)&d_parent->d_iname);
    }else if(i == 2){
         bpf_probe_read(&e.dir3, sizeof(d_parent->d_iname), (const void*)&d_parent->d_iname);
    }else if(i == 3){
         bpf_probe_read(&e.dir4, sizeof(d_parent->d_iname), (const void*)&d_parent->d_iname);
    }
    dentry = d_parent;
}


上边循环中,可以用数组来保存目录的名称,但是具体实现过程,编译没有过,暂时用这个临时方法代替。报错问题还在研究中。


3).文件唯一性标记问题
sed,vim等命令修改文件,每次更新,文件的inode会变化,这个和命令的实现机制有关,有的时候可能还是需要用文件的名称来做唯一标记。


 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

daolongzhang

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值