[PATCH 6/6] objtool: Add Direction Flag validation

From: Peter Zijlstra
Date: Mon Feb 25 2019 - 07:53:32 EST


Having DF escape is BAD(tm).

Signed-off-by: Peter Zijlstra (Intel) <peterz@xxxxxxxxxxxxx>
---
tools/objtool/arch.h | 4 +++-
tools/objtool/arch/x86/decode.c | 8 ++++++++
tools/objtool/check.c | 21 +++++++++++++++++++++
tools/objtool/check.h | 2 +-
4 files changed, 33 insertions(+), 2 deletions(-)

--- a/tools/objtool/arch.h
+++ b/tools/objtool/arch.h
@@ -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 {
--- a/tools/objtool/arch/x86/decode.c
+++ b/tools/objtool/arch/x86/decode.c
@@ -456,6 +456,14 @@ int arch_decode_instruction(struct elf *
*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)

--- a/tools/objtool/check.c
+++ b/tools/objtool/check.c
@@ -1950,6 +1950,9 @@ static int validate_branch(struct objtoo
if (state.uaccess)
WARN_FUNC("return with UACCESS enabled", sec, insn->offset);

+ if (state.df)
+ WARN_FUNC("return with DF set", sec, insn->offset);
+
if (func && has_modified_stack_frame(&state)) {
WARN_FUNC("return with modified stack frame",
sec, insn->offset);
@@ -1971,6 +1974,10 @@ static int validate_branch(struct objtoo
WARN_FUNC("call to %s() with UACCESS enabled",
sec, insn->offset, insn_dest_name(insn));
}
+ if (state.df) {
+ WARN_FUNC("call to %s() with DF set",
+ sec, insn->offset, insn_dest_name(insn));
+ }

if (insn->type == INSN_CALL) {
if (is_fentry_call(insn))
@@ -2054,6 +2061,20 @@ static int validate_branch(struct objtoo
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;
}
--- a/tools/objtool/check.h
+++ b/tools/objtool/check.h
@@ -31,7 +31,7 @@ struct insn_state {
int stack_size;
unsigned char type;
bool bp_scratch;
- bool drap, end, uaccess, uaccess_safe;
+ bool drap, end, uaccess, uaccess_safe, df;
int drap_reg, drap_offset;
struct cfi_reg vals[CFI_NUM_REGS];
};