diff -Nur linux.old/fs/exec.c linux.new/fs/exec.c
--- linux.old/fs/exec.c	Fri Nov 15 17:39:34 2002
+++ linux.new/fs/exec.c	Fri Nov 15 17:44:51 2002
@@ -21,6 +21,8 @@
  * trying until we recognize the file or we run out of supported binary
  * formats. 
  */
+/* per process task_unmapped_base (C) 2002 Kasper Dupont <kasperd@daimi.au.dk>
+ */
 
 #include <linux/config.h>
 #include <linux/slab.h>
@@ -572,6 +574,29 @@
 	    permission(bprm->file->f_dentry->d_inode,MAY_READ))
 		current->mm->dumpable = 0;
 
+	/* FIXME FIXME FIXME! This is probably too late.
+	 * We need to use RLIM_INFINITY while setting up
+	 * the executable, but at that time dumpable is
+	 * not yet computed. We probably need to reorder
+	 * parts of the code.
+	 *
+	 * Perhaps I was wrong, perhaps this is actually
+	 * the right place to do all this. Somebody please
+	 * verify this. [KD]
+	 */
+	{
+	  int base=vm_task_unmapped_base;
+	  if (current->mm->dumpable) {
+	    base=current->rlim[RLIMIT_TUMB].rlim_cur;
+	    if (base==RLIM_INFINITY) base=vm_task_unmapped_base;
+	  } else {
+	    current->rlim[RLIMIT_TUMB].rlim_max=RLIM_INFINITY;
+	  }	
+	  current->rlim[RLIMIT_TUMB].rlim_cur=current->rlim[RLIMIT_TUMB].rlim_max;
+	  if ((base<1)||(base>TUMB_MAX)) base=TUMB_DEF;
+	  current->mm->task_unmapped_base=base<<PAGE_SHIFT;
+	}
+
 	/* An exec changes our domain. We are no longer part of the thread
 	   group */
 	   
diff -Nur linux.old/include/asm-i386/resource.h linux.new/include/asm-i386/resource.h
--- linux.old/include/asm-i386/resource.h	Fri Nov 15 17:39:35 2002
+++ linux.new/include/asm-i386/resource.h	Fri Nov 15 17:44:51 2002
@@ -16,8 +16,9 @@
 #define RLIMIT_MEMLOCK	8		/* max locked-in-memory address space */
 #define RLIMIT_AS	9		/* address space limit */
 #define RLIMIT_LOCKS	10		/* maximum file locks held */
+#define RLIMIT_TUMB     11		/* task_unmapped_base */
 
-#define RLIM_NLIMITS	11
+#define RLIM_NLIMITS	12
 
 /*
  * SuS says limits have to be unsigned.
@@ -40,6 +41,7 @@
 	{ RLIM_INFINITY, RLIM_INFINITY },		\
 	{ RLIM_INFINITY, RLIM_INFINITY },		\
         { RLIM_INFINITY, RLIM_INFINITY },		\
+        { RLIM_INFINITY, RLIM_INFINITY },		\
 }
 
 #endif /* __KERNEL__ */
diff -Nur linux.old/include/linux/mm.h linux.new/include/linux/mm.h
--- linux.old/include/linux/mm.h	Fri Nov 15 17:39:36 2002
+++ linux.new/include/linux/mm.h	Fri Nov 15 17:44:51 2002
@@ -116,6 +116,11 @@
 extern int vm_min_readahead;
 extern int vm_max_readahead;
 
+#define BYTE2PAGE(x) (((unsigned long)x)>>((unsigned long)PAGE_SHIFT))
+#define TUMB_MAX (BYTE2PAGE(PAGE_OFFSET)-3)
+#define TUMB_DEF (BYTE2PAGE(TASK_UNMAPPED_BASE))
+extern int vm_task_unmapped_base;
+
 /*
  * mapping from the currently active vm_flags protection bits (the
  * low four bits) to a page protection mask..
diff -Nur linux.old/include/linux/sched.h linux.new/include/linux/sched.h
--- linux.old/include/linux/sched.h	Fri Nov 15 17:39:42 2002
+++ linux.new/include/linux/sched.h	Fri Nov 15 17:44:51 2002
@@ -233,6 +233,8 @@
 
 	unsigned dumpable:1;
 
+        unsigned long task_unmapped_base;
+
 	/* Architecture-specific MM context */
 	mm_context_t context;
 };
diff -Nur linux.old/include/linux/sysctl.h linux.new/include/linux/sysctl.h
--- linux.old/include/linux/sysctl.h	Fri Nov 15 17:39:37 2002
+++ linux.new/include/linux/sysctl.h	Fri Nov 15 17:46:52 2002
@@ -143,6 +143,7 @@
 	VM_MAX_MAP_COUNT=11,	/* int: Maximum number of active map areas */
 	VM_MIN_READAHEAD=12,    /* Min file readahead */
 	VM_MAX_READAHEAD=13,    /* Max file readahead */
+	VM_TASK_UNMAPPED_BASE=14, /* task_unmapped_base */
 };
 
 
diff -Nur linux.old/kernel/sys.c linux.new/kernel/sys.c
--- linux.old/kernel/sys.c	Fri Nov 15 17:39:38 2002
+++ linux.new/kernel/sys.c	Fri Nov 15 17:44:51 2002
@@ -3,6 +3,8 @@
  *
  *  Copyright (C) 1991, 1992  Linus Torvalds
  */
+/* per process task_unmapped_base (C) 2002 Kasper Dupont <kasperd@daimi.au.dk>
+ */
 
 #include <linux/module.h>
 #include <linux/mm.h>
@@ -1112,6 +1114,8 @@
 
 #endif
 
+#define TUMB_INVAL(x) (((x<1)||(x>TUMB_MAX))&&(x!=RLIM_INFINITY))
+
 asmlinkage long sys_setrlimit(unsigned int resource, struct rlimit *rlim)
 {
 	struct rlimit new_rlim, *old_rlim;
@@ -1121,10 +1125,15 @@
 	if(copy_from_user(&new_rlim, rlim, sizeof(*rlim)))
 		return -EFAULT;
 	old_rlim = current->rlim + resource;
-	if (((new_rlim.rlim_cur > old_rlim->rlim_max) ||
-	     (new_rlim.rlim_max > old_rlim->rlim_max)) &&
-	    !capable(CAP_SYS_RESOURCE))
-		return -EPERM;
+	if (resource == RLIMIT_TUMB) {
+	  if (TUMB_INVAL(new_rlim.rlim_cur)||
+	      TUMB_INVAL(new_rlim.rlim_max)) return -EINVAL;
+	} else {
+	  if (((new_rlim.rlim_cur > old_rlim->rlim_max) ||
+	       (new_rlim.rlim_max > old_rlim->rlim_max)) &&
+	      !capable(CAP_SYS_RESOURCE))
+	          return -EPERM;
+	}
 	if (resource == RLIMIT_NOFILE) {
 		if (new_rlim.rlim_cur > NR_OPEN || new_rlim.rlim_max > NR_OPEN)
 			return -EPERM;
diff -Nur linux.old/kernel/sysctl.c linux.new/kernel/sysctl.c
--- linux.old/kernel/sysctl.c	Fri Nov 15 17:39:39 2002
+++ linux.new/kernel/sysctl.c	Fri Nov 15 17:44:51 2002
@@ -17,6 +17,8 @@
  * The list_for_each() macro wasn't appropriate for the sysctl loop.
  *  Removed it and replaced it with older style, 03/23/00, Bill Wendling
  */
+/* per process task_unmapped_base (C) 2002 Kasper Dupont <kasperd@daimi.au.dk>
+ */
 
 #include <linux/config.h>
 #include <linux/slab.h>
@@ -275,6 +277,8 @@
 	&vm_min_readahead,sizeof(int), 0644, NULL, &proc_dointvec},
 	{VM_MAX_READAHEAD, "max-readahead",
 	&vm_max_readahead,sizeof(int), 0644, NULL, &proc_dointvec},
+	{VM_TASK_UNMAPPED_BASE, "task_unmapped_base",
+	&vm_task_unmapped_base,sizeof(int), 0644, NULL, &proc_dointvec},
 	{VM_MAX_MAP_COUNT, "max_map_count",
 	 &max_map_count, sizeof(int), 0644, NULL, &proc_dointvec},
 	{0}
diff -Nur linux.old/mm/mmap.c linux.new/mm/mmap.c
--- linux.old/mm/mmap.c	Fri Nov 15 17:39:40 2002
+++ linux.new/mm/mmap.c	Fri Nov 15 17:44:51 2002
@@ -3,6 +3,8 @@
  *
  * Written by obz.
  */
+/* per process task_unmapped_base (C) 2002 Kasper Dupont <kasperd@daimi.au.dk>
+ */
 #include <linux/slab.h>
 #include <linux/shm.h>
 #include <linux/mman.h>
@@ -45,6 +47,8 @@
 };
 
 int sysctl_overcommit_memory;
+int vm_task_unmapped_base = TUMB_DEF;
+EXPORT_SYMBOL(vm_task_unmapped_base);
 int max_map_count = DEFAULT_MAX_MAP_COUNT;
 
 /* Check that a process has enough memory to allocate a
@@ -624,7 +628,7 @@
 		    (!vma || addr + len <= vma->vm_start))
 			return addr;
 	}
-	addr = PAGE_ALIGN(TASK_UNMAPPED_BASE);
+	addr = PAGE_ALIGN(current->mm->task_unmapped_base);
 
 	for (vma = find_vma(current->mm, addr); ; vma = vma->vm_next) {
 		/* At this point:  (!vma || addr < vma->vm_end). */
