[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;