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 /sys | |
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.
Diffstat (limited to 'sys')
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 { |