From: Peter Zijlstra <peterz@infradead.org>
To: David Woodhouse <dwmw2@infradead.org>,
Thomas Gleixner <tglx@linutronix.de>,
Josh Poimboeuf <jpoimboe@redhat.com>
Cc: linux-kernel@vger.kernel.org, Dave Hansen <dave.hansen@intel.com>,
Ashok Raj <ashok.raj@intel.com>,
Tim Chen <tim.c.chen@linux.intel.com>,
Andy Lutomirski <luto@kernel.org>,
Linus Torvalds <torvalds@linux-foundation.org>,
Greg KH <gregkh@linuxfoundation.org>,
Andrea Arcangeli <aarcange@redhat.com>,
Andi Kleen <ak@linux.intel.com>,
Arjan Van De Ven <arjan.van.de.ven@intel.com>,
Dan Williams <dan.j.williams@intel.com>,
Paolo Bonzini <pbonzini@redhat.com>,
Jun Nakajima <jun.nakajima@intel.com>,
Asit Mallick <asit.k.mallick@intel.com>,
Peter Zijlstra <peterz@infradead.org>,
David Woodhouse <dwmw@amazon.co.uk>
Subject: [PATCH 2/7] objtool: Add retpoline validation
Date: Thu, 01 Feb 2018 15:34:23 +0100 [thread overview]
Message-ID: <20180201143821.856464827@infradead.org> (raw)
In-Reply-To: 20180201143421.088202488@infradead.org
[-- Attachment #1: peterz-objtool-indirect.patch --]
[-- Type: text/plain, Size: 5537 bytes --]
David requested a objtool validation pass for RETPOLINE enabled
builds, where it validates no unannotated indirect jumps or calls are
left.
Add an additional .discard.retpoline_safe section to allow annotating
the few indirect sites that are required and safe.
Reviewed-by: David Woodhouse <dwmw@amazon.co.uk>
Requested-by: David Woodhouse <dwmw2@infradead.org>
Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org>
---
scripts/Makefile.build | 4 +
tools/objtool/builtin-check.c | 3 -
tools/objtool/builtin.h | 2
tools/objtool/check.c | 86 +++++++++++++++++++++++++++++++++++++++++-
tools/objtool/check.h | 1
5 files changed, 93 insertions(+), 3 deletions(-)
--- a/scripts/Makefile.build
+++ b/scripts/Makefile.build
@@ -269,6 +269,10 @@ objtool_args += --no-unreachable
else
objtool_args += $(call cc-ifversion, -lt, 0405, --no-unreachable)
endif
+ifdef CONFIG_RETPOLINE
+ objtool_args += --retpoline
+endif
+
ifdef CONFIG_MODVERSIONS
objtool_o = $(@D)/.tmp_$(@F)
--- a/tools/objtool/builtin-check.c
+++ b/tools/objtool/builtin-check.c
@@ -29,7 +29,7 @@
#include "builtin.h"
#include "check.h"
-bool no_fp, no_unreachable;
+bool no_fp, no_unreachable, retpoline;
static const char * const check_usage[] = {
"objtool check [<options>] file.o",
@@ -39,6 +39,7 @@ static const char * const check_usage[]
const struct option check_options[] = {
OPT_BOOLEAN('f', "no-fp", &no_fp, "Skip frame pointer validation"),
OPT_BOOLEAN('u', "no-unreachable", &no_unreachable, "Skip 'unreachable instruction' warnings"),
+ OPT_BOOLEAN('r', "retpoline", &retpoline, "Validate retpoline assumptions"),
OPT_END(),
};
--- a/tools/objtool/builtin.h
+++ b/tools/objtool/builtin.h
@@ -20,7 +20,7 @@
#include <subcmd/parse-options.h>
extern const struct option check_options[];
-extern bool no_fp, no_unreachable;
+extern bool no_fp, no_unreachable, retpoline;
extern int cmd_check(int argc, const char **argv);
extern int cmd_orc(int argc, const char **argv);
--- a/tools/objtool/check.c
+++ b/tools/objtool/check.c
@@ -496,6 +496,7 @@ static int add_jump_destinations(struct
* disguise, so convert them accordingly.
*/
insn->type = INSN_JUMP_DYNAMIC;
+ insn->retpoline_safe = true;
continue;
} else {
/* sibling call */
@@ -547,7 +548,8 @@ static int add_call_destinations(struct
if (!insn->call_dest && !insn->ignore) {
WARN_FUNC("unsupported intra-function call",
insn->sec, insn->offset);
- WARN("If this is a retpoline, please patch it in with alternatives and annotate it with ANNOTATE_NOSPEC_ALTERNATIVE.");
+ if (retpoline)
+ WARN("If this is a retpoline, please patch it in with alternatives and annotate it with ANNOTATE_NOSPEC_ALTERNATIVE.");
return -1;
}
@@ -1070,6 +1072,54 @@ static int read_unwind_hints(struct objt
return 0;
}
+static int read_retpoline_hints(struct objtool_file *file)
+{
+ struct section *sec, *relasec;
+ struct instruction *insn;
+ struct rela *rela;
+ int i;
+
+ sec = find_section_by_name(file->elf, ".discard.retpoline_safe");
+ if (!sec)
+ return 0;
+
+ relasec = sec->rela;
+ if (!relasec) {
+ WARN("missing .rela.discard.retpoline_safe section");
+ return -1;
+ }
+
+ if (sec->len % sizeof(unsigned long)) {
+ WARN("retpoline_safe size mismatch: %d %ld", sec->len, sizeof(unsigned long));
+ return -1;
+ }
+
+ for (i = 0; i < sec->len / sizeof(unsigned long); i++) {
+ rela = find_rela_by_dest(sec, i * sizeof(unsigned long));
+ if (!rela) {
+ WARN("can't find rela for retpoline_safe[%d]", i);
+ return -1;
+ }
+
+ insn = find_insn(file, rela->sym->sec, rela->addend);
+ if (!insn) {
+ WARN("can't find insn for retpoline_safe[%d]", i);
+ return -1;
+ }
+
+ if (insn->type != INSN_JUMP_DYNAMIC &&
+ insn->type != INSN_CALL_DYNAMIC) {
+ WARN_FUNC("retpoline_safe hint not a indirect jump/call",
+ insn->sec, insn->offset);
+ return -1;
+ }
+
+ insn->retpoline_safe = true;
+ }
+
+ return 0;
+}
+
static int decode_sections(struct objtool_file *file)
{
int ret;
@@ -1108,6 +1158,10 @@ static int decode_sections(struct objtoo
if (ret)
return ret;
+ ret = read_retpoline_hints(file);
+ if (ret)
+ return ret;
+
return 0;
}
@@ -1853,6 +1907,29 @@ static int validate_unwind_hints(struct
return warnings;
}
+static int validate_retpoline(struct objtool_file *file)
+{
+ struct instruction *insn;
+ int warnings = 0;
+
+ for_each_insn(file, insn) {
+ if (insn->type != INSN_JUMP_DYNAMIC &&
+ insn->type != INSN_CALL_DYNAMIC)
+ continue;
+
+ if (insn->retpoline_safe)
+ continue;
+
+ WARN_FUNC("indirect %s found in RETPOLINE build",
+ insn->sec, insn->offset,
+ insn->type == INSN_JUMP_DYNAMIC ? "jump" : "call");
+
+ warnings++;
+ }
+
+ return warnings;
+}
+
static bool is_kasan_insn(struct instruction *insn)
{
return (insn->type == INSN_CALL &&
@@ -2028,6 +2105,13 @@ int check(const char *_objname, bool orc
if (list_empty(&file.insn_list))
goto out;
+ if (retpoline) {
+ ret = validate_retpoline(&file);
+ if (ret < 0)
+ return ret;
+ warnings += ret;
+ }
+
ret = validate_functions(&file);
if (ret < 0)
goto out;
--- a/tools/objtool/check.h
+++ b/tools/objtool/check.h
@@ -45,6 +45,7 @@ struct instruction {
unsigned char type;
unsigned long immediate;
bool alt_group, visited, dead_end, ignore, hint, save, restore, ignore_alts;
+ bool retpoline_safe;
struct symbol *call_dest;
struct instruction *jump_dest;
struct list_head alts;
next prev parent reply other threads:[~2018-02-01 14:34 UTC|newest]
Thread overview: 24+ messages / expand[flat|nested] mbox.gz Atom feed top
2018-02-01 14:34 [PATCH 0/7] objtool: retpoline validation Peter Zijlstra
2018-02-01 14:34 ` [PATCH 1/7] objtool: Use existing global variables for options Peter Zijlstra
2018-02-01 14:34 ` Peter Zijlstra [this message]
2018-02-01 14:34 ` [PATCH 3/7] objtool: Add module specific retpoline rules Peter Zijlstra
2018-02-01 14:34 ` [PATCH 4/7] x86,nospec: Annotate indirect calls/jumps Peter Zijlstra
2018-02-01 14:55 ` David Woodhouse
2018-02-01 15:11 ` Peter Zijlstra
2018-02-01 15:13 ` Peter Zijlstra
2018-02-01 15:21 ` Josh Poimboeuf
2018-02-01 15:30 ` Peter Zijlstra
2018-02-01 14:34 ` [PATCH 5/7] x86/paravirt: Annotate indirect calls Peter Zijlstra
2018-02-01 14:34 ` [PATCH 6/7] x86: Annotate indirect jump in head_64.S Peter Zijlstra
2018-02-01 14:34 ` [PATCH 7/7] x86,sme: Annotate indirect call Peter Zijlstra
2018-02-01 15:28 ` [PATCH 0/7] objtool: retpoline validation Josh Poimboeuf
2018-02-01 15:32 ` David Woodhouse
2018-02-01 15:40 ` Peter Zijlstra
2018-02-01 16:51 ` David Woodhouse
2018-02-01 17:14 ` Peter Zijlstra
2018-02-01 17:43 ` Josh Poimboeuf
2018-02-01 18:16 ` Tim Chen
2018-02-06 21:23 ` David Woodhouse
2018-02-01 15:32 ` Peter Zijlstra
2018-02-01 19:36 ` Peter Zijlstra
2018-02-01 15:50 ` 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=20180201143821.856464827@infradead.org \
--to=peterz@infradead.org \
--cc=aarcange@redhat.com \
--cc=ak@linux.intel.com \
--cc=arjan.van.de.ven@intel.com \
--cc=ashok.raj@intel.com \
--cc=asit.k.mallick@intel.com \
--cc=dan.j.williams@intel.com \
--cc=dave.hansen@intel.com \
--cc=dwmw2@infradead.org \
--cc=dwmw@amazon.co.uk \
--cc=gregkh@linuxfoundation.org \
--cc=jpoimboe@redhat.com \
--cc=jun.nakajima@intel.com \
--cc=linux-kernel@vger.kernel.org \
--cc=luto@kernel.org \
--cc=pbonzini@redhat.com \
--cc=tglx@linutronix.de \
--cc=tim.c.chen@linux.intel.com \
--cc=torvalds@linux-foundation.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 an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.