Add hardware stack overflow protection under DPMI.
authorGuillermo J. Rozas <edu/mit/csail/zurich/gjr>
Fri, 18 Sep 1992 05:54:21 +0000 (05:54 +0000)
committerGuillermo J. Rozas <edu/mit/csail/zurich/gjr>
Fri, 18 Sep 1992 05:54:21 +0000 (05:54 +0000)
v7/src/microcode/dosexcp.c
v7/src/microcode/dossig.c
v7/src/microcode/dostrap.c

index 6e83a2c339388d42797a1e72564d1154110792f9..cfe0b41d68011d4965640d8baef5f55d122540ff 100644 (file)
@@ -1,6 +1,6 @@
 /* -*-C-*-
 
-$Header: /Users/cph/tmp/foo/mit-scheme/mit-scheme/v7/src/microcode/Attic/dosexcp.c,v 1.2 1992/07/28 14:34:05 jinx Exp $
+$Id: dosexcp.c,v 1.3 1992/09/18 05:54:21 jinx Exp $
 
 Copyright (c) 1992 Massachusetts Institute of Technology
 
@@ -41,115 +41,6 @@ MIT in each case. */
 #include "dosinsn.h"
 #include "dosexcp.h"
 \f
-/* It would be nice to be able to use something akin to Zortech's int_intercept
-   to get control of trap handlers, but Zortech's DOSX does not
-   provide that ability.  In fact, it shadows the exception numbers
-   with DOS interrupts (for compatibility), but does not map the traps
-   to an accessible region.
-
-   In the meantime, exceptions are only caught under DPMI if running DOSX,
-   or everywhere if running X32.
-*/
-
-#if 0
-
-#include <int.h>
-
-static unsigned long *
-DEFUN (store_trap_data, (trap_stack_ptr, intno, code, pd), 
-       unsigned long ** trap_stack_ptr 
-       AND unsigned char intno AND unsigned char code
-       AND struct INT_DATA * pd)
-{
-  unsigned long 
-    * trap_stack,
-    * trapped_stack;
-  
-  union
-  { 
-    unsigned long long_value;
-    struct
-    { 
-      unsigned char code;
-      unsigned char ss_is_ds;
-      unsigned char intno;
-      unsigned char padding;
-    } byte_values;
-  } code_word;
-
-  trap_stack = (* trap_stack_ptr);
-  trapped_stack = ((unsigned long) pd->regs.oldstack_off);
-
-  code_word.byte_values.code = code;
-  code_word.byte_values.intno = intno;
-  code_word.byte_values.ss_is_ds = (pd->oldstack_seg == pd->sregs.ds);
-  code_word.byte_values.padding = 0;
-
-  *--trap_stack = code_word.long_value;
-  *--trap_stack = pd->regs.e.eax;
-  *--trap_stack = pd->regs.e.ecx;
-  *--trap_stack = pd->regs.e.edx;
-  *--trap_stack = pd->regs.e.ebx;
-
-  /* The following checks whether there was a ring change when the
-     interrupt was taken.  If there was, the old SP is pushed on the
-     exception trap frame which lives on the stack of the new
-     privilege level, otherwise the trap frame was pushed on the 
-     interrupted stack, which is shared by the low-level handler.
-     Compare the PL of the two PCs.
-   */
-  *--trap_stack = (((pd->regs.sregs.cs & 0x3) == (trapped_stack[3] & 0x3))
-                   ? (trapped_stack + 5)
-                  : (trapped_stack[5]));       /* esp */
-  *--trap_stack = trapped_stack[0];            /* ebp */
-  *--trap_stack = pd->regs.e.esi;
-  *--trap_stack = pd->regs.e.edi;
-  *--trap_stack = trapped_stack[2];            /* eip */
-  *--trap_stack = pd->regs.e.flags;
-  (* trap_stack_ptr) = trap_stack;
-  return (trapped_stack + 2);
-}
-\f
-static int
-DEFUN (dosx_trap_handler, (intno, pd), 
-       unsigned char intno AND struct INT_DATA * pd)
-{
-  extern void asm_trap_handler ();
-  extern unsigned long
-    * asm_trap_stack,
-    * asm_trap_stack_limit,
-    * asm_trap_stack_base;
-  unsigned long * pc_loc;
-  int code;
-
-  code = 0;
-  if (asm_trap_stack <= asm_trap_stack_limit)
-  {
-    /* Lose badly.  Too many nested traps. */
-    asm_trap_stack = asm_trap_stack_base;
-    code = 1;
-  }
-  pc_loc = store_trap_data (&asm_trap_stack, intno, code, pd);
-  (* pc_loc) = ((unsigned long) asm_trap_handler);
-  return (0);
-}
-
-#define DEFINE_TRAP_HANDLER(name,intno)                \
-extern int EXFUN (name, (struct INT_DATA *));  \
-int                                            \
-DEFUN (name, (pd), struct INT_DATA * pd)       \
-{                                              \
-  return (dosx_trap_handler (intno, pd));      \
-}
-
-DEFINE_TRAP_HANDLER (handle_integer_divide_by_0, DOS_INTVECT_DIVIDE_BY_0)
-DEFINE_TRAP_HANDLER (handle_overflow, DOS_INTVECT_OVERFLOW)
-DEFINE_TRAP_HANDLER (handle_bounds_check, DOS_INTVECT_PRINT_SCREEN)
-DEFINE_TRAP_HANDLER (handle_invalid_opcode, DOS_INVALID_OPCODE)
-/* And many more friends. */
-
-#endif /* 0 */
-\f
 int
 DPMI_get_exception_vector (unsigned exception,
                           unsigned short * cs_selector,
@@ -226,11 +117,7 @@ make_DPMI_exception_trampoline (unsigned exception,
 
   PUSH_INSN (exception);
   PUSH_INSN (getDS ());
-#if 0
-  PUSH_INSN (getCS ());
-#else
   PUSH_INSN (0);               /* Use same CS and near calls and returns */
-#endif
   PUSH_INSN (funcptr);
   PUSH_INSN (getDS ());                /* Assumed to be on Heap if not null! */
   PUSH_INSN (stack);
@@ -309,6 +196,82 @@ DPMI_restore_exception_handler (unsigned exception,
   return (DOS_SUCCESS);
 }
 \f
+extern int DPMI_free_scheme_stack (unsigned short);
+extern int DPMI_alloc_scheme_stack (unsigned short *,
+                                   unsigned short *,
+                                   unsigned long);
+
+int
+DPMI_free_scheme_stack (unsigned short ss)
+{
+  union REGS regs;
+
+  regs.x.ax = 0x1;
+  regs.x.bx = ss;
+  int86 (0x31, &regs, &regs);
+  return ((regs.e.cflag != 0) ? DOS_FAILURE : DOS_SUCCESS);
+}
+
+#define I386_PAGE_BITS 12
+#define I386_PAGE_SIZE (1 << I386_PAGE_BITS)
+#define I386_PAGE_MASK (I386_PAGE_SIZE - 1) 
+
+int
+DPMI_alloc_scheme_stack (unsigned short * ds,
+                        unsigned short * ss,
+                        unsigned long limit)
+{
+  unsigned short ds_sel, css_sel, ss_sel;
+  unsigned long descriptor[2];
+  struct SREGS sregs;
+  union REGS regs;
+
+  limit = ((limit + I386_PAGE_MASK) & (~ I386_PAGE_MASK));
+
+  segread (&sregs);
+  css_sel = sregs.ss;
+  ds_sel = sregs.ds;
+
+  regs.x.ax = 0x0;             /* Allocate LDT Descriptor */
+  regs.x.cx = 1;
+  int86 (0x31, &regs, &regs);
+  if (regs.e.cflag != 0)
+    return (DOS_FAILURE);
+  ss_sel = regs.x.ax;
+
+  sregs.es = ds_sel;
+  regs.x.ax = 0xb;             /* Get Descriptor */
+  regs.x.bx = css_sel;
+  regs.e.edi = ((unsigned long) &descriptor[0]);
+  int86x (0x31, &regs, &regs, &sregs);
+  if (regs.e.cflag != 0)
+  {
+fail:
+    DPMI_free_scheme_stack (ss_sel);
+    fprintf (stderr, "DPMI_alloc_scheme_stack: failed.\n");
+    return (DOS_FAILURE);    
+  }
+  
+  /* Set the granularity bit and the limit */
+  descriptor[1] = (descriptor[1] | (1UL << 23));
+  descriptor[1] &= (~ (0xfUL << 16));
+  descriptor[1] |= ((limit >> (I386_PAGE_BITS + 16)) << 16);
+
+  descriptor[0] &= 0xffff0000UL;
+  descriptor[0] |= ((limit >> I386_PAGE_BITS) & I386_PAGE_MASK);
+
+  regs.x.ax = 0xc;             /* Set Descriptor */
+  regs.x.bx = ss_sel;
+  regs.e.edi = ((unsigned long) &descriptor[0]);
+  int86x (0x31, &regs, &regs, &sregs);
+  if (regs.e.cflag != 0)
+    goto fail;
+
+  *ds = ds_sel;
+  *ss = ss_sel;
+  return (DOS_SUCCESS);
+}
+\f
 int
 X32_get_exception_vector (unsigned exception,
                          unsigned short * cs_selector,
index 2d57858d83305ed758c3b226f0757366fa13ecd0..20ae28ac103a49c55ce83adb5ffa4e31050392f0 100644 (file)
@@ -1,6 +1,6 @@
 /* -*-C-*-
 
-$Id: dossig.c,v 1.5 1992/09/03 07:29:39 jinx Exp $
+$Id: dossig.c,v 1.6 1992/09/18 05:53:55 jinx Exp $
 
 Copyright (c) 1992 Massachusetts Institute of Technology
 
@@ -822,6 +822,15 @@ DEFUN_VOID (DOS_initialize_interrupts)
   return;
 } 
 \f
+extern int EXFUN (DPMI_free_scheme_stack, (unsigned short));
+extern int EXFUN (DPMI_alloc_scheme_stack,
+                 (unsigned short *, unsigned short *, unsigned long));
+
+extern unsigned short Scheme_Stack_Segment_Selector;
+extern unsigned short scheme_ss, scheme_ds;
+unsigned short scheme_ds = 0;
+unsigned short scheme_ss = 0;
+
 static char i386_exceptions_to_handle[] =
 {
   DOS_EXCP_Integer_divide_by_zero,
@@ -862,6 +871,11 @@ DEFUN (restore_exception_handler, (iv, restore),
     return (DOS_FAILURE);
   if (excp == DOS_EXCP_Stack_exception)
   {
+    if (scheme_ss != 0)
+    {
+      Scheme_Stack_Segment_Selector = scheme_ds;
+      DPMI_free_scheme_stack (scheme_ss);
+    }
     free (stack_exception_fault_stack);
     stack_exception_fault_stack = ((void *) NULL);
   }
@@ -890,6 +904,25 @@ DEFUN (exception_handler, (trapno, trapcode, scp),
   /*NOTREACHED*/
 }
 
+static void
+DEFUN (DPMI_stack_fault_handler, (trapno, trapcode, scp),
+       unsigned trapno AND unsigned trapcode AND struct sigcontext * scp)
+{
+  Scheme_Stack_Segment_Selector = scheme_ds;
+  trap_handler ("hardware exception", ((int) trapno), trapcode, scp);
+  /*NOTREACHED*/
+}
+
+extern void EXFUN (dos386_stack_reset, (void));
+
+void
+DEFUN_VOID (dos386_stack_reset)
+{
+  if (scheme_ss != 0)
+    Scheme_Stack_Segment_Selector = scheme_ss;
+  return;
+}
+
 static void
 DEFUN (install_exception_handlers, (get_vector, set_handler, restore),
        int EXFUN ((* get_vector),
@@ -918,19 +951,33 @@ DEFUN (install_exception_handlers, (get_vector, set_handler, restore),
       continue;
     if (excp == DOS_EXCP_Stack_exception)
     {
+      void EXFUN ((* handler), (unsigned, unsigned, struct sigcontext *));
       char * stack;
 
       stack = ((char *) (malloc (STACK_EXCEPTION_STACK_SIZE)));
       if (stack == ((char *) NULL))
        continue;
+      handler = exception_handler;
+      if ((under_DPMI_p ())
+         && ((DPMI_alloc_scheme_stack (&scheme_ds, &scheme_ss,
+                                       (Regs[REGBLOCK_STACK_GUARD])))
+             == DOS_SUCCESS))
+      {
+       Scheme_Stack_Segment_Selector = scheme_ss;
+       handler = DPMI_stack_fault_handler;
+      }
       if (((* set_handler) (((unsigned) excp),
-                           exception_handler,
-                           ((void *)
-                            (stack 
-                             + STACK_EXCEPTION_STACK_SIZE))))
+                           handler,
+                           ((void *) (stack + STACK_EXCEPTION_STACK_SIZE))))
          != DOS_SUCCESS)
       {
        free (stack);
+       if (handler != exception_handler)
+       {
+         Scheme_Stack_Segment_Selector = scheme_ds;
+         DPMI_free_scheme_stack (scheme_ss);
+         scheme_ss = 0;
+       }
        continue;
       }
       stack_exception_fault_stack = ((void *) stack);
index 323721d3448075af1965ddbd074090a4974af206..dce456b4b8686cc16fdb331cb9c72e2aaa184ff2 100644 (file)
@@ -1,6 +1,6 @@
 /* -*-C-*-
 
-$Header: /Users/cph/tmp/foo/mit-scheme/mit-scheme/v7/src/microcode/Attic/dostrap.c,v 1.1 1992/05/05 06:55:13 jinx Exp $
+$Id: dostrap.c,v 1.2 1992/09/18 05:54:06 jinx Exp $
 
 Copyright (c) 1992 Massachusetts Institute of Technology
 
@@ -413,6 +413,7 @@ DEFUN (setup_trap_frame, (trapno, info, scp, trinfo, new_stack_pointer),
       ((handler = (Get_Fixed_Obj_Slot (Trap_Handler))) == SHARP_F))
     {
       fprintf (stderr, "There is no trap handler for recovery!\n");
+      fprintf (stderr, "Trap = %s.\n", (find_trap_name (trapno)));
       fflush (stderr);
       termination_trap ();
     }
@@ -569,6 +570,7 @@ DEFUN (continue_from_trap, (trapno, info, scp),
        SIGINFO_T info AND
        struct FULL_SIGCONTEXT * scp)
 {
+  extern unsigned short scheme_ss;
   int pc_in_C;
   int pc_in_heap;
   int pc_in_constant_space;
@@ -625,7 +627,9 @@ DEFUN (continue_from_trap, (trapno, info, scp),
 
   scheme_sp_valid =
     (pc_in_scheme
-     && ((scp->sc_ss & 0xffff) == (scp->sc_ds & 0xffff))
+     && (((scp->sc_ss & 0xffff) == (scp->sc_ds & 0xffff))
+        || ((scheme_ss != 0)
+            && ((scp->sc_ss & 0xffff) == scheme_ss)))
      && ((scp->sc_ds & 0xffff) == (initial_C_ds & 0xffff))
      && ((scheme_sp < ((long) Stack_Top)) &&
         (scheme_sp >= ((long) Absolute_Stack_Base)) &&