Re: [PATCH] ftrace: avoid replacing the list func with itself

From: Song Shuai
Date: Mon Nov 21 2022 - 21:29:36 EST


Song Shuai <suagrfillet@xxxxxxxxx> 于2022年10月26日周三 13:20写道:
>
> The list func (ftrace_ops_list_func) will be patched first
> before the transition between old and new calls are set,
> which fixed the race described in this commit `59338f75`.
>
> While ftrace_trace_function changes from the list func to a
> ftrace_ops func, like unregistering the klp_ops to leave the only
> global_ops in ftrace_ops_list, the ftrace_[regs]_call will be
> replaced with the list func although it already exists. So there
> should be a condition to avoid this.
>
> This patch backups saved_ftrace_func by saved_ftrace_func_old
> which will be compared with the list func before trying to patch it.
>
Ping...

Thanks,
Song
> Signed-off-by: Song Shuai <suagrfillet@xxxxxxxxx>
> ---
> kernel/trace/ftrace.c | 7 ++++++-
> 1 file changed, 6 insertions(+), 1 deletion(-)
>
> diff --git a/kernel/trace/ftrace.c b/kernel/trace/ftrace.c
> index bc921a3f7ea8..56b1a42e1937 100644
> --- a/kernel/trace/ftrace.c
> +++ b/kernel/trace/ftrace.c
> @@ -2755,6 +2755,8 @@ void __weak ftrace_arch_code_modify_post_process(void)
> {
> }
>
> +static ftrace_func_t saved_ftrace_func_old;
> +
> void ftrace_modify_all_code(int command)
> {
> int update = command & FTRACE_UPDATE_TRACE_FUNC;
> @@ -2774,7 +2776,7 @@ void ftrace_modify_all_code(int command)
> * to make sure the ops are having the right functions
> * traced.
> */
> - if (update) {
> + if (update && saved_ftrace_func_old != ftrace_ops_list_func) {
> err = ftrace_update_ftrace_func(ftrace_ops_list_func);
> if (FTRACE_WARN_ON(err))
> return;
> @@ -2918,6 +2920,7 @@ static void ftrace_trampoline_free(struct ftrace_ops *ops)
> static void ftrace_startup_enable(int command)
> {
> if (saved_ftrace_func != ftrace_trace_function) {
> + saved_ftrace_func_old = saved_ftrace_func;
> saved_ftrace_func = ftrace_trace_function;
> command |= FTRACE_UPDATE_TRACE_FUNC;
> }
> @@ -3007,6 +3010,7 @@ int ftrace_shutdown(struct ftrace_ops *ops, int command)
> ops->flags &= ~FTRACE_OPS_FL_ENABLED;
>
> if (saved_ftrace_func != ftrace_trace_function) {
> + saved_ftrace_func_old = saved_ftrace_func;
> saved_ftrace_func = ftrace_trace_function;
> command |= FTRACE_UPDATE_TRACE_FUNC;
> }
> @@ -8321,6 +8325,7 @@ static void ftrace_startup_sysctl(void)
>
> /* Force update next time */
> saved_ftrace_func = NULL;
> + saved_ftrace_func_old = NULL;
> /* ftrace_start_up is true if we want ftrace running */
> if (ftrace_start_up) {
> command = FTRACE_UPDATE_CALLS;
> --
> 2.20.1
>