From: Peter Zijlstra <peterz@infradead.org>
To: tglx@linutronix.de, jpoimboe@redhat.com
Cc: linux-kernel@vger.kernel.org, x86@kernel.org,
peterz@infradead.org, mhiramat@kernel.org, mbenes@suse.cz,
brgerst@gmail.com
Subject: [PATCH v2 19/19] objtool: Detect loading function pointers across noinstr
Date: Tue, 17 Mar 2020 18:02:53 +0100 [thread overview]
Message-ID: <20200317170910.983729109@infradead.org> (raw)
In-Reply-To: <20200317170234.897520633@infradead.org>
Detect if noinstr text loads functions pointers from regular text,
doing so is a definite sign that indirect function calls are unsafe.
Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org>
---
tools/objtool/arch.h | 2 +
tools/objtool/check.c | 68 ++++++++++++++++++++++++++++++++++++++++++++++++++
tools/objtool/check.h | 2 -
3 files changed, 71 insertions(+), 1 deletion(-)
--- a/tools/objtool/arch.h
+++ b/tools/objtool/arch.h
@@ -75,4 +75,6 @@ int arch_decode_instruction(struct elf *
bool arch_callee_saved_reg(unsigned char reg);
+#define MAX_INSN_SIZE 15
+
#endif /* _ARCH_H */
--- a/tools/objtool/check.c
+++ b/tools/objtool/check.c
@@ -42,6 +42,25 @@ struct instruction *find_insn(struct obj
return NULL;
}
+static struct instruction *find_insn_containing(struct objtool_file *file, struct section *sec,
+ unsigned long offset)
+{
+ struct instruction *insn;
+ unsigned long o;
+
+ for_offset_range(o, offset - MAX_INSN_SIZE - 1, offset) {
+ hash_for_each_possible(file->insn_hash, insn, hash, sec_offset_hash(sec, o)) {
+ if (insn->sec != sec)
+ continue;
+
+ if (insn->offset <= offset && insn->offset + insn->len > offset)
+ return insn;
+ }
+ }
+
+ return NULL;
+}
+
static struct instruction *next_insn_same_sec(struct objtool_file *file,
struct instruction *insn)
{
@@ -2102,6 +2121,29 @@ static int validate_return(struct symbol
return 0;
}
+static int validate_rela(struct instruction *insn, struct insn_state *state)
+{
+ /*
+ * Assume that any text rela that's not a CALL or JMP is a load of a
+ * function pointer.
+ */
+
+ switch (insn->type) {
+ case INSN_CALL:
+ case INSN_CALL_DYNAMIC:
+ case INSN_JUMP_CONDITIONAL:
+ case INSN_JUMP_UNCONDITIONAL:
+ return 0;
+ }
+
+ if (state->noinstr && state->instr <= 0 && insn->has_text_rela) {
+ WARN_FUNC("loading non-noinstr function pointer", insn->sec, insn->offset);
+ return 1;
+ }
+
+ return 0;
+}
+
/*
* Follow the branch starting at the given instruction, and recursively follow
* any other branches (jumps). Meanwhile, track the frame pointer state at
@@ -2217,6 +2259,10 @@ static int validate_branch(struct objtoo
return 0;
}
+ ret = validate_rela(insn, &state);
+ if (ret)
+ return ret;
+
switch (insn->type) {
case INSN_RETURN:
@@ -2485,6 +2531,25 @@ static bool ignore_unreachable_insn(stru
return false;
}
+static void prepare_insn_rela(struct objtool_file *file, struct section *sec)
+{
+ struct instruction *insn;
+ struct rela *rela;
+
+ if (!sec->rela)
+ return;
+
+ list_for_each_entry(rela, &sec->rela->rela_list, list) {
+ insn = find_insn_containing(file, sec, rela->offset);
+ if (!insn)
+ continue;
+
+ insn->has_text_rela = rela->sym && rela->sym->sec &&
+ rela->sym->sec->text &&
+ !rela->sym->sec->noinstr;
+ }
+}
+
static int validate_sec_functions(struct objtool_file *file, struct section *sec)
{
struct symbol *func;
@@ -2507,6 +2572,9 @@ static int validate_sec_functions(struct
if (vmlinux)
state.noinstr = sec->noinstr;
+ if (state.noinstr)
+ prepare_insn_rela(file, sec);
+
list_for_each_entry(func, &sec->symbol_list, list) {
if (func->type != STT_FUNC)
continue;
--- a/tools/objtool/check.h
+++ b/tools/objtool/check.h
@@ -36,7 +36,7 @@ struct instruction {
enum insn_type type;
unsigned long immediate;
bool alt_group, dead_end, ignore, hint, save, restore, ignore_alts;
- bool retpoline_safe;
+ bool retpoline_safe, has_text_rela;
s8 instr;
u8 visited;
struct symbol *call_dest;
next prev parent reply other threads:[~2020-03-17 17:12 UTC|newest]
Thread overview: 37+ messages / expand[flat|nested] mbox.gz Atom feed top
2020-03-17 17:02 [PATCH v2 00/19] objtool: vmlinux.o and noinstr validation Peter Zijlstra
2020-03-17 17:02 ` [PATCH v2 01/19] objtool: Introduce validate_return() Peter Zijlstra
2020-03-17 17:02 ` [PATCH v2 02/19] objtool: Rename func_for_each_insn() Peter Zijlstra
2020-03-17 17:02 ` [PATCH v2 03/19] objtool: Rename func_for_each_insn_all() Peter Zijlstra
2020-03-17 17:02 ` [PATCH v2 04/19] x86/kexec: Use RIP relative addressing Peter Zijlstra
2020-03-17 17:02 ` [PATCH v2 05/19] objtool: Optimize find_symbol_by_index() Peter Zijlstra
2020-03-17 17:02 ` [PATCH v2 06/19] objtool: Add a statistics mode Peter Zijlstra
2020-03-17 17:02 ` [PATCH v2 07/19] objtool: Optimize find_section_by_index() Peter Zijlstra
2020-03-17 17:02 ` [PATCH v2 08/19] objtool: Optimize find_section_by_name() Peter Zijlstra
2020-03-17 17:02 ` [PATCH v2 09/19] objtool: Optimize find_symbol_*() and read_symbols() Peter Zijlstra
2020-03-17 17:02 ` [PATCH v2 10/19] objtool: Rename find_containing_func() Peter Zijlstra
2020-03-17 17:02 ` [PATCH v2 11/19] objtool: Resize insn_hash Peter Zijlstra
2020-03-17 17:02 ` [PATCH v2 12/19] objtool: Optimize find_symbol_by_name() Peter Zijlstra
2020-03-17 17:02 ` [PATCH v2 13/19] objtool: Optimize read_sections() Peter Zijlstra
2020-03-17 17:02 ` [PATCH v2 14/19] objtool: Delete cleanup() Peter Zijlstra
2020-03-17 17:02 ` [PATCH v2 15/19] objtool: Optimize find_rela_by_dest_range() Peter Zijlstra
2020-03-17 17:02 ` [PATCH v2 16/19] objtool: Implement noinstr validation Peter Zijlstra
2020-03-17 21:00 ` Josh Poimboeuf
2020-03-18 9:03 ` Peter Zijlstra
2020-03-18 10:06 ` Peter Zijlstra
2020-03-18 13:21 ` Peter Zijlstra
2020-03-17 17:02 ` [PATCH v2 17/19] objtool: Optimize !vmlinux.o again Peter Zijlstra
2020-03-18 13:20 ` Peter Zijlstra
2020-03-20 16:20 ` Miroslav Benes
2020-03-21 15:14 ` Peter Zijlstra
2020-03-21 16:11 ` Peter Zijlstra
2020-03-23 7:27 ` Miroslav Benes
2020-03-17 17:02 ` [PATCH v2 18/19] objtool: Use sec_offset_hash() for insn_hash Peter Zijlstra
2020-03-17 17:02 ` Peter Zijlstra [this message]
2020-03-17 23:39 ` [PATCH v2 19/19] objtool: Detect loading function pointers across noinstr kbuild test robot
2020-03-17 23:43 ` Nick Desaulniers
2020-03-18 11:02 ` Peter Zijlstra
2020-03-18 7:18 ` kbuild test robot
2020-03-17 21:05 ` [PATCH v2 00/19] objtool: vmlinux.o and noinstr validation Josh Poimboeuf
2020-03-18 13:18 ` [RFC][PATCH v2 20/19] kbuild/objtool: Add objtool-vmlinux.o pass Peter Zijlstra
2020-03-18 14:13 ` Peter Zijlstra
2020-03-18 18:34 ` Josh Poimboeuf
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=20200317170910.983729109@infradead.org \
--to=peterz@infradead.org \
--cc=brgerst@gmail.com \
--cc=jpoimboe@redhat.com \
--cc=linux-kernel@vger.kernel.org \
--cc=mbenes@suse.cz \
--cc=mhiramat@kernel.org \
--cc=tglx@linutronix.de \
--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®