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.
This commit is contained in:
Peter Wemm 2003-09-25 01:10:26 +00:00
parent 26824d8c47
commit c460ac3a00
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=120422
29 changed files with 123 additions and 104 deletions

View File

@ -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 = {

View File

@ -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_ */

View File

@ -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 = {

View File

@ -87,7 +87,8 @@ struct sysentvec osf1_sysvec = {
PS_STRINGS,
VM_PROT_ALL,
exec_copyout_strings,
exec_setregs
exec_setregs,
NULL
};
/*

View File

@ -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 = {

View File

@ -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_ */

View File

@ -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_ */

View File

@ -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;
}
}
}

View File

@ -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 */

View File

@ -114,7 +114,8 @@ static struct sysentvec pecoff_sysvec = {
PS_STRINGS,
VM_PROT_ALL,
exec_copyout_strings,
exec_setregs
exec_setregs,
NULL
};

View File

@ -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 = {

View File

@ -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 = {

View File

@ -83,7 +83,8 @@ struct sysentvec ibcs2_svr3_sysvec = {
PS_STRINGS,
VM_PROT_ALL,
exec_copyout_strings,
exec_setregs
exec_setregs,
NULL
};
static int

View File

@ -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_ */

View File

@ -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 = {

View File

@ -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 = {

View File

@ -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 = {

View File

@ -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 = {

View File

@ -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_ */

View File

@ -81,7 +81,8 @@ struct sysentvec aout_sysvec = {
PS_STRINGS,
VM_PROT_ALL,
exec_copyout_strings,
exec_setregs
exec_setregs,
NULL
};
static int

View File

@ -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;

View File

@ -284,6 +284,7 @@ struct sysentvec null_sysvec = {
PS_STRINGS,
VM_PROT_ALL,
NULL,
NULL,
NULL
};

View File

@ -841,6 +841,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

View File

@ -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_ */

View File

@ -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 = {

View File

@ -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_ */

View File

@ -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 = {

View File

@ -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

View File

@ -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 {