summaryrefslogtreecommitdiff
path: root/sys/vm
diff options
context:
space:
mode:
authorMatthew Dillon <dillon@FreeBSD.org>2000-02-16 21:11:33 +0000
committerMatthew Dillon <dillon@FreeBSD.org>2000-02-16 21:11:33 +0000
commit1f6889a1eb5070dfa739f4158cfb33f13b7a462d (patch)
treeffa24ad6f287af901091f289951217e582cb5261 /sys/vm
parentc2ebb466e57077c7d5851580569936c90ba1e24d (diff)
Notes
Diffstat (limited to 'sys/vm')
-rw-r--r--sys/vm/vm_kern.h1
-rw-r--r--sys/vm/vm_map.c8
-rw-r--r--sys/vm/vm_mmap.c46
3 files changed, 50 insertions, 5 deletions
diff --git a/sys/vm/vm_kern.h b/sys/vm/vm_kern.h
index 2f1fe76aae44..a962c1782f53 100644
--- a/sys/vm/vm_kern.h
+++ b/sys/vm/vm_kern.h
@@ -75,6 +75,7 @@ extern vm_map_t mb_map;
extern int mb_map_full;
extern vm_map_t clean_map;
extern vm_map_t exec_map;
+extern u_int vm_kmem_size;
extern vm_offset_t kernel_vm_end;
/* XXX - elsewhere? */
diff --git a/sys/vm/vm_map.c b/sys/vm/vm_map.c
index 3f5382e1909f..7acaa5118b4d 100644
--- a/sys/vm/vm_map.c
+++ b/sys/vm/vm_map.c
@@ -284,7 +284,13 @@ static vm_map_entry_t
vm_map_entry_create(map)
vm_map_t map;
{
- return zalloc((map->system_map || !mapentzone) ? kmapentzone : mapentzone);
+ vm_map_entry_t new_entry;
+
+ new_entry = zalloc((map->system_map || !mapentzone) ?
+ kmapentzone : mapentzone);
+ if (new_entry == NULL)
+ panic("vm_map_entry_create: kernel resources exhausted");
+ return(new_entry);
}
/*
diff --git a/sys/vm/vm_mmap.c b/sys/vm/vm_mmap.c
index bb106f3d0094..b42239cdab87 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);