lkml.org 
[lkml]   [2018]   [Jan]   [11]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    Date
    From
    Subject[tip:x86/pti] objtool: Allow alternatives to be ignored
    Commit-ID:  258c76059cece01bebae098e81bacb1af2edad17
    Gitweb: https://git.kernel.org/tip/258c76059cece01bebae098e81bacb1af2edad17
    Author: Josh Poimboeuf <jpoimboe@redhat.com>
    AuthorDate: Thu, 11 Jan 2018 21:46:24 +0000
    Committer: Thomas Gleixner <tglx@linutronix.de>
    CommitDate: Fri, 12 Jan 2018 00:14:28 +0100

    objtool: Allow alternatives to be ignored

    Getting objtool to understand retpolines is going to be a bit of a
    challenge. For now, take advantage of the fact that retpolines are
    patched in with alternatives. Just read the original (sane)
    non-alternative instruction, and ignore the patched-in retpoline.

    This allows objtool to understand the control flow *around* the
    retpoline, even if it can't yet follow what's inside. This means the
    ORC unwinder will fail to unwind from inside a retpoline, but will work
    fine otherwise.

    Signed-off-by: Josh Poimboeuf <jpoimboe@redhat.com>
    Signed-off-by: David Woodhouse <dwmw@amazon.co.uk>
    Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
    Cc: gnomes@lxorguk.ukuu.org.uk
    Cc: Rik van Riel <riel@redhat.com>
    Cc: Andi Kleen <ak@linux.intel.com>
    Cc: thomas.lendacky@amd.com
    Cc: Peter Zijlstra <peterz@infradead.org>
    Cc: Linus Torvalds <torvalds@linux-foundation.org>
    Cc: Jiri Kosina <jikos@kernel.org>
    Cc: Andy Lutomirski <luto@amacapital.net>
    Cc: Dave Hansen <dave.hansen@intel.com>
    Cc: Kees Cook <keescook@google.com>
    Cc: Tim Chen <tim.c.chen@linux.intel.com>
    Cc: Greg Kroah-Hartman <gregkh@linux-foundation.org>
    Cc: Paul Turner <pjt@google.com>
    Link: https://lkml.kernel.org/r/1515707194-20531-3-git-send-email-dwmw@amazon.co.uk

    ---
    tools/objtool/check.c | 62 ++++++++++++++++++++++++++++++++++++++++++++++-----
    tools/objtool/check.h | 2 +-
    2 files changed, 57 insertions(+), 7 deletions(-)

    diff --git a/tools/objtool/check.c b/tools/objtool/check.c
    index de053fb..f40d46e 100644
    --- a/tools/objtool/check.c
    +++ b/tools/objtool/check.c
    @@ -428,6 +428,40 @@ static void add_ignores(struct objtool_file *file)
    }

    /*
    + * FIXME: For now, just ignore any alternatives which add retpolines. This is
    + * a temporary hack, as it doesn't allow ORC to unwind from inside a retpoline.
    + * But it at least allows objtool to understand the control flow *around* the
    + * retpoline.
    + */
    +static int add_nospec_ignores(struct objtool_file *file)
    +{
    + struct section *sec;
    + struct rela *rela;
    + struct instruction *insn;
    +
    + sec = find_section_by_name(file->elf, ".rela.discard.nospec");
    + 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.nospec entry");
    + return -1;
    + }
    +
    + insn->ignore_alts = true;
    + }
    +
    + return 0;
    +}
    +
    +/*
    * Find the destination instructions for all jumps.
    */
    static int add_jump_destinations(struct objtool_file *file)
    @@ -509,11 +543,18 @@ static int add_call_destinations(struct objtool_file *file)
    dest_off = insn->offset + insn->len + insn->immediate;
    insn->call_dest = find_symbol_by_offset(insn->sec,
    dest_off);
    + /*
    + * FIXME: Thanks to retpolines, it's now considered
    + * normal for a function to call within itself. So
    + * disable this warning for now.
    + */
    +#if 0
    if (!insn->call_dest) {
    WARN_FUNC("can't find call dest symbol at offset 0x%lx",
    insn->sec, insn->offset, dest_off);
    return -1;
    }
    +#endif
    } else if (rela->sym->type == STT_SECTION) {
    insn->call_dest = find_symbol_by_offset(rela->sym->sec,
    rela->addend+4);
    @@ -678,12 +719,6 @@ static int add_special_section_alts(struct objtool_file *file)
    return ret;

    list_for_each_entry_safe(special_alt, tmp, &special_alts, list) {
    - alt = malloc(sizeof(*alt));
    - if (!alt) {
    - WARN("malloc failed");
    - ret = -1;
    - goto out;
    - }

    orig_insn = find_insn(file, special_alt->orig_sec,
    special_alt->orig_off);
    @@ -694,6 +729,10 @@ static int add_special_section_alts(struct objtool_file *file)
    goto out;
    }

    + /* Ignore retpoline alternatives. */
    + if (orig_insn->ignore_alts)
    + continue;
    +
    new_insn = NULL;
    if (!special_alt->group || special_alt->new_len) {
    new_insn = find_insn(file, special_alt->new_sec,
    @@ -719,6 +758,13 @@ static int add_special_section_alts(struct objtool_file *file)
    goto out;
    }

    + alt = malloc(sizeof(*alt));
    + if (!alt) {
    + WARN("malloc failed");
    + ret = -1;
    + goto out;
    + }
    +
    alt->insn = new_insn;
    list_add_tail(&alt->list, &orig_insn->alts);

    @@ -1035,6 +1081,10 @@ static int decode_sections(struct objtool_file *file)

    add_ignores(file);

    + ret = add_nospec_ignores(file);
    + if (ret)
    + return ret;
    +
    ret = add_jump_destinations(file);
    if (ret)
    return ret;
    diff --git a/tools/objtool/check.h b/tools/objtool/check.h
    index 47d9ea7..dbadb30 100644
    --- a/tools/objtool/check.h
    +++ b/tools/objtool/check.h
    @@ -44,7 +44,7 @@ struct instruction {
    unsigned int len;
    unsigned char type;
    unsigned long immediate;
    - bool alt_group, visited, dead_end, ignore, hint, save, restore;
    + bool alt_group, visited, dead_end, ignore, hint, save, restore, ignore_alts;
    struct symbol *call_dest;
    struct instruction *jump_dest;
    struct list_head alts;
    \
     
     \ /
      Last update: 2018-01-14 23:24    [W:3.515 / U:0.008 seconds]
    ©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site