From: Kris Van Hees Date: Mon, 20 Feb 2017 12:16:48 +0000 (-0500) Subject: dtrace: ensure we skip the entire SDT probe point X-Git-Tag: v4.1.12-98.0.20170517_2143~41^2~5 X-Git-Url: https://www.infradead.org/git/?a=commitdiff_plain;h=15a3aac15ccf680381e1ae85ad8d2fe89fb87b1b;p=users%2Fjedix%2Flinux-maple.git dtrace: ensure we skip the entire SDT probe point With the introduction of FBT support, the logic for skipping instructions (with potential emulation of the skipped instruction) changed. This change did not take into account the fact that is-enabled probes on x86_64 use a 3-byte sequence for setting ax to 0, followed by a 2-byte NOP. The old logic resulted in failing to skip the setting of ax correctly. New logic uses the knowledge that all SDT probes on x86_64 are of the same length (ASM_CALL_SIZE) and therefore we can simply skip that number of bytes and continue without any emulation. Orabug: 25557283 Signed-off-by: Kris Van Hees Acked-by: Nick Alcock --- diff --git a/arch/x86/kernel/dtrace_sdt.c b/arch/x86/kernel/dtrace_sdt.c index f9bc1a89aba6..87d0ca0be6a4 100644 --- a/arch/x86/kernel/dtrace_sdt.c +++ b/arch/x86/kernel/dtrace_sdt.c @@ -54,10 +54,10 @@ void dtrace_sdt_init_arch(void) { /* * A little unusual, but potentially necessary. While we could use a - * single NOP sequence of length SDT_NOP_SIZE, we need to consider the + * single NOP sequence of length ASM_CALL_SIZE, we need to consider the * fact that when a SDT probe point is enabled, a single invalid opcode * is written on the first byte of this NOP sequence. By using a - * sequence of a 1-byte NOP, followed by a (SDT_NOP_SIZE - 1) byte NOP + * sequence of a 1-byte NOP, followed by a (ASM_CALL_SIZE - 1) byte NOP * sequence, we play it pretty safe. */ add_nops(nops, 1); diff --git a/arch/x86/kernel/dtrace_util.c b/arch/x86/kernel/dtrace_util.c index d273da033fcb..3cf71850f360 100644 --- a/arch/x86/kernel/dtrace_util.c +++ b/arch/x86/kernel/dtrace_util.c @@ -125,13 +125,16 @@ int dtrace_die_notifier(struct notifier_block *nb, unsigned long val, switch (rval) { case DTRACE_INVOP_NOPS: /* - * Probe points are encoded as a single-byte NOP, - * followed by a multi-byte NOP. We can therefore - * safely report this case as equivalent to a single - * NOP that needs to be emulated. Execution will - * continue with the multi-byte NOP. + * SDT probe points are encoded as either: + * - a 1-byte NOP followed by a multi-byte NOP + * - a multi-byte code sequence (to set AX to 0), + * followed by a multi-byte NOP + * In both cases, the total length of the probe point + * instruction is ASM_CALL_SITE bytes, so we can safely + * skip that number of bytes here. */ - rval = DTRACE_INVOP_NOP; + dargs->regs->ip += ASM_CALL_SIZE; + return NOTIFY_OK | NOTIFY_STOP_MASK; case DTRACE_INVOP_MOV_RSP_RBP: case DTRACE_INVOP_NOP: case DTRACE_INVOP_PUSH_BP: @@ -172,13 +175,16 @@ int dtrace_die_notifier(struct notifier_block *nb, unsigned long val, switch (rval) { case DTRACE_INVOP_NOPS: /* - * Probe points are encoded as a single-byte NOP, - * followed by a multi-byte NOP. We can therefore - * safely report this case as equivalent to a single - * NOP that needs to be emulated. Execution will - * continue with the multi-byte NOP. + * SDT probe points are encoded as either: + * - a 1-byte NOP followed by a multi-byte NOP + * - a multi-byte code sequence (to set AX to 0), + * followed by a multi-byte NOP + * In both cases, the total length of the probe point + * instruction is ASM_CALL_SITE bytes, so we can safely + * skip that number of bytes here. */ - rval = DTRACE_INVOP_NOP; + dargs->regs->ip += ASM_CALL_SIZE; + return NOTIFY_OK | NOTIFY_STOP_MASK; case DTRACE_INVOP_MOV_RSP_RBP: case DTRACE_INVOP_NOP: case DTRACE_INVOP_PUSH_BP: