Changeset View
Changeset View
Standalone View
Standalone View
sys/kern/imgact_elf.c
Show First 20 Lines • Show All 726 Lines • ▼ Show 20 Lines | __CONCAT(exec_, __elfN(imgact))(struct image_params *imgp) | ||||
struct vmspace *vmspace; | struct vmspace *vmspace; | ||||
vm_prot_t prot; | vm_prot_t prot; | ||||
u_long text_size = 0, data_size = 0, total_size = 0; | u_long text_size = 0, data_size = 0, total_size = 0; | ||||
u_long text_addr = 0, data_addr = 0; | u_long text_addr = 0, data_addr = 0; | ||||
u_long seg_size, seg_addr; | u_long seg_size, seg_addr; | ||||
u_long addr, baddr, et_dyn_addr, entry = 0, proghdr = 0; | u_long addr, baddr, et_dyn_addr, entry = 0, proghdr = 0; | ||||
int32_t osrel = 0; | int32_t osrel = 0; | ||||
int error = 0, i, n, interp_name_len = 0; | int error = 0, i, n, interp_name_len = 0; | ||||
const char *interp = NULL, *newinterp = NULL; | const char *interp = NULL, *newinterp = NULL; | ||||
kib: Could you do a follow-up, after this patch is committed, to clear the declaration blocks in the… | |||||
Elf_Brandinfo *brand_info; | Elf_Brandinfo *brand_info; | ||||
char *path; | char *path; | ||||
struct sysentvec *sv; | struct sysentvec *sv; | ||||
/* | /* | ||||
* Do we have a valid ELF header ? | * Do we have a valid ELF header ? | ||||
* | * | ||||
* Only allow ET_EXEC & ET_DYN here, reject ET_DYN later | * Only allow ET_EXEC & ET_DYN here, reject ET_DYN later | ||||
* if particular brand doesn't support it. | * if particular brand doesn't support it. | ||||
*/ | */ | ||||
if (__elfN(check_header)(hdr) != 0 || | if (__elfN(check_header)(hdr) != 0 || | ||||
(hdr->e_type != ET_EXEC && hdr->e_type != ET_DYN)) | (hdr->e_type != ET_EXEC && hdr->e_type != ET_DYN)) | ||||
return (-1); | return (-1); | ||||
/* | /* | ||||
* From here on down, we return an errno, not -1, as we've | * From here on down, we return an errno, not -1, as we've | ||||
* detected an ELF file. | * detected an ELF file. | ||||
*/ | */ | ||||
if ((hdr->e_phoff > PAGE_SIZE) || | if ((hdr->e_phoff > PAGE_SIZE) || | ||||
(u_int)hdr->e_phentsize * hdr->e_phnum > PAGE_SIZE - hdr->e_phoff) { | (u_int)hdr->e_phentsize * hdr->e_phnum > PAGE_SIZE - hdr->e_phoff) { | ||||
/* Only support headers in first page for now */ | /* Only support headers in first page for now */ | ||||
return (ENOEXEC); | return (ENOEXEC); | ||||
Not Done Inline ActionsIt is program headerS, at least I saw this usage most of the time, I believe. kib: It is program headerS, at least I saw this usage most of the time, I believe. | |||||
} | } | ||||
phdr = (const Elf_Phdr *)(imgp->image_header + hdr->e_phoff); | phdr = (const Elf_Phdr *)(imgp->image_header + hdr->e_phoff); | ||||
if (!aligned(phdr, Elf_Addr)) | if (!aligned(phdr, Elf_Addr)) | ||||
return (ENOEXEC); | return (ENOEXEC); | ||||
n = 0; | n = 0; | ||||
baddr = 0; | baddr = 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; | ||||
n++; | n++; | ||||
break; | break; | ||||
case PT_INTERP: | case PT_INTERP: | ||||
/* Path to interpreter */ | /* Path to interpreter */ | ||||
if (phdr[i].p_filesz > MAXPATHLEN || | if (phdr[i].p_filesz > MAXPATHLEN || | ||||
phdr[i].p_offset > PAGE_SIZE || | phdr[i].p_offset > PAGE_SIZE || | ||||
phdr[i].p_filesz > PAGE_SIZE - phdr[i].p_offset) | phdr[i].p_filesz > PAGE_SIZE - phdr[i].p_offset) | ||||
return (ENOEXEC); | return (ENOEXEC); | ||||
Not Done Inline ActionsThis is not correct, I think. This is not about interpreter, but about interpreter header, pointing to the file name to use. Might be, 'Invalid PT_INTERP' is enough ? kib: This is not correct, I think. This is not about interpreter, but about interpreter header… | |||||
interp = imgp->image_header + phdr[i].p_offset; | interp = imgp->image_header + phdr[i].p_offset; | ||||
interp_name_len = phdr[i].p_filesz; | interp_name_len = phdr[i].p_filesz; | ||||
break; | break; | ||||
case PT_GNU_STACK: | case PT_GNU_STACK: | ||||
if (__elfN(nxstack)) | if (__elfN(nxstack)) | ||||
imgp->stack_prot = | imgp->stack_prot = | ||||
__elfN(trans_prot)(phdr[i].p_flags); | __elfN(trans_prot)(phdr[i].p_flags); | ||||
imgp->stack_sz = phdr[i].p_memsz; | imgp->stack_sz = phdr[i].p_memsz; | ||||
break; | break; | ||||
} | } | ||||
} | } | ||||
brand_info = __elfN(get_brandinfo)(imgp, interp, interp_name_len, | brand_info = __elfN(get_brandinfo)(imgp, interp, interp_name_len, | ||||
&osrel); | &osrel); | ||||
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]); | ||||
return (ENOEXEC); | return (ENOEXEC); | ||||
} | } | ||||
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) | ||||
return (ENOEXEC); | return (ENOEXEC); | ||||
Not Done Inline Actions'Cannot execute shared object' kib: 'Cannot execute shared object' | |||||
/* | /* | ||||
* 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) | ||||
et_dyn_addr = ET_DYN_LOAD_ADDR; | et_dyn_addr = ET_DYN_LOAD_ADDR; | ||||
else | else | ||||
et_dyn_addr = 0; | et_dyn_addr = 0; | ||||
▲ Show 20 Lines • Show All 88 Lines • ▼ Show 20 Lines | __CONCAT(exec_, __elfN(imgact))(struct image_params *imgp) | ||||
entry = (u_long)hdr->e_entry + et_dyn_addr; | entry = (u_long)hdr->e_entry + et_dyn_addr; | ||||
/* | /* | ||||
* Check limits. It should be safe to check the | * Check limits. It should be safe to check the | ||||
* limits after loading the segments since we do | * limits after loading the segments since we do | ||||
* not actually fault in all the segments pages. | * not actually fault in all the segments pages. | ||||
*/ | */ | ||||
PROC_LOCK(imgp->proc); | PROC_LOCK(imgp->proc); | ||||
if (data_size > lim_cur(imgp->proc, RLIMIT_DATA) || | if (data_size > lim_cur(imgp->proc, RLIMIT_DATA)) { | ||||
text_size > maxtsiz || | |||||
total_size > lim_cur(imgp->proc, RLIMIT_VMEM) || | |||||
racct_set(imgp->proc, RACCT_DATA, data_size) != 0 || | |||||
racct_set(imgp->proc, RACCT_VMEM, total_size) != 0) { | |||||
PROC_UNLOCK(imgp->proc); | PROC_UNLOCK(imgp->proc); | ||||
Not Done Inline ActionsI could also combine RLIMIT_DATA and RACCT_DATA into a single "Data segment size exceeds limit" and similar for _VMEM. Having distinct messages allows for finer-grained troubleshooting steps, but perhaps it's not necessary. emaste: I could also combine RLIMIT_DATA and RACCT_DATA into a single "Data segment size exceeds limit"… | |||||
uprintf("Data segment size exceeds process limit\n"); | |||||
return (ENOMEM); | |||||
} else if (text_size > maxtsiz) { | |||||
PROC_UNLOCK(imgp->proc); | |||||
uprintf("Text segment size exceeds system limit\n"); | |||||
return (ENOMEM); | |||||
} else if (total_size > lim_cur(imgp->proc, RLIMIT_VMEM)) { | |||||
PROC_UNLOCK(imgp->proc); | |||||
uprintf("Total segment size exceeds process limit\n"); | |||||
return (ENOMEM); | |||||
} else if (racct_set(imgp->proc, RACCT_DATA, data_size) != 0) { | |||||
PROC_UNLOCK(imgp->proc); | |||||
uprintf("Data segment size exceeds resource limit\n"); | |||||
return (ENOMEM); | |||||
} else if (racct_set(imgp->proc, RACCT_VMEM, total_size) != 0) { | |||||
PROC_UNLOCK(imgp->proc); | |||||
uprintf("Total segment size exceeds resource limit\n"); | |||||
return (ENOMEM); | return (ENOMEM); | ||||
} | } | ||||
vmspace = imgp->proc->p_vmspace; | 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; | ||||
▲ Show 20 Lines • Show All 1,247 Lines • Show Last 20 Lines |
Could you do a follow-up, after this patch is committed, to clear the declaration blocks in the imgact_elf.c ? Initializations should go into the code blocks; vars should be reordered, pointers first, primitive arithmetic types afterward.