瀏覽代碼

arm64: ftrace: modify a stack frame in a safe way

Function graph tracer modifies a return address (LR) in a stack frame by
calling ftrace_prepare_return() in a traced function's function prologue.
The current code does this modification before preserving an original
address at ftrace_push_return_trace() and there is always a small window
of inconsistency when an interrupt occurs.

This doesn't matter, as far as an interrupt stack is introduced, because
stack tracer won't be invoked in an interrupt context. But it would be
better to proactively minimize such a window by moving the LR modification
after ftrace_push_return_trace().

Signed-off-by: AKASHI Takahiro <takahiro.akashi@linaro.org>
Signed-off-by: Will Deacon <will.deacon@arm.com>
AKASHI Takahiro 9 年之前
父節點
當前提交
79fdee9b63
共有 1 個文件被更改,包括 4 次插入7 次删除
  1. 4 7
      arch/arm64/kernel/ftrace.c

+ 4 - 7
arch/arm64/kernel/ftrace.c

@@ -129,23 +129,20 @@ void prepare_ftrace_return(unsigned long *parent, unsigned long self_addr,
 	 * on other archs. It's unlikely on AArch64.
 	 * on other archs. It's unlikely on AArch64.
 	 */
 	 */
 	old = *parent;
 	old = *parent;
-	*parent = return_hooker;
 
 
 	trace.func = self_addr;
 	trace.func = self_addr;
 	trace.depth = current->curr_ret_stack + 1;
 	trace.depth = current->curr_ret_stack + 1;
 
 
 	/* Only trace if the calling function expects to */
 	/* Only trace if the calling function expects to */
-	if (!ftrace_graph_entry(&trace)) {
-		*parent = old;
+	if (!ftrace_graph_entry(&trace))
 		return;
 		return;
-	}
 
 
 	err = ftrace_push_return_trace(old, self_addr, &trace.depth,
 	err = ftrace_push_return_trace(old, self_addr, &trace.depth,
 				       frame_pointer);
 				       frame_pointer);
-	if (err == -EBUSY) {
-		*parent = old;
+	if (err == -EBUSY)
 		return;
 		return;
-	}
+	else
+		*parent = return_hooker;
 }
 }
 
 
 #ifdef CONFIG_DYNAMIC_FTRACE
 #ifdef CONFIG_DYNAMIC_FTRACE