Changeset View
Standalone View
sys/kern/imgact_elf.c
Show First 20 Lines • Show All 132 Lines • ▼ Show 20 Lines | |||||
#if __ELF_WORD_SIZE == 32 | #if __ELF_WORD_SIZE == 32 | ||||
#if defined(__amd64__) | #if defined(__amd64__) | ||||
int i386_read_exec = 0; | int i386_read_exec = 0; | ||||
SYSCTL_INT(_kern_elf32, OID_AUTO, read_exec, CTLFLAG_RW, &i386_read_exec, 0, | SYSCTL_INT(_kern_elf32, OID_AUTO, read_exec, CTLFLAG_RW, &i386_read_exec, 0, | ||||
"enable execution from readable segments"); | "enable execution from readable segments"); | ||||
#endif | #endif | ||||
#endif | #endif | ||||
static int __elfN(aslr_enabled) = 1; | |||||
SYSCTL_INT(__CONCAT(_kern_elf, __ELF_WORD_SIZE), OID_AUTO, | |||||
emaste: "enable" is more common in the tree than "enabled" (27 to 3 on my laptop) and IMO preferable. | |||||
aslr_enabled, CTLFLAG_RWTUN, &__elfN(aslr_enabled), 0, | |||||
__XSTRING(__CONCAT(ELF, __ELF_WORD_SIZE)) | |||||
Not Done Inline ActionsThe current implementation is an ASR and not ASLR, please correct them and the word of ASLR is an acronym, so please convert them to upper case. op: The current implementation is an ASR and not ASLR, please correct them and the word of ASLR is… | |||||
Not Done Inline Actions
I'm not sure how to parse this statement.
No, by convention sysctl notes are lower case - e.g net.inet.tcp, not net.inet.TCP. On my system, of 3397 sysctls only 42 have upper case characters, and those are programmatically generated from existing names (e.g. kern.timecounter.tc.TSC-low.quality). emaste: > The current implementation is an ASR and not ASLR
I'm not sure how to parse this statement. | |||||
Not Done Inline Actions
Sigh, that should have been 'nodes' are lower case. The sysctl description here should indeed be a capitalized ASLR. emaste: > No, by convention sysctl notes are lower case
Sigh, that should have been 'nodes' are lower… | |||||
Not Done Inline Actionsthe acronym should probably be expanded; aslr_enabled with a description "enable alsr" doesn't provide any extra information. maybe "enable map address randomization"? emaste: the acronym should probably be expanded; aslr_enabled with a description "enable alsr" doesn't… | |||||
": enable address map randomization"); | |||||
static int __elfN(pie_aslr_enabled) = 1; | |||||
Not Done Inline ActionsIs there really a necessity for separately enabling ASR for the PIE execution base? I'm thinking that either ASR is on for the entire executable image or it's off. lattera-gmail.com: Is there really a necessity for separately enabling ASR for the PIE execution base? I'm… | |||||
Not Done Inline ActionsI don't follow what you mean by the "entire executable image." emaste: I don't follow what you mean by the "entire executable image." | |||||
SYSCTL_INT(__CONCAT(_kern_elf, __ELF_WORD_SIZE), OID_AUTO, | |||||
pie_aslr_enabled, CTLFLAG_RWTUN, &__elfN(pie_aslr_enabled), 0, | |||||
__XSTRING(__CONCAT(ELF, __ELF_WORD_SIZE)) | |||||
": enable address map randomization for PIE binaries"); | |||||
static int __elfN(aslr_honor_sbrk) = 0; | |||||
Not Done Inline Actionsaslr_care_sbrk seems strange. perhaps honor_sbrk? emaste: aslr_care_sbrk seems strange. perhaps honor_sbrk? | |||||
Not Done Inline ActionsI'm surprised that the default value for honor_sbrk is 0. The review description suggests that the default is intended to be 1. markj: I'm surprised that the default value for honor_sbrk is 0. The review description suggests that… | |||||
Done Inline ActionsI think at one time defaults were changed to be the most aggressive mode for testing. Also it was needed, AFAIR, to make the consumers happy which use whole 32bit address space, like pypy. Anyway, aslr will be disabled by default. kib: I think at one time defaults were changed to be the most aggressive mode for testing. Also it… | |||||
SYSCTL_INT(__CONCAT(_kern_elf, __ELF_WORD_SIZE), OID_AUTO, | |||||
aslr_honor_sbrk, CTLFLAG_RW, &__elfN(aslr_honor_sbrk), 0, | |||||
__XSTRING(__CONCAT(ELF, __ELF_WORD_SIZE)) ": assume sbrk is used"); | |||||
static Elf_Brandinfo *elf_brand_list[MAX_BRANDS]; | static Elf_Brandinfo *elf_brand_list[MAX_BRANDS]; | ||||
#define trunc_page_ps(va, ps) rounddown2(va, ps) | #define trunc_page_ps(va, ps) rounddown2(va, ps) | ||||
#define round_page_ps(va, ps) roundup2(va, ps) | #define round_page_ps(va, ps) roundup2(va, ps) | ||||
#define aligned(a, t) (trunc_page_ps((u_long)(a), sizeof(t)) == (u_long)(a)) | #define aligned(a, t) (trunc_page_ps((u_long)(a), sizeof(t)) == (u_long)(a)) | ||||
static const char FREEBSD_ABI_VENDOR[] = "FreeBSD"; | static const char FREEBSD_ABI_VENDOR[] = "FreeBSD"; | ||||
▲ Show 20 Lines • Show All 621 Lines • ▼ Show 20 Lines | fail: | ||||
if (nd->ni_vp) | if (nd->ni_vp) | ||||
vput(nd->ni_vp); | vput(nd->ni_vp); | ||||
free(tempdata, M_TEMP); | free(tempdata, M_TEMP); | ||||
return (error); | return (error); | ||||
} | } | ||||
static u_long | |||||
__CONCAT(rnd_, __elfN(base))(vm_map_t map __unused, u_long minv, u_long maxv, | |||||
u_int align) | |||||
{ | |||||
u_long rbase, res; | |||||
MPASS(vm_map_min(map) <= minv); | |||||
MPASS(maxv <= vm_map_max(map)); | |||||
MPASS(minv < maxv); | |||||
arc4rand(&rbase, sizeof(rbase), 0); | |||||
res = roundup(minv, (u_long)align) + rbase % (maxv - minv); | |||||
res &= ~((u_long)align - 1); | |||||
KASSERT(res >= minv, | |||||
("res %#lx < minv %#lx, maxv %#lx rbase %#lx", | |||||
res, minv, maxv, rbase)); | |||||
KASSERT(res < maxv, | |||||
("res %#lx > maxv %#lx, minv %#lx rbase %#lx", | |||||
res, maxv, minv, rbase)); | |||||
return (res); | |||||
} | |||||
/* | |||||
* Impossible et_dyn_addr initial value indicating that the real base | |||||
* must be calculated later with some randomization applied. | |||||
*/ | |||||
#define ET_DYN_ADDR_RAND 1 | |||||
static int | static int | ||||
__CONCAT(exec_, __elfN(imgact))(struct image_params *imgp) | __CONCAT(exec_, __elfN(imgact))(struct image_params *imgp) | ||||
{ | { | ||||
struct thread *td; | struct thread *td; | ||||
const Elf_Ehdr *hdr; | const Elf_Ehdr *hdr; | ||||
const Elf_Phdr *phdr; | const Elf_Phdr *phdr; | ||||
Elf_Auxargs *elf_auxargs; | Elf_Auxargs *elf_auxargs; | ||||
struct vmspace *vmspace; | struct vmspace *vmspace; | ||||
vm_map_t map; | |||||
const char *err_str, *newinterp; | const char *err_str, *newinterp; | ||||
char *interp, *interp_buf, *path; | char *interp, *interp_buf, *path; | ||||
Elf_Brandinfo *brand_info; | Elf_Brandinfo *brand_info; | ||||
struct sysentvec *sv; | struct sysentvec *sv; | ||||
vm_prot_t prot; | vm_prot_t prot; | ||||
u_long text_size, data_size, total_size, text_addr, data_addr; | u_long text_size, data_size, total_size, text_addr, data_addr; | ||||
u_long seg_size, seg_addr, addr, baddr, et_dyn_addr, entry, proghdr; | u_long seg_size, seg_addr, addr, baddr, et_dyn_addr, entry, proghdr; | ||||
u_long maxalign, mapsz, maxv, maxv1; | |||||
uint32_t fctl0; | uint32_t fctl0; | ||||
int32_t osrel; | int32_t osrel; | ||||
int error, i, n, interp_name_len, have_interp; | int error, i, n, interp_name_len, have_interp; | ||||
hdr = (const Elf_Ehdr *)imgp->image_header; | hdr = (const Elf_Ehdr *)imgp->image_header; | ||||
/* | /* | ||||
* Do we have a valid ELF header ? | * Do we have a valid ELF header ? | ||||
Show All 27 Lines | __CONCAT(exec_, __elfN(imgact))(struct image_params *imgp) | ||||
osrel = 0; | osrel = 0; | ||||
fctl0 = 0; | fctl0 = 0; | ||||
text_size = data_size = total_size = text_addr = data_addr = 0; | text_size = data_size = total_size = text_addr = data_addr = 0; | ||||
entry = proghdr = 0; | entry = proghdr = 0; | ||||
interp_name_len = 0; | interp_name_len = 0; | ||||
err_str = newinterp = NULL; | err_str = newinterp = NULL; | ||||
interp = interp_buf = NULL; | interp = interp_buf = NULL; | ||||
td = curthread; | td = curthread; | ||||
maxalign = PAGE_SIZE; | |||||
mapsz = 0; | |||||
for (i = 0; i < hdr->e_phnum; i++) { | for (i = 0; i < hdr->e_phnum; i++) { | ||||
switch (phdr[i].p_type) { | switch (phdr[i].p_type) { | ||||
case PT_LOAD: | case PT_LOAD: | ||||
if (n == 0) | if (n == 0) | ||||
baddr = phdr[i].p_vaddr; | baddr = phdr[i].p_vaddr; | ||||
if (phdr[i].p_align > maxalign) | |||||
maxalign = phdr[i].p_align; | |||||
mapsz += phdr[i].p_memsz; | |||||
n++; | n++; | ||||
break; | break; | ||||
case PT_INTERP: | case PT_INTERP: | ||||
/* Path to interpreter */ | /* Path to interpreter */ | ||||
if (phdr[i].p_filesz < 2 || | if (phdr[i].p_filesz < 2 || | ||||
phdr[i].p_filesz > MAXPATHLEN) { | phdr[i].p_filesz > MAXPATHLEN) { | ||||
uprintf("Invalid PT_INTERP\n"); | uprintf("Invalid PT_INTERP\n"); | ||||
error = ENOEXEC; | error = ENOEXEC; | ||||
▲ Show 20 Lines • Show All 44 Lines • ▼ Show 20 Lines | __CONCAT(exec_, __elfN(imgact))(struct image_params *imgp) | ||||
brand_info = __elfN(get_brandinfo)(imgp, interp, interp_name_len, | brand_info = __elfN(get_brandinfo)(imgp, interp, interp_name_len, | ||||
&osrel, &fctl0); | &osrel, &fctl0); | ||||
if (brand_info == NULL) { | if (brand_info == NULL) { | ||||
uprintf("ELF binary type \"%u\" not known.\n", | uprintf("ELF binary type \"%u\" not known.\n", | ||||
hdr->e_ident[EI_OSABI]); | hdr->e_ident[EI_OSABI]); | ||||
error = ENOEXEC; | error = ENOEXEC; | ||||
goto ret; | goto ret; | ||||
} | } | ||||
sv = brand_info->sysvec; | |||||
et_dyn_addr = 0; | et_dyn_addr = 0; | ||||
Not Done Inline ActionsOne of the reservations FreeBSD had about HardenedBSD's patch was that it was setting this particular variable multiple times. I guess that's not a concern anymore? lattera-gmail.com: One of the reservations FreeBSD had about HardenedBSD's patch was that it was setting this… | |||||
Not Done Inline ActionsThe comment was about minimizing diffs, not about setting the variable multiple times per se. I suspect the comment in D473 was motivated by the size of that review, based on a desire to minimize the scale of changes in order to ease the review. That said, this change and and other non-functional changes in this review could be committed separately too. emaste: The comment was about minimizing diffs, not about setting the variable multiple times per se. I… | |||||
if (hdr->e_type == ET_DYN) { | if (hdr->e_type == ET_DYN) { | ||||
if ((brand_info->flags & BI_CAN_EXEC_DYN) == 0) { | if ((brand_info->flags & BI_CAN_EXEC_DYN) == 0) { | ||||
uprintf("Cannot execute shared object\n"); | uprintf("Cannot execute shared object\n"); | ||||
error = ENOEXEC; | error = ENOEXEC; | ||||
goto ret; | goto ret; | ||||
} | } | ||||
/* | /* | ||||
* Honour the base load address from the dso if it is | * Honour the base load address from the dso if it is | ||||
* non-zero for some reason. | * non-zero for some reason. | ||||
*/ | */ | ||||
if (baddr == 0) | if (baddr == 0) { | ||||
if ((sv->sv_flags & SV_ASLR) == 0 || | |||||
(fctl0 & NT_FREEBSD_FCTL_NO_ASLR) != 0) | |||||
et_dyn_addr = ET_DYN_LOAD_ADDR; | et_dyn_addr = ET_DYN_LOAD_ADDR; | ||||
else if ((__elfN(pie_aslr_enabled) && | |||||
(imgp->proc->p_flag2 & P2_ASLR_DISABLE) == 0) || | |||||
(imgp->proc->p_flag2 & P2_ASLR_ENABLE) != 0) | |||||
et_dyn_addr = ET_DYN_ADDR_RAND; | |||||
else | |||||
et_dyn_addr = ET_DYN_LOAD_ADDR; | |||||
} | } | ||||
sv = brand_info->sysvec; | } | ||||
if (interp != NULL && brand_info->interp_newpath != NULL) | if (interp != NULL && brand_info->interp_newpath != NULL) | ||||
newinterp = brand_info->interp_newpath; | newinterp = brand_info->interp_newpath; | ||||
/* | /* | ||||
* Avoid a possible deadlock if the current address space is destroyed | * Avoid a possible deadlock if the current address space is destroyed | ||||
* and that address space maps the locked vnode. In the common case, | * and that address space maps the locked vnode. In the common case, | ||||
Not Done Inline ActionsThis changes the underlying meaning of the et_dyn_addr variable. Though I don't object to it, I just thought it is worth the note. The author of later modifications to this code will need to keep that in mind. Maybe a comment in the code would be a good idea? lattera-gmail.com: This changes the underlying meaning of the et_dyn_addr variable. Though I don't object to it, I… | |||||
Not Done Inline ActionsCould you please use a defined name here instead of a raw value? For example #define ET_DYN_LOAD_RAND_ADDR or something similar? op: Could you please use a defined name here instead of a raw value?
For example #define… | |||||
Not Done Inline ActionsI agree with avoiding an uncommented magic number. emaste: I agree with avoiding an uncommented magic number. | |||||
Not Done Inline ActionsCan you #define or at least comment this 1 emaste: Can you `#define` or at least comment this 1 | |||||
* the locked vnode's v_usecount is decremented but remains greater | * the locked vnode's v_usecount is decremented but remains greater | ||||
* than zero. Consequently, the vnode lock is not needed by vrele(). | * than zero. Consequently, the vnode lock is not needed by vrele(). | ||||
* However, in cases where the vnode lock is external, such as nullfs, | * However, in cases where the vnode lock is external, such as nullfs, | ||||
* v_usecount may become zero. | * v_usecount may become zero. | ||||
* | * | ||||
* The VV_TEXT flag prevents modifications to the executable while | * The VV_TEXT flag prevents modifications to the executable while | ||||
* the vnode is unlocked. | * the vnode is unlocked. | ||||
*/ | */ | ||||
VOP_UNLOCK(imgp->vp, 0); | VOP_UNLOCK(imgp->vp, 0); | ||||
/* | |||||
* Decide to enable randomization of user mappings. First, | |||||
Done Inline Actions"Decide whether to" markj: "Decide whether to" | |||||
* reset user preferences for the setid binaries. Then, | |||||
* account for the support of the randomization by the ABI, by | |||||
* user preferences, and make special treatment for PIE | |||||
* binaries. | |||||
*/ | |||||
if (imgp->credential_setid) { | |||||
PROC_LOCK(imgp->proc); | |||||
imgp->proc->p_flag2 &= ~(P2_ASLR_ENABLE | P2_ASLR_DISABLE); | |||||
PROC_UNLOCK(imgp->proc); | |||||
} | |||||
if ((sv->sv_flags & SV_ASLR) == 0 || | |||||
(imgp->proc->p_flag2 & P2_ASLR_DISABLE) != 0 || | |||||
(fctl0 & NT_FREEBSD_FCTL_NO_ASLR) != 0) { | |||||
KASSERT(et_dyn_addr != ET_DYN_ADDR_RAND, | |||||
("et_dyn_addr == RAND and !ASLR")); | |||||
} else if ((imgp->proc->p_flag2 & P2_ASLR_ENABLE) != 0 || | |||||
(__elfN(aslr_enabled) && hdr->e_type == ET_EXEC) || | |||||
et_dyn_addr == ET_DYN_ADDR_RAND) { | |||||
imgp->map_flags |= MAP_ASLR; | |||||
/* | |||||
* If user does not care about sbrk, utilize the bss | |||||
* grow region for mappings as well. We can select | |||||
* the base for the image anywere and still not suffer | |||||
* from the fragmentation. | |||||
*/ | |||||
if (!__elfN(aslr_honor_sbrk) || | |||||
(imgp->proc->p_flag2 & P2_ASLR_IGNSTART) != 0) | |||||
imgp->map_flags |= MAP_ASLR_IGNSTART; | |||||
} | |||||
error = exec_new_vmspace(imgp, sv); | error = exec_new_vmspace(imgp, sv); | ||||
vmspace = imgp->proc->p_vmspace; | |||||
map = &vmspace->vm_map; | |||||
imgp->proc->p_sysent = sv; | imgp->proc->p_sysent = sv; | ||||
maxv = vm_map_max(map) - lim_max(td, RLIMIT_STACK); | |||||
if (et_dyn_addr == ET_DYN_ADDR_RAND) { | |||||
KASSERT((map->flags & MAP_ASLR) != 0, | |||||
("ET_DYN_ADDR_RAND but !MAP_ASLR")); | |||||
et_dyn_addr = __CONCAT(rnd_, __elfN(base))(map, | |||||
vm_map_min(map) + mapsz + lim_max(td, RLIMIT_DATA), | |||||
/* reserve half of the address space to interpreter */ | |||||
maxv / 2, 1UL << flsl(maxalign)); | |||||
} | |||||
vn_lock(imgp->vp, LK_EXCLUSIVE | LK_RETRY); | vn_lock(imgp->vp, LK_EXCLUSIVE | LK_RETRY); | ||||
if (error != 0) | if (error != 0) | ||||
goto ret; | goto ret; | ||||
for (i = 0; i < hdr->e_phnum; i++) { | for (i = 0; i < hdr->e_phnum; i++) { | ||||
switch (phdr[i].p_type) { | switch (phdr[i].p_type) { | ||||
case PT_LOAD: /* Loadable segment */ | case PT_LOAD: /* Loadable segment */ | ||||
if (phdr[i].p_memsz == 0) | if (phdr[i].p_memsz == 0) | ||||
break; | break; | ||||
prot = __elfN(trans_prot)(phdr[i].p_flags); | prot = __elfN(trans_prot)(phdr[i].p_flags); | ||||
error = __elfN(load_section)(imgp, phdr[i].p_offset, | error = __elfN(load_section)(imgp, phdr[i].p_offset, | ||||
(caddr_t)(uintptr_t)phdr[i].p_vaddr + et_dyn_addr, | (caddr_t)(uintptr_t)phdr[i].p_vaddr + et_dyn_addr, | ||||
phdr[i].p_memsz, phdr[i].p_filesz, prot, | phdr[i].p_memsz, phdr[i].p_filesz, prot, | ||||
sv->sv_pagesize); | sv->sv_pagesize); | ||||
if (error != 0) | if (error != 0) | ||||
Not Done Inline ActionsWhy you need two arc4random() call on 64 bit systems? This is the arc4random()'s implementation: uint32_t arc4random(void) { uint32_t ret; arc4rand(&ret, sizeof ret, 0); return ret; } Just change this two call to simple one: arc4rand(&rbase, sizeof(rbase), 0) or arc4rand(&rbase, __ELF_WORD_SIZE / NBBY, 0) op: Why you need two arc4random() call on 64 bit systems?
This is the arc4random()'s… | |||||
goto ret; | goto ret; | ||||
/* | /* | ||||
* If this segment contains the program headers, | * If this segment contains the program headers, | ||||
* remember their virtual address for the AT_PHDR | * remember their virtual address for the AT_PHDR | ||||
* aux entry. Static binaries don't usually include | * aux entry. Static binaries don't usually include | ||||
* a PT_PHDR entry. | * a PT_PHDR entry. | ||||
Not Done Inline ActionsMoving exec_new_vmspace() after imgp->proc->p_sysent = sv breaks the Linuxulator; see PR222800 emaste: Moving `exec_new_vmspace()` after `imgp->proc->p_sysent = sv` breaks the Linuxulator; see… | |||||
*/ | */ | ||||
if (phdr[i].p_offset == 0 && | if (phdr[i].p_offset == 0 && | ||||
hdr->e_phoff + hdr->e_phnum * hdr->e_phentsize | hdr->e_phoff + hdr->e_phnum * hdr->e_phentsize | ||||
<= phdr[i].p_filesz) | <= phdr[i].p_filesz) | ||||
proghdr = phdr[i].p_vaddr + hdr->e_phoff + | proghdr = phdr[i].p_vaddr + hdr->e_phoff + | ||||
et_dyn_addr; | et_dyn_addr; | ||||
Not Done Inline ActionsThe assertion description would be clearer if this said ET_DYN_ADDR_RAND instead of et_dyn_addr. jmallett: The assertion description would be clearer if this said ET_DYN_ADDR_RAND instead of et_dyn_addr. | |||||
seg_addr = trunc_page(phdr[i].p_vaddr + et_dyn_addr); | seg_addr = trunc_page(phdr[i].p_vaddr + et_dyn_addr); | ||||
seg_size = round_page(phdr[i].p_memsz + | seg_size = round_page(phdr[i].p_memsz + | ||||
phdr[i].p_vaddr + et_dyn_addr - seg_addr); | phdr[i].p_vaddr + et_dyn_addr - seg_addr); | ||||
/* | /* | ||||
* Make the largest executable segment the official | * Make the largest executable segment the official | ||||
* text segment and all others data. | * text segment and all others data. | ||||
▲ Show 20 Lines • Show All 47 Lines • ▼ Show 20 Lines | else if (racct_set(imgp->proc, RACCT_VMEM, total_size) != 0) | ||||
err_str = "Total segment size exceeds resource limit"; | err_str = "Total segment size exceeds resource limit"; | ||||
if (err_str != NULL) { | if (err_str != NULL) { | ||||
PROC_UNLOCK(imgp->proc); | PROC_UNLOCK(imgp->proc); | ||||
uprintf("%s\n", err_str); | uprintf("%s\n", err_str); | ||||
error = ENOMEM; | error = ENOMEM; | ||||
goto ret; | goto ret; | ||||
} | } | ||||
vmspace = imgp->proc->p_vmspace; | |||||
vmspace->vm_tsize = text_size >> PAGE_SHIFT; | vmspace->vm_tsize = text_size >> PAGE_SHIFT; | ||||
vmspace->vm_taddr = (caddr_t)(uintptr_t)text_addr; | vmspace->vm_taddr = (caddr_t)(uintptr_t)text_addr; | ||||
vmspace->vm_dsize = data_size >> PAGE_SHIFT; | vmspace->vm_dsize = data_size >> PAGE_SHIFT; | ||||
vmspace->vm_daddr = (caddr_t)(uintptr_t)data_addr; | vmspace->vm_daddr = (caddr_t)(uintptr_t)data_addr; | ||||
/* | /* | ||||
* We load the dynamic linker where a userland call | * We load the dynamic linker where a userland call | ||||
* to mmap(0, ...) would put it. The rationale behind this | * to mmap(0, ...) would put it. The rationale behind this | ||||
* calculation is that it leaves room for the heap to grow to | * calculation is that it leaves room for the heap to grow to | ||||
* its maximum allowed size. | * its maximum allowed size. | ||||
*/ | */ | ||||
addr = round_page((vm_offset_t)vmspace->vm_daddr + lim_max(td, | addr = round_page((vm_offset_t)vmspace->vm_daddr + lim_max(td, | ||||
RLIMIT_DATA)); | RLIMIT_DATA)); | ||||
if ((map->flags & MAP_ASLR) != 0) { | |||||
maxv1 = (maxv + addr) / 2; | |||||
if (maxv1 <= addr) /* Fix overflow */ | |||||
maxv1 = maxv; | |||||
map->anon_loc = __CONCAT(rnd_, __elfN(base))(map, addr, maxv1, | |||||
MAXPAGESIZES > 1 ? pagesizes[1] : pagesizes[0]); | |||||
} else { | |||||
map->anon_loc = addr; | |||||
} | |||||
PROC_UNLOCK(imgp->proc); | PROC_UNLOCK(imgp->proc); | ||||
imgp->entry_addr = entry; | imgp->entry_addr = entry; | ||||
if (interp != NULL) { | if (interp != NULL) { | ||||
have_interp = FALSE; | have_interp = FALSE; | ||||
VOP_UNLOCK(imgp->vp, 0); | VOP_UNLOCK(imgp->vp, 0); | ||||
if ((map->flags & MAP_ASLR) != 0) { | |||||
/* Assume that interpeter fits into 1/4 of AS */ | |||||
maxv1 = (maxv + addr) / 2; | |||||
if (maxv1 <= addr) /* Fix overflow */ | |||||
maxv1 = maxv; | |||||
addr = __CONCAT(rnd_, __elfN(base))(map, addr, | |||||
maxv1, PAGE_SIZE); | |||||
} | |||||
if (brand_info->emul_path != NULL && | if (brand_info->emul_path != NULL && | ||||
brand_info->emul_path[0] != '\0') { | brand_info->emul_path[0] != '\0') { | ||||
path = malloc(MAXPATHLEN, M_TEMP, M_WAITOK); | path = malloc(MAXPATHLEN, M_TEMP, M_WAITOK); | ||||
snprintf(path, MAXPATHLEN, "%s%s", | snprintf(path, MAXPATHLEN, "%s%s", | ||||
brand_info->emul_path, interp); | brand_info->emul_path, interp); | ||||
error = __elfN(load_file)(imgp->proc, path, &addr, | error = __elfN(load_file)(imgp->proc, path, &addr, | ||||
&imgp->entry_addr, sv->sv_pagesize); | &imgp->entry_addr, sv->sv_pagesize); | ||||
free(path, M_TEMP); | free(path, M_TEMP); | ||||
▲ Show 20 Lines • Show All 1,488 Lines • Show Last 20 Lines |
"enable" is more common in the tree than "enabled" (27 to 3 on my laptop) and IMO preferable.
Also, should we have a kern.elfN.aslr.* tree? So e.g. kern.elf64.aslr.enable, perhaps kern.elf64.aslr.pie_enable?