lkml.org 
[lkml]   [1996]   [Jun]   [6]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
Patch in this message
/
Date
From
SubjectRe: the mmap() problem, a'la "grep x /dev/zero"


On Wed, 5 Jun 1996, Ingo Molnar wrote:
>
> is there anything one could do tracing down this problem?

I suspect it's just the fact that Linux doesn't check for memory availability
when doing memory mappings. It _does_ check when increasing the bss, so it
was just a matter of doing that check in both places (the check should
probably be improved too).

I'm including totally untested patches - I haven't even rebooted (or
compiled) this kernel yet, but the more testers, the merrier. The worst
that can happen is that nothing works, it eats your harddisk, and the
machine goes up in smoke.,.

(most of this patch is actually just moving "sys_brk()" to where it
belongs)

Please do tell if this makes a difference for you..

Linus

-----
diff -u --recursive --new-file pre2.0.12/linux/kernel/sys.c linux/kernel/sys.c
--- pre2.0.12/linux/kernel/sys.c Mon May 13 23:02:50 1996
+++ linux/kernel/sys.c Thu Jun 6 09:28:51 1996
@@ -18,8 +18,6 @@
#include <linux/stat.h>
#include <linux/mman.h>
#include <linux/mm.h>
-#include <linux/pagemap.h>
-#include <linux/swap.h>
#include <linux/fcntl.h>
#include <linux/acct.h>
#include <linux/tty.h>
@@ -548,70 +546,6 @@
put_user(current->cstime,&tbuf->tms_cstime);
}
return jiffies;
-}
-
-asmlinkage unsigned long sys_brk(unsigned long brk)
-{
- int freepages;
- unsigned long rlim;
- unsigned long newbrk, oldbrk;
-
- if (brk < current->mm->end_code)
- return current->mm->brk;
- newbrk = PAGE_ALIGN(brk);
- oldbrk = PAGE_ALIGN(current->mm->brk);
- if (oldbrk == newbrk)
- return current->mm->brk = brk;
-
- /*
- * Always allow shrinking brk
- */
- if (brk <= current->mm->brk) {
- current->mm->brk = brk;
- do_munmap(newbrk, oldbrk-newbrk);
- return brk;
- }
- /*
- * Check against rlimit and stack..
- */
- rlim = current->rlim[RLIMIT_DATA].rlim_cur;
- if (rlim >= RLIM_INFINITY)
- rlim = ~0;
- if (brk - current->mm->end_code > rlim)
- return current->mm->brk;
- /*
- * Check against existing mmap mappings.
- */
- if (find_vma_intersection(current, oldbrk, newbrk+PAGE_SIZE))
- return current->mm->brk;
- /*
- * stupid algorithm to decide if we have enough memory: while
- * simple, it hopefully works in most obvious cases.. Easy to
- * fool it, but this should catch most mistakes.
- */
- freepages = buffermem >> PAGE_SHIFT;
- freepages += page_cache_size;
- freepages >>= 1;
- freepages += nr_free_pages;
- freepages += nr_swap_pages;
- freepages -= MAP_NR(high_memory) >> 4;
- freepages -= (newbrk-oldbrk) >> PAGE_SHIFT;
- if (freepages < 0)
- return current->mm->brk;
-#if 0
- freepages += current->mm->rss;
- freepages -= oldbrk >> 12;
- if (freepages < 0)
- return current->mm->brk;
-#endif
- /*
- * Ok, we have probably got enough memory - let it rip.
- */
- current->mm->brk = brk;
- do_mmap(NULL, oldbrk, newbrk-oldbrk,
- PROT_READ|PROT_WRITE|PROT_EXEC,
- MAP_FIXED|MAP_PRIVATE, 0);
- return brk;
}

/*
diff -u --recursive --new-file pre2.0.12/linux/mm/mmap.c linux/mm/mmap.c
--- pre2.0.12/linux/mm/mmap.c Wed Jun 5 10:41:29 1996
+++ linux/mm/mmap.c Thu Jun 6 09:29:59 1996
@@ -12,6 +12,8 @@
#include <linux/mman.h>
#include <linux/string.h>
#include <linux/malloc.h>
+#include <linux/pagemap.h>
+#include <linux/swap.h>

#include <asm/segment.h>
#include <asm/system.h>
@@ -40,6 +42,78 @@
};

/*
+ * Check that a process has enough memory to allocate a
+ * new virtual mapping.
+ */
+static inline int vm_enough_memory(long pages)
+{
+ /*
+ * stupid algorithm to decide if we have enough memory: while
+ * simple, it hopefully works in most obvious cases.. Easy to
+ * fool it, but this should catch most mistakes.
+ */
+ long freepages;
+ freepages = buffermem >> PAGE_SHIFT;
+ freepages += page_cache_size;
+ freepages >>= 1;
+ freepages += nr_free_pages;
+ freepages += nr_swap_pages;
+ freepages -= MAP_NR(high_memory) >> 4;
+ return freepages > pages;
+}
+
+asmlinkage unsigned long sys_brk(unsigned long brk)
+{
+ unsigned long rlim;
+ unsigned long newbrk, oldbrk;
+
+ if (brk < current->mm->end_code)
+ return current->mm->brk;
+ newbrk = PAGE_ALIGN(brk);
+ oldbrk = PAGE_ALIGN(current->mm->brk);
+ if (oldbrk == newbrk)
+ return current->mm->brk = brk;
+
+ /*
+ * Always allow shrinking brk
+ */
+ if (brk <= current->mm->brk) {
+ current->mm->brk = brk;
+ do_munmap(newbrk, oldbrk-newbrk);
+ return brk;
+ }
+ /*
+ * Check against rlimit and stack..
+ */
+ rlim = current->rlim[RLIMIT_DATA].rlim_cur;
+ if (rlim >= RLIM_INFINITY)
+ rlim = ~0;
+ if (brk - current->mm->end_code > rlim)
+ return current->mm->brk;
+
+ /*
+ * Check against existing mmap mappings.
+ */
+ if (find_vma_intersection(current, oldbrk, newbrk+PAGE_SIZE))
+ return current->mm->brk;
+
+ /*
+ * Check if we have enough memory..
+ */
+ if (!vm_enough_memory((newbrk-oldbrk) >> PAGE_SHIFT))
+ return current->mm->brk;
+
+ /*
+ * Ok, looks good - let it rip.
+ */
+ current->mm->brk = brk;
+ do_mmap(NULL, oldbrk, newbrk-oldbrk,
+ PROT_READ|PROT_WRITE|PROT_EXEC,
+ MAP_FIXED|MAP_PRIVATE, 0);
+ return brk;
+}
+
+/*
* Combine the mmap "prot" and "flags" argument into one "vm_flags" used
* internally. Essentially, translate the "PROT_xxx" and "MAP_xxx" bits
* into "VM_xxx".
@@ -178,6 +252,14 @@
vma->vm_pte = 0;

do_munmap(addr, len); /* Clear old maps */
+
+ /* Private writable mapping? Check memory availability.. */
+ if ((vma->vm_flags & (VM_SHARED | VM_WRITE)) == VM_WRITE) {
+ if (!vm_enough_memory(len >> PAGE_SHIFT)) {
+ kfree(vma);
+ return -ENOMEM;
+ }
+ }

if (file) {
int error = file->f_op->mmap(file->f_inode, file, vma);
diff -u --recursive --new-file pre2.0.12/linux/mm/vmscan.c linux/mm/vmscan.c
--- pre2.0.12/linux/mm/vmscan.c Fri Apr 12 15:52:10 1996
+++ linux/mm/vmscan.c Wed Jun 5 14:36:35 1996
@@ -334,7 +334,12 @@
{
static int state = 0;
int i=6;
+ int stop;

+ /* we don't try as hard if we're not waiting.. */
+ stop = 3;
+ if (wait)
+ stop = 0;
switch (state) {
do {
case 0:
@@ -349,7 +354,8 @@
if (swap_out(i, dma, wait))
return 1;
state = 0;
- } while (i--);
+ i--;
+ } while ((i - stop) >= 0);
}
return 0;
}
------

\
 
 \ /
  Last update: 2005-03-22 13:37    [W:0.073 / U:0.748 seconds]
©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site