Skip to content

Commit

Permalink
objtool: Add Direction Flag validation
Browse files Browse the repository at this point in the history
Having DF escape is BAD(tm).

Linus; you suggested this one, but since DF really is only used from
ASM and the failure case is fairly obvious, do we really need this?

OTOH the patch is fairly small and simple, so let's just do this
to demonstrate objtool's superior awesomeness.

Suggested-by: Linus Torvalds <torvalds@linux-foundation.org>
Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org>
Acked-by: Josh Poimboeuf <jpoimboe@redhat.com>
Cc: Borislav Petkov <bp@alien8.de>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Thomas Gleixner <tglx@linutronix.de>
Signed-off-by: Ingo Molnar <mingo@kernel.org>
  • Loading branch information
Peter Zijlstra authored and Ingo Molnar committed Apr 3, 2019
1 parent ea24213 commit 2f0f9e9
Show file tree
Hide file tree
Showing 4 changed files with 37 additions and 2 deletions.
4 changes: 3 additions & 1 deletion tools/objtool/arch.h
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,9 @@
#define INSN_NOP 10
#define INSN_STAC 11
#define INSN_CLAC 12
#define INSN_OTHER 13
#define INSN_STD 13
#define INSN_CLD 14
#define INSN_OTHER 15
#define INSN_LAST INSN_OTHER

enum op_dest_type {
Expand Down
8 changes: 8 additions & 0 deletions tools/objtool/arch/x86/decode.c
Original file line number Diff line number Diff line change
Expand Up @@ -451,6 +451,14 @@ int arch_decode_instruction(struct elf *elf, struct section *sec,
*type = INSN_CALL;
break;

case 0xfc:
*type = INSN_CLD;
break;

case 0xfd:
*type = INSN_STD;
break;

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

Expand Down
25 changes: 25 additions & 0 deletions tools/objtool/check.c
Original file line number Diff line number Diff line change
Expand Up @@ -1903,6 +1903,12 @@ static int validate_call(struct instruction *insn, struct insn_state *state)
return 1;
}

if (state->df) {
WARN_FUNC("call to %s() with DF set",
insn->sec, insn->offset, insn_dest_name(insn));
return 1;
}

return 0;
}

Expand Down Expand Up @@ -2044,6 +2050,11 @@ static int validate_branch(struct objtool_file *file, struct instruction *first,
return 1;
}

if (state.df) {
WARN_FUNC("return with DF set", sec, insn->offset);
return 1;
}

if (func && has_modified_stack_frame(&state)) {
WARN_FUNC("return with modified stack frame",
sec, insn->offset);
Expand Down Expand Up @@ -2172,6 +2183,20 @@ static int validate_branch(struct objtool_file *file, struct instruction *first,
state.uaccess = false;
break;

case INSN_STD:
if (state.df)
WARN_FUNC("recursive STD", sec, insn->offset);

state.df = true;
break;

case INSN_CLD:
if (!state.df && insn->func)
WARN_FUNC("redundant CLD", sec, insn->offset);

state.df = false;
break;

default:
break;
}
Expand Down
2 changes: 1 addition & 1 deletion tools/objtool/check.h
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ struct insn_state {
int stack_size;
unsigned char type;
bool bp_scratch;
bool drap, end, uaccess;
bool drap, end, uaccess, df;
unsigned int uaccess_stack;
int drap_reg, drap_offset;
struct cfi_reg vals[CFI_NUM_REGS];
Expand Down

0 comments on commit 2f0f9e9

Please sign in to comment.