summaryrefslogtreecommitdiff
path: root/tools/objtool
diff options
context:
space:
mode:
authorPeter Zijlstra <peterz@infradead.org>2020-06-03 21:09:06 +0300
committerPeter Zijlstra <peterz@infradead.org>2020-06-15 15:10:09 +0300
commit6b643a07a7e41f9e11cfbb9bba4c5c9791ac2997 (patch)
tree6d273e16bc0f0d0e72f0036144882300c7986f98 /tools/objtool
parent14d3b376b6c3f66d62559d457d32edf565472163 (diff)
downloadlinux-6b643a07a7e41f9e11cfbb9bba4c5c9791ac2997.tar.xz
x86/entry, ubsan, objtool: Whitelist __ubsan_handle_*()
The UBSAN instrumentation only inserts external CALLs when things go 'BAD', much like WARN(). So treat them similar to WARN()s for noinstr, that is: allow them, at the risk of taking the machine down, to get their message out. Suggested-by: Marco Elver <elver@google.com> Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org> Acked-by: Marco Elver <elver@google.com>
Diffstat (limited to 'tools/objtool')
-rw-r--r--tools/objtool/check.c28
1 files changed, 27 insertions, 1 deletions
diff --git a/tools/objtool/check.c b/tools/objtool/check.c
index 5fbb90a80d23..3e214f879ada 100644
--- a/tools/objtool/check.c
+++ b/tools/objtool/check.c
@@ -2190,10 +2190,36 @@ static inline const char *call_dest_name(struct instruction *insn)
return "{dynamic}";
}
+static inline bool noinstr_call_dest(struct symbol *func)
+{
+ /*
+ * We can't deal with indirect function calls at present;
+ * assume they're instrumented.
+ */
+ if (!func)
+ return false;
+
+ /*
+ * If the symbol is from a noinstr section; we good.
+ */
+ if (func->sec->noinstr)
+ return true;
+
+ /*
+ * The __ubsan_handle_*() calls are like WARN(), they only happen when
+ * something 'BAD' happened. At the risk of taking the machine down,
+ * let them proceed to get the message out.
+ */
+ if (!strncmp(func->name, "__ubsan_handle_", 15))
+ return true;
+
+ return false;
+}
+
static int validate_call(struct instruction *insn, struct insn_state *state)
{
if (state->noinstr && state->instr <= 0 &&
- (!insn->call_dest || !insn->call_dest->sec->noinstr)) {
+ !noinstr_call_dest(insn->call_dest)) {
WARN_FUNC("call to %s() leaves .noinstr.text section",
insn->sec, insn->offset, call_dest_name(insn));
return 1;