summaryrefslogtreecommitdiffstats
path: root/sys/vm/vm_mmap.c
diff options
context:
space:
mode:
authordillon <dillon@FreeBSD.org>2000-02-16 21:11:33 +0000
committerdillon <dillon@FreeBSD.org>2000-02-16 21:11:33 +0000
commit7a2987cf9410d129917e89db27af78911bd0fb60 (patch)
treee9fa93a9df696f57e919e1e8f97b841d07227b0b /sys/vm/vm_mmap.c
parente8cfdc976f1f31ae86f30a656797e2820c9f439b (diff)
downloadFreeBSD-src-7a2987cf9410d129917e89db27af78911bd0fb60.zip
FreeBSD-src-7a2987cf9410d129917e89db27af78911bd0fb60.tar.gz
Fix null-pointer dereference crash when the system is intentionally
run out of KVM through a mmap()/fork() bomb that allocates hundreds of thousands of vm_map_entry structures. Add panic to make null-pointer dereference crash a little more verbose. Add a new sysctl, vm.max_proc_mmap, which specifies the maximum number of mmap()'d spaces (discrete vm_map_entry's in the process). The value defaults to around 9000 for a 128MB machine. The test is scaled for the number of processes sharing a vmspace (aka linux threads). Setting the value to 0 disables the feature. PR: kern/16573 Approved by: jkh
Diffstat (limited to 'sys/vm/vm_mmap.c')
-rw-r--r--sys/vm/vm_mmap.c46
1 files changed, 42 insertions, 4 deletions
diff --git a/sys/vm/vm_mmap.c b/sys/vm/vm_mmap.c
index bb106f3..b42239c 100644
--- a/sys/vm/vm_mmap.c
+++ b/sys/vm/vm_mmap.c
@@ -49,6 +49,7 @@
#include "opt_rlimit.h"
#include <sys/param.h>
+#include <sys/kernel.h>
#include <sys/systm.h>
#include <sys/sysproto.h>
#include <sys/filedesc.h>
@@ -60,6 +61,7 @@
#include <sys/conf.h>
#include <sys/stat.h>
#include <sys/vmmeter.h>
+#include <sys/sysctl.h>
#include <vm/vm.h>
#include <vm/vm_param.h>
@@ -72,6 +74,7 @@
#include <vm/vm_pageout.h>
#include <vm/vm_extern.h>
#include <vm/vm_page.h>
+#include <vm/vm_kern.h>
#ifndef _SYS_SYSPROTO_H_
struct sbrk_args {
@@ -79,6 +82,29 @@ struct sbrk_args {
};
#endif
+static int max_proc_mmap;
+SYSCTL_INT(_vm, OID_AUTO, max_proc_mmap, CTLFLAG_RW, &max_proc_mmap, 0, "");
+
+/*
+ * Set the maximum number of vm_map_entry structures per process. Roughly
+ * speaking vm_map_entry structures are tiny, so allowing them to eat 1/100
+ * of our KVM malloc space still results in generous limits. We want a
+ * default that is good enough to prevent the kernel running out of resources
+ * if attacked from compromised user account but generous enough such that
+ * multi-threaded processes are not unduly inconvenienced.
+ */
+
+static void vmmapentry_rsrc_init __P((void *));
+SYSINIT(vmmersrc, SI_SUB_KVM_RSRC, SI_ORDER_FIRST, vmmapentry_rsrc_init, NULL)
+
+static void
+vmmapentry_rsrc_init(dummy)
+ void *dummy;
+{
+ max_proc_mmap = vm_kmem_size / sizeof(struct vm_map_entry);
+ max_proc_mmap /= 100;
+}
+
/* ARGSUSED */
int
sbrk(p, uap)
@@ -171,6 +197,7 @@ mmap(p, uap)
int flags, error;
int disablexworkaround;
off_t pos;
+ struct vmspace *vms = p->p_vmspace;
addr = (vm_offset_t) uap->addr;
size = uap->len;
@@ -234,9 +261,9 @@ mmap(p, uap)
* location.
*/
else if (addr == 0 ||
- (addr >= round_page((vm_offset_t)p->p_vmspace->vm_taddr) &&
- addr < round_page((vm_offset_t)p->p_vmspace->vm_daddr + MAXDSIZ)))
- addr = round_page((vm_offset_t)p->p_vmspace->vm_daddr + MAXDSIZ);
+ (addr >= round_page((vm_offset_t)vms->vm_taddr) &&
+ addr < round_page((vm_offset_t)vms->vm_daddr + MAXDSIZ)))
+ addr = round_page((vm_offset_t)vms->vm_daddr + MAXDSIZ);
if (flags & MAP_ANON) {
/*
@@ -332,7 +359,18 @@ mmap(p, uap)
handle = (void *)vp;
}
}
- error = vm_mmap(&p->p_vmspace->vm_map, &addr, size, prot, maxprot,
+
+ /*
+ * Do not allow more then a certain number of vm_map_entry structures
+ * per process. Scale with the number of rforks sharing the map
+ * to make the limit reasonable for threads.
+ */
+ if (max_proc_mmap &&
+ vms->vm_map.nentries >= max_proc_mmap * vms->vm_refcnt) {
+ return (ENOMEM);
+ }
+
+ error = vm_mmap(&vms->vm_map, &addr, size, prot, maxprot,
flags, handle, pos);
if (error == 0)
p->p_retval[0] = (register_t) (addr + pageoff);
OpenPOWER on IntegriCloud