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:
parent
26824d8c47
commit
c460ac3a00
@ -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 = {
|
||||
|
@ -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_ */
|
||||
|
@ -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 = {
|
||||
|
@ -87,7 +87,8 @@ struct sysentvec osf1_sysvec = {
|
||||
PS_STRINGS,
|
||||
VM_PROT_ALL,
|
||||
exec_copyout_strings,
|
||||
exec_setregs
|
||||
exec_setregs,
|
||||
NULL
|
||||
};
|
||||
|
||||
/*
|
||||
|
@ -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 = {
|
||||
|
@ -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_ */
|
||||
|
@ -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_ */
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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 */
|
||||
|
@ -114,7 +114,8 @@ static struct sysentvec pecoff_sysvec = {
|
||||
PS_STRINGS,
|
||||
VM_PROT_ALL,
|
||||
exec_copyout_strings,
|
||||
exec_setregs
|
||||
exec_setregs,
|
||||
NULL
|
||||
|
||||
};
|
||||
|
||||
|
@ -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 = {
|
||||
|
@ -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 = {
|
||||
|
@ -83,7 +83,8 @@ struct sysentvec ibcs2_svr3_sysvec = {
|
||||
PS_STRINGS,
|
||||
VM_PROT_ALL,
|
||||
exec_copyout_strings,
|
||||
exec_setregs
|
||||
exec_setregs,
|
||||
NULL
|
||||
};
|
||||
|
||||
static int
|
||||
|
@ -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_ */
|
||||
|
@ -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 = {
|
||||
|
@ -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 = {
|
||||
|
@ -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 = {
|
||||
|
@ -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 = {
|
||||
|
@ -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_ */
|
||||
|
@ -81,7 +81,8 @@ struct sysentvec aout_sysvec = {
|
||||
PS_STRINGS,
|
||||
VM_PROT_ALL,
|
||||
exec_copyout_strings,
|
||||
exec_setregs
|
||||
exec_setregs,
|
||||
NULL
|
||||
};
|
||||
|
||||
static int
|
||||
|
@ -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;
|
||||
|
||||
|
@ -284,6 +284,7 @@ struct sysentvec null_sysvec = {
|
||||
PS_STRINGS,
|
||||
VM_PROT_ALL,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL
|
||||
};
|
||||
|
||||
|
@ -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
|
||||
|
@ -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_ */
|
||||
|
@ -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 = {
|
||||
|
@ -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_ */
|
||||
|
@ -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 = {
|
||||
|
@ -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
|
||||
|
@ -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 {
|
||||
|
Loading…
x
Reference in New Issue
Block a user