lists.openwall.net   lists  /  announce  owl-users  owl-dev  john-users  john-dev  passwdqc-users  yescrypt  popa3d-users  /  oss-security  kernel-hardening  musl  sabotage  tlsify  passwords  /  crypt-dev  xvendor  /  Bugtraq  Full-Disclosure  linux-kernel  linux-netdev  linux-ext4  linux-hardening  linux-cve-announce  PHC 
Open Source and information security mailing list archives
 
Hash Suite: Windows password security audit tool. GUI, reports in PDF.
[<prev] [next>] [thread-next>] [day] [month] [year] [list]
Date:	Fri, 13 May 2016 00:27:06 -0600
From:	"Jan Beulich" <JBeulich@...e.com>
To:	"Josh Poimboeuf" <jpoimboe@...hat.com>
Cc:	<linux-kernel@...r.kernel.org>
Subject: [PATCH] objtool: cope with pre-4.5 gcc (and non-gcc)

The kernel's unreachable() translates to __builtin_unreachable() only
for gcc 4.5 and newer, and else expands to an infinite loop. Avoid
"function has unreachable instruction" warnings for this case by
inspecting the instructions immediately following the UD2. This cuts
down the number of files getting such warnings by about 99% for me.

Signed-off-by: Jan Beulich <jbeulich@...e.com>
---
 tools/objtool/builtin-check.c |   37 ++++++++++++++++++++++++++++++++++++-
 1 file changed, 36 insertions(+), 1 deletion(-)

--- 4.6-rc7/tools/objtool/builtin-check.c
+++ 4.6-rc7-objtool-BUG-older-gcc/tools/objtool/builtin-check.c
@@ -1033,6 +1033,39 @@ static bool is_ubsan_insn(struct instruc
 			"__ubsan_handle_builtin_unreachable"));
 }
 
+/*
+ * BUG() uses unreachable(), which on older gcc translates to an infinite
+ * loop, i.e. a branch targeting itself (or a group of immediately preceding
+ * NOPs). Avoid that branch (and the NOPs) getting considered unreachable,
+ * despite it really being so.
+ */
+static void mark_post_bug_insns(struct objtool_file *file,
+				struct instruction *insn)
+{
+	const struct instruction *first_nop = NULL;
+
+	if (insn->type != INSN_BUG)
+		return;
+
+	while ((insn = next_insn_same_sec(file, insn)) != NULL) {
+		switch (insn->type) {
+		case INSN_NOP:
+			insn->visited = true;
+			if (!first_nop)
+				first_nop = insn;
+			continue;
+		case INSN_JUMP_UNCONDITIONAL:
+			if (insn->jump_dest == insn ||
+			    (first_nop && insn->jump_dest == first_nop))
+				insn->visited = true;
+			break;
+		default:
+			break;
+		}
+		break;
+	}
+}
+
 static bool ignore_unreachable_insn(struct symbol *func,
 				    struct instruction *insn)
 {
@@ -1095,8 +1128,10 @@ static int validate_functions(struct obj
 				continue;
 
 			func_for_each_insn(file, func, insn) {
-				if (insn->visited)
+				if (insn->visited) {
+					mark_post_bug_insns(file, insn);
 					continue;
+				}
 
 				insn->visited = true;
 



Powered by blists - more mailing lists