lkml.org 
[lkml]   [2022]   [Mar]   [9]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    Date
    From
    Subject[tip: x86/core] objtool: Add IBT/ENDBR decoding
    The following commit has been merged into the x86/core branch of tip:

    Commit-ID: df280fcb49f91de003afcac7b4da806d3ded52d6
    Gitweb: https://git.kernel.org/tip/df280fcb49f91de003afcac7b4da806d3ded52d6
    Author: Peter Zijlstra <peterz@infradead.org>
    AuthorDate: Tue, 08 Mar 2022 16:30:53 +01:00
    Committer: Peter Zijlstra <peterz@infradead.org>
    CommitterDate: Tue, 08 Mar 2022 23:53:38 +01:00

    objtool: Add IBT/ENDBR decoding

    Intel IBT requires the target of any indirect CALL or JMP instruction
    to be the ENDBR instruction; optionally it allows those two
    instructions to have a NOTRACK prefix in order to avoid this
    requirement.

    The kernel will not enable the use of NOTRACK, as such any occurence
    of it in compiler generated code should be flagged.

    Teach objtool to Decode ENDBR instructions and WARN about NOTRACK
    prefixes.

    Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org>
    Acked-by: Josh Poimboeuf <jpoimboe@redhat.com>
    Link: https://lore.kernel.org/r/20220308154319.645963517@infradead.org
    ---
    tools/objtool/arch/x86/decode.c | 34 +++++++++++++++++++++++----
    tools/objtool/include/objtool/arch.h | 1 +-
    2 files changed, 30 insertions(+), 5 deletions(-)

    diff --git a/tools/objtool/arch/x86/decode.c b/tools/objtool/arch/x86/decode.c
    index 479e769..943cb41 100644
    --- a/tools/objtool/arch/x86/decode.c
    +++ b/tools/objtool/arch/x86/decode.c
    @@ -103,6 +103,18 @@ unsigned long arch_jump_destination(struct instruction *insn)
    #define rm_is_mem(reg) (mod_is_mem() && !is_RIP() && rm_is(reg))
    #define rm_is_reg(reg) (mod_is_reg() && modrm_rm == (reg))

    +static bool has_notrack_prefix(struct insn *insn)
    +{
    + int i;
    +
    + for (i = 0; i < insn->prefixes.nbytes; i++) {
    + if (insn->prefixes.bytes[i] == 0x3e)
    + return true;
    + }
    +
    + return false;
    +}
    +
    int arch_decode_instruction(struct objtool_file *file, const struct section *sec,
    unsigned long offset, unsigned int maxlen,
    unsigned int *len, enum insn_type *type,
    @@ -112,7 +124,7 @@ int arch_decode_instruction(struct objtool_file *file, const struct section *sec
    const struct elf *elf = file->elf;
    struct insn insn;
    int x86_64, ret;
    - unsigned char op1, op2, op3,
    + unsigned char op1, op2, op3, prefix,
    rex = 0, rex_b = 0, rex_r = 0, rex_w = 0, rex_x = 0,
    modrm = 0, modrm_mod = 0, modrm_rm = 0, modrm_reg = 0,
    sib = 0, /* sib_scale = 0, */ sib_index = 0, sib_base = 0;
    @@ -137,6 +149,8 @@ int arch_decode_instruction(struct objtool_file *file, const struct section *sec
    if (insn.vex_prefix.nbytes)
    return 0;

    + prefix = insn.prefixes.bytes[0];
    +
    op1 = insn.opcode.bytes[0];
    op2 = insn.opcode.bytes[1];
    op3 = insn.opcode.bytes[2];
    @@ -492,6 +506,12 @@ int arch_decode_instruction(struct objtool_file *file, const struct section *sec
    /* nopl/nopw */
    *type = INSN_NOP;

    + } else if (op2 == 0x1e) {
    +
    + if (prefix == 0xf3 && (modrm == 0xfa || modrm == 0xfb))
    + *type = INSN_ENDBR;
    +
    +
    } else if (op2 == 0x38 && op3 == 0xf8) {
    if (insn.prefixes.nbytes == 1 &&
    insn.prefixes.bytes[0] == 0xf2) {
    @@ -636,20 +656,24 @@ int arch_decode_instruction(struct objtool_file *file, const struct section *sec
    break;

    case 0xff:
    - if (modrm_reg == 2 || modrm_reg == 3)
    + if (modrm_reg == 2 || modrm_reg == 3) {

    *type = INSN_CALL_DYNAMIC;
    + if (has_notrack_prefix(&insn))
    + WARN("notrack prefix found at %s:0x%lx", sec->name, offset);

    - else if (modrm_reg == 4)
    + } else if (modrm_reg == 4) {

    *type = INSN_JUMP_DYNAMIC;
    + if (has_notrack_prefix(&insn))
    + WARN("notrack prefix found at %s:0x%lx", sec->name, offset);

    - else if (modrm_reg == 5)
    + } else if (modrm_reg == 5) {

    /* jmpf */
    *type = INSN_CONTEXT_SWITCH;

    - else if (modrm_reg == 6) {
    + } else if (modrm_reg == 6) {

    /* push from mem */
    ADD_OP(op) {
    diff --git a/tools/objtool/include/objtool/arch.h b/tools/objtool/include/objtool/arch.h
    index 76bae30..9b19cc3 100644
    --- a/tools/objtool/include/objtool/arch.h
    +++ b/tools/objtool/include/objtool/arch.h
    @@ -27,6 +27,7 @@ enum insn_type {
    INSN_STD,
    INSN_CLD,
    INSN_TRAP,
    + INSN_ENDBR,
    INSN_OTHER,
    };

    \
     
     \ /
      Last update: 2022-03-09 08:56    [W:7.966 / U:0.064 seconds]
    ©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site