Skip to content

Commit 2d1bcbc

Browse files
committed
Merge tag 'probes-fixes-v6.4-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/trace/linux-trace
Pull probes fixes from Masami Hiramatsu: - Initialize 'ret' local variables on fprobe_handler() to fix the smatch warning. With this, fprobe function exit handler is not working randomly. - Fix to use preempt_enable/disable_notrace for rethook handler to prevent recursive call of fprobe exit handler (which is based on rethook) - Fix recursive call issue on fprobe_kprobe_handler() - Fix to detect recursive call on fprobe_exit_handler() - Fix to make all arch-dependent rethook code notrace (the arch-independent code is already notrace)" * tag 'probes-fixes-v6.4-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/trace/linux-trace: rethook, fprobe: do not trace rethook related functions fprobe: add recursion detection in fprobe_exit_handler fprobe: make fprobe_kprobe_handler recursion free rethook: use preempt_{disable, enable}_notrace in rethook_trampoline_handler tracing: fprobe: Initialize ret valiable to fix smatch error
2 parents 1f594fe + 571a2a5 commit 2d1bcbc

File tree

5 files changed

+64
-17
lines changed

5 files changed

+64
-17
lines changed

arch/riscv/kernel/probes/Makefile

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,3 +4,5 @@ obj-$(CONFIG_RETHOOK) += rethook.o rethook_trampoline.o
44
obj-$(CONFIG_KPROBES_ON_FTRACE) += ftrace.o
55
obj-$(CONFIG_UPROBES) += uprobes.o decode-insn.o simulate-insn.o
66
CFLAGS_REMOVE_simulate-insn.o = $(CC_FLAGS_FTRACE)
7+
CFLAGS_REMOVE_rethook.o = $(CC_FLAGS_FTRACE)
8+
CFLAGS_REMOVE_rethook_trampoline.o = $(CC_FLAGS_FTRACE)

arch/s390/kernel/Makefile

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ CFLAGS_REMOVE_ftrace.o = $(CC_FLAGS_FTRACE)
1010

1111
# Do not trace early setup code
1212
CFLAGS_REMOVE_early.o = $(CC_FLAGS_FTRACE)
13+
CFLAGS_REMOVE_rethook.o = $(CC_FLAGS_FTRACE)
1314

1415
endif
1516

arch/x86/kernel/Makefile

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ CFLAGS_REMOVE_ftrace.o = -pg
1717
CFLAGS_REMOVE_early_printk.o = -pg
1818
CFLAGS_REMOVE_head64.o = -pg
1919
CFLAGS_REMOVE_sev.o = -pg
20+
CFLAGS_REMOVE_rethook.o = -pg
2021
endif
2122

2223
KASAN_SANITIZE_head$(BITS).o := n

kernel/trace/fprobe.c

Lines changed: 58 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -17,36 +17,30 @@
1717
struct fprobe_rethook_node {
1818
struct rethook_node node;
1919
unsigned long entry_ip;
20+
unsigned long entry_parent_ip;
2021
char data[];
2122
};
2223

23-
static void fprobe_handler(unsigned long ip, unsigned long parent_ip,
24-
struct ftrace_ops *ops, struct ftrace_regs *fregs)
24+
static inline void __fprobe_handler(unsigned long ip, unsigned long parent_ip,
25+
struct ftrace_ops *ops, struct ftrace_regs *fregs)
2526
{
2627
struct fprobe_rethook_node *fpr;
2728
struct rethook_node *rh = NULL;
2829
struct fprobe *fp;
2930
void *entry_data = NULL;
30-
int bit, ret;
31+
int ret = 0;
3132

3233
fp = container_of(ops, struct fprobe, ops);
33-
if (fprobe_disabled(fp))
34-
return;
35-
36-
bit = ftrace_test_recursion_trylock(ip, parent_ip);
37-
if (bit < 0) {
38-
fp->nmissed++;
39-
return;
40-
}
4134

4235
if (fp->exit_handler) {
4336
rh = rethook_try_get(fp->rethook);
4437
if (!rh) {
4538
fp->nmissed++;
46-
goto out;
39+
return;
4740
}
4841
fpr = container_of(rh, struct fprobe_rethook_node, node);
4942
fpr->entry_ip = ip;
43+
fpr->entry_parent_ip = parent_ip;
5044
if (fp->entry_data_size)
5145
entry_data = fpr->data;
5246
}
@@ -61,38 +55,87 @@ static void fprobe_handler(unsigned long ip, unsigned long parent_ip,
6155
else
6256
rethook_hook(rh, ftrace_get_regs(fregs), true);
6357
}
64-
out:
58+
}
59+
60+
static void fprobe_handler(unsigned long ip, unsigned long parent_ip,
61+
struct ftrace_ops *ops, struct ftrace_regs *fregs)
62+
{
63+
struct fprobe *fp;
64+
int bit;
65+
66+
fp = container_of(ops, struct fprobe, ops);
67+
if (fprobe_disabled(fp))
68+
return;
69+
70+
/* recursion detection has to go before any traceable function and
71+
* all functions before this point should be marked as notrace
72+
*/
73+
bit = ftrace_test_recursion_trylock(ip, parent_ip);
74+
if (bit < 0) {
75+
fp->nmissed++;
76+
return;
77+
}
78+
__fprobe_handler(ip, parent_ip, ops, fregs);
6579
ftrace_test_recursion_unlock(bit);
80+
6681
}
6782
NOKPROBE_SYMBOL(fprobe_handler);
6883

6984
static void fprobe_kprobe_handler(unsigned long ip, unsigned long parent_ip,
7085
struct ftrace_ops *ops, struct ftrace_regs *fregs)
7186
{
72-
struct fprobe *fp = container_of(ops, struct fprobe, ops);
87+
struct fprobe *fp;
88+
int bit;
89+
90+
fp = container_of(ops, struct fprobe, ops);
91+
if (fprobe_disabled(fp))
92+
return;
93+
94+
/* recursion detection has to go before any traceable function and
95+
* all functions called before this point should be marked as notrace
96+
*/
97+
bit = ftrace_test_recursion_trylock(ip, parent_ip);
98+
if (bit < 0) {
99+
fp->nmissed++;
100+
return;
101+
}
73102

74103
if (unlikely(kprobe_running())) {
75104
fp->nmissed++;
76105
return;
77106
}
107+
78108
kprobe_busy_begin();
79-
fprobe_handler(ip, parent_ip, ops, fregs);
109+
__fprobe_handler(ip, parent_ip, ops, fregs);
80110
kprobe_busy_end();
111+
ftrace_test_recursion_unlock(bit);
81112
}
82113

83114
static void fprobe_exit_handler(struct rethook_node *rh, void *data,
84115
struct pt_regs *regs)
85116
{
86117
struct fprobe *fp = (struct fprobe *)data;
87118
struct fprobe_rethook_node *fpr;
119+
int bit;
88120

89121
if (!fp || fprobe_disabled(fp))
90122
return;
91123

92124
fpr = container_of(rh, struct fprobe_rethook_node, node);
93125

126+
/*
127+
* we need to assure no calls to traceable functions in-between the
128+
* end of fprobe_handler and the beginning of fprobe_exit_handler.
129+
*/
130+
bit = ftrace_test_recursion_trylock(fpr->entry_ip, fpr->entry_parent_ip);
131+
if (bit < 0) {
132+
fp->nmissed++;
133+
return;
134+
}
135+
94136
fp->exit_handler(fp, fpr->entry_ip, regs,
95137
fp->entry_data_size ? (void *)fpr->data : NULL);
138+
ftrace_test_recursion_unlock(bit);
96139
}
97140
NOKPROBE_SYMBOL(fprobe_exit_handler);
98141

kernel/trace/rethook.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -288,7 +288,7 @@ unsigned long rethook_trampoline_handler(struct pt_regs *regs,
288288
* These loops must be protected from rethook_free_rcu() because those
289289
* are accessing 'rhn->rethook'.
290290
*/
291-
preempt_disable();
291+
preempt_disable_notrace();
292292

293293
/*
294294
* Run the handler on the shadow stack. Do not unlink the list here because
@@ -321,7 +321,7 @@ unsigned long rethook_trampoline_handler(struct pt_regs *regs,
321321
first = first->next;
322322
rethook_recycle(rhn);
323323
}
324-
preempt_enable();
324+
preempt_enable_notrace();
325325

326326
return correct_ret_addr;
327327
}

0 commit comments

Comments
 (0)