summaryrefslogtreecommitdiffstats
path: root/sys/cddl
diff options
context:
space:
mode:
authorrstone <rstone@FreeBSD.org>2011-11-10 22:03:35 +0000
committerrstone <rstone@FreeBSD.org>2011-11-10 22:03:35 +0000
commit9a10c6ad497f79900b180e2cafaac12ce43f8cc3 (patch)
treed0762d253bccb6c8856a7d269d26754a2ce85721 /sys/cddl
parent975afb573ac8cf465f2b2fd0a57385899e446948 (diff)
downloadFreeBSD-src-9a10c6ad497f79900b180e2cafaac12ce43f8cc3.zip
FreeBSD-src-9a10c6ad497f79900b180e2cafaac12ce43f8cc3.tar.gz
On i386, fbt probes are implemented by writing an invalid opcode over
certain instructions in a function prologue or epilogue. DTrace has a hook into the invalid opcode fault handler that checks whether the fault was due to an probe and if so, runs the DTrace magic. Upon returning from an invalid opcode fault caused by a probe, DTrace must emulate the instruction that was replaced with the invalid opcode and then return control to the instruction following the invalid opcode. There were a pair of related bugs in the emulation for the leave instruction. The leave instruction is used to pop off a stack frame prior to returning from a function. The emulation for this instruction must move the trap frame for the invalid opcode fault down the stack to the bottom of the stack frame that is being removed, and then execute an iret. At two points in this process, the emulation code was storing values above the current value of the stack pointer. This opened up a window in which if we were two take an interrupt, the trap frame for the interrupt would overwrite the values stored on the stack, causing the system to panic later. The first bug was that at one point the emulation code saves the new value for $esp above the current stack pointer value. The fix is to save this value instead inside of the original trap frame. At this point we do not need the original trap frame so this is safe. The second bug is that when the emulate code loads $esp from the stack, it points part-way through the new trap frame instead of at its beginning. The emulation code adjusts the stack pointer to the correct value immediately afterwards, but this still leaves a one instruction window in which an interrupt would corrupt this trap frame. Fix this by adjusting the stack frame value before loading it into $esp. This fixes panics in invop_leave on i386 when using fbt return probes. Reviewed by: rpaulo, attilio MFC after: 1 week
Diffstat (limited to 'sys/cddl')
-rw-r--r--sys/cddl/dev/dtrace/i386/dtrace_asm.S6
1 files changed, 3 insertions, 3 deletions
diff --git a/sys/cddl/dev/dtrace/i386/dtrace_asm.S b/sys/cddl/dev/dtrace/i386/dtrace_asm.S
index 787a3c8..1a92818 100644
--- a/sys/cddl/dev/dtrace/i386/dtrace_asm.S
+++ b/sys/cddl/dev/dtrace/i386/dtrace_asm.S
@@ -125,11 +125,11 @@ invop_leave:
movl 8(%esp), %eax /* load calling EIP */
incl %eax /* increment over LOCK prefix */
movl %eax, -8(%ebx) /* store calling EIP */
- movl %ebx, -4(%esp) /* temporarily store new %esp */
+ subl $8, %ebx /* adjust for three pushes, one pop */
+ movl %ebx, 8(%esp) /* temporarily store new %esp */
popl %ebx /* pop off temp */
popl %eax /* pop off temp */
- movl -12(%esp), %esp /* set stack pointer */
- subl $8, %esp /* adjust for three pushes, one pop */
+ movl (%esp), %esp /* set stack pointer */
iret /* return from interrupt */
invop_nop:
/*
OpenPOWER on IntegriCloud