From 3e0ba3a1639010d24ca69fa790b3e6db4208cd66 Mon Sep 17 00:00:00 2001 From: Mark Johnston Date: Wed, 19 Mar 2014 01:27:56 +0000 Subject: [PATCH] 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. Reviewed by: rpaulo MFC after: 3 weeks --- sys/amd64/amd64/trap.c | 40 +++++++++++++++++++++------------------- sys/i386/i386/trap.c | 40 +++++++++++++++++++++------------------- 2 files changed, 42 insertions(+), 38 deletions(-) diff --git a/sys/amd64/amd64/trap.c b/sys/amd64/amd64/trap.c index f7d0afdad58a..f9fa8f2492b2 100644 --- a/sys/amd64/amd64/trap.c +++ b/sys/amd64/amd64/trap.c @@ -192,6 +192,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; @@ -243,28 +246,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, ®s); - if (type == T_BPTFLT && - dtrace_pid_probe_ptr != NULL && - dtrace_pid_probe_ptr(®s) == 0) - goto out; - else if (type == T_DTRACE_RET && - dtrace_return_probe_ptr != NULL && - dtrace_return_probe_ptr(®s) == 0) - goto out; - } if (dtrace_trap_func != NULL && (*dtrace_trap_func)(frame, type)) goto out; #endif @@ -319,6 +304,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, ®s); + if (dtrace_pid_probe_ptr != NULL && + dtrace_pid_probe_ptr(®s) == 0) + goto out; + } +#endif frame->tf_rflags &= ~PSL_T; i = SIGTRAP; ucode = (type == T_TRCTRAP ? TRAP_TRACE : TRAP_BRKPT); @@ -444,6 +437,15 @@ trap(struct trapframe *frame) goto userout; i = SIGFPE; break; +#ifdef KDTRACE_HOOKS + case T_DTRACE_RET: + enable_intr(); + fill_frame_regs(frame, ®s); + if (dtrace_return_probe_ptr != NULL && + dtrace_return_probe_ptr(®s) == 0) + goto out; + break; +#endif } } else { /* kernel trap */ diff --git a/sys/i386/i386/trap.c b/sys/i386/i386/trap.c index 884e0f057af1..be76575a816f 100644 --- a/sys/i386/i386/trap.c +++ b/sys/i386/i386/trap.c @@ -206,6 +206,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; @@ -262,28 +265,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, ®s); - if (type == T_BPTFLT && - dtrace_pid_probe_ptr != NULL && - dtrace_pid_probe_ptr(®s) == 0) - goto out; - if (type == T_DTRACE_RET && - dtrace_return_probe_ptr != NULL && - dtrace_return_probe_ptr(®s) == 0) - goto out; - } if ((type == T_PROTFLT || type == T_PAGEFLT) && dtrace_trap_func != NULL && (*dtrace_trap_func)(frame, type)) goto out; @@ -357,6 +342,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, ®s); + if (dtrace_pid_probe_ptr != NULL && + dtrace_pid_probe_ptr(®s) == 0) + goto out; + } +#endif frame->tf_eflags &= ~PSL_T; i = SIGTRAP; ucode = (type == T_TRCTRAP ? TRAP_TRACE : TRAP_BRKPT); @@ -536,6 +529,15 @@ trap(struct trapframe *frame) #endif i = SIGFPE; break; +#ifdef KDTRACE_HOOKS + case T_DTRACE_RET: + enable_intr(); + fill_frame_regs(frame, ®s); + if (dtrace_return_probe_ptr != NULL && + dtrace_return_probe_ptr(®s) == 0) + goto out; + break; +#endif } } else { /* kernel trap */