iovisor / bcc

BCC - Tools for BPF-based Linux IO analysis, networking, monitoring, and more
Apache License 2.0
20.58k stars 3.88k forks source link

how to get file path while tracing unlink system call to track deletion of files #3635

Open Dinakaranevil opened 3 years ago

Dinakaranevil commented 3 years ago

I wanted to trace unlink_at system call to find whether files are getting deleted or not for this solution i used bcc python

#!/usr/bin/python3

from bcc import BPF
from time import sleep
import psutil
from bcc.utils import printb
import os

bpf_source='''
#include <linux/sched.h>

BPF_PERF_OUTPUT(events);

struct data_t{
    u32 pid;
    char fname[NAME_MAX];
    char comm[TASK_COMM_LEN];

};
struct sys_enter_unlinkat_args_t{
    uint64_t _unused;
    u32 nr;
    u64 dfd;
    char *fname;
    u64 flags;
    u64 mode;

};

int sys_enter_unlinkat_fn(struct sys_enter_unlinkat_args_t *args)
{

    struct data_t data = {};
    bpf_get_current_comm(&data.comm, sizeof(data.comm));
    bpf_trace_printk("%s",data.comm);

    u32 pid = (u32)(bpf_get_current_pid_tgid() >> 32);
    u32 tid = (u32)bpf_get_current_pid_tgid();

    bpf_trace_printk("unlinkat has occured %d \\n",pid);
    data.pid=pid;

    bpf_probe_read_str(data.fname,64,args->fname);
    events.perf_submit(args,&data,sizeof(data));

    return 0;

}
'''

bpf= BPF(text=bpf_source)
bpf.attach_tracepoint(tp="syscalls:sys_enter_unlinkat",fn_name="sys_enter_unlinkat_fn")
print("%s %-16s %-16s %-16s" %("PID","ARG","COMMAND","PATH"))
def print_event(cpu, data, size):
    event = bpf["events"].event(data)
     printb(b"%d %-16s %-16s " %(event.pid,event.fname,event.comm))

bpf["events"].open_perf_buffer(print_event)
while 1:
    try:
        bpf.perf_buffer_poll()
    except KeyboardInterrupt:
        exit()

A) Is this the way to track files that are deleted by tracing unlink system call B)if A is the proper approach then so to achieve file path i just went through issue #237 there are two recommnedations

1)to use dentry and traverse it continuosly but its not recommended for longer run its not recommended 2)to use bpf_dpath but this helper function needs struct file as an input and i am not sure how to get that

please provide your insights on this

yonghong-song commented 3 years ago

The following approach is the best, but it is not supported by the kernel yet. Use kfunc with kernel function security_path_unlink. linux/security.h:int security_path_unlink(const struct path dir, struct dentry dentry); The kernel bpf_d_path helper:

@chenhengqi has a upstream patch for this, but not merged yet.

In the same time, you can still attach to security_path_unlink() function with kfunc or kprobe, but you need to do your own path traversal similar to kernel code in bpf program.

Dinakaranevil commented 3 years ago

Hi @yonghong-song thanks for the insights

but you need to do your own path traversal similar to kernel code in bpf program.

this means should we check the file exits each time if security_path_unlink function is executed could you give some more info on this

Dinakaranevil commented 3 years ago

Hi @chenhengqi

@chenhengqi has a upstream patch for this, but not merged yet. can you attach any related issues so that i get notified when it is merged

chenhengqi commented 3 years ago

Still on my TODO list, will pick up that work soon.

Dinakaranevil commented 3 years ago

Hi @chenhengqi , Is there anyway that i can help you out with it

Dinakaranevil commented 3 years ago

Hi @chenhengqi ,@yongshong-song , Can i try to identify the deletion of files even before the deletion of files happens so that i can hook a function to take the backup and then deletion of file happens.

chenhengqi commented 3 years ago

Use LSM_PROBE to hook security_path_unlink, reject such call and make the backup, then delete the file. (I am not sure whether this way works)