Skip to content

Commit

Permalink
x86/entry, ubsan, objtool: Whitelist __ubsan_handle_*()
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
Peter Zijlstra committed Jun 15, 2020
1 parent 14d3b37 commit 6b643a0
Show file tree
Hide file tree
Showing 2 changed files with 28 additions and 2 deletions.
2 changes: 1 addition & 1 deletion include/linux/compiler_types.h
Original file line number Diff line number Diff line change
Expand Up @@ -199,7 +199,7 @@ struct ftrace_likely_data {
/* Section for code which can't be instrumented at all */
#define noinstr \
noinline notrace __attribute((__section__(".noinstr.text"))) \
__no_kcsan __no_sanitize_address __no_sanitize_undefined
__no_kcsan __no_sanitize_address

#endif /* __KERNEL__ */

Expand Down
28 changes: 27 additions & 1 deletion tools/objtool/check.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down

0 comments on commit 6b643a0

Please sign in to comment.