Having DF escape is BAD(tm).

Signed-off-by: Peter Zijlstra (Intel) <pet...@infradead.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
@@ -1930,6 +1930,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);
@@ -1951,6 +1954,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))
@@ -2034,6 +2041,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];
 };


Reply via email to