Merge branch 'x86-pti-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git...
[muen/linux.git] / arch / x86 / kernel / kprobes / opt.c
index e941136e24d834b20b4c15670f0d7a9fd6def1a1..203d398802a3cb4d5d8a0c9183c5f5de60b7f5d6 100644 (file)
@@ -40,6 +40,7 @@
 #include <asm/debugreg.h>
 #include <asm/set_memory.h>
 #include <asm/sections.h>
+#include <asm/nospec-branch.h>
 
 #include "common.h"
 
@@ -203,7 +204,7 @@ static int copy_optimized_instructions(u8 *dest, u8 *src, u8 *real)
 }
 
 /* Check whether insn is indirect jump */
-static int insn_is_indirect_jump(struct insn *insn)
+static int __insn_is_indirect_jump(struct insn *insn)
 {
        return ((insn->opcode.bytes[0] == 0xff &&
                (X86_MODRM_REG(insn->modrm.value) & 6) == 4) || /* Jump */
@@ -237,6 +238,26 @@ static int insn_jump_into_range(struct insn *insn, unsigned long start, int len)
        return (start <= target && target <= start + len);
 }
 
+static int insn_is_indirect_jump(struct insn *insn)
+{
+       int ret = __insn_is_indirect_jump(insn);
+
+#ifdef CONFIG_RETPOLINE
+       /*
+        * Jump to x86_indirect_thunk_* is treated as an indirect jump.
+        * Note that even with CONFIG_RETPOLINE=y, the kernel compiled with
+        * older gcc may use indirect jump. So we add this check instead of
+        * replace indirect-jump check.
+        */
+       if (!ret)
+               ret = insn_jump_into_range(insn,
+                               (unsigned long)__indirect_thunk_start,
+                               (unsigned long)__indirect_thunk_end -
+                               (unsigned long)__indirect_thunk_start);
+#endif
+       return ret;
+}
+
 /* Decode whole function to ensure any instructions don't jump into target */
 static int can_optimize(unsigned long paddr)
 {