summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authormarkj <markj@FreeBSD.org>2014-07-29 20:33:18 +0000
committermarkj <markj@FreeBSD.org>2014-07-29 20:33:18 +0000
commit8116ff75971b8c4b280da201f4633ac0e874bc59 (patch)
tree125f3b5dfa4d23a22124872867655bb8d82de512
parent2bf1f153936d4170c6ea1d53fe3e7b790f68e606 (diff)
downloadFreeBSD-src-8116ff75971b8c4b280da201f4633ac0e874bc59.zip
FreeBSD-src-8116ff75971b8c4b280da201f4633ac0e874bc59.tar.gz
MFC r263329:
Only invoke fasttrap hooks for traps from user mode, and ensure that they're called with interrupts enabled. Calling fasttrap_pid_probe() with interrupts disabled can lead to deadlock if fasttrap writes to the process' address space.
-rw-r--r--sys/amd64/amd64/trap.c40
-rw-r--r--sys/i386/i386/trap.c40
2 files changed, 42 insertions, 38 deletions
diff --git a/sys/amd64/amd64/trap.c b/sys/amd64/amd64/trap.c
index 1fdc5d9..1077d48 100644
--- a/sys/amd64/amd64/trap.c
+++ b/sys/amd64/amd64/trap.c
@@ -193,6 +193,9 @@ SYSCTL_INT(_machdep, OID_AUTO, uprintf_signal, CTLFLAG_RW,
void
trap(struct trapframe *frame)
{
+#ifdef KDTRACE_HOOKS
+ struct reg regs;
+#endif
struct thread *td = curthread;
struct proc *p = td->td_proc;
int i = 0, ucode = 0, code;
@@ -244,28 +247,10 @@ trap(struct trapframe *frame)
/*
* A trap can occur while DTrace executes a probe. Before
* executing the probe, DTrace blocks re-scheduling and sets
- * a flag in it's per-cpu flags to indicate that it doesn't
+ * a flag in its per-cpu flags to indicate that it doesn't
* want to fault. On returning from the probe, the no-fault
* flag is cleared and finally re-scheduling is enabled.
- *
- * If the DTrace kernel module has registered a trap handler,
- * call it and if it returns non-zero, assume that it has
- * handled the trap and modified the trap frame so that this
- * function can return normally.
*/
- if (type == T_DTRACE_RET || type == T_BPTFLT) {
- struct reg regs;
-
- fill_frame_regs(frame, &regs);
- if (type == T_BPTFLT &&
- dtrace_pid_probe_ptr != NULL &&
- dtrace_pid_probe_ptr(&regs) == 0)
- goto out;
- else if (type == T_DTRACE_RET &&
- dtrace_return_probe_ptr != NULL &&
- dtrace_return_probe_ptr(&regs) == 0)
- goto out;
- }
if (dtrace_trap_func != NULL && (*dtrace_trap_func)(frame, type))
goto out;
#endif
@@ -320,6 +305,14 @@ trap(struct trapframe *frame)
case T_BPTFLT: /* bpt instruction fault */
case T_TRCTRAP: /* trace trap */
enable_intr();
+#ifdef KDTRACE_HOOKS
+ if (type == T_BPTFLT) {
+ fill_frame_regs(frame, &regs);
+ if (dtrace_pid_probe_ptr != NULL &&
+ dtrace_pid_probe_ptr(&regs) == 0)
+ goto out;
+ }
+#endif
frame->tf_rflags &= ~PSL_T;
i = SIGTRAP;
ucode = (type == T_TRCTRAP ? TRAP_TRACE : TRAP_BRKPT);
@@ -449,6 +442,15 @@ trap(struct trapframe *frame)
goto userout;
i = SIGFPE;
break;
+#ifdef KDTRACE_HOOKS
+ case T_DTRACE_RET:
+ enable_intr();
+ fill_frame_regs(frame, &regs);
+ if (dtrace_return_probe_ptr != NULL &&
+ dtrace_return_probe_ptr(&regs) == 0)
+ goto out;
+ break;
+#endif
}
} else {
/* kernel trap */
diff --git a/sys/i386/i386/trap.c b/sys/i386/i386/trap.c
index 4806434..7b9ce8c 100644
--- a/sys/i386/i386/trap.c
+++ b/sys/i386/i386/trap.c
@@ -207,6 +207,9 @@ SYSCTL_INT(_machdep, OID_AUTO, uprintf_signal, CTLFLAG_RW,
void
trap(struct trapframe *frame)
{
+#ifdef KDTRACE_HOOKS
+ struct reg regs;
+#endif
struct thread *td = curthread;
struct proc *p = td->td_proc;
int i = 0, ucode = 0, code;
@@ -263,28 +266,10 @@ trap(struct trapframe *frame)
/*
* A trap can occur while DTrace executes a probe. Before
* executing the probe, DTrace blocks re-scheduling and sets
- * a flag in it's per-cpu flags to indicate that it doesn't
+ * a flag in its per-cpu flags to indicate that it doesn't
* want to fault. On returning from the probe, the no-fault
* flag is cleared and finally re-scheduling is enabled.
- *
- * If the DTrace kernel module has registered a trap handler,
- * call it and if it returns non-zero, assume that it has
- * handled the trap and modified the trap frame so that this
- * function can return normally.
*/
- if (type == T_DTRACE_RET || type == T_BPTFLT) {
- struct reg regs;
-
- fill_frame_regs(frame, &regs);
- if (type == T_BPTFLT &&
- dtrace_pid_probe_ptr != NULL &&
- dtrace_pid_probe_ptr(&regs) == 0)
- goto out;
- if (type == T_DTRACE_RET &&
- dtrace_return_probe_ptr != NULL &&
- dtrace_return_probe_ptr(&regs) == 0)
- goto out;
- }
if ((type == T_PROTFLT || type == T_PAGEFLT) &&
dtrace_trap_func != NULL && (*dtrace_trap_func)(frame, type))
goto out;
@@ -358,6 +343,14 @@ trap(struct trapframe *frame)
case T_BPTFLT: /* bpt instruction fault */
case T_TRCTRAP: /* trace trap */
enable_intr();
+#ifdef KDTRACE_HOOKS
+ if (type == T_BPTFLT) {
+ fill_frame_regs(frame, &regs);
+ if (dtrace_pid_probe_ptr != NULL &&
+ dtrace_pid_probe_ptr(&regs) == 0)
+ goto out;
+ }
+#endif
frame->tf_eflags &= ~PSL_T;
i = SIGTRAP;
ucode = (type == T_TRCTRAP ? TRAP_TRACE : TRAP_BRKPT);
@@ -541,6 +534,15 @@ trap(struct trapframe *frame)
#endif
i = SIGFPE;
break;
+#ifdef KDTRACE_HOOKS
+ case T_DTRACE_RET:
+ enable_intr();
+ fill_frame_regs(frame, &regs);
+ if (dtrace_return_probe_ptr != NULL &&
+ dtrace_return_probe_ptr(&regs) == 0)
+ goto out;
+ break;
+#endif
}
} else {
/* kernel trap */
OpenPOWER on IntegriCloud