Commit 6b643a07 authored by Peter Zijlstra's avatar Peter Zijlstra

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: default avatarMarco Elver <elver@google.com>
Signed-off-by: default avatarPeter Zijlstra (Intel) <peterz@infradead.org>
Acked-by: default avatarMarco Elver <elver@google.com>
parent 14d3b376
...@@ -199,7 +199,7 @@ struct ftrace_likely_data { ...@@ -199,7 +199,7 @@ struct ftrace_likely_data {
/* Section for code which can't be instrumented at all */ /* Section for code which can't be instrumented at all */
#define noinstr \ #define noinstr \
noinline notrace __attribute((__section__(".noinstr.text"))) \ noinline notrace __attribute((__section__(".noinstr.text"))) \
__no_kcsan __no_sanitize_address __no_sanitize_undefined __no_kcsan __no_sanitize_address
#endif /* __KERNEL__ */ #endif /* __KERNEL__ */
......
...@@ -2190,10 +2190,36 @@ static inline const char *call_dest_name(struct instruction *insn) ...@@ -2190,10 +2190,36 @@ static inline const char *call_dest_name(struct instruction *insn)
return "{dynamic}"; 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) static int validate_call(struct instruction *insn, struct insn_state *state)
{ {
if (state->noinstr && state->instr <= 0 && 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", WARN_FUNC("call to %s() leaves .noinstr.text section",
insn->sec, insn->offset, call_dest_name(insn)); insn->sec, insn->offset, call_dest_name(insn));
return 1; return 1;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment