Subject: Re: 2nd review of fixes to sig_return() and LDT's
To: Chris G. Demetriou <cgd@nobozo.CS.Berkeley.EDU>
From: John Brezak <brezak@apollo.hp.com>
List: port-i386
Date: 01/08/1994 00:43:26
Ok, try this one. It eliminates the bogus force_signal() stuff and
uses trapsignal() in sigreturn() when a problem in the sigcontext is
detected. The only question I have is what T_<fault> to use. I took
a stab at it here.

*** machdep.c.orig      Fri Jan  7 05:49:35 1994
--- machdep.c   Sat Jan  8 00:38:52 1994
***************
*** 511,534 ****
        fp = (struct sigframe *)
             ((caddr_t)scp - offsetof(struct sigframe, sf_sc));
  
!       if (useracc((caddr_t)fp, sizeof(*fp), 0) == 0)
                return(EINVAL);
  
!       if (useracc((caddr_t)scp, sizeof(*scp), 0) == 0)
                return(EINVAL);
  
        /* make sure they aren't trying to do anything funny */
!       if ((scp->sc_ps & PSL_MBZ) != 0 || (scp->sc_ps & PSL_MBO) != PSL_MBO)
                return(EINVAL);
  
        /* compare IOPL; we can't insist that it's always 3 or the X server
           will fail */
!       if ((tf->tf_eflags & PSL_IOPL) < (scp->sc_efl & PSL_IOPL))
                return(EINVAL);
  
        p->p_sigacts->ps_onstack = scp->sc_onstack & 01;
        p->p_sigmask = scp->sc_mask &~
            (sigmask(SIGKILL)|sigmask(SIGCONT)|sigmask(SIGSTOP));
  
        /*
         * Restore signal context.
--- 511,566 ----
        fp = (struct sigframe *)
             ((caddr_t)scp - offsetof(struct sigframe, sf_sc));
  
!       if (useracc((caddr_t)fp, sizeof(*fp), 0) == 0) {
!               trapsignal(p, SIGBUS, T_STKFLT);
                return(EINVAL);
+       }
  
!       if (useracc((caddr_t)scp, sizeof(*scp), 0) == 0) {
!               trapsignal(p, SIGBUS, T_STKFLT);
                return(EINVAL);
+       }
  
        /* make sure they aren't trying to do anything funny */
!       if ((scp->sc_ps & PSL_MBZ) != 0 || (scp->sc_ps & PSL_MBO) != PSL_MBO) {
!               trapsignal(p, SIGBUS, T_PROTFLT);
                return(EINVAL);
+       }
  
        /* compare IOPL; we can't insist that it's always 3 or the X server
           will fail */
!       if ((tf->tf_eflags & PSL_IOPL) < (scp->sc_efl & PSL_IOPL)) {
!               trapsignal(p, SIGBUS, T_PROTFLT);
                return(EINVAL);
+       }
  
        p->p_sigacts->ps_onstack = scp->sc_onstack & 01;
        p->p_sigmask = scp->sc_mask &~
            (sigmask(SIGKILL)|sigmask(SIGCONT)|sigmask(SIGSTOP));
+ 
+       /*
+        * Sanity check the user's selectors and error if they
+        * are suspect.
+        */
+ #define max_ldt_sel(pcb) \
+       ((((pcb)->pcb_ldt)? \
+           (gdt_segs[GUSERLDT_SEL].ssd_limit + 1) : \
+               sizeof(ldt))/sizeof(union descriptor))
+ 
+ #define valid_sel(sel) \
+       (((sel) == 0) || \
+         (ISPL((sel)) == SEL_UPL && ISLDT((sel))) || \
+         (ISLDT((sel)) && IDXSEL((sel)) < max_ldt_sel((struct pcb *)(p->p_addr))))
+ 
+       if (scp->sc_cs&0xffff != _ucodesel || scp->sc_ss&0xffff != _udatasel ||
+           scp->sc_ds&0xffff != _udatasel || scp->sc_es&0xffff != _udatasel) {
+               if (!valid_sel(scp->sc_cs) || !valid_sel(scp->sc_ss) ||
+                   !valid_sel(scp->sc_ds) || !valid_sel(scp->sc_es)) {
+                   trapsignal(p, SIGBUS, T_PROTFLT);
+                   return(EINVAL);
+               }
+       }
+ #undef valid_sel
  
        /*
         * Restore signal context.

=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
 John Brezak                    UUCP:     uunet!apollo.hp!brezak
 Hewlett Packard/Apollo         Internet: brezak@ch.hp.com
 300 Apollo Drive               Phone:    (508) 436-4915
 Chelmsford, Massachusetts      Fax:      (508) 436-5103


------------------------------------------------------------------------------