Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

fprobe: Skip exit_handler if entry_handler returns !0

Skip hooking function return and calling exit_handler if the
entry_handler() returns !0.

Link: https://lkml.kernel.org/r/167526699798.433354.10998365726830117303.stgit@mhiramat.roam.corp.google.com

Cc: Florent Revest <revest@chromium.org>
Cc: Mark Rutland <mark.rutland@arm.com>
Cc: Will Deacon <will@kernel.org>
Signed-off-by: Masami Hiramatsu (Google) <mhiramat@kernel.org>
Signed-off-by: Steven Rostedt (Google) <rostedt@goodmis.org>

authored by

Masami Hiramatsu (Google) and committed by
Steven Rostedt (Google)
39d95420 7e7ef1bf

+32 -13
+2 -2
include/linux/fprobe.h
··· 34 34 size_t entry_data_size; 35 35 int nr_maxactive; 36 36 37 - void (*entry_handler)(struct fprobe *fp, unsigned long entry_ip, 38 - struct pt_regs *regs, void *entry_data); 37 + int (*entry_handler)(struct fprobe *fp, unsigned long entry_ip, 38 + struct pt_regs *regs, void *entry_data); 39 39 void (*exit_handler)(struct fprobe *fp, unsigned long entry_ip, 40 40 struct pt_regs *regs, void *entry_data); 41 41 };
+13 -2
kernel/trace/bpf_trace.c
··· 2644 2644 return err; 2645 2645 } 2646 2646 2647 - static void 2647 + static int 2648 2648 kprobe_multi_link_handler(struct fprobe *fp, unsigned long fentry_ip, 2649 2649 struct pt_regs *regs, void *data) 2650 + { 2651 + struct bpf_kprobe_multi_link *link; 2652 + 2653 + link = container_of(fp, struct bpf_kprobe_multi_link, fp); 2654 + kprobe_multi_link_prog_run(link, get_entry_ip(fentry_ip), regs); 2655 + return 0; 2656 + } 2657 + 2658 + static void 2659 + kprobe_multi_link_exit_handler(struct fprobe *fp, unsigned long fentry_ip, 2660 + struct pt_regs *regs, void *data) 2650 2661 { 2651 2662 struct bpf_kprobe_multi_link *link; 2652 2663 ··· 2859 2848 goto error; 2860 2849 2861 2850 if (flags & BPF_F_KPROBE_MULTI_RETURN) 2862 - link->fp.exit_handler = kprobe_multi_link_handler; 2851 + link->fp.exit_handler = kprobe_multi_link_exit_handler; 2863 2852 else 2864 2853 link->fp.entry_handler = kprobe_multi_link_handler; 2865 2854
+9 -5
kernel/trace/fprobe.c
··· 27 27 struct rethook_node *rh = NULL; 28 28 struct fprobe *fp; 29 29 void *entry_data = NULL; 30 - int bit; 30 + int bit, ret; 31 31 32 32 fp = container_of(ops, struct fprobe, ops); 33 33 if (fprobe_disabled(fp)) ··· 52 52 } 53 53 54 54 if (fp->entry_handler) 55 - fp->entry_handler(fp, ip, ftrace_get_regs(fregs), entry_data); 55 + ret = fp->entry_handler(fp, ip, ftrace_get_regs(fregs), entry_data); 56 56 57 - if (rh) 58 - rethook_hook(rh, ftrace_get_regs(fregs), true); 59 - 57 + /* If entry_handler returns !0, nmissed is not counted. */ 58 + if (rh) { 59 + if (ret) 60 + rethook_recycle(rh); 61 + else 62 + rethook_hook(rh, ftrace_get_regs(fregs), true); 63 + } 60 64 out: 61 65 ftrace_test_recursion_unlock(bit); 62 66 }
+5 -2
lib/test_fprobe.c
··· 37 37 return nest(value + 2); 38 38 } 39 39 40 - static notrace void fp_entry_handler(struct fprobe *fp, unsigned long ip, 40 + static notrace int fp_entry_handler(struct fprobe *fp, unsigned long ip, 41 41 struct pt_regs *regs, void *data) 42 42 { 43 43 KUNIT_EXPECT_FALSE(current_test, preemptible()); ··· 51 51 *(u32 *)data = entry_val; 52 52 } else 53 53 KUNIT_EXPECT_NULL(current_test, data); 54 + 55 + return 0; 54 56 } 55 57 56 58 static notrace void fp_exit_handler(struct fprobe *fp, unsigned long ip, ··· 76 74 KUNIT_EXPECT_NULL(current_test, data); 77 75 } 78 76 79 - static notrace void nest_entry_handler(struct fprobe *fp, unsigned long ip, 77 + static notrace int nest_entry_handler(struct fprobe *fp, unsigned long ip, 80 78 struct pt_regs *regs, void *data) 81 79 { 82 80 KUNIT_EXPECT_FALSE(current_test, preemptible()); 81 + return 0; 83 82 } 84 83 85 84 static notrace void nest_exit_handler(struct fprobe *fp, unsigned long ip,
+3 -2
samples/fprobe/fprobe_example.c
··· 48 48 stack_trace_print(stacks, len, 24); 49 49 } 50 50 51 - static void sample_entry_handler(struct fprobe *fp, unsigned long ip, 52 - struct pt_regs *regs, void *data) 51 + static int sample_entry_handler(struct fprobe *fp, unsigned long ip, 52 + struct pt_regs *regs, void *data) 53 53 { 54 54 if (use_trace) 55 55 /* ··· 62 62 nhit++; 63 63 if (stackdump) 64 64 show_backtrace(); 65 + return 0; 65 66 } 66 67 67 68 static void sample_exit_handler(struct fprobe *fp, unsigned long ip, struct pt_regs *regs,