Skip to content

Commit

Permalink
objtool: Fix segfault in ignore_unreachable_insn()
Browse files Browse the repository at this point in the history
Peter Zijlstra's patch for converting WARN() to use UD2 triggered a
bunch of false "unreachable instruction" warnings, which then triggered
a seg fault in ignore_unreachable_insn().

The seg fault happened when it tried to dereference a NULL 'insn->func'
pointer.  Thanks to static_cpu_has(), some functions can jump to a
non-function area in the .altinstr_aux section.  That breaks
ignore_unreachable_insn()'s assumption that it's always inside the
original function.

Make sure ignore_unreachable_insn() only follows jumps within the
current function.

Reported-by: Borislav Petkov <[email protected]>
Signed-off-by: Josh Poimboeuf <[email protected]>
Signed-off-by: Peter Zijlstra (Intel) <[email protected]>
Cc: Andy Lutomirski <[email protected]>
Cc: Arjan van de Ven <[email protected]>
Cc: Brian Gerst <[email protected]>
Cc: Denys Vlasenko <[email protected]>
Cc: H. Peter Anvin <[email protected]>
Cc: Linus Torvalds <[email protected]>
Cc: Peter Zijlstra <[email protected]>
Cc: Thomas Gleixner <[email protected]>
Cc: kbuild test robot <[email protected]>
Link: http://lkml.kernel.org/r/bace77a60d5af9b45eddb8f8fb9c776c8de657ef.1518130694.git.jpoimboe@redhat.com
Signed-off-by: Ingo Molnar <[email protected]>
  • Loading branch information
jpoimboe authored and Ingo Molnar committed Feb 15, 2018
1 parent 9279ddf commit fe24e27
Showing 1 changed file with 9 additions and 3 deletions.
12 changes: 9 additions & 3 deletions tools/objtool/check.c
Original file line number Diff line number Diff line change
Expand Up @@ -1935,13 +1935,19 @@ static bool ignore_unreachable_insn(struct instruction *insn)
if (is_kasan_insn(insn) || is_ubsan_insn(insn))
return true;

if (insn->type == INSN_JUMP_UNCONDITIONAL && insn->jump_dest) {
insn = insn->jump_dest;
continue;
if (insn->type == INSN_JUMP_UNCONDITIONAL) {
if (insn->jump_dest &&
insn->jump_dest->func == insn->func) {
insn = insn->jump_dest;
continue;
}

break;
}

if (insn->offset + insn->len >= insn->func->offset + insn->func->len)
break;

insn = list_next_entry(insn, list);
}

Expand Down

0 comments on commit fe24e27

Please sign in to comment.