mirror of https://lore.kernel.org/lkml/
 help / color / mirror / Atom feed
From: "tip-bot2 for Peter Zijlstra" <tip-bot2@linutronix.de>
To: linux-tip-commits@vger.kernel.org
Cc: "Peter Zijlstra (Intel)" <peterz@infradead.org>,
	Miroslav Benes <mbenes@suse.cz>,
	Alexandre Chartre <alexandre.chartre@oracle.com>,
	Josh Poimboeuf <jpoimboe@redhat.com>, x86 <x86@kernel.org>,
	LKML <linux-kernel@vger.kernel.org>
Subject: [tip: objtool/core] objtool: Implement noinstr validation
Date: Wed, 22 Apr 2020 22:24:32 -0000	[thread overview]
Message-ID: <158759427292.28353.10002474084884955071.tip-bot2@tip-bot2> (raw)
In-Reply-To: <20200416115119.106268040@infradead.org>

The following commit has been merged into the objtool/core branch of tip:

Commit-ID:     1f6d80c69ef603a6b6b5b4eb8b0e77286b053702
Gitweb:        https://git.kernel.org/tip/1f6d80c69ef603a6b6b5b4eb8b0e77286b053702
Author:        Peter Zijlstra <peterz@infradead.org>
AuthorDate:    Tue, 10 Mar 2020 18:57:41 +01:00
Committer:     Peter Zijlstra <peterz@infradead.org>
CommitterDate: Wed, 22 Apr 2020 23:10:07 +02:00

objtool: Implement noinstr validation

Validate that any call out of .noinstr.text is in between
instr_begin() and instr_end() annotations.

This annotation is useful to ensure correct behaviour wrt tracing
sensitive code like entry/exit and idle code. When we run code in a
sensitive context we want a guarantee no unknown code is ran.

Since this validation relies on knowing the section of call
destination symbols, we must run it on vmlinux.o instead of on
individual object files.

Add two options:

 -d/--duplicate "duplicate validation for vmlinux"
 -l/--vmlinux "vmlinux.o validation"

Where the latter auto-detects when objname ends with "vmlinux.o" and
the former will force all validations, also those already done on
!vmlinux object files.

Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org>
Reviewed-by: Miroslav Benes <mbenes@suse.cz>
Reviewed-by: Alexandre Chartre <alexandre.chartre@oracle.com>
Acked-by: Josh Poimboeuf <jpoimboe@redhat.com>
Link: https://lkml.kernel.org/r/20200416115119.106268040@infradead.org
---
 tools/objtool/builtin-check.c | 11 +++-
 tools/objtool/builtin.h       |  2 +-
 tools/objtool/check.c         | 98 ++++++++++++++++++++++++++++++++++-
 tools/objtool/check.h         |  3 +-
 tools/objtool/elf.h           |  2 +-
 5 files changed, 112 insertions(+), 4 deletions(-)

diff --git a/tools/objtool/builtin-check.c b/tools/objtool/builtin-check.c
index 10fbe75..be42b71 100644
--- a/tools/objtool/builtin-check.c
+++ b/tools/objtool/builtin-check.c
@@ -14,10 +14,11 @@
  */
 
 #include <subcmd/parse-options.h>
+#include <string.h>
 #include "builtin.h"
 #include "check.h"
 
-bool no_fp, no_unreachable, retpoline, module, backtrace, uaccess, stats;
+bool no_fp, no_unreachable, retpoline, module, backtrace, uaccess, stats, validate_dup, vmlinux;
 
 static const char * const check_usage[] = {
 	"objtool check [<options>] file.o",
@@ -32,12 +33,14 @@ const struct option check_options[] = {
 	OPT_BOOLEAN('b', "backtrace", &backtrace, "unwind on error"),
 	OPT_BOOLEAN('a', "uaccess", &uaccess, "enable uaccess checking"),
 	OPT_BOOLEAN('s', "stats", &stats, "print statistics"),
+	OPT_BOOLEAN('d', "duplicate", &validate_dup, "duplicate validation for vmlinux.o"),
+	OPT_BOOLEAN('l', "vmlinux", &vmlinux, "vmlinux.o validation"),
 	OPT_END(),
 };
 
 int cmd_check(int argc, const char **argv)
 {
-	const char *objname;
+	const char *objname, *s;
 
 	argc = parse_options(argc, argv, check_options, check_usage, 0);
 
@@ -46,5 +49,9 @@ int cmd_check(int argc, const char **argv)
 
 	objname = argv[0];
 
+	s = strstr(objname, "vmlinux.o");
+	if (s && !s[9])
+		vmlinux = true;
+
 	return check(objname, false);
 }
diff --git a/tools/objtool/builtin.h b/tools/objtool/builtin.h
index 0b90790..85c979c 100644
--- a/tools/objtool/builtin.h
+++ b/tools/objtool/builtin.h
@@ -8,7 +8,7 @@
 #include <subcmd/parse-options.h>
 
 extern const struct option check_options[];
-extern bool no_fp, no_unreachable, retpoline, module, backtrace, uaccess, stats;
+extern bool no_fp, no_unreachable, retpoline, module, backtrace, uaccess, stats, validate_dup, vmlinux;
 
 extern int cmd_check(int argc, const char **argv);
 extern int cmd_orc(int argc, const char **argv);
diff --git a/tools/objtool/check.c b/tools/objtool/check.c
index 7e67b3c..39d1d4f 100644
--- a/tools/objtool/check.c
+++ b/tools/objtool/check.c
@@ -257,6 +257,9 @@ static int decode_instructions(struct objtool_file *file)
 		    strncmp(sec->name, ".discard.", 9))
 			sec->text = true;
 
+		if (!strcmp(sec->name, ".noinstr.text"))
+			sec->noinstr = true;
+
 		for (offset = 0; offset < sec->len; offset += insn->len) {
 			insn = malloc(sizeof(*insn));
 			if (!insn) {
@@ -1356,6 +1359,53 @@ static int read_retpoline_hints(struct objtool_file *file)
 	return 0;
 }
 
+static int read_instr_hints(struct objtool_file *file)
+{
+	struct section *sec;
+	struct instruction *insn;
+	struct rela *rela;
+
+	sec = find_section_by_name(file->elf, ".rela.discard.instr_end");
+	if (!sec)
+		return 0;
+
+	list_for_each_entry(rela, &sec->rela_list, list) {
+		if (rela->sym->type != STT_SECTION) {
+			WARN("unexpected relocation symbol type in %s", sec->name);
+			return -1;
+		}
+
+		insn = find_insn(file, rela->sym->sec, rela->addend);
+		if (!insn) {
+			WARN("bad .discard.instr_end entry");
+			return -1;
+		}
+
+		insn->instr--;
+	}
+
+	sec = find_section_by_name(file->elf, ".rela.discard.instr_begin");
+	if (!sec)
+		return 0;
+
+	list_for_each_entry(rela, &sec->rela_list, list) {
+		if (rela->sym->type != STT_SECTION) {
+			WARN("unexpected relocation symbol type in %s", sec->name);
+			return -1;
+		}
+
+		insn = find_insn(file, rela->sym->sec, rela->addend);
+		if (!insn) {
+			WARN("bad .discard.instr_begin entry");
+			return -1;
+		}
+
+		insn->instr++;
+	}
+
+	return 0;
+}
+
 static void mark_rodata(struct objtool_file *file)
 {
 	struct section *sec;
@@ -1427,6 +1477,10 @@ static int decode_sections(struct objtool_file *file)
 	if (ret)
 		return ret;
 
+	ret = read_instr_hints(file);
+	if (ret)
+		return ret;
+
 	return 0;
 }
 
@@ -2023,6 +2077,13 @@ static inline const char *call_dest_name(struct instruction *insn)
 
 static int validate_call(struct instruction *insn, struct insn_state *state)
 {
+	if (state->noinstr && state->instr <= 0 &&
+	    (!insn->call_dest || insn->call_dest->sec != insn->sec)) {
+		WARN_FUNC("call to %s() leaves .noinstr.text section",
+				insn->sec, insn->offset, call_dest_name(insn));
+		return 1;
+	}
+
 	if (state->uaccess && !func_uaccess_safe(insn->call_dest)) {
 		WARN_FUNC("call to %s() with UACCESS enabled",
 				insn->sec, insn->offset, call_dest_name(insn));
@@ -2051,6 +2112,12 @@ static int validate_sibling_call(struct instruction *insn, struct insn_state *st
 
 static int validate_return(struct symbol *func, struct instruction *insn, struct insn_state *state)
 {
+	if (state->noinstr && state->instr > 0) {
+		WARN_FUNC("return with instrumentation enabled",
+			  insn->sec, insn->offset);
+		return 1;
+	}
+
 	if (state->uaccess && !func_uaccess_safe(func)) {
 		WARN_FUNC("return with UACCESS enabled",
 			  insn->sec, insn->offset);
@@ -2131,6 +2198,9 @@ static int validate_branch(struct objtool_file *file, struct symbol *func,
 				return 0;
 		}
 
+		if (state.noinstr)
+			state.instr += insn->instr;
+
 		if (insn->hint)
 			state.cfi = insn->cfi;
 		else
@@ -2438,6 +2508,14 @@ static int validate_section(struct objtool_file *file, struct section *sec)
 	struct insn_state state;
 	int ret, warnings = 0;
 
+	/*
+	 * We need the full vmlinux for noinstr validation, otherwise we can
+	 * not correctly determine insn->call_dest->sec (external symbols do
+	 * not have a section).
+	 */
+	if (vmlinux)
+		state.noinstr = sec->noinstr;
+
 	list_for_each_entry(func, &sec->symbol_list, list) {
 		if (func->type != STT_FUNC)
 			continue;
@@ -2472,6 +2550,17 @@ static int validate_section(struct objtool_file *file, struct section *sec)
 	return warnings;
 }
 
+static int validate_vmlinux_functions(struct objtool_file *file)
+{
+	struct section *sec;
+
+	sec = find_section_by_name(file->elf, ".noinstr.text");
+	if (!sec)
+		return 0;
+
+	return validate_section(file, sec);
+}
+
 static int validate_functions(struct objtool_file *file)
 {
 	struct section *sec;
@@ -2529,6 +2618,15 @@ int check(const char *_objname, bool orc)
 	if (list_empty(&file.insn_list))
 		goto out;
 
+	if (vmlinux && !validate_dup) {
+		ret = validate_vmlinux_functions(&file);
+		if (ret < 0)
+			goto out;
+
+		warnings += ret;
+		goto out;
+	}
+
 	if (retpoline) {
 		ret = validate_retpoline(&file);
 		if (ret < 0)
diff --git a/tools/objtool/check.h b/tools/objtool/check.h
index 99413d4..12a9660 100644
--- a/tools/objtool/check.h
+++ b/tools/objtool/check.h
@@ -18,6 +18,8 @@ struct insn_state {
 	unsigned int uaccess_stack;
 	bool uaccess;
 	bool df;
+	bool noinstr;
+	s8 instr;
 };
 
 struct instruction {
@@ -31,6 +33,7 @@ struct instruction {
 	bool alt_group, dead_end, ignore, ignore_alts;
 	bool hint;
 	bool retpoline_safe;
+	s8 instr;
 	u8 visited;
 	u8 ret_offset;
 	struct symbol *call_dest;
diff --git a/tools/objtool/elf.h b/tools/objtool/elf.h
index 0b79c23..eb79cb9 100644
--- a/tools/objtool/elf.h
+++ b/tools/objtool/elf.h
@@ -39,7 +39,7 @@ struct section {
 	char *name;
 	int idx;
 	unsigned int len;
-	bool changed, text, rodata;
+	bool changed, text, rodata, noinstr;
 };
 
 struct symbol {

  reply	other threads:[~2020-04-22 22:26 UTC|newest]

Thread overview: 64+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2020-04-16 11:47 [PATCH v5 00/17] objtool: vmlinux.o and " Peter Zijlstra
2020-04-16 11:47 ` [PATCH v5 01/17] objtool: Support multiple stack_op per instruction Peter Zijlstra
2020-04-16 11:47 ` [PATCH v5 02/17] objtool: Better handle IRET Peter Zijlstra
2020-04-17 11:29   ` Miroslav Benes
2020-04-17 12:25     ` Peter Zijlstra
2020-04-17 12:35       ` Miroslav Benes
2020-04-17 17:37   ` Alexandre Chartre
2020-04-17 18:23     ` Peter Zijlstra
2020-04-17 23:53       ` Andy Lutomirski
2020-04-18 17:18         ` Josh Poimboeuf
2020-04-22 22:24   ` [tip: objtool/core] " tip-bot2 for Peter Zijlstra
2020-04-23  7:49   ` tip-bot2 for Peter Zijlstra
2020-04-16 11:47 ` [PATCH v5 03/17] objtool: Introduce HINT_RET_OFFSET Peter Zijlstra
2020-04-22 22:24   ` [tip: objtool/core] " tip-bot2 for Peter Zijlstra
2020-04-23  7:49   ` tip-bot2 for Peter Zijlstra
2020-04-16 11:47 ` [PATCH v5 04/17] x86,ftrace: Fix ftrace_regs_caller() unwind Peter Zijlstra
2020-04-17 19:24   ` Alexandre Chartre
2020-04-22  0:33   ` Steven Rostedt
2020-04-22  9:44     ` Peter Zijlstra
2020-04-22 13:33       ` Steven Rostedt
2020-04-22 20:20       ` Steven Rostedt
2020-04-22 22:24   ` [tip: objtool/core] " tip-bot2 for Peter Zijlstra
2020-04-23  7:49   ` tip-bot2 for Peter Zijlstra
2020-04-16 11:47 ` [PATCH v5 05/17] x86,ftrace: Use SIZEOF_PTREGS Peter Zijlstra
2020-04-22 22:24   ` [tip: objtool/core] " tip-bot2 for Peter Zijlstra
2020-04-23  7:49   ` tip-bot2 for Peter Zijlstra
2020-04-16 11:47 ` [PATCH v5 06/17] x86,ftrace: Shrink ftrace_regs_caller() by one byte Peter Zijlstra
2020-04-22 22:24   ` [tip: objtool/core] " tip-bot2 for Peter Zijlstra
2020-04-23  7:49   ` tip-bot2 for Peter Zijlstra
2020-04-16 11:47 ` [PATCH v5 07/17] objtool: Remove SAVE/RESTORE hints Peter Zijlstra
2020-04-22 22:24   ` [tip: objtool/core] " tip-bot2 for Peter Zijlstra
2020-04-23  7:49   ` tip-bot2 for Peter Zijlstra
2020-04-16 11:47 ` [PATCH v5 08/17] objtool: Rename struct cfi_state Peter Zijlstra
2020-04-22 22:24   ` [tip: objtool/core] " tip-bot2 for Peter Zijlstra
2020-04-23  7:49   ` tip-bot2 for Peter Zijlstra
2020-04-16 11:47 ` [PATCH v5 09/17] objtool: Fix !CFI insn_state propagation Peter Zijlstra
2020-04-22 22:24   ` [tip: objtool/core] " tip-bot2 for Peter Zijlstra
2020-04-23  7:49   ` tip-bot2 for Peter Zijlstra
2020-04-16 11:47 ` [PATCH v5 10/17] objtool: Implement noinstr validation Peter Zijlstra
2020-04-22 22:24   ` tip-bot2 for Peter Zijlstra [this message]
2020-04-23  7:49   ` [tip: objtool/core] " tip-bot2 for Peter Zijlstra
2020-04-16 11:47 ` [PATCH v5 11/17] objtool: Optimize !vmlinux.o again Peter Zijlstra
2020-04-22 22:24   ` [tip: objtool/core] " tip-bot2 for Peter Zijlstra
2020-04-23  7:49   ` tip-bot2 for Peter Zijlstra
2020-04-16 11:47 ` [PATCH v5 12/17] objtool: Use sec_offset_hash() for insn_hash Peter Zijlstra
2020-04-22 22:24   ` [tip: objtool/core] " tip-bot2 for Peter Zijlstra
2020-04-23  7:49   ` tip-bot2 for Peter Zijlstra
2020-04-16 11:47 ` [PATCH v5 13/17] kbuild/objtool: Add objtool-vmlinux.o pass Peter Zijlstra
2020-04-22 22:24   ` [tip: objtool/core] " tip-bot2 for Peter Zijlstra
2020-04-23  7:49   ` tip-bot2 for Peter Zijlstra
2020-04-16 11:47 ` [PATCH v5 14/17] objtool: Avoid iterating !text section symbols Peter Zijlstra
2020-04-22 22:24   ` [tip: objtool/core] " tip-bot2 for Peter Zijlstra
2020-04-23  7:49   ` tip-bot2 for Peter Zijlstra
2020-04-16 11:47 ` [PATCH v5 15/17] objtool: Rearrange validate_section() Peter Zijlstra
2020-04-22 22:24   ` [tip: objtool/core] " tip-bot2 for Peter Zijlstra
2020-04-23  7:49   ` tip-bot2 for Peter Zijlstra
2020-04-16 11:47 ` [PATCH v5 16/17] objtool: Add STT_NOTYPE noinstr validation Peter Zijlstra
2020-04-22 22:24   ` [tip: objtool/core] " tip-bot2 for Peter Zijlstra
2020-04-23  7:49   ` tip-bot2 for Peter Zijlstra
2020-04-16 11:47 ` [PATCH v5 17/17] objtool: Also consider .entry.text as noinstr Peter Zijlstra
2020-04-22 22:24   ` [tip: objtool/core] " tip-bot2 for Thomas Gleixner
2020-04-23  7:49   ` tip-bot2 for Thomas Gleixner
2020-04-17 12:33 ` [PATCH v5 00/17] objtool: vmlinux.o and noinstr validation Miroslav Benes
2020-04-17 20:22 ` Alexandre Chartre

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=158759427292.28353.10002474084884955071.tip-bot2@tip-bot2 \
    --to=tip-bot2@linutronix.de \
    --cc=alexandre.chartre@oracle.com \
    --cc=jpoimboe@redhat.com \
    --cc=linux-kernel@vger.kernel.org \
    --cc=linux-tip-commits@vger.kernel.org \
    --cc=mbenes@suse.cz \
    --cc=peterz@infradead.org \
    --cc=x86@kernel.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox

all inboxes | Powered by JetHome®