J'ai récemment joué avec ftrace pour surveiller certaines caractéristiques de comportement de mon système. J'ai géré la commutation de la trace on/off via un petit script. Après l'exécution du script, mon système planterait et redémarrerait lui-même. Initialement, je pensais qu'il y avait peut-être une erreur avec le script lui-même, mais j'ai depuis déterminé que le crash et le redémarrage sont le résultat d'un traceur vers/sys/kernel/debug/tracing/current_tracer lorsque current_tracer
est défini sur function_graph .ftrace: panne du système lors du changement de current_tracer depuis function_graph via echo
C'est, la séquence de commandes suivante produira le crash/reboot:
echo "function_graph" > /sys/kernel/debug/tracing/current_tracer
echo "function" > /sys/kernel/debug/tracing/current_tracer
Durning le redémarrage après l'accident causé par les déclarations echo
ci-dessus, je vois beaucoup de sortie qui se lit comme suit:
inode<inode>
devenus orphelins compensation
j'ai essayé de reproduire ce problème en remplaçant la valeur current_tracer
de function_graph à quelque chose d'autre dans un programme 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;
}
Étrangement, le programme C ne se bloque pas mon système.
J'ai d'abord rencontré ce problème lors de l'utilisation d'Ubuntu (environnement Unity) 16.04 LTS et j'ai confirmé qu'il s'agissait d'un problème sur les noyaux 4.4.0 et 4.5.5. J'ai également testé ce problème sur une machine exécutant Ubuntu (environnement Mate) 15.10, sur les noyaux 4.2.0 et 4.5.5, mais je n'ai pas réussi à reproduire le problème. Cela m'a seulement confus davantage.
Quelqu'un peut-il me donner un aperçu de ce qui se passe? Plus précisément, pourquoi devrais-je pouvoir write()
mais pas echo
vers/sys/kernel/debug/tracing/current_tracer?
Mise à jour
Comme Vielmetti a fait remarquer, d'autres ont eu un problème similaire (comme on le voit here).
Le
ftrace_disable_ftrace_graph_caller()
modifie l'instruction jmp àftrace_graph_call
en supposant qu'il est un 5 octets près de JMP (E9). Cependant, il s'agit d'un jmp court composé de 2 octets seulement (eb). Etftrace_stub()
est situé juste en dessous duftrace_graph_caller
si modification casse ci-dessus l'instruction résultant dans le noyau oops sur leftrace_stub()
avec l'opcode invalide comme ci-dessous:
Le patch (ci-dessous) a résolu le problème echo
, mais je ne comprends toujours pas pourquoi echo
cassait précédemment lorsque write()
ne l'était pas.
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)
via https://lkml.org/lkml/2016/5/16/493
Avez-vous essayé de reproduire en utilisant un seul programme C (sans appels 'exec' sauf éventuellement pour l'appel' dd')? Parfois, les coquilles font des trucs funky. – o11c
Avez-vous envisagé de poser votre question sur l'un des sites Linux Stack Exchange? – ashes999
@ o11c, l'erreur semble se produire uniquement lors de l'écriture dans '/ sys/kernel/debug/tracing/current_tracer'. Je dis cela parce que je peux produire ce problème sans invoquer le script entier, mais plutôt en faisant juste un 'echo'ing à ce fichier. J'ai écouté votre suggestion dans cet esprit, et j'ai mis à jour mon post. – buratino