Author: markj
Date: Tue Jul 29 20:33:18 2014
New Revision: 269253
URL: http://svnweb.freebsd.org/changeset/base/269253

Log:
  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.

Modified:
  stable/10/sys/amd64/amd64/trap.c
  stable/10/sys/i386/i386/trap.c
Directory Properties:
  stable/10/   (props changed)

Modified: stable/10/sys/amd64/amd64/trap.c
==============================================================================
--- stable/10/sys/amd64/amd64/trap.c    Tue Jul 29 19:49:38 2014        
(r269252)
+++ stable/10/sys/amd64/amd64/trap.c    Tue Jul 29 20:33:18 2014        
(r269253)
@@ -193,6 +193,9 @@ SYSCTL_INT(_machdep, OID_AUTO, uprintf_s
 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 */

Modified: stable/10/sys/i386/i386/trap.c
==============================================================================
--- stable/10/sys/i386/i386/trap.c      Tue Jul 29 19:49:38 2014        
(r269252)
+++ stable/10/sys/i386/i386/trap.c      Tue Jul 29 20:33:18 2014        
(r269253)
@@ -207,6 +207,9 @@ SYSCTL_INT(_machdep, OID_AUTO, uprintf_s
 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 */
_______________________________________________
svn-src-all@freebsd.org mailing list
http://lists.freebsd.org/mailman/listinfo/svn-src-all
To unsubscribe, send any mail to "svn-src-all-unsubscr...@freebsd.org"

Reply via email to