gpt4 book ai didi

linux - ftrace:通过 echo 从 function_graph 更改 current_tracer 时系统崩溃

转载 作者:IT王子 更新时间:2023-10-29 00:13:23 35 4
gpt4 key购买 nike

我最近一直在使用 ftrace 来监控我系统的一些行为特征。我一直在处理通过一个小脚本打开/关闭跟踪。运行脚本后,我的系统会崩溃并自行重启。最初,我认为脚本本身可能存在错误,但后来我确定崩溃和重启是 echo 的结果。在 current_tracer 时将一些跟踪器添加到/sys/kernel/debug/tracing/current_tracer设置为 function_graph。

也就是说,以下命令序列将产生崩溃/重启:

echo "function_graph" > /sys/kernel/debug/tracing/current_tracer
echo "function" > /sys/kernel/debug/tracing/current_tracer

以上导致的死机后重启过程中echo语句,我看到很多输出内容如下:

clearing orphaned inode <inode>

我试图通过替换 current_tracer 来重现这个问题。从 function_graph 到 C 程序中其他东西的值:

#include <stdio.h>
#include <fcntl.h>
#include <unistd.h>
#include <string.h>
#include <stdlib.h>

int openCurrentTracer()
{
int fd = open("/sys/kernel/debug/tracing/current_tracer", O_WRONLY);
if(fd < 0)
exit(1);

return fd;
}

int writeTracer(int fd, char* tracer)
{
if(write(fd, tracer, strlen(tracer)) != strlen(tracer)) {
printf("Failure writing %s\n", tracer);
return 0;
}

return 1;
}

int main(int argc, char* argv[])
{
int fd = openCurrentTracer();

char* blockTracer = "blk";
if(!writeTracer(fd, blockTracer))
return 1;
close(fd);

fd = openCurrentTracer();
char* graphTracer = "function_graph";
if(!writeTracer(fd, graphTracer))
return 1;
close(fd);

printf("Preparing to fail!\n");

fd = openCurrentTracer();
if(!writeTracer(fd, blockTracer))
return 1;
close(fd);

return 0;
}

奇怪的是,C 程序并没有使我的系统崩溃。

我最初在使用 Ubuntu(Unity 环境)16.04 LTS 时遇到了这个问题,并确认它是 4.4.0 和 4.5.5 内核上的问题。我还在运行 Ubuntu(Mate 环境)15.10、4.2.0 和 4.5.5 内核的机器上测试了这个问题,但无法重现该问题。这只会让我更加困惑。

任何人都可以告诉我正在发生的事情吗?具体来说,为什么我能够 write()但不是 echo到/sys/kernel/debug/tracing/current_tracer?

更新

正如 vielmetti 所指出的,其他人也有类似的问题(如 here 所示)。

The ftrace_disable_ftrace_graph_caller() modifies jmp instruction at ftrace_graph_call assuming it's a 5 bytes near jmp (e9 ). However it's a short jmp consisting of 2 bytes only (eb ). And ftrace_stub() is located just below the ftrace_graph_caller so modification above breaks the instruction resulting in kernel oops on the ftrace_stub() with the invalid opcode like below:

补丁(如下所示)解决了 echo问题,但我还是不明白为什么echo以前在 write() 时发生故障不是。

diff --git a/arch/x86/kernel/mcount_64.S b/arch/x86/kernel/mcount_64.S
index ed48a9f465f8..e13a695c3084 100644
--- a/arch/x86/kernel/mcount_64.S
+++ b/arch/x86/kernel/mcount_64.S
@@ -182,7 +182,8 @@ GLOBAL(ftrace_graph_call)
jmp ftrace_stub
#endif

-GLOBAL(ftrace_stub)
+/* This is weak to keep gas from relaxing the jumps */
+WEAK(ftrace_stub)
retq
END(ftrace_caller)

通过https://lkml.org/lkml/2016/5/16/493

最佳答案

看来您并不是唯一注意到此行为的人。我明白了

作为问题的报告,以及

作为解决它的内核补丁。通读整个线程,问题似乎出在一些编译器优化上。

关于linux - ftrace:通过 echo 从 function_graph 更改 current_tracer 时系统崩溃,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/37543901/

35 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com