diff options
author | Masami Hiramatsu <masami.hiramatsu.pt@hitachi.com> | 2014-11-21 05:25:16 -0500 |
---|---|---|
committer | Steven Rostedt <rostedt@goodmis.org> | 2014-11-21 14:42:10 -0500 |
commit | f8b8be8a310a55856fd2c369dade08088d85df3b (patch) | |
tree | 4c427a2981e4b66392b5bf9d7f8988479040150c /include/linux/ftrace.h | |
parent | a017784f1b236cbc42ce83b4345a667c21113481 (diff) |
ftrace, kprobes: Support IPMODIFY flag to find IP modify conflict
Introduce FTRACE_OPS_FL_IPMODIFY to avoid conflict among
ftrace users who may modify regs->ip to change the execution
path. If two or more users modify the regs->ip on the same
function entry, one of them will be broken. So they must add
IPMODIFY flag and make sure that ftrace_set_filter_ip() succeeds.
Note that ftrace doesn't allow ftrace_ops which has IPMODIFY
flag to have notrace hash, and the ftrace_ops must have a
filter hash (so that the ftrace_ops can hook only specific
entries), because it strongly depends on the address and
must be allowed for only few selected functions.
Link: http://lkml.kernel.org/r/20141121102516.11844.27829.stgit@localhost.localdomain
Cc: Jiri Kosina <jkosina@suse.cz>
Cc: Seth Jennings <sjenning@redhat.com>
Cc: Petr Mladek <pmladek@suse.cz>
Cc: Vojtech Pavlik <vojtech@suse.cz>
Cc: Miroslav Benes <mbenes@suse.cz>
Cc: Ingo Molnar <mingo@kernel.org>
Cc: Ananth N Mavinakayanahalli <ananth@in.ibm.com>
Cc: Josh Poimboeuf <jpoimboe@redhat.com>
Cc: Namhyung Kim <namhyung@kernel.org>
Signed-off-by: Masami Hiramatsu <masami.hiramatsu.pt@hitachi.com>
[ fixed up some of the comments ]
Signed-off-by: Steven Rostedt <rostedt@goodmis.org>
Diffstat (limited to 'include/linux/ftrace.h')
-rw-r--r-- | include/linux/ftrace.h | 16 |
1 files changed, 14 insertions, 2 deletions
diff --git a/include/linux/ftrace.h b/include/linux/ftrace.h index 7b2616fa2472..ed501953f0b2 100644 --- a/include/linux/ftrace.h +++ b/include/linux/ftrace.h | |||
@@ -61,6 +61,11 @@ ftrace_func_t ftrace_ops_get_func(struct ftrace_ops *ops); | |||
61 | /* | 61 | /* |
62 | * FTRACE_OPS_FL_* bits denote the state of ftrace_ops struct and are | 62 | * FTRACE_OPS_FL_* bits denote the state of ftrace_ops struct and are |
63 | * set in the flags member. | 63 | * set in the flags member. |
64 | * CONTROL, SAVE_REGS, SAVE_REGS_IF_SUPPORTED, RECURSION_SAFE, STUB and | ||
65 | * IPMODIFY are a kind of attribute flags which can be set only before | ||
66 | * registering the ftrace_ops, and can not be modified while registered. | ||
67 | * Changing those attribute flags after regsitering ftrace_ops will | ||
68 | * cause unexpected results. | ||
64 | * | 69 | * |
65 | * ENABLED - set/unset when ftrace_ops is registered/unregistered | 70 | * ENABLED - set/unset when ftrace_ops is registered/unregistered |
66 | * DYNAMIC - set when ftrace_ops is registered to denote dynamically | 71 | * DYNAMIC - set when ftrace_ops is registered to denote dynamically |
@@ -101,6 +106,10 @@ ftrace_func_t ftrace_ops_get_func(struct ftrace_ops *ops); | |||
101 | * The ftrace_ops trampoline can be set by the ftrace users, and | 106 | * The ftrace_ops trampoline can be set by the ftrace users, and |
102 | * in such cases the arch must not modify it. Only the arch ftrace | 107 | * in such cases the arch must not modify it. Only the arch ftrace |
103 | * core code should set this flag. | 108 | * core code should set this flag. |
109 | * IPMODIFY - The ops can modify the IP register. This can only be set with | ||
110 | * SAVE_REGS. If another ops with this flag set is already registered | ||
111 | * for any of the functions that this ops will be registered for, then | ||
112 | * this ops will fail to register or set_filter_ip. | ||
104 | */ | 113 | */ |
105 | enum { | 114 | enum { |
106 | FTRACE_OPS_FL_ENABLED = 1 << 0, | 115 | FTRACE_OPS_FL_ENABLED = 1 << 0, |
@@ -116,6 +125,7 @@ enum { | |||
116 | FTRACE_OPS_FL_REMOVING = 1 << 10, | 125 | FTRACE_OPS_FL_REMOVING = 1 << 10, |
117 | FTRACE_OPS_FL_MODIFYING = 1 << 11, | 126 | FTRACE_OPS_FL_MODIFYING = 1 << 11, |
118 | FTRACE_OPS_FL_ALLOC_TRAMP = 1 << 12, | 127 | FTRACE_OPS_FL_ALLOC_TRAMP = 1 << 12, |
128 | FTRACE_OPS_FL_IPMODIFY = 1 << 13, | ||
119 | }; | 129 | }; |
120 | 130 | ||
121 | #ifdef CONFIG_DYNAMIC_FTRACE | 131 | #ifdef CONFIG_DYNAMIC_FTRACE |
@@ -310,6 +320,7 @@ bool is_ftrace_trampoline(unsigned long addr); | |||
310 | * ENABLED - the function is being traced | 320 | * ENABLED - the function is being traced |
311 | * REGS - the record wants the function to save regs | 321 | * REGS - the record wants the function to save regs |
312 | * REGS_EN - the function is set up to save regs. | 322 | * REGS_EN - the function is set up to save regs. |
323 | * IPMODIFY - the record allows for the IP address to be changed. | ||
313 | * | 324 | * |
314 | * When a new ftrace_ops is registered and wants a function to save | 325 | * When a new ftrace_ops is registered and wants a function to save |
315 | * pt_regs, the rec->flag REGS is set. When the function has been | 326 | * pt_regs, the rec->flag REGS is set. When the function has been |
@@ -323,10 +334,11 @@ enum { | |||
323 | FTRACE_FL_REGS_EN = (1UL << 29), | 334 | FTRACE_FL_REGS_EN = (1UL << 29), |
324 | FTRACE_FL_TRAMP = (1UL << 28), | 335 | FTRACE_FL_TRAMP = (1UL << 28), |
325 | FTRACE_FL_TRAMP_EN = (1UL << 27), | 336 | FTRACE_FL_TRAMP_EN = (1UL << 27), |
337 | FTRACE_FL_IPMODIFY = (1UL << 26), | ||
326 | }; | 338 | }; |
327 | 339 | ||
328 | #define FTRACE_REF_MAX_SHIFT 27 | 340 | #define FTRACE_REF_MAX_SHIFT 26 |
329 | #define FTRACE_FL_BITS 5 | 341 | #define FTRACE_FL_BITS 6 |
330 | #define FTRACE_FL_MASKED_BITS ((1UL << FTRACE_FL_BITS) - 1) | 342 | #define FTRACE_FL_MASKED_BITS ((1UL << FTRACE_FL_BITS) - 1) |
331 | #define FTRACE_FL_MASK (FTRACE_FL_MASKED_BITS << FTRACE_REF_MAX_SHIFT) | 343 | #define FTRACE_FL_MASK (FTRACE_FL_MASKED_BITS << FTRACE_REF_MAX_SHIFT) |
332 | #define FTRACE_REF_MAX ((1UL << FTRACE_REF_MAX_SHIFT) - 1) | 344 | #define FTRACE_REF_MAX ((1UL << FTRACE_REF_MAX_SHIFT) - 1) |