Author: markj
Date: Thu Feb 16 23:05:20 2017
New Revision: 313841
URL: https://svnweb.freebsd.org/changeset/base/313841

Log:
  Prevent CPU migration when checking the DTrace nofault flag on x86.
  
  dtrace_trap() consumes page and protection faults triggered by code running
  in DTrace probe context. Such faults occur with interrupts disabled and are
  detected using a per-CPU flag. Regular faults cause dtrace_trap() to be
  called with interrupts enabled, and nothing was ensuring that the flag was
  read from the correct CPU. This may result in dtrace_trap() consuming
  unrelated page and protection faults when DTrace is enabled, causing the
  fault handler to return without actually having handled the fault.
  
  Diagnosed by: Ryan Libby <rli...@gmail.com>
  MFC after:    3 days
  Sponsored by: Dell EMC Isilon

Modified:
  head/sys/cddl/dev/dtrace/amd64/dtrace_subr.c
  head/sys/cddl/dev/dtrace/i386/dtrace_subr.c

Modified: head/sys/cddl/dev/dtrace/amd64/dtrace_subr.c
==============================================================================
--- head/sys/cddl/dev/dtrace/amd64/dtrace_subr.c        Thu Feb 16 22:29:37 
2017        (r313840)
+++ head/sys/cddl/dev/dtrace/amd64/dtrace_subr.c        Thu Feb 16 23:05:20 
2017        (r313841)
@@ -384,6 +384,8 @@ dtrace_gethrestime(void)
 int
 dtrace_trap(struct trapframe *frame, u_int type)
 {
+       uint16_t nofault;
+
        /*
         * A trap can occur while DTrace executes a probe. Before
         * executing the probe, DTrace blocks re-scheduling and sets
@@ -393,7 +395,12 @@ dtrace_trap(struct trapframe *frame, u_i
         *
         * Check if DTrace has enabled 'no-fault' mode:
         */
-       if ((cpu_core[curcpu].cpuc_dtrace_flags & CPU_DTRACE_NOFAULT) != 0) {
+       sched_pin();
+       nofault = cpu_core[curcpu].cpuc_dtrace_flags & CPU_DTRACE_NOFAULT;
+       sched_unpin();
+       if (nofault) {
+               KASSERT((read_rflags() & PSL_I) == 0, ("interrupts enabled"));
+
                /*
                 * There are only a couple of trap types that are expected.
                 * All the rest will be handled in the usual way.

Modified: head/sys/cddl/dev/dtrace/i386/dtrace_subr.c
==============================================================================
--- head/sys/cddl/dev/dtrace/i386/dtrace_subr.c Thu Feb 16 22:29:37 2017        
(r313840)
+++ head/sys/cddl/dev/dtrace/i386/dtrace_subr.c Thu Feb 16 23:05:20 2017        
(r313841)
@@ -386,6 +386,8 @@ dtrace_gethrestime(void)
 int
 dtrace_trap(struct trapframe *frame, u_int type)
 {
+       uint16_t nofault;
+
        /*
         * A trap can occur while DTrace executes a probe. Before
         * executing the probe, DTrace blocks re-scheduling and sets
@@ -395,7 +397,12 @@ dtrace_trap(struct trapframe *frame, u_i
         *
         * Check if DTrace has enabled 'no-fault' mode:
         */
-       if ((cpu_core[curcpu].cpuc_dtrace_flags & CPU_DTRACE_NOFAULT) != 0) {
+       sched_pin();
+       nofault = cpu_core[curcpu].cpuc_dtrace_flags & CPU_DTRACE_NOFAULT;
+       sched_unpin();
+       if (nofault) {
+               KASSERT((read_eflags() & PSL_I) == 0, ("interrupts enabled"));
+
                /*
                 * There are only a couple of trap types that are expected.
                 * All the rest will be handled in the usual way.
_______________________________________________
svn-src-head@freebsd.org mailing list
https://lists.freebsd.org/mailman/listinfo/svn-src-head
To unsubscribe, send any mail to "svn-src-head-unsubscr...@freebsd.org"

Reply via email to