History

ftrace: selftest: remove broken trace_direct_tramp

The ftrace selftest code has a trace_direct_tramp() function which it uses as a direct call trampoline. This happens to work on x86, since the direct call's return address is in the usual place, and can be returned to via a RET, but in general the calling convention for direct calls is different from regular function calls, and requires a trampoline written in assembly. On s390, regular function calls place the return address in %r14, and an ftrace patch-site in an instrumented function places the trampoline's return address (which is within the instrumented function) in %r0, preserving the original %r14 value in-place. As a regular C function will return to the address in %r14, using a C function as the trampoline results in the trampoline returning to the caller of the instrumented function, skipping the body of the instrumented function. Note that the s390 issue is not detcted by the ftrace selftest code, as the instrumented function is trivial, and returning back into the caller happens to be equivalent. On arm64, regular function calls place the return address in x30, and an ftrace patch-site in an instrumented function saves this into r9 and places the trampoline's return address (within the instrumented function) in x30. A regular C function will return to the address in x30, but will not restore x9 into x30. Consequently, using a C function as the trampoline results in returning to the trampoline's return address having corrupted x30, such that when the instrumented function returns, it will return back into itself. To avoid future issues in this area, remove the trace_direct_tramp() function, and require that each architecture with direct calls provides a stub trampoline, named ftrace_stub_direct_tramp. This can be written to handle the architecture's trampoline calling convention, and in future could be used elsewhere (e.g. in the ftrace ops sample, to measure the overhead of direct calls), so we may as well always build it in. Link: https://lkml.kernel.org/r/20230321140424.345218-8-revest@chromium.org

Mark Rutland committed 3 years ago

Commit fee86a41 parent 60c89715 files · +18 −10Browse files

Unified · Split

5 files
  1. arch/s390/kernel/mcount.S +5 −0
  2. arch/x86/kernel/ftrace_32.S +5 −0
  3. arch/x86/kernel/ftrace_64.S +4 −0
  4. include/linux/ftrace.h +2 −0
  5. kernel/trace/trace_selftest.c +2 −10
arch/s390/kernel/mcount.S+5−0
@@ -32,6 +32,11 @@ ENTRY(ftrace_stub) · 31 unmodified lines
32 BR_EX %r1432 BR_EX %r14
33ENDPROC(ftrace_stub)33ENDPROC(ftrace_stub)
34 34
35SYM_CODE_START(ftrace_stub_direct_tramp)
36 lgr %r1, %r0
37 BR_EX %r1
38SYM_CODE_END(ftrace_stub_direct_tramp)
39
35 .macro ftrace_regs_entry, allregs=040 .macro ftrace_regs_entry, allregs=0
36 stg %r14,(__SF_GPRS+8*8)(%r15) # save traced function caller41 stg %r14,(__SF_GPRS+8*8)(%r15) # save traced function caller
37 42
arch/x86/kernel/ftrace_32.S+5−0
@@ -163,6 +163,11 @@ SYM_INNER_LABEL(ftrace_regs_call, SYM_L_GLOBAL) · 162 unmodified lines
163 jmp .Lftrace_ret163 jmp .Lftrace_ret
164SYM_CODE_END(ftrace_regs_caller)164SYM_CODE_END(ftrace_regs_caller)
165 165
166SYM_FUNC_START(ftrace_stub_direct_tramp)
167 CALL_DEPTH_ACCOUNT
168 RET
169SYM_FUNC_END(ftrace_stub_direct_tramp)
170
166#ifdef CONFIG_FUNCTION_GRAPH_TRACER171#ifdef CONFIG_FUNCTION_GRAPH_TRACER
167SYM_CODE_START(ftrace_graph_caller)172SYM_CODE_START(ftrace_graph_caller)
168 pushl %eax173 pushl %eax
arch/x86/kernel/ftrace_64.S+4−0
@@ -309,6 +309,10 @@ SYM_INNER_LABEL(ftrace_regs_caller_end, SYM_L_GLOBAL) · 308 unmodified lines
309SYM_FUNC_END(ftrace_regs_caller)309SYM_FUNC_END(ftrace_regs_caller)
310STACK_FRAME_NON_STANDARD_FP(ftrace_regs_caller)310STACK_FRAME_NON_STANDARD_FP(ftrace_regs_caller)
311 311
312SYM_FUNC_START(ftrace_stub_direct_tramp)
313 CALL_DEPTH_ACCOUNT
314 RET
315SYM_FUNC_END(ftrace_stub_direct_tramp)
312 316
313#else /* ! CONFIG_DYNAMIC_FTRACE */317#else /* ! CONFIG_DYNAMIC_FTRACE */
314 318
include/linux/ftrace.h+2−0
@@ -413,6 +413,8 @@ int unregister_ftrace_direct(struct ftrace_ops *ops, unsigned long addr, · 412 unmodified lines
413int modify_ftrace_direct(struct ftrace_ops *ops, unsigned long addr);413int modify_ftrace_direct(struct ftrace_ops *ops, unsigned long addr);
414int modify_ftrace_direct_nolock(struct ftrace_ops *ops, unsigned long addr);414int modify_ftrace_direct_nolock(struct ftrace_ops *ops, unsigned long addr);
415 415
416void ftrace_stub_direct_tramp(void);
417
416#else418#else
417struct ftrace_ops;419struct ftrace_ops;
418# define ftrace_direct_func_count 0420# define ftrace_direct_func_count 0
kernel/trace/trace_selftest.c+2−10
@@ -786,14 +786,6 @@ static struct fgraph_ops fgraph_ops __initdata = { · 785 unmodified lines
786 786
787#ifdef CONFIG_DYNAMIC_FTRACE_WITH_DIRECT_CALLS787#ifdef CONFIG_DYNAMIC_FTRACE_WITH_DIRECT_CALLS
788static struct ftrace_ops direct;788static struct ftrace_ops direct;
789#ifndef CALL_DEPTH_ACCOUNT
790#define CALL_DEPTH_ACCOUNT ""
791#endif
792
793noinline __noclone static void trace_direct_tramp(void)
794{
795 asm(CALL_DEPTH_ACCOUNT);
796}
797#endif789#endif
798 790
799/*791/*
@@ -873,7 +865,7 @@ trace_selftest_startup_function_graph(struct tracer *trace, · 73 unmodified lines
873 */865 */
874 ftrace_set_filter_ip(&direct, (unsigned long)DYN_FTRACE_TEST_NAME, 0, 0);866 ftrace_set_filter_ip(&direct, (unsigned long)DYN_FTRACE_TEST_NAME, 0, 0);
875 ret = register_ftrace_direct(&direct,867 ret = register_ftrace_direct(&direct,
876 (unsigned long)trace_direct_tramp);868 (unsigned long)ftrace_stub_direct_tramp);
877 if (ret)869 if (ret)
878 goto out;870 goto out;
879 871
@@ -894,7 +886,7 @@ trace_selftest_startup_function_graph(struct tracer *trace, · 14 unmodified lines
894 unregister_ftrace_graph(&fgraph_ops);886 unregister_ftrace_graph(&fgraph_ops);
895 887
896 ret = unregister_ftrace_direct(&direct,888 ret = unregister_ftrace_direct(&direct,
897 (unsigned long) trace_direct_tramp,889 (unsigned long)ftrace_stub_direct_tramp,
898 true);890 true);
899 if (ret)891 if (ret)
900 goto out;892 goto out;

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t