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-prev] [thread-next>] [day] [month] [year] [list]
Date:	Fri, 17 Jul 2015 11:47:17 -0500
From:	Josh Poimboeuf <jpoimboe@...hat.com>
To:	Thomas Gleixner <tglx@...utronix.de>,
	Ingo Molnar <mingo@...hat.com>,
	"H. Peter Anvin" <hpa@...or.com>
Cc:	Michal Marek <mmarek@...e.cz>,
	Peter Zijlstra <peterz@...radead.org>,
	Andy Lutomirski <luto@...nel.org>,
	Borislav Petkov <bp@...en8.de>,
	Linus Torvalds <torvalds@...ux-foundation.org>,
	Andi Kleen <andi@...stfloor.org>,
	Pedro Alves <palves@...hat.com>, x86@...nel.org,
	live-patching@...r.kernel.org, linux-kernel@...r.kernel.org
Subject: [RFC PATCH 01/21] stackvalidate: Process ignores earlier and add more ignore checks

Process the ignore macros earlier and associate them with their
corresponding instructions.  This allows ignores to be checked in
get_jump_destinations() which is needed for some funky xen code which
introduces fake instructions (XEN_EMULATE_PREFIX).

Signed-off-by: Josh Poimboeuf <jpoimboe@...hat.com>
---
 scripts/stackvalidate/stackvalidate.c | 77 +++++++++++++++++++++++++----------
 1 file changed, 56 insertions(+), 21 deletions(-)

diff --git a/scripts/stackvalidate/stackvalidate.c b/scripts/stackvalidate/stackvalidate.c
index a817130..6173412 100644
--- a/scripts/stackvalidate/stackvalidate.c
+++ b/scripts/stackvalidate/stackvalidate.c
@@ -49,7 +49,7 @@ struct instruction {
 	unsigned int len, state;
 	unsigned char type;
 	unsigned long immediate;
-	bool alt_group, visited;
+	bool alt_group, visited, ignore;
 	struct symbol *call_dest;
 	struct instruction *jump_dest;
 	struct list_head alts;
@@ -106,8 +106,7 @@ static struct argp argp = { options, parse_opt, args_doc, 0 };
 /*
  * Check for the STACKVALIDATE_IGNORE_INSN macro.
  */
-static bool ignore_insn(struct elf *elf, struct section *sec,
-			unsigned long offset)
+static bool ignore_insn(struct elf *elf, struct instruction *insn)
 {
 	struct section *macro_sec;
 	struct rela *rela;
@@ -118,8 +117,8 @@ static bool ignore_insn(struct elf *elf, struct section *sec,
 
 	list_for_each_entry(rela, &macro_sec->rela->relas, list)
 		if (rela->sym->type == STT_SECTION &&
-		    rela->sym == sec->sym &&
-		    rela->addend == offset)
+		    rela->sym == insn->sec->sym &&
+		    rela->addend == insn->offset)
 			return true;
 
 	return false;
@@ -138,9 +137,11 @@ static bool ignore_func(struct elf *elf, struct symbol *func)
 		return false;
 
 	list_for_each_entry(rela, &macro_sec->rela->relas, list)
-		if (rela->sym == func)
+		if (rela->sym->sec == func->sec &&
+		    rela->addend == func->offset)
 			return true;
 
+
 	return false;
 }
 
@@ -266,6 +267,44 @@ static int decode_instructions(struct elf *elf)
 }
 
 /*
+ * Warnings shouldn't be reported for ignored instructions.  Set insn->ignore
+ * for each ignored instruction and each instruction contained in an ignored
+ * function.
+ */
+static void get_ignores(struct elf *elf)
+{
+	struct instruction *insn;
+	struct section *sec;
+	struct symbol *func;
+
+	list_for_each_entry(insn, &insns, list)
+		insn->ignore = ignore_insn(elf, insn);
+
+	list_for_each_entry(sec, &elf->sections, list) {
+		list_for_each_entry(func, &sec->symbols, list) {
+			if (func->type != STT_FUNC)
+				continue;
+
+			if (!ignore_func(elf, func))
+				continue;
+
+			insn = find_instruction(sec, func->offset);
+			if (!insn)
+				continue;
+
+			list_for_each_entry_from(insn, &insns, list) {
+				if (insn->sec != func->sec ||
+				    insn->offset >= func->offset + func->len)
+					break;
+
+				insn->ignore = true;
+				insn->visited = true;
+			}
+		}
+	}
+}
+
+/*
  * Find the destination instructions for all jumps.
  */
 static int get_jump_destinations(struct elf *elf)
@@ -300,7 +339,7 @@ static int get_jump_destinations(struct elf *elf)
 		}
 
 		insn->jump_dest = find_instruction(dest_sec, dest_off);
-		if (!insn->jump_dest) {
+		if (!insn->jump_dest && !insn->ignore) {
 
 			/*
 			 * This is a special case where an alt instruction
@@ -591,6 +630,8 @@ static int decode_sections(struct elf *elf)
 	if (ret)
 		return ret;
 
+	get_ignores(elf);
+
 	ret = get_jump_destinations(elf);
 	if (ret)
 		return ret;
@@ -734,7 +775,8 @@ static int validate_branch(struct elf *elf, struct instruction *first,
 			break;
 
 		case INSN_JUMP_DYNAMIC:
-			if (list_empty(&insn->alts) && insn->state) {
+			if (list_empty(&insn->alts) && insn->state &&
+			    !insn->ignore) {
 				WARN("%s: sibling call from callable instruction with changed frame pointer",
 				     offstr(sec, insn->offset));
 				warnings++;
@@ -743,9 +785,11 @@ static int validate_branch(struct elf *elf, struct instruction *first,
 			return warnings;
 
 		case INSN_CONTEXT_SWITCH:
-			WARN("%s: kernel entry/exit from callable instruction",
-			     offstr(sec, insn->offset));
-			warnings++;
+			if (!insn->ignore) {
+				WARN("%s: kernel entry/exit from callable instruction",
+				     offstr(sec, insn->offset));
+				warnings++;
+			}
 
 			return warnings;
 
@@ -786,15 +830,6 @@ static int validate_functions(struct elf *elf)
 				continue;
 			}
 
-			if (ignore_func(elf, func)) {
-				list_for_each_entry_from(insn, &insns, list) {
-					if (insn->sec != func->sec ||
-					    insn->offset >= func->offset + func->len)
-						break;
-					insn->visited = true;
-				}
-			}
-
 			ret = validate_branch(elf, insn, 0);
 			warnings += ret;
 		}
@@ -835,7 +870,7 @@ static int validate_uncallable_instructions(struct elf *elf)
 
 	list_for_each_entry(insn, &insns, list) {
 		if (!insn->visited && insn->type == INSN_RETURN &&
-		    !ignore_insn(elf, insn->sec, insn->offset)) {
+		    !insn->ignore) {
 			WARN("%s: return instruction outside of a callable function",
 			     offstr(insn->sec, insn->offset));
 			warnings++;
-- 
2.1.0

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@...r.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/

Powered by blists - more mailing lists