summaryrefslogtreecommitdiffstats
path: root/sys
diff options
context:
space:
mode:
authordyson <dyson@FreeBSD.org>1996-06-25 00:36:46 +0000
committerdyson <dyson@FreeBSD.org>1996-06-25 00:36:46 +0000
commit43e1aa7ef69aa819981bc28c15e92cd10b208224 (patch)
tree4d96d00820fa9c96145184617d17a801a1f30215 /sys
parent31ea3a3bd61ebe1950d42628e97c677bba342cd8 (diff)
downloadFreeBSD-src-43e1aa7ef69aa819981bc28c15e92cd10b208224.zip
FreeBSD-src-43e1aa7ef69aa819981bc28c15e92cd10b208224.tar.gz
Fix some serious problems with limits checking in the sbrk(2)/brk(2)
code. Reviewed by: bde
Diffstat (limited to 'sys')
-rw-r--r--sys/vm/vm_unix.c38
1 files changed, 25 insertions, 13 deletions
diff --git a/sys/vm/vm_unix.c b/sys/vm/vm_unix.c
index 46531e8..1f7f77f 100644
--- a/sys/vm/vm_unix.c
+++ b/sys/vm/vm_unix.c
@@ -38,7 +38,7 @@
* from: Utah $Hdr: vm_unix.c 1.1 89/11/07$
*
* @(#)vm_unix.c 8.1 (Berkeley) 6/11/93
- * $Id: vm_unix.c,v 1.9 1995/12/07 12:48:29 davidg Exp $
+ * $Id: vm_unix.c,v 1.10 1996/01/19 04:00:27 dyson Exp $
*/
/*
@@ -72,33 +72,45 @@ obreak(p, uap, retval)
int *retval;
{
register struct vmspace *vm = p->p_vmspace;
- vm_offset_t new, old;
+ vm_offset_t new, old, base;
int rv;
- register int diff;
- old = (vm_offset_t) vm->vm_daddr;
+ base = round_page((vm_offset_t) vm->vm_daddr);
new = round_page(uap->nsize);
- if ((int) (new - old) > p->p_rlimit[RLIMIT_DATA].rlim_cur)
- return (ENOMEM);
- old = round_page(old + ctob(vm->vm_dsize));
- diff = new - old;
- if (diff > 0) {
+ if (new > base) {
+ if ((new - base) > (unsigned) p->p_rlimit[RLIMIT_DATA].rlim_cur)
+ return ENOMEM;
+ if (new >= VM_MAXUSER_ADDRESS)
+ return (ENOMEM);
+ } else if (new < base) {
+ /*
+ * This is simply an invalid value. If someone wants to
+ * do fancy address space manipulations, mmap and munmap
+ * can do most of what the user would want.
+ */
+ return EINVAL;
+ }
+
+ old = base + ctob(vm->vm_dsize);
+
+ if (new > old) {
+ vm_size_t diff;
if (swap_pager_full) {
return (ENOMEM);
}
+ diff = new - old;
rv = vm_map_find(&vm->vm_map, NULL, 0, &old, diff, FALSE,
VM_PROT_ALL, VM_PROT_ALL, 0);
if (rv != KERN_SUCCESS) {
return (ENOMEM);
}
vm->vm_dsize += btoc(diff);
- } else if (diff < 0) {
- diff = -diff;
- rv = vm_map_remove(&vm->vm_map, new, new + diff);
+ } else if (new < old) {
+ rv = vm_map_remove(&vm->vm_map, new, old);
if (rv != KERN_SUCCESS) {
return (ENOMEM);
}
- vm->vm_dsize -= btoc(diff);
+ vm->vm_dsize -= btoc(old - new);
}
return (0);
}
OpenPOWER on IntegriCloud