[eros-cvs] cvs commit: eros/src/base/sys/eros/i486 SaveArea.h

shap@eros.cs.jhu.edu shap@eros.cs.jhu.edu
Mon, 12 Mar 2001 22:09:37 -0500


shap        01/03/12 22:09:37

  Modified:    src/base/sys/arch/i486/kernel UserContext.cxx
               src/base/sys/eros/i486 SaveArea.h
  Log:
  Fix the sa_IsKernel test to verify CS != 0. When CS==0 we know it's
  user mode and bogus.  Patch up the ValidateRegValues() function to be
  slightly more easily updated and to check explicitly for exactly those
  values of CS/DS/etc that are actually kosher rather than checking for
  the user mode bits only.
  
  This appears to solve the bug demonstrated by Charlie's memmap test,
  which caused a kernel panic.

Revision  Changes    Path
1.257     +35 -54    eros/src/base/sys/arch/i486/kernel/UserContext.cxx

Index: UserContext.cxx
===================================================================
RCS file: /cvs/eros/src/base/sys/arch/i486/kernel/UserContext.cxx,v
retrieving revision 1.256
retrieving revision 1.257
diff -u -r1.256 -r1.257
--- UserContext.cxx	2001/03/05 05:22:01	1.256
+++ UserContext.cxx	2001/03/13 03:09:37	1.257
@@ -509,68 +509,48 @@
   
   uint32_t code = 0;
   uint32_t info = 0;
+
+  uint32_t wantCode =
+    isUserContext ? Selector::DomainCode : Selector::KProcCode;
+
+  uint32_t wantData =
+    isUserContext ? Selector::DomainData : Selector::KProcData;
   
-  if ( fixRegs.CS && ((fixRegs.CS & 0x7) != 0x3) ){
-#if 0
-    MsgLog::dprintf(true, "Ctxt 0x%08x has bad CS value\n", this);
-#endif
-    code = FC_RegValue;
-    info = fixRegs.CS;
-  }
-  else if ( fixRegs.DS && ((fixRegs.DS & 0x7) != 0x3) ){
-#if 0
-    MsgLog::dprintf(true, "Ctxt 0x%08x has bad DS value\n", this);
-#endif
-    code = FC_RegValue;
-    info = fixRegs.DS;
-  }
-  else if ( fixRegs.ES && ((fixRegs.ES & 0x7) != 0x3) ){
-#if 0
-    MsgLog::dprintf(true, "Ctxt 0x%08x has bad ES value\n", this);
-#endif
-    code = FC_RegValue;
-    info = fixRegs.ES;
-  }
-  else if ( fixRegs.FS && ((fixRegs.FS & 0x7) != 0x3) ){
-#if 0
-    MsgLog::dprintf(true, "Ctxt 0x%08x has bad FS value\n", this);
-#endif
-    code = FC_RegValue;
-    info = fixRegs.FS;
-  }
-  else if ( fixRegs.GS && ((fixRegs.GS & 0x7) != 0x3) ){
-#if 0
-    MsgLog::dprintf(true, "Ctxt 0x%08x has bad GS value\n", this);
-#endif
-    code = FC_RegValue;
-    info = fixRegs.GS;
-  }
-  else if ( fixRegs.SS && ((fixRegs.SS & 0x7) != 0x3) ){
-#if 0
-    MsgLog::dprintf(true, "Ctxt 0x%08x has bad SS value\n", this);
-#endif
-    code = FC_RegValue;
-    info = fixRegs.SS;
-  }
-  else if ( (fixRegs.EFLAGS & EFLAGS_Interrupt) == 0 ) {
-#if 0
-    MsgLog::dprintf(true, "Ctxt 0x%08x has bad EFLAGS value 0x%08x\n", this, fixRegs.EFLAGS);
-#endif
+  /* FIX: The whole segment register check needs to be MUCH more
+   * specific. There are only a few allowable values, and they should
+   * be explicitly tested here.
+   */
+
+#define validate(seg, want) \
+  do { \
+    if ((seg) && ((seg) != (want))) {   \
+      code = FC_RegValue;               \
+      info = (seg);                     \
+      goto fault;                       \
+    }                                   \
+  } while (0)        
+
+  validate(fixRegs.CS, wantCode);
+
+  /* Strictly speaking, it's okay for a user program to place the code
+   * segment value in a data segment register, so long as read-only
+   * access is sufficient. Fix this when somebody complains someday. */
+  validate(fixRegs.DS, wantData);
+  validate(fixRegs.ES, wantData);
+  validate(fixRegs.FS, wantData);
+  validate(fixRegs.GS, wantData);
+  validate(fixRegs.SS, wantData);
+  
+#undef validate
+  
+  if ( (fixRegs.EFLAGS & EFLAGS_Interrupt) == 0 ) {
     /* interrupts must be enabled, various others not: */
     code = FC_RegValue;
   }
   else if ( fixRegs.EFLAGS & EFLAGS_Nested ) {
-#if 0
-    MsgLog::dprintf(true, "Ctxt 0x%08x has bad EFLAGS value 0x%08x\n", this, fixRegs.EFLAGS);
-    /* Some flags must be clear: */
-#endif
     code = FC_RegValue;
   }
   else if ( (fixRegs.EFLAGS & EFLAGS_IOPL) && ! HasDevicePriveleges() ) {
-#if 0
-    MsgLog::dprintf(true, "Ctxt 0x%08x has bad EFLAGS value 0x%08x\n", this, fixRegs.EFLAGS);
-    /* Some flags must be clear: */
-#endif
     code = FC_RegValue;
   }
 
@@ -591,6 +571,7 @@
      and need not be checked. */
 #endif
   
+ fault:
   if (code)
     SetFault(code, info, true);
   



1.2       +2 -1      eros/src/base/sys/eros/i486/SaveArea.h

Index: SaveArea.h
===================================================================
RCS file: /cvs/eros/src/base/sys/eros/i486/SaveArea.h,v
retrieving revision 1.1
retrieving revision 1.2
diff -u -r1.1 -r1.2
--- SaveArea.h	2000/10/16 00:48:35	1.1
+++ SaveArea.h	2001/03/13 03:09:37	1.2
@@ -41,7 +41,8 @@
 inline bool
 sa_IsKernel(const fixregs_t* fx)
 {
-  if ( ((fx->CS & 0x3u) < 0x3u) &&
+  if ( fx->CS &&
+       ((fx->CS & 0x3u) < 0x3u) &&
        ((fx->EFLAGS & EFLAGS_Virt8086) == 0) )
     return true;
   return false;