4.15-stable review patch.  If anyone has any objections, please let me know.

------------------

From: Josh Poimboeuf <jpoim...@redhat.com>

commit fe24e27128252c230a34a6c628da2bf1676781ea upstream.

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 <b...@alien8.de>
Signed-off-by: Josh Poimboeuf <jpoim...@redhat.com>
Signed-off-by: Peter Zijlstra (Intel) <pet...@infradead.org>
Cc: Andy Lutomirski <l...@kernel.org>
Cc: Arjan van de Ven <ar...@linux.intel.com>
Cc: Brian Gerst <brge...@gmail.com>
Cc: Denys Vlasenko <dvlas...@redhat.com>
Cc: H. Peter Anvin <h...@zytor.com>
Cc: Linus Torvalds <torva...@linux-foundation.org>
Cc: Peter Zijlstra <pet...@infradead.org>
Cc: Thomas Gleixner <t...@linutronix.de>
Cc: kbuild test robot <fengguang...@intel.com>
Link: 
http://lkml.kernel.org/r/bace77a60d5af9b45eddb8f8fb9c776c8de657ef.1518130694.git.jpoim...@redhat.com
Signed-off-by: Ingo Molnar <mi...@kernel.org>
Signed-off-by: Greg Kroah-Hartman <gre...@linuxfoundation.org>

---
 tools/objtool/check.c |   12 +++++++++---
 1 file changed, 9 insertions(+), 3 deletions(-)

--- a/tools/objtool/check.c
+++ b/tools/objtool/check.c
@@ -1935,13 +1935,19 @@ static bool ignore_unreachable_insn(stru
                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);
        }
 


Reply via email to