diff options
author | dg <dg@FreeBSD.org> | 1993-07-27 10:52:31 +0000 |
---|---|---|
committer | dg <dg@FreeBSD.org> | 1993-07-27 10:52:31 +0000 |
commit | ed0c2480407bece983d693e1753de8d830a5f5ba (patch) | |
tree | f74d745c1c162578afcb421239425fdd31e58e8a /sys/kern/subr_trap.c | |
parent | 17f98e8cfc1b74c9d12ce4853fc1d7635a20dfb1 (diff) | |
download | FreeBSD-src-ed0c2480407bece983d693e1753de8d830a5f5ba.zip FreeBSD-src-ed0c2480407bece983d693e1753de8d830a5f5ba.tar.gz |
* Applied fixes from Bruce Evans to fix COW bugs, >1MB kernel loading,
profiling, and various protection checks that cause security holes
and system crashes.
* Changed min/max/bcmp/ffs/strlen to be static inline functions
- included from cpufunc.h in via systm.h. This change
improves performance in many parts of the kernel - up to 5% in the
networking layer alone. Note that this requires systm.h to be included
in any file that uses these functions otherwise it won't be able to
find them during the load.
* Fixed incorrect call to splx() in if_is.c
* Fixed bogus variable assignment to splx() in if_ed.c
Diffstat (limited to 'sys/kern/subr_trap.c')
-rw-r--r-- | sys/kern/subr_trap.c | 84 |
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); } /* |