From d83fc032c1696194e2310903e59cda97a8aaf694 Mon Sep 17 00:00:00 2001 From: Rong Tao Date: Sun, 5 Nov 2023 13:18:46 +0800 Subject: [PATCH] tools/filegone: Support rename/unlink failed situation When deleting or renaming a file or folder for which you do not have permissions, vfs_unlink/rename will fail and we should skip the failure. Reproducing the problem: Terminal 1: $ sudo ./filegone.py Terminal 2, failed 1,2,3,4: $ sudo touch /etc/a.txt $ sudo mkdir /etc/a.dir $ # Permission deny $ rm -f /etc/a.txt rm: cannot remove '/etc/a.txt': Permission denied << 1 $ mv /etc/a.txt /etc/b.txt mv: cannot move '/etc/a.txt' to '/etc/b.txt': Permission denied << 2 $ rmdir /etc/a.dir rmdir: failed to remove '/etc/a.dir': Permission denied << 3 $ mv /etc/a.dir /etc/b.dir mv: cannot move '/etc/a.dir' to '/etc/b.dir': Permission denied << 4 $ # Success gone $ sudo mv /etc/a.txt /etc/b.txt $ sudo rm /etc/b.txt $ sudo mv /etc/a.dir /etc/b.dir $ sudo rmdir /etc/b.dir Then terminal 1, wrong statistic 1,2,3,4: $ sudo ./filegone.py TIME PID COMM ACTION FILE 13:32:11 10767 rm DELETE a.txt << 1 13:32:11 10768 mv RENAME a.txt > b.txt << 2 13:32:11 10769 rmdir DELETE a.dir << 3 13:32:11 10770 mv RENAME a.dir > b.dir << 4 13:32:11 10772 mv RENAME a.txt > b.txt 13:32:11 10774 rm DELETE b.txt 13:32:11 10776 mv RENAME a.dir > b.dir 13:32:11 10778 rmdir DELETE b.dir This commit fix the statistical error above, the result: $ sudo ./filegone.py TIME PID COMM ACTION FILE 13:36:52 10937 mv RENAME a.txt > b.txt 13:36:52 10939 rm DELETE b.txt 13:36:52 10941 mv RENAME a.dir > b.dir 13:36:52 10943 rmdir DELETE b.dir Signed-off-by: Rong Tao --- tools/filegone.py | 35 +++++++++++++++++++++++++++++++---- 1 file changed, 31 insertions(+), 4 deletions(-) diff --git a/tools/filegone.py b/tools/filegone.py index dee3f642cfad..d3ce5aa92693 100755 --- a/tools/filegone.py +++ b/tools/filegone.py @@ -10,6 +10,7 @@ # # 08-Nov-2022 Curu. modified from filelife # 19-Nov-2022 Rong Tao Check btf struct field instead of KERNEL_VERSION macro. +# 05-Nov-2023 Rong Tao Support rename/unlink failed situation. from __future__ import print_function from bcc import BPF @@ -47,11 +48,13 @@ }; BPF_PERF_OUTPUT(events); +BPF_HASH(submit_data, u64, struct data_t); // trace file deletion and output details TRACE_VFS_UNLINK_FUNC { - u32 pid = bpf_get_current_pid_tgid() >> 32; + u64 pid_tgid = bpf_get_current_pid_tgid(); + u32 pid = pid_tgid >> 32; FILTER @@ -65,7 +68,7 @@ data.action = 'D'; bpf_probe_read(&data.fname, sizeof(data.fname), d_name.name); - events.perf_submit(ctx, &data, sizeof(data)); + submit_data.update(&pid_tgid, &data); return 0; } @@ -73,7 +76,8 @@ // trace file rename TRACE_VFS_RENAME_FUNC - u32 pid = bpf_get_current_pid_tgid() >> 32; + u64 pid_tgid = bpf_get_current_pid_tgid(); + u32 pid = pid_tgid >> 32; FILTER @@ -88,10 +92,30 @@ data.action = 'R'; bpf_probe_read(&data.fname, sizeof(data.fname), s_name.name); bpf_probe_read(&data.fname2, sizeof(data.fname), d_name.name); - events.perf_submit(ctx, &data, sizeof(data)); + submit_data.update(&pid_tgid, &data); return 0; } + +int trace_return(struct pt_regs *ctx) +{ + struct data_t *data; + u64 pid_tgid = bpf_get_current_pid_tgid(); + int ret = PT_REGS_RC(ctx); + + data = submit_data.lookup(&pid_tgid); + if (data == 0) + return 0; + + submit_data.delete(&pid_tgid); + + /* Skip failed */ + if (ret) + return 0; + + events.perf_submit(ctx, data, sizeof(*data)); + return 0; +} """ bpf_vfs_rename_text_old=""" @@ -150,6 +174,9 @@ def action2str(action): b.attach_kprobe(event="vfs_unlink", fn_name="trace_unlink") b.attach_kprobe(event="vfs_rmdir", fn_name="trace_unlink") b.attach_kprobe(event="vfs_rename", fn_name="trace_rename") +b.attach_kretprobe(event="vfs_unlink", fn_name="trace_return") +b.attach_kretprobe(event="vfs_rmdir", fn_name="trace_return") +b.attach_kretprobe(event="vfs_rename", fn_name="trace_return") # header print("%-8s %-7s %-16s %6s %s" % ("TIME", "PID", "COMM", "ACTION", "FILE"))