Skip to content

Commit cb16330

Browse files
committed
fprobe: Pass return address to the handlers
Pass return address as 'ret_ip' to the fprobe entry and return handlers so that the fprobe user handler can get the reutrn address without analyzing arch-dependent pt_regs. Link: https://lore.kernel.org/all/168507467664.913472.11642316698862778600.stgit@mhiramat.roam.corp.google.com/ Signed-off-by: Masami Hiramatsu (Google) <[email protected]>
1 parent 9561de3 commit cb16330

File tree

8 files changed

+26
-14
lines changed

8 files changed

+26
-14
lines changed

include/linux/fprobe.h

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -35,9 +35,11 @@ struct fprobe {
3535
int nr_maxactive;
3636

3737
int (*entry_handler)(struct fprobe *fp, unsigned long entry_ip,
38-
struct pt_regs *regs, void *entry_data);
38+
unsigned long ret_ip, struct pt_regs *regs,
39+
void *entry_data);
3940
void (*exit_handler)(struct fprobe *fp, unsigned long entry_ip,
40-
struct pt_regs *regs, void *entry_data);
41+
unsigned long ret_ip, struct pt_regs *regs,
42+
void *entry_data);
4143
};
4244

4345
/* This fprobe is soft-disabled. */

include/linux/rethook.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@
1414

1515
struct rethook_node;
1616

17-
typedef void (*rethook_handler_t) (struct rethook_node *, void *, struct pt_regs *);
17+
typedef void (*rethook_handler_t) (struct rethook_node *, void *, unsigned long, struct pt_regs *);
1818

1919
/**
2020
* struct rethook - The rethook management data structure.

kernel/kprobes.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2127,6 +2127,7 @@ static int pre_handler_kretprobe(struct kprobe *p, struct pt_regs *regs)
21272127
NOKPROBE_SYMBOL(pre_handler_kretprobe);
21282128

21292129
static void kretprobe_rethook_handler(struct rethook_node *rh, void *data,
2130+
unsigned long ret_addr,
21302131
struct pt_regs *regs)
21312132
{
21322133
struct kretprobe *rp = (struct kretprobe *)data;

kernel/trace/bpf_trace.c

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2642,7 +2642,8 @@ kprobe_multi_link_prog_run(struct bpf_kprobe_multi_link *link,
26422642

26432643
static int
26442644
kprobe_multi_link_handler(struct fprobe *fp, unsigned long fentry_ip,
2645-
struct pt_regs *regs, void *data)
2645+
unsigned long ret_ip, struct pt_regs *regs,
2646+
void *data)
26462647
{
26472648
struct bpf_kprobe_multi_link *link;
26482649

@@ -2653,7 +2654,8 @@ kprobe_multi_link_handler(struct fprobe *fp, unsigned long fentry_ip,
26532654

26542655
static void
26552656
kprobe_multi_link_exit_handler(struct fprobe *fp, unsigned long fentry_ip,
2656-
struct pt_regs *regs, void *data)
2657+
unsigned long ret_ip, struct pt_regs *regs,
2658+
void *data)
26572659
{
26582660
struct bpf_kprobe_multi_link *link;
26592661

kernel/trace/fprobe.c

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,7 @@ static inline void __fprobe_handler(unsigned long ip, unsigned long parent_ip,
4646
}
4747

4848
if (fp->entry_handler)
49-
ret = fp->entry_handler(fp, ip, ftrace_get_regs(fregs), entry_data);
49+
ret = fp->entry_handler(fp, ip, parent_ip, ftrace_get_regs(fregs), entry_data);
5050

5151
/* If entry_handler returns !0, nmissed is not counted. */
5252
if (rh) {
@@ -112,7 +112,7 @@ static void fprobe_kprobe_handler(unsigned long ip, unsigned long parent_ip,
112112
}
113113

114114
static void fprobe_exit_handler(struct rethook_node *rh, void *data,
115-
struct pt_regs *regs)
115+
unsigned long ret_ip, struct pt_regs *regs)
116116
{
117117
struct fprobe *fp = (struct fprobe *)data;
118118
struct fprobe_rethook_node *fpr;
@@ -133,7 +133,7 @@ static void fprobe_exit_handler(struct rethook_node *rh, void *data,
133133
return;
134134
}
135135

136-
fp->exit_handler(fp, fpr->entry_ip, regs,
136+
fp->exit_handler(fp, fpr->entry_ip, ret_ip, regs,
137137
fp->entry_data_size ? (void *)fpr->data : NULL);
138138
ftrace_test_recursion_unlock(bit);
139139
}

kernel/trace/rethook.c

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -301,7 +301,8 @@ unsigned long rethook_trampoline_handler(struct pt_regs *regs,
301301
break;
302302
handler = READ_ONCE(rhn->rethook->handler);
303303
if (handler)
304-
handler(rhn, rhn->rethook->data, regs);
304+
handler(rhn, rhn->rethook->data,
305+
correct_ret_addr, regs);
305306

306307
if (first == node)
307308
break;

lib/test_fprobe.c

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,8 @@ static noinline u32 fprobe_selftest_nest_target(u32 value, u32 (*nest)(u32))
3939
}
4040

4141
static notrace int fp_entry_handler(struct fprobe *fp, unsigned long ip,
42-
struct pt_regs *regs, void *data)
42+
unsigned long ret_ip,
43+
struct pt_regs *regs, void *data)
4344
{
4445
KUNIT_EXPECT_FALSE(current_test, preemptible());
4546
/* This can be called on the fprobe_selftest_target and the fprobe_selftest_target2 */
@@ -57,6 +58,7 @@ static notrace int fp_entry_handler(struct fprobe *fp, unsigned long ip,
5758
}
5859

5960
static notrace void fp_exit_handler(struct fprobe *fp, unsigned long ip,
61+
unsigned long ret_ip,
6062
struct pt_regs *regs, void *data)
6163
{
6264
unsigned long ret = regs_return_value(regs);
@@ -78,14 +80,16 @@ static notrace void fp_exit_handler(struct fprobe *fp, unsigned long ip,
7880
}
7981

8082
static notrace int nest_entry_handler(struct fprobe *fp, unsigned long ip,
81-
struct pt_regs *regs, void *data)
83+
unsigned long ret_ip,
84+
struct pt_regs *regs, void *data)
8285
{
8386
KUNIT_EXPECT_FALSE(current_test, preemptible());
8487
return 0;
8588
}
8689

8790
static notrace void nest_exit_handler(struct fprobe *fp, unsigned long ip,
88-
struct pt_regs *regs, void *data)
91+
unsigned long ret_ip,
92+
struct pt_regs *regs, void *data)
8993
{
9094
KUNIT_EXPECT_FALSE(current_test, preemptible());
9195
KUNIT_EXPECT_EQ(current_test, ip, target_nest_ip);

samples/fprobe/fprobe_example.c

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,7 @@ static void show_backtrace(void)
4949
}
5050

5151
static int sample_entry_handler(struct fprobe *fp, unsigned long ip,
52+
unsigned long ret_ip,
5253
struct pt_regs *regs, void *data)
5354
{
5455
if (use_trace)
@@ -65,10 +66,11 @@ static int sample_entry_handler(struct fprobe *fp, unsigned long ip,
6566
return 0;
6667
}
6768

68-
static void sample_exit_handler(struct fprobe *fp, unsigned long ip, struct pt_regs *regs,
69+
static void sample_exit_handler(struct fprobe *fp, unsigned long ip,
70+
unsigned long ret_ip, struct pt_regs *regs,
6971
void *data)
7072
{
71-
unsigned long rip = instruction_pointer(regs);
73+
unsigned long rip = ret_ip;
7274

7375
if (use_trace)
7476
/*

0 commit comments

Comments
 (0)