summaryrefslogtreecommitdiffstats
path: root/sys/kern/subr_trap.c
diff options
context:
space:
mode:
Diffstat (limited to 'sys/kern/subr_trap.c')
-rw-r--r--sys/kern/subr_trap.c84
1 files changed, 73 insertions, 11 deletions
diff --git a/sys/kern/subr_trap.c b/sys/kern/subr_trap.c
index 57195f3..22fc6da 100644
--- a/sys/kern/subr_trap.c
+++ b/sys/kern/subr_trap.c
@@ -43,7 +43,7 @@
* 08 Apr 93 Bruce Evans Several VM system fixes
* Paul Kranenburg Add counter for vmstat
*/
-static char rcsid[] = "$Header: /usr/bill/working/sys/i386/i386/RCS/trap.c,v 1.2 92/01/21 14:22:13 william Exp $";
+static char rcsid[] = "$Header: /a/cvs/386BSD/src/sys/i386/i386/trap.c,v 1.1.1.1 1993/06/12 14:58:05 rgrimes Exp $";
/*
* 386 Trap and System call handleing
@@ -70,6 +70,21 @@ static char rcsid[] = "$Header: /usr/bill/working/sys/i386/i386/RCS/trap.c,v 1.2
#include "machine/trap.h"
+#ifdef __GNUC__
+
+/*
+ * The "r" contraint could be "rm" except for fatal bugs in gas. As usual,
+ * we omit the size from the mov instruction to avoid nonfatal bugs in gas.
+ */
+#define read_gs() ({ u_short gs; __asm("mov %%gs,%0" : "=r" (gs)); gs; })
+#define write_gs(gs) __asm("mov %0,%%gs" : : "r" ((u_short) gs))
+
+#else /* not __GNUC__ */
+
+u_short read_gs __P((void));
+void write_gs __P((/* promoted u_short */ int gs));
+
+#endif /* __GNUC__ */
struct sysent sysent[];
int nsysent;
@@ -112,9 +127,25 @@ trap(frame)
frame.tf_trapno, frame.tf_err, frame.tf_eip,
frame.tf_cs, rcr2(), frame.tf_esp);*/
if(curpcb == 0 || curproc == 0) goto we_re_toast;
- if (curpcb->pcb_onfault && frame.tf_trapno != 0xc) {
+ if (curpcb->pcb_onfault && frame.tf_trapno != T_PAGEFLT) {
+ extern int _udatasel;
+
+ if (read_gs() != (u_short) _udatasel)
+ /*
+ * Some user has corrupted %gs but we depend on it in
+ * copyout() etc. Fix it up and retry.
+ *
+ * (We don't preserve %fs or %gs, so users can change
+ * them to either _ucodesel, _udatasel or a not-present
+ * selector, possibly ORed with 0 to 3, making them
+ * volatile for other users. Not preserving them saves
+ * time and doesn't lose functionality or open security
+ * holes.)
+ */
+ write_gs(_udatasel);
+ else
copyfault:
- frame.tf_eip = (int)curpcb->pcb_onfault;
+ frame.tf_eip = (int)curpcb->pcb_onfault;
return;
}
@@ -396,18 +427,49 @@ out:
}
/*
- * Compensate for 386 brain damage (missing URKR)
+ * Compensate for 386 brain damage (missing URKR).
+ * This is a little simpler than the pagefault handler in trap() because
+ * it the page tables have already been faulted in and high addresses
+ * are thrown out early for other reasons.
*/
-int trapwrite(unsigned addr) {
- int rv;
+int trapwrite(addr)
+ unsigned addr;
+{
+ unsigned nss;
+ struct proc *p;
vm_offset_t va;
+ struct vmspace *vm;
va = trunc_page((vm_offset_t)addr);
- if (va > VM_MAXUSER_ADDRESS) return(1);
- rv = vm_fault(&curproc->p_vmspace->vm_map, va,
- VM_PROT_READ | VM_PROT_WRITE, FALSE);
- if (rv == KERN_SUCCESS) return(0);
- else return(1);
+ /*
+ * XXX - MAX is END. Changed > to >= for temp. fix.
+ */
+ if (va >= VM_MAXUSER_ADDRESS)
+ return (1);
+ /*
+ * XXX: rude stack hack adapted from trap().
+ */
+ nss = 0;
+ p = curproc;
+ vm = p->p_vmspace;
+ if ((caddr_t)va >= vm->vm_maxsaddr && dostacklimits) {
+ nss = clrnd(btoc((unsigned)vm->vm_maxsaddr + MAXSSIZ
+ - (unsigned)va));
+ if (nss > btoc(p->p_rlimit[RLIMIT_STACK].rlim_cur))
+ return (1);
+ }
+
+ if (vm_fault(&vm->vm_map, va, VM_PROT_READ | VM_PROT_WRITE, FALSE)
+ != KERN_SUCCESS)
+ return (1);
+
+ /*
+ * XXX: continuation of rude stack hack
+ */
+ if (nss > vm->vm_ssize)
+ vm->vm_ssize = nss;
+
+ return (0);
}
/*
OpenPOWER on IntegriCloud