Fix a nasty memory corruption issue which can occur due to the kernel bcopy's
authorMatthew Dillon <dillon@dragonflybsd.org>
Fri, 9 May 2008 06:35:12 +0000 (06:35 +0000)
committerMatthew Dillon <dillon@dragonflybsd.org>
Fri, 9 May 2008 06:35:12 +0000 (06:35 +0000)
use of the FP unit.  If the destination address faults the NPX code can
lose track of the fact that the kernel was using the FP unit.  When the
fault is resolved the kernel bcopy resumes with corrupted FP registers.

The most common situation where this could occur is with pipes, and generally
only when the system is paging heavily and causing multiple processes to
fault in the kernel FP bcopy code.

sys/platform/pc32/i386/bcopy.s
sys/platform/pc32/i386/genassym.c
sys/platform/pc32/isa/npx.c
sys/sys/thread.h

index 7ba6a90..a27b101 100644 (file)
@@ -31,7 +31,7 @@
  * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
  * 
- * $DragonFly: src/sys/platform/pc32/i386/bcopy.s,v 1.9 2007/01/09 23:34:02 dillon Exp $
+ * $DragonFly: src/sys/platform/pc32/i386/bcopy.s,v 1.10 2008/05/09 06:35:11 dillon Exp $
  */
 /*
  * bcopy(source:%esi, target:%edi, count:%ecx)
@@ -312,6 +312,7 @@ ENTRY(asm_generic_bcopy)
 100: ;                                                                 \
        leal    GD_SAVEFPU(%eax),%ecx ;                                 \
        movl    %ecx,TD_SAVEFPU(%edx) ;                                 \
+       orl     $TDF_KERNELFP,TD_FLAGS(%edx) ;                          \
        clts ;                                                          \
        movl    %edx,GD_NPXTHREAD(%eax) ;       /* race(3) */           \
        subl    $TDPRI_CRIT,TD_PRI(%edx) ;      /* crit_exit() */       \
@@ -350,6 +351,7 @@ ENTRY(asm_generic_bcopy)
        movl    MYCPU,%ecx ;                    \
        movl    GD_CURTHREAD(%ecx),%edx ;       \
        movl    $0,GD_NPXTHREAD(%ecx) ;         \
+       andl    $~TDF_KERNELFP,TD_FLAGS(%edx) ; \
        movl    %ebx,TD_SAVEFPU(%edx) ;         \
        smsw    %ax ;                           \
        popl    %ebx ;                          \
index 3f8ebce..8170d0a 100644 (file)
@@ -35,7 +35,7 @@
  *
  *     from: @(#)genassym.c    5.11 (Berkeley) 5/10/91
  * $FreeBSD: src/sys/i386/i386/genassym.c,v 1.86.2.3 2002/03/03 05:42:49 nyan Exp $
- * $DragonFly: src/sys/platform/pc32/i386/genassym.c,v 1.57 2007/06/29 21:54:10 dillon Exp $
+ * $DragonFly: src/sys/platform/pc32/i386/genassym.c,v 1.58 2008/05/09 06:35:11 dillon Exp $
  */
 
 #include <sys/param.h>
@@ -92,6 +92,8 @@ ASSYM(TD_MPCOUNT, offsetof(struct thread, td_mpcount));
 #endif
 ASSYM(TD_FLAGS, offsetof(struct thread, td_flags));
 ASSYM(TDF_RUNNING, TDF_RUNNING);
+ASSYM(TDF_USINGFP, TDF_USINGFP);
+ASSYM(TDF_KERNELFP, TDF_KERNELFP);
 #ifdef SMP
 ASSYM(MP_FREE_LOCK, MP_FREE_LOCK);
 #endif
index 43ef1a6..b0a9754 100644 (file)
@@ -33,7 +33,7 @@
  *
  *     from: @(#)npx.c 7.2 (Berkeley) 5/12/91
  * $FreeBSD: src/sys/i386/isa/npx.c,v 1.80.2.3 2001/10/20 19:04:38 tegge Exp $
- * $DragonFly: src/sys/platform/pc32/isa/npx.c,v 1.47 2008/01/30 11:57:09 swildner Exp $
+ * $DragonFly: src/sys/platform/pc32/isa/npx.c,v 1.48 2008/05/09 06:35:12 dillon Exp $
  */
 
 #include "opt_cpu.h"
@@ -871,7 +871,7 @@ npxdna(void)
         * used the FP unit.  This also occurs when a thread pushes a
         * signal handler and uses FP in the handler.
         */
-       if ((td->td_flags & TDF_USINGFP) == 0) {
+       if ((td->td_flags & (TDF_USINGFP | TDF_KERNELFP)) == 0) {
                td->td_flags |= TDF_USINGFP;
                npxinit(__INITIAL_NPXCW__);
                didinit = 1;
@@ -1013,6 +1013,8 @@ npxpush(mcontext_t *mctx)
 {
        thread_t td = curthread;
 
+       KKASSERT((td->td_flags & TDF_KERNELFP) == 0);
+
        if (td->td_flags & TDF_USINGFP) {
                if (mdcpu->gd_npxthread == td) {
                        /*
@@ -1046,6 +1048,8 @@ npxpop(mcontext_t *mctx)
 {
        thread_t td = curthread;
 
+       KKASSERT((td->td_flags & TDF_KERNELFP) == 0);
+
        switch(mctx->mc_ownedfp) {
        case _MC_FPOWNED_NONE:
                /*
index 4272198..5267a0b 100644 (file)
@@ -7,7 +7,7 @@
  * Types which must already be defined when this header is included by
  * userland:   struct md_thread
  * 
- * $DragonFly: src/sys/sys/thread.h,v 1.91 2008/03/01 06:21:26 dillon Exp $
+ * $DragonFly: src/sys/sys/thread.h,v 1.92 2008/05/09 06:35:10 dillon Exp $
  */
 
 #ifndef _SYS_THREAD_H_
@@ -282,6 +282,7 @@ struct thread {
 #define TDF_MPSAFE             0x00200000      /* (thread creation) */
 #define TDF_EXITING            0x00400000      /* thread exiting */
 #define TDF_USINGFP            0x00800000      /* thread using fp coproc */
+#define TDF_KERNELFP           0x01000000      /* kernel using fp coproc */
 
 /*
  * Thread priorities.  Typically only one thread from any given