我一直在玩ftrace來監視我的系統的一些行爲特徵。我一直在通過一個小腳本處理打開/關閉軌跡。運行腳本後,我的系統會崩潰並重新啓動。最初,我認爲腳本本身可能存在錯誤,但是我確定當current_tracer
設置爲function_graph時,崩潰和重新啓動是由於/ sys/kernel/debug/tracing/current_tracer中的某個跟蹤器導致的。 。ftrace:從function_graph通過echo更改current_tracer時系統崩潰
即,下面的命令序列將產生崩潰/重新啓動:
echo "function_graph" > /sys/kernel/debug/tracing/current_tracer
echo "function" > /sys/kernel/debug/tracing/current_tracer
德寧引起上述echo
語句崩潰後重新啓動,我看到很多輸出的讀取:
結算孤立的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內核上測試過這個問題,但無法重現該問題。這隻會讓我更加困惑。
任何人都可以給我洞察發生了什麼?具體來說,爲什麼我能夠在/ sys/kernel/debug/tracing/current_tracer中將write()
而不是echo
?
更新
由於vielmetti指出,其他人也有類似的問題(如圖here)。
的
ftrace_disable_ftrace_graph_caller()
在ftrace_graph_call
修改jmp指令假設它的鄰近的jmp(E9)一個5個字節。 但它是一個由2個字節組成的簡短jmp(eb)。而ftrace_stub()
就位於ftrace_graph_caller
下方,以便 修改上述打破導致內核指令哎呀上 的ftrace_stub()
與無效操作如下圖所示:
的修補程序(如下圖所示)解決了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
您是否試過使用單個C程序進行復制(除了可能調用'dd'外沒有'exec'調用)?有時候貝殼會做些時髦的東西。 – o11c
你有沒有考慮過在其中一個Linux Stack Exchange站點上提問? – ashes999
@ o11c,錯誤似乎只在寫入'/ sys/kernel/debug/tracing/current_tracer'時纔會發生。我這樣說是因爲我可以在不調用整個腳本的情況下產生這個問題,而只是對該文件進行回聲。我謹慎地聽取了你的建議,並且更新了我的帖子。 – buratino