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 + */ #include #include @@ -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<>((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 + */ #include #include @@ -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 + */ #include #include @@ -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 + */ #include #include #include @@ -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). */