diff --git a/tools/opensnoop.py b/tools/opensnoop.py index 51d3dc055345..3b508875f880 100755 --- a/tools/opensnoop.py +++ b/tools/opensnoop.py @@ -112,8 +112,52 @@ bpf_text_kprobe = """ BPF_HASH(infotmp, u64, struct val_t); -int trace_entry(struct pt_regs *ctx, int dfd, const char __user *filename, int flags) +int trace_return(struct pt_regs *ctx) +{ + u64 id = bpf_get_current_pid_tgid(); + struct val_t *valp; + struct data_t data = {}; + + u64 tsp = bpf_ktime_get_ns(); + + valp = infotmp.lookup(&id); + if (valp == 0) { + // missed entry + return 0; + } + bpf_probe_read_kernel(&data.comm, sizeof(data.comm), valp->comm); + bpf_probe_read_user(&data.fname, sizeof(data.fname), (void *)valp->fname); + data.id = valp->id; + data.ts = tsp / 1000; + data.uid = bpf_get_current_uid_gid(); + data.flags = valp->flags; // EXTENDED_STRUCT_MEMBER + data.ret = PT_REGS_RC(ctx); + + events.perf_submit(ctx, &data, sizeof(data)); + infotmp.delete(&id); + + return 0; +} +""" + +bpf_text_kprobe_header_open = """ +int syscall__trace_entry_open(struct pt_regs *ctx, const char __user *filename, int flags) { +""" + +bpf_text_kprobe_header_openat = """ +int syscall__trace_entry_openat(struct pt_regs *ctx, int dfd, const char __user *filename, int flags) +{ +""" + +bpf_text_kprobe_header_openat2 = """ +#include +int syscall__trace_entry_openat2(struct pt_regs *ctx, int dfd, const char __user *filename, struct open_how *how) +{ + int flags = how->flags; +""" + +bpf_text_kprobe_body = """ struct val_t val = {}; u64 id = bpf_get_current_pid_tgid(); u32 pid = id >> 32; // PID is higher part @@ -137,38 +181,50 @@ return 0; }; +""" -int trace_return(struct pt_regs *ctx) +bpf_text_kfunc_header_open = """ +#if defined(CONFIG_ARCH_HAS_SYSCALL_WRAPPER) && !defined(__s390x__) +KRETFUNC_PROBE(FNNAME, struct pt_regs *regs, int ret) { - u64 id = bpf_get_current_pid_tgid(); - struct val_t *valp; - struct data_t data = {}; - - u64 tsp = bpf_ktime_get_ns(); - - valp = infotmp.lookup(&id); - if (valp == 0) { - // missed entry - return 0; - } - bpf_probe_read_kernel(&data.comm, sizeof(data.comm), valp->comm); - bpf_probe_read_user(&data.fname, sizeof(data.fname), (void *)valp->fname); - data.id = valp->id; - data.ts = tsp / 1000; - data.uid = bpf_get_current_uid_gid(); - data.flags = valp->flags; // EXTENDED_STRUCT_MEMBER - data.ret = PT_REGS_RC(ctx); - - events.perf_submit(ctx, &data, sizeof(data)); - infotmp.delete(&id); + const char __user *filename = (char *)PT_REGS_PARM1(regs); + int flags = PT_REGS_PARM2(regs); +#else +KRETFUNC_PROBE(FNNAME, const char __user *filename, int flags, int ret) +{ +#endif +""" - return 0; -} +bpf_text_kfunc_header_openat = """ +#if defined(CONFIG_ARCH_HAS_SYSCALL_WRAPPER) && !defined(__s390x__) +KRETFUNC_PROBE(FNNAME, struct pt_regs *regs, int ret) +{ + int dfd = PT_REGS_PARM1(regs); + const char __user *filename = (char *)PT_REGS_PARM2(regs); + int flags = PT_REGS_PARM3(regs); +#else +KRETFUNC_PROBE(FNNAME, int dfd, const char __user *filename, int flags, int ret) +{ +#endif """ -bpf_text_kfunc= """ -KRETFUNC_PROBE(do_sys_open, int dfd, const char __user *filename, int flags, int mode, int ret) +bpf_text_kfunc_header_openat2 = """ +#include +#if defined(CONFIG_ARCH_HAS_SYSCALL_WRAPPER) && !defined(__s390x__) +KRETFUNC_PROBE(FNNAME, struct pt_regs *regs, int ret) { + int dfd = PT_REGS_PARM1(regs); + const char __user *filename = (char *)PT_REGS_PARM2(regs); + struct open_how __user *how = (struct open_how *)PT_REGS_PARM3(regs); + int flags = how->flags; +#else +KRETFUNC_PROBE(FNNAME, int dfd, const char __user *filename, struct open_how __user *how, int ret) +{ + int flags = how->flags; +#endif +""" + +bpf_text_kfunc_body = """ u64 id = bpf_get_current_pid_tgid(); u32 pid = id >> 32; // PID is higher part u32 tid = id; // Cast and get the lower part @@ -199,12 +255,38 @@ } """ +b = BPF(text='') +# open and openat are always in place since 2.6.16 +fnname_open = b.get_syscall_prefix().decode() + 'open' +fnname_openat = b.get_syscall_prefix().decode() + 'openat' +fnname_openat2 = b.get_syscall_prefix().decode() + 'openat2' +if b.ksymname(fnname_openat2) == -1: + fnname_openat2 = None + is_support_kfunc = BPF.support_kfunc() if is_support_kfunc: - bpf_text += bpf_text_kfunc + bpf_text += bpf_text_kfunc_header_open.replace('FNNAME', fnname_open) + bpf_text += bpf_text_kfunc_body + + bpf_text += bpf_text_kfunc_header_openat.replace('FNNAME', fnname_openat) + bpf_text += bpf_text_kfunc_body + + if fnname_openat2: + bpf_text += bpf_text_kfunc_header_openat2.replace('FNNAME', fnname_openat2) + bpf_text += bpf_text_kfunc_body else: bpf_text += bpf_text_kprobe + bpf_text += bpf_text_kprobe_header_open + bpf_text += bpf_text_kprobe_body + + bpf_text += bpf_text_kprobe_header_openat + bpf_text += bpf_text_kprobe_body + + if fnname_openat2: + bpf_text += bpf_text_kprobe_header_openat2 + bpf_text += bpf_text_kprobe_body + if args.tid: # TID trumps PID bpf_text = bpf_text.replace('PID_TID_FILTER', 'if (tid != %s) { return 0; }' % args.tid) @@ -235,8 +317,15 @@ # initialize BPF b = BPF(text=bpf_text) if not is_support_kfunc: - b.attach_kprobe(event="do_sys_open", fn_name="trace_entry") - b.attach_kretprobe(event="do_sys_open", fn_name="trace_return") + b.attach_kprobe(event=fnname_open, fn_name="syscall__trace_entry_open") + b.attach_kretprobe(event=fnname_open, fn_name="trace_return") + + b.attach_kprobe(event=fnname_openat, fn_name="syscall__trace_entry_openat") + b.attach_kretprobe(event=fnname_openat, fn_name="trace_return") + + if fnname_openat2: + b.attach_kprobe(event=fnname_openat2, fn_name="syscall__trace_entry_openat2") + b.attach_kretprobe(event=fnname_openat2, fn_name="trace_return") initial_ts = 0