]> www.infradead.org Git - users/jedix/linux-maple.git/commitdiff
dtrace: make x86_64 FBT return probe detection less restrictive
authorKris Van Hees <kris.van.hees@oracle.com>
Tue, 16 May 2017 03:29:16 +0000 (23:29 -0400)
committerKris Van Hees <kris.van.hees@oracle.com>
Tue, 23 May 2017 13:44:39 +0000 (09:44 -0400)
The FBT return probe detection mechanism on x86_64 was requiring that
the "ret" instruction be followed by a "push %rbp" or "nop", which is
much too restrictive.  The new code allows probing of all "ret"
instructions that occur in a function regardless of what instructions
follows.

In order to make this possible, the functions to set and clear FBT
probes on x86_64 (dtrace_invop_add() and dtrace_invop_remove()) have
been modified to accept a 2nd argument that indicates the instruction
to patch the probe location with.  This is needed because FBT return
probes need a different instruction on x86_64 (LOCK prefix to force
an invalid opcode trap isn't safe because we do not know what
instruction may follow the "ret").

This commit also fixes the declaration of the dtrace_bad_address()
function that was missing its return type.

Orabug: 25949048
Signed-off-by: Kris Van Hees <kris.van.hees@oracle.com>
Acked-by: Nick Alcock <nick.alcock@oracle.com>
arch/x86/include/asm/dtrace_util.h
arch/x86/kernel/dtrace_fbt.c
arch/x86/kernel/dtrace_util.c

index d53b11f2d1a851a40044fc022fa4b65ece30ca34..43e1de8434ecd7f964a400b4e9184d2a8440b46c 100644 (file)
 
 #ifndef __ASSEMBLY__
 
+#include <asm/dtrace_arch.h>
 #include <asm/ptrace.h>
 
 extern int dtrace_invop_add(uint8_t (*func)(struct pt_regs *));
 extern void dtrace_invop_remove(uint8_t (*func)(struct pt_regs *));
 
-extern void dtrace_invop_enable(uint8_t *);
-extern void dtrace_invop_disable(uint8_t *, uint8_t);
+extern void dtrace_invop_enable(asm_instr_t *, asm_instr_t);
+extern void dtrace_invop_disable(asm_instr_t *, asm_instr_t);
 
 extern int dtrace_user_addr_is_exec(uintptr_t);
 
index 43f0b83af80cfb5ac8ff8905f2d20cbe0a2314be..97ee749665c8a2e116d0402b0132704e14b173d4 100644 (file)
@@ -80,7 +80,6 @@ void dtrace_fbt_init(fbt_add_probe_fn fbt_add_probe)
        while (kallsyms_iter_update(&sym, pos++)) {
                asm_instr_t     *addr, *end;
                int             state = 0, insc = 0;
-               void            *efbp = NULL;
                void            *fbtp = NULL;
 
                /*
@@ -162,17 +161,14 @@ void dtrace_fbt_init(fbt_add_probe_fn fbt_add_probe)
                                        state = 2;
                                break;
                        case 1: /* look for ret */
-                               if (*addr == FBT_RET &&
-                                   (*(addr + 1) == FBT_PUSHL_EBP ||
-                                    *(addr + 1) == FBT_NOP)) {
+                               if (*addr == FBT_RET) {
                                        uintptr_t       off;
 
                                        off = addr - (asm_instr_t *)sym.value;
-                                       fbt_add_probe(
+                                       fbtp = fbt_add_probe(
                                                dtrace_kmod, sym.name,
                                                FBT_RETURN, *addr, addr, off,
                                                fbtp);
-                                       state = 2;
                                }
                                break;
                        }
index f246c4c5fdd067d27437ffd3a6306e5ce6662951..edd5fdf05290eb828ef969501cf8fc4eb4059a00 100644 (file)
@@ -262,22 +262,22 @@ EXPORT_SYMBOL(dtrace_invop_remove);
  * Enable an INVOP-based probe, i.e. ensure that an INVOP trap is triggered at
  * the specified address.
  */
-void dtrace_invop_enable(uint8_t *addr)
+void dtrace_invop_enable(asm_instr_t *addr, asm_instr_t opcode)
 {
-       text_poke(addr, ((unsigned char []){INVOP_TRAP_INSTR}), 1);
+       text_poke(addr, ((unsigned char []){opcode}), 1);
 }
 EXPORT_SYMBOL(dtrace_invop_enable);
 
 /*
  * Disable an INVOP-based probe.
  */
-void dtrace_invop_disable(uint8_t *addr, uint8_t opcode)
+void dtrace_invop_disable(asm_instr_t *addr, asm_instr_t opcode)
 {
        text_poke(addr, ((unsigned char []){opcode}), 1);
 }
 EXPORT_SYMBOL(dtrace_invop_disable);
 
-static inline dtrace_bad_address(void *addr)
+static inline int dtrace_bad_address(void *addr)
 {
        unsigned long   dummy;