]> www.infradead.org Git - users/jedix/linux-maple.git/commitdiff
dtrace: ensure we skip the entire SDT probe point
authorKris Van Hees <kris.van.hees@oracle.com>
Mon, 20 Feb 2017 12:16:48 +0000 (07:16 -0500)
committerKris Van Hees <kris.van.hees@oracle.com>
Sat, 4 Mar 2017 02:08:24 +0000 (21:08 -0500)
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 <kris.van.hees@oracle.com>
Acked-by: Nick Alcock <nick.alcock@oracle.com>
arch/x86/kernel/dtrace_sdt.c
arch/x86/kernel/dtrace_util.c

index f9bc1a89aba651dff08ca509d1bd9bfc731dc34d..87d0ca0be6a4b0d5e5f3e43946da26d803f9d359 100644 (file)
@@ -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);
index d273da033fcb676effb5ef8d7d7c229bc60d766e..3cf71850f36012e33f364fb1f35c962c2adb35a2 100644 (file)
@@ -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: