[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-Id: <20190225125232.277640072@infradead.org>
Date: Mon, 25 Feb 2019 13:43:36 +0100
From: Peter Zijlstra <peterz@...radead.org>
To: torvalds@...ux-foundation.org, tglx@...utronix.de, hpa@...or.com,
julien.thierry@....com, will.deacon@....com, luto@...capital.net,
mingo@...nel.org, catalin.marinas@....com, james.morse@....com,
valentin.schneider@....com, brgerst@...il.com, jpoimboe@...hat.com,
luto@...nel.org, bp@...en8.de, dvlasenk@...hat.com
Cc: linux-kernel@...r.kernel.org, peterz@...radead.org
Subject: [PATCH 6/6] objtool: Add Direction Flag validation
Having DF escape is BAD(tm).
Signed-off-by: Peter Zijlstra (Intel) <peterz@...radead.org>
---
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];
};
Powered by blists - more mailing lists