diff options
author | peter <peter@FreeBSD.org> | 2003-09-25 01:10:26 +0000 |
---|---|---|
committer | peter <peter@FreeBSD.org> | 2003-09-25 01:10:26 +0000 |
commit | 8ecb3577d83113cde0885b76799ccebb323abf8b (patch) | |
tree | f89d7e04e53ed33050987a5b51945ab490d9ba4d | |
parent | 100e3b7635a597fd1f017e000172234099e518e9 (diff) | |
download | FreeBSD-src-8ecb3577d83113cde0885b76799ccebb323abf8b.zip FreeBSD-src-8ecb3577d83113cde0885b76799ccebb323abf8b.tar.gz |
Add sysentvec->sv_fixlimits() hook so that we can catch cases on 64 bit
systems where the data/stack/etc limits are too big for a 32 bit process.
Move the 5 or so identical instances of ELF_RTLD_ADDR() into imgact_elf.c.
Supply an ia32_fixlimits function. Export the clip/default values to
sysctl under the compat.ia32 heirarchy.
Have mmap(0, ...) respect the current p->p_limits[RLIMIT_DATA].rlim_max
value rather than the sysctl tweakable variable. This allows mmap to
place mappings at sensible locations when limits have been reduced.
Have the imgact_elf.c ld-elf.so.1 placement algorithm use the same
method as mmap(0, ...) now does.
Note that we cannot remove all references to the sysctl tweakable
maxdsiz etc variables because /etc/login.conf specifies a datasize
of 'unlimited'. And that causes exec etc to fail since it can no
longer find space to mmap things.
29 files changed, 123 insertions, 104 deletions
diff --git a/sys/alpha/alpha/elf_machdep.c b/sys/alpha/alpha/elf_machdep.c index ae9d55e..c76f4d91 100644 --- a/sys/alpha/alpha/elf_machdep.c +++ b/sys/alpha/alpha/elf_machdep.c @@ -73,7 +73,8 @@ struct sysentvec elf64_freebsd_sysvec = { PS_STRINGS, VM_PROT_ALL, exec_copyout_strings, - exec_setregs + exec_setregs, + NULL }; static Elf64_Brandinfo freebsd_brand_info = { diff --git a/sys/alpha/include/elf.h b/sys/alpha/include/elf.h index f606ada..a0fb706 100644 --- a/sys/alpha/include/elf.h +++ b/sys/alpha/include/elf.h @@ -135,16 +135,4 @@ __ElfType(Auxinfo); #define ELF_TARG_MACH EM_ALPHA #define ELF_TARG_VER 1 -#ifdef _KERNEL - -/* - * On the Alpha we load the dynamic linker where a userland call - * to mmap(0, ...) would put it. The rationale behind this - * calculation is that it leaves room for the heap to grow to - * its maximum allowed size. - */ -#define ELF_RTLD_ADDR(vmspace) \ - (round_page((vm_offset_t)(vmspace)->vm_daddr + maxdsiz)) - -#endif #endif /* !_MACHINE_ELF_H_ */ diff --git a/sys/alpha/linux/linux_sysvec.c b/sys/alpha/linux/linux_sysvec.c index 278014b..09cbadd 100644 --- a/sys/alpha/linux/linux_sysvec.c +++ b/sys/alpha/linux/linux_sysvec.c @@ -200,7 +200,8 @@ struct sysentvec elf_linux_sysvec = { PS_STRINGS, VM_PROT_ALL, exec_copyout_strings, - exec_setregs + exec_setregs, + NULL }; static Elf64_Brandinfo linux_brand = { diff --git a/sys/alpha/osf1/osf1_sysvec.c b/sys/alpha/osf1/osf1_sysvec.c index d11ceb6..0dea307 100644 --- a/sys/alpha/osf1/osf1_sysvec.c +++ b/sys/alpha/osf1/osf1_sysvec.c @@ -87,7 +87,8 @@ struct sysentvec osf1_sysvec = { PS_STRINGS, VM_PROT_ALL, exec_copyout_strings, - exec_setregs + exec_setregs, + NULL }; /* diff --git a/sys/amd64/amd64/elf_machdep.c b/sys/amd64/amd64/elf_machdep.c index 3d2e73c..0d80b42 100644 --- a/sys/amd64/amd64/elf_machdep.c +++ b/sys/amd64/amd64/elf_machdep.c @@ -70,7 +70,8 @@ struct sysentvec elf64_freebsd_sysvec = { PS_STRINGS, VM_PROT_ALL, exec_copyout_strings, - exec_setregs + exec_setregs, + NULL }; static Elf64_Brandinfo freebsd_brand_info = { diff --git a/sys/amd64/include/elf.h b/sys/amd64/include/elf.h index b675859..c1a88696 100644 --- a/sys/amd64/include/elf.h +++ b/sys/amd64/include/elf.h @@ -137,16 +137,4 @@ __ElfType(Auxinfo); #define ELF_TARG_MACH EM_X86_64 #define ELF_TARG_VER 1 -#ifdef _KERNEL - -/* - * On the i386 we load the dynamic linker where a userland call - * to mmap(0, ...) would put it. The rationale behind this - * calculation is that it leaves room for the heap to grow to - * its maximum allowed size. - */ -#define ELF_RTLD_ADDR(vmspace) \ - (round_page((vm_offset_t)(vmspace)->vm_daddr + maxdsiz)) - -#endif /* _KERNEL */ #endif /* !_MACHINE_ELF_H_ */ diff --git a/sys/arm/include/elf.h b/sys/arm/include/elf.h index 07cd0a6..8425ab1 100644 --- a/sys/arm/include/elf.h +++ b/sys/arm/include/elf.h @@ -91,16 +91,4 @@ #define ELF_TARG_MACH EM_ARM #define ELF_TARG_VER 1 -#ifdef _KERNEL - -/* - * On the StrongARM we load the dynamic linker where a userland call - * to mmap(0, ...) would put it. The rationale behind this - * calculation is that it leaves room for the heap to grow to - * its maximum allowed size. - */ -#define ELF_RTLD_ADDR(vmspace) \ - (round_page((vm_offset_t)(vmspace)->vm_daddr + maxdsiz)) - -#endif /* _KERNEL */ #endif /* !_MACHINE_ELF_H_ */ diff --git a/sys/compat/ia32/ia32_sysvec.c b/sys/compat/ia32/ia32_sysvec.c index 5efb4d8..bbaa56a 100644 --- a/sys/compat/ia32/ia32_sysvec.c +++ b/sys/compat/ia32/ia32_sysvec.c @@ -78,9 +78,12 @@ __FBSDID("$FreeBSD$"); static register_t *ia32_copyout_strings(struct image_params *imgp); static void ia32_setregs(struct thread *td, u_long entry, u_long stack, u_long ps_strings); +static void ia32_fixlimits(struct image_params *imgp); extern struct sysent freebsd32_sysent[]; +SYSCTL_NODE(_compat, OID_AUTO, ia32, CTLFLAG_RW, 0, "ia32 mode"); + struct sysentvec ia32_freebsd_sysvec = { SYS_MAXSYSCALL, freebsd32_sysent, @@ -106,7 +109,8 @@ struct sysentvec ia32_freebsd_sysvec = { FREEBSD32_PS_STRINGS, VM_PROT_ALL, ia32_copyout_strings, - ia32_setregs + ia32_setregs, + ia32_fixlimits }; @@ -283,3 +287,62 @@ ia32_setregs(td, entry, stack, ps_strings) pcb->pcb_flags |= PCB_FULLCTX; td->td_retval[1] = 0; } + +static u_long ia32_maxdsiz = IA32_MAXDSIZ; +SYSCTL_ULONG(_compat_ia32, OID_AUTO, maxdsiz, CTLFLAG_RW, &ia32_maxdsiz, 0, ""); +static u_long ia32_maxssiz = IA32_MAXSSIZ; +SYSCTL_ULONG(_compat_ia32, OID_AUTO, maxssiz, CTLFLAG_RW, &ia32_maxssiz, 0, ""); +static u_long ia32_maxvmem = IA32_MAXVMEM; +SYSCTL_ULONG(_compat_ia32, OID_AUTO, maxvmem, CTLFLAG_RW, &ia32_maxvmem, 0, ""); + +static void +ia32_fixlimits(struct image_params *imgp) +{ + struct proc *p = imgp->proc; + + if (ia32_maxdsiz != 0) { + if (p->p_rlimit[RLIMIT_DATA].rlim_cur > ia32_maxdsiz || + p->p_rlimit[RLIMIT_DATA].rlim_max > ia32_maxdsiz) { + if (p->p_limit->p_refcnt > 1) { + p->p_limit->p_refcnt--; + p->p_limit = limcopy(p->p_limit); + } + if (p->p_rlimit[RLIMIT_DATA].rlim_cur > ia32_maxdsiz) + p->p_rlimit[RLIMIT_DATA].rlim_cur = + ia32_maxdsiz; + if (p->p_rlimit[RLIMIT_DATA].rlim_max > ia32_maxdsiz) + p->p_rlimit[RLIMIT_DATA].rlim_max = + ia32_maxdsiz; + } + } + if (ia32_maxssiz != 0) { + if (p->p_rlimit[RLIMIT_STACK].rlim_cur > ia32_maxssiz || + p->p_rlimit[RLIMIT_STACK].rlim_max > ia32_maxssiz) { + if (p->p_limit->p_refcnt > 1) { + p->p_limit->p_refcnt--; + p->p_limit = limcopy(p->p_limit); + } + if (p->p_rlimit[RLIMIT_STACK].rlim_cur > ia32_maxssiz) + p->p_rlimit[RLIMIT_STACK].rlim_cur = + ia32_maxssiz; + if (p->p_rlimit[RLIMIT_STACK].rlim_max > ia32_maxssiz) + p->p_rlimit[RLIMIT_STACK].rlim_max = + ia32_maxssiz; + } + } + if (ia32_maxvmem != 0) { + if (p->p_rlimit[RLIMIT_VMEM].rlim_cur > ia32_maxvmem || + p->p_rlimit[RLIMIT_VMEM].rlim_max > ia32_maxvmem) { + if (p->p_limit->p_refcnt > 1) { + p->p_limit->p_refcnt--; + p->p_limit = limcopy(p->p_limit); + } + if (p->p_rlimit[RLIMIT_VMEM].rlim_cur > ia32_maxvmem) + p->p_rlimit[RLIMIT_VMEM].rlim_cur = + ia32_maxvmem; + if (p->p_rlimit[RLIMIT_VMEM].rlim_max > ia32_maxvmem) + p->p_rlimit[RLIMIT_VMEM].rlim_max = + ia32_maxvmem; + } + } +} diff --git a/sys/compat/ia32/ia32_util.h b/sys/compat/ia32/ia32_util.h index 06f78cf..f6de375 100644 --- a/sys/compat/ia32/ia32_util.h +++ b/sys/compat/ia32/ia32_util.h @@ -38,3 +38,7 @@ #include <sys/cdefs.h> #define FREEBSD32_USRSTACK ((1ul << 32) - PAGE_SIZE) + +#define IA32_MAXDSIZ (512*1024*1024) /* 512MB */ +#define IA32_MAXSSIZ (64*1024*1024) /* 64MB */ +#define IA32_MAXVMEM 0 /* Unlimited */ diff --git a/sys/compat/pecoff/imgact_pecoff.c b/sys/compat/pecoff/imgact_pecoff.c index 34e8e1c..1049d39 100644 --- a/sys/compat/pecoff/imgact_pecoff.c +++ b/sys/compat/pecoff/imgact_pecoff.c @@ -114,7 +114,8 @@ static struct sysentvec pecoff_sysvec = { PS_STRINGS, VM_PROT_ALL, exec_copyout_strings, - exec_setregs + exec_setregs, + NULL }; diff --git a/sys/compat/svr4/svr4_sysvec.c b/sys/compat/svr4/svr4_sysvec.c index 125f460..c488da2 100644 --- a/sys/compat/svr4/svr4_sysvec.c +++ b/sys/compat/svr4/svr4_sysvec.c @@ -189,7 +189,8 @@ struct sysentvec svr4_sysvec = { PS_STRINGS, VM_PROT_ALL, exec_copyout_strings, - exec_setregs + exec_setregs, + NULL }; Elf32_Brandinfo svr4_brand = { diff --git a/sys/i386/i386/elf_machdep.c b/sys/i386/i386/elf_machdep.c index 4d4b6d2..48cb238 100644 --- a/sys/i386/i386/elf_machdep.c +++ b/sys/i386/i386/elf_machdep.c @@ -70,7 +70,8 @@ struct sysentvec elf32_freebsd_sysvec = { PS_STRINGS, VM_PROT_ALL, exec_copyout_strings, - exec_setregs + exec_setregs, + NULL }; static Elf32_Brandinfo freebsd_brand_info = { diff --git a/sys/i386/ibcs2/ibcs2_sysvec.c b/sys/i386/ibcs2/ibcs2_sysvec.c index c08e9ef..af5015d 100644 --- a/sys/i386/ibcs2/ibcs2_sysvec.c +++ b/sys/i386/ibcs2/ibcs2_sysvec.c @@ -83,7 +83,8 @@ struct sysentvec ibcs2_svr3_sysvec = { PS_STRINGS, VM_PROT_ALL, exec_copyout_strings, - exec_setregs + exec_setregs, + NULL }; static int diff --git a/sys/i386/include/elf.h b/sys/i386/include/elf.h index c9ec741..4bf341d 100644 --- a/sys/i386/include/elf.h +++ b/sys/i386/include/elf.h @@ -131,16 +131,4 @@ __ElfType(Auxinfo); #define ELF_TARG_MACH EM_386 #define ELF_TARG_VER 1 -#ifdef _KERNEL - -/* - * On the i386 we load the dynamic linker where a userland call - * to mmap(0, ...) would put it. The rationale behind this - * calculation is that it leaves room for the heap to grow to - * its maximum allowed size. - */ -#define ELF_RTLD_ADDR(vmspace) \ - (round_page((vm_offset_t)(vmspace)->vm_daddr + maxdsiz)) - -#endif /* _KERNEL */ #endif /* !_MACHINE_ELF_H_ */ diff --git a/sys/i386/linux/linux_sysvec.c b/sys/i386/linux/linux_sysvec.c index 0e92296..fc57c1f 100644 --- a/sys/i386/linux/linux_sysvec.c +++ b/sys/i386/linux/linux_sysvec.c @@ -860,7 +860,8 @@ struct sysentvec linux_sysvec = { PS_STRINGS, VM_PROT_ALL, exec_copyout_strings, - exec_linux_setregs + exec_linux_setregs, + NULL }; struct sysentvec elf_linux_sysvec = { @@ -888,7 +889,8 @@ struct sysentvec elf_linux_sysvec = { PS_STRINGS, VM_PROT_ALL, exec_copyout_strings, - exec_linux_setregs + exec_linux_setregs, + NULL }; static Elf32_Brandinfo linux_brand = { diff --git a/sys/ia64/ia32/ia32_signal.c b/sys/ia64/ia32/ia32_signal.c index 3871aa2..cadd38e 100644 --- a/sys/ia64/ia32/ia32_signal.c +++ b/sys/ia64/ia32/ia32_signal.c @@ -115,7 +115,8 @@ struct sysentvec ia32_freebsd_sysvec = { IA32_PS_STRINGS, VM_PROT_ALL, ia32_copyout_strings, - ia32_setregs + ia32_setregs, + NULL }; static Elf32_Brandinfo ia32_brand_info = { diff --git a/sys/ia64/ia32/ia32_sysvec.c b/sys/ia64/ia32/ia32_sysvec.c index 3871aa2..cadd38e 100644 --- a/sys/ia64/ia32/ia32_sysvec.c +++ b/sys/ia64/ia32/ia32_sysvec.c @@ -115,7 +115,8 @@ struct sysentvec ia32_freebsd_sysvec = { IA32_PS_STRINGS, VM_PROT_ALL, ia32_copyout_strings, - ia32_setregs + ia32_setregs, + NULL }; static Elf32_Brandinfo ia32_brand_info = { diff --git a/sys/ia64/ia64/elf_machdep.c b/sys/ia64/ia64/elf_machdep.c index b7d87ce..a637113 100644 --- a/sys/ia64/ia64/elf_machdep.c +++ b/sys/ia64/ia64/elf_machdep.c @@ -76,7 +76,8 @@ struct sysentvec elf64_freebsd_sysvec = { PS_STRINGS, VM_PROT_ALL, exec_copyout_strings, - exec_setregs + exec_setregs, + NULL }; static Elf64_Brandinfo freebsd_brand_info = { diff --git a/sys/ia64/include/elf.h b/sys/ia64/include/elf.h index 0146394..6babea9 100644 --- a/sys/ia64/include/elf.h +++ b/sys/ia64/include/elf.h @@ -235,16 +235,4 @@ __ElfType(Auxinfo); #define DT_IA64_PLT_RESERVE 0x70000000 -#ifdef _KERNEL - -/* - * On the ia64 we load the dynamic linker where a userland call - * to mmap(0, ...) would put it. The rationale behind this - * calculation is that it leaves room for the heap to grow to - * its maximum allowed size. - */ -#define ELF_RTLD_ADDR(vmspace) \ - (round_page((vm_offset_t)(vmspace)->vm_daddr + maxdsiz)) - -#endif /* _KERNEL */ #endif /* !_MACHINE_ELF_H_ */ diff --git a/sys/kern/imgact_aout.c b/sys/kern/imgact_aout.c index 37e9fe2..4cb7b63 100644 --- a/sys/kern/imgact_aout.c +++ b/sys/kern/imgact_aout.c @@ -81,7 +81,8 @@ struct sysentvec aout_sysvec = { PS_STRINGS, VM_PROT_ALL, exec_copyout_strings, - exec_setregs + exec_setregs, + NULL }; static int diff --git a/sys/kern/imgact_elf.c b/sys/kern/imgact_elf.c index 349078b..330437a 100644 --- a/sys/kern/imgact_elf.c +++ b/sys/kern/imgact_elf.c @@ -806,7 +806,14 @@ __CONCAT(exec_, __elfN(imgact))(struct image_params *imgp) vmspace->vm_dsize = data_size >> PAGE_SHIFT; vmspace->vm_daddr = (caddr_t)(uintptr_t)data_addr; - addr = ELF_RTLD_ADDR(vmspace); + /* + * We load the dynamic linker where a userland call + * to mmap(0, ...) would put it. The rationale behind this + * calculation is that it leaves room for the heap to grow to + * its maximum allowed size. + */ + addr = round_page((vm_offset_t)imgp->proc->p_vmspace->vm_daddr + + imgp->proc->p_rlimit[RLIMIT_DATA].rlim_max); imgp->entry_addr = entry; diff --git a/sys/kern/init_main.c b/sys/kern/init_main.c index d006522..bff07b1 100644 --- a/sys/kern/init_main.c +++ b/sys/kern/init_main.c @@ -284,6 +284,7 @@ struct sysentvec null_sysvec = { PS_STRINGS, VM_PROT_ALL, NULL, + NULL, NULL }; diff --git a/sys/kern/kern_exec.c b/sys/kern/kern_exec.c index 8ff2dda..5b0d44f 100644 --- a/sys/kern/kern_exec.c +++ b/sys/kern/kern_exec.c @@ -842,6 +842,15 @@ exec_new_vmspace(imgp, sv) EVENTHANDLER_INVOKE(process_exec, p); /* + * Here is as good a place as any to do any resource limit cleanups. + * This is needed if a 64 bit binary exec's a 32 bit binary - the + * data size limit may need to be changed to a value that makes + * sense for the 32 bit binary. + */ + if (sv->sv_fixlimits) + sv->sv_fixlimits(imgp); + + /* * Blow away entire process VM, if address space not shared, * otherwise, create a new VM space so that other threads are * not disrupted diff --git a/sys/powerpc/include/elf.h b/sys/powerpc/include/elf.h index 01248f0..7fc1b36 100644 --- a/sys/powerpc/include/elf.h +++ b/sys/powerpc/include/elf.h @@ -158,16 +158,4 @@ __ElfType(Auxinfo); #define ELF_TARG_MACH EM_PPC #define ELF_TARG_VER 1 -#ifdef _KERNEL - -/* - * On the PowerPC we load the dynamic linker where a userland call - * to mmap(0, ...) would put it. The rationale behind this - * calculation is that it leaves room for the heap to grow to - * its maximum allowed size. - */ -#define ELF_RTLD_ADDR(vmspace) \ - (round_page((vm_offset_t)(vmspace)->vm_daddr + maxdsiz)) - -#endif /* _KERNEL */ #endif /* !_MACHINE_ELF_H_ */ diff --git a/sys/powerpc/powerpc/elf_machdep.c b/sys/powerpc/powerpc/elf_machdep.c index 72b6a55..eab70db 100644 --- a/sys/powerpc/powerpc/elf_machdep.c +++ b/sys/powerpc/powerpc/elf_machdep.c @@ -72,7 +72,8 @@ struct sysentvec elf32_freebsd_sysvec = { PS_STRINGS, VM_PROT_ALL, exec_copyout_strings, - exec_setregs + exec_setregs, + NULL }; static Elf32_Brandinfo freebsd_brand_info = { diff --git a/sys/sparc64/include/elf.h b/sys/sparc64/include/elf.h index 5532bc9..d4f1824 100644 --- a/sys/sparc64/include/elf.h +++ b/sys/sparc64/include/elf.h @@ -171,16 +171,4 @@ __ElfType(Auxinfo); #define ELF_TARG_MACH ELF_ARCH #define ELF_TARG_VER 1 -#ifdef _KERNEL - -/* - * On the Sparc64 we load the dynamic linker where a userland call - * to mmap(0, ...) would put it. The rationale behind this - * calculation is that it leaves room for the heap to grow to - * its maximum allowed size. - */ -#define ELF_RTLD_ADDR(vmspace) \ - (round_page((vm_offset_t)(vmspace)->vm_daddr + maxdsiz)) - -#endif /* _KERNEL */ #endif /* !_MACHINE_ELF_H_ */ diff --git a/sys/sparc64/sparc64/elf_machdep.c b/sys/sparc64/sparc64/elf_machdep.c index b848dbf..bb2c185 100644 --- a/sys/sparc64/sparc64/elf_machdep.c +++ b/sys/sparc64/sparc64/elf_machdep.c @@ -83,7 +83,8 @@ struct sysentvec elf64_freebsd_sysvec = { PS_STRINGS, VM_PROT_READ | VM_PROT_WRITE, exec_copyout_strings, - exec_setregs + exec_setregs, + NULL }; static Elf64_Brandinfo freebsd_brand_info = { diff --git a/sys/sys/sysent.h b/sys/sys/sysent.h index 7206c6f..950df69 100644 --- a/sys/sys/sysent.h +++ b/sys/sys/sysent.h @@ -84,6 +84,7 @@ struct sysentvec { int sv_stackprot; /* vm protection for stack */ register_t *(*sv_copyout_strings)(struct image_params *); void (*sv_setregs)(struct thread *, u_long, u_long, u_long); + void (*sv_fixlimits)(struct image_params *); }; #ifdef _KERNEL diff --git a/sys/vm/vm_mmap.c b/sys/vm/vm_mmap.c index d38a631..933e580 100644 --- a/sys/vm/vm_mmap.c +++ b/sys/vm/vm_mmap.c @@ -277,8 +277,10 @@ mmap(td, uap) */ else if (addr == 0 || (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); + addr < round_page((vm_offset_t)vms->vm_daddr + + td->td_proc->p_rlimit[RLIMIT_DATA].rlim_max))) + addr = round_page((vm_offset_t)vms->vm_daddr + + td->td_proc->p_rlimit[RLIMIT_DATA].rlim_max); mtx_lock(&Giant); /* syscall marked mp-safe but isn't */ do { |