提交 7f11f5ec 编写于 作者: P Petr Mladek 提交者: Steven Rostedt

ftrace/x86: BUG when ftrace recovery fails

Ftrace modifies function calls using Int3 breakpoints on x86.
The breakpoints are handled only when the patching is in progress.
If something goes wrong, there is a recovery code that removes
the breakpoints. If this fails, the system might get silently
rebooted when a remaining break is not handled or an invalid
instruction is proceed.

We should BUG() when the breakpoint could not be removed. Otherwise,
the system silently crashes when the function finishes the Int3
handler is disabled.

Note that we need to modify remove_breakpoint() to return non-zero
value only when there is an error. The return value was ignored before,
so it does not cause any troubles.

Link: http://lkml.kernel.org/r/1393258342-29978-4-git-send-email-pmladek@suse.czSigned-off-by: NPetr Mladek <pmladek@suse.cz>
Signed-off-by: NSteven Rostedt <rostedt@goodmis.org>
上级 cd21067f
...@@ -425,7 +425,7 @@ static int remove_breakpoint(struct dyn_ftrace *rec) ...@@ -425,7 +425,7 @@ static int remove_breakpoint(struct dyn_ftrace *rec)
/* If this does not have a breakpoint, we are done */ /* If this does not have a breakpoint, we are done */
if (ins[0] != brk) if (ins[0] != brk)
return -1; return 0;
nop = ftrace_nop_replace(); nop = ftrace_nop_replace();
...@@ -625,7 +625,12 @@ void ftrace_replace_code(int enable) ...@@ -625,7 +625,12 @@ void ftrace_replace_code(int enable)
printk(KERN_WARNING "Failed on %s (%d):\n", report, count); printk(KERN_WARNING "Failed on %s (%d):\n", report, count);
for_ftrace_rec_iter(iter) { for_ftrace_rec_iter(iter) {
rec = ftrace_rec_iter_record(iter); rec = ftrace_rec_iter_record(iter);
remove_breakpoint(rec); /*
* Breakpoints are handled only when this function is in
* progress. The system could not work with them.
*/
if (remove_breakpoint(rec))
BUG();
} }
run_sync(); run_sync();
} }
...@@ -649,12 +654,19 @@ ftrace_modify_code(unsigned long ip, unsigned const char *old_code, ...@@ -649,12 +654,19 @@ ftrace_modify_code(unsigned long ip, unsigned const char *old_code,
run_sync(); run_sync();
ret = ftrace_write(ip, new_code, 1); ret = ftrace_write(ip, new_code, 1);
/*
* The breakpoint is handled only when this function is in progress.
* The system could not work if we could not remove it.
*/
BUG_ON(ret);
out: out:
run_sync(); run_sync();
return ret; return ret;
fail_update: fail_update:
ftrace_write(ip, old_code, 1); /* Also here the system could not work with the breakpoint */
if (ftrace_write(ip, old_code, 1))
BUG();
goto out; goto out;
} }
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册