Avoid two suword() calls per auxarg entry.
Instead, construct an auxargs array and copy it out all at once. Use an array of Elf_Auxinfo rather than pairs of Elf_Addr * to represent the array. This is the correct type where pairs of words just happend to work. To reduce the size of the diff, AUXARGS_ENTRY is altered to act on this array rather than introducing a new macro. Return errors on copyout() and suword() failures and handle them in the caller. Incidentally fixes AT_RANDOM and AT_EXECFN in 32-bit linux on amd64 which incorrectly used AUXARG_ENTRY instead of AUXARGS_ENTRY_32 (now removed due to the use of proper types). Reviewed by: kib Comments from: emaste, jhb Obtained from: CheriBSD Sponsored by: DARPA, AFRL Differential Revision: https://reviews.freebsd.org/D15485
This commit is contained in:
parent
b50b5555ef
commit
5f77b8a88b
@ -240,11 +240,11 @@ static int
|
||||
linux_fixup_elf(register_t **stack_base, struct image_params *imgp)
|
||||
{
|
||||
Elf_Auxargs *args;
|
||||
Elf_Addr *base;
|
||||
Elf_Addr *pos;
|
||||
Elf_Auxinfo *argarray, *pos;
|
||||
Elf_Addr *auxbase, *base;
|
||||
struct ps_strings *arginfo;
|
||||
struct proc *p;
|
||||
int issetugid;
|
||||
int error, issetugid;
|
||||
|
||||
p = imgp->proc;
|
||||
arginfo = (struct ps_strings *)p->p_sysent->sv_psstrings;
|
||||
@ -253,7 +253,9 @@ linux_fixup_elf(register_t **stack_base, struct image_params *imgp)
|
||||
("unsafe linux_fixup_elf(), should be curproc"));
|
||||
base = (Elf64_Addr *)*stack_base;
|
||||
args = (Elf64_Auxargs *)imgp->auxargs;
|
||||
pos = base + (imgp->args->argc + imgp->args->envc + 2);
|
||||
auxbase = base + imgp->args->argc + 1 + imgp->args->envc + 1;
|
||||
argarray = pos = malloc(LINUX_AT_COUNT * sizeof(*pos), M_TEMP,
|
||||
M_WAITOK | M_ZERO);
|
||||
|
||||
issetugid = p->p_flag & P_SUGID ? 1 : 0;
|
||||
AUXARGS_ENTRY(pos, LINUX_AT_SYSINFO_EHDR,
|
||||
@ -281,9 +283,17 @@ linux_fixup_elf(register_t **stack_base, struct image_params *imgp)
|
||||
AUXARGS_ENTRY(pos, AT_NULL, 0);
|
||||
free(imgp->auxargs, M_TEMP);
|
||||
imgp->auxargs = NULL;
|
||||
KASSERT((pos - argarray) / sizeof(*pos) <= LINUX_AT_COUNT,
|
||||
("Too many auxargs"));
|
||||
|
||||
error = copyout(argarray, auxbase, sizeof(*argarray) * LINUX_AT_COUNT);
|
||||
free(argarray, M_TEMP);
|
||||
if (error != 0)
|
||||
return (error);
|
||||
|
||||
base--;
|
||||
suword(base, (uint64_t)imgp->args->argc);
|
||||
if (suword(base, (uint64_t)imgp->args->argc) == -1)
|
||||
return (EFAULT);
|
||||
|
||||
*stack_base = (register_t *)base;
|
||||
return (0);
|
||||
|
@ -89,12 +89,6 @@ __FBSDID("$FreeBSD$");
|
||||
|
||||
MODULE_VERSION(linux, 1);
|
||||
|
||||
#define AUXARGS_ENTRY_32(pos, id, val) \
|
||||
do { \
|
||||
suword32(pos++, id); \
|
||||
suword32(pos++, val); \
|
||||
} while (0)
|
||||
|
||||
/*
|
||||
* Allow the sendsig functions to use the ldebug() facility even though they
|
||||
* are not syscalls themselves. Map them to syscall 0. This is slightly less
|
||||
@ -202,10 +196,10 @@ static int
|
||||
linux_fixup_elf(register_t **stack_base, struct image_params *imgp)
|
||||
{
|
||||
Elf32_Auxargs *args;
|
||||
Elf32_Addr *base;
|
||||
Elf32_Addr *pos;
|
||||
Elf32_Auxinfo *argarray, *pos;
|
||||
Elf32_Addr *auxbase, *base;
|
||||
struct linux32_ps_strings *arginfo;
|
||||
int issetugid;
|
||||
int error, issetugid;
|
||||
|
||||
arginfo = (struct linux32_ps_strings *)LINUX32_PS_STRINGS;
|
||||
|
||||
@ -213,13 +207,15 @@ linux_fixup_elf(register_t **stack_base, struct image_params *imgp)
|
||||
("unsafe linux_fixup_elf(), should be curproc"));
|
||||
base = (Elf32_Addr *)*stack_base;
|
||||
args = (Elf32_Auxargs *)imgp->auxargs;
|
||||
pos = base + (imgp->args->argc + imgp->args->envc + 2);
|
||||
auxbase = base + (imgp->args->argc + 1 + imgp->args->envc + 1);
|
||||
argarray = pos = malloc(LINUX_AT_COUNT * sizeof(*pos), M_TEMP,
|
||||
M_WAITOK | M_ZERO);
|
||||
|
||||
issetugid = imgp->proc->p_flag & P_SUGID ? 1 : 0;
|
||||
AUXARGS_ENTRY_32(pos, LINUX_AT_SYSINFO_EHDR,
|
||||
AUXARGS_ENTRY(pos, LINUX_AT_SYSINFO_EHDR,
|
||||
imgp->proc->p_sysent->sv_shared_page_base);
|
||||
AUXARGS_ENTRY_32(pos, LINUX_AT_SYSINFO, linux32_vsyscall);
|
||||
AUXARGS_ENTRY_32(pos, LINUX_AT_HWCAP, cpu_feature);
|
||||
AUXARGS_ENTRY(pos, LINUX_AT_SYSINFO, linux32_vsyscall);
|
||||
AUXARGS_ENTRY(pos, LINUX_AT_HWCAP, cpu_feature);
|
||||
|
||||
/*
|
||||
* Do not export AT_CLKTCK when emulating Linux kernel prior to 2.4.0,
|
||||
@ -230,32 +226,40 @@ linux_fixup_elf(register_t **stack_base, struct image_params *imgp)
|
||||
* Also see linux_times() implementation.
|
||||
*/
|
||||
if (linux_kernver(curthread) >= LINUX_KERNVER_2004000)
|
||||
AUXARGS_ENTRY_32(pos, LINUX_AT_CLKTCK, stclohz);
|
||||
AUXARGS_ENTRY_32(pos, AT_PHDR, args->phdr);
|
||||
AUXARGS_ENTRY_32(pos, AT_PHENT, args->phent);
|
||||
AUXARGS_ENTRY_32(pos, AT_PHNUM, args->phnum);
|
||||
AUXARGS_ENTRY_32(pos, AT_PAGESZ, args->pagesz);
|
||||
AUXARGS_ENTRY_32(pos, AT_FLAGS, args->flags);
|
||||
AUXARGS_ENTRY_32(pos, AT_ENTRY, args->entry);
|
||||
AUXARGS_ENTRY_32(pos, AT_BASE, args->base);
|
||||
AUXARGS_ENTRY_32(pos, LINUX_AT_SECURE, issetugid);
|
||||
AUXARGS_ENTRY_32(pos, AT_UID, imgp->proc->p_ucred->cr_ruid);
|
||||
AUXARGS_ENTRY_32(pos, AT_EUID, imgp->proc->p_ucred->cr_svuid);
|
||||
AUXARGS_ENTRY_32(pos, AT_GID, imgp->proc->p_ucred->cr_rgid);
|
||||
AUXARGS_ENTRY_32(pos, AT_EGID, imgp->proc->p_ucred->cr_svgid);
|
||||
AUXARGS_ENTRY_32(pos, LINUX_AT_PLATFORM, PTROUT(linux_platform));
|
||||
AUXARGS_ENTRY(pos, LINUX_AT_CLKTCK, stclohz);
|
||||
AUXARGS_ENTRY(pos, AT_PHDR, args->phdr);
|
||||
AUXARGS_ENTRY(pos, AT_PHENT, args->phent);
|
||||
AUXARGS_ENTRY(pos, AT_PHNUM, args->phnum);
|
||||
AUXARGS_ENTRY(pos, AT_PAGESZ, args->pagesz);
|
||||
AUXARGS_ENTRY(pos, AT_FLAGS, args->flags);
|
||||
AUXARGS_ENTRY(pos, AT_ENTRY, args->entry);
|
||||
AUXARGS_ENTRY(pos, AT_BASE, args->base);
|
||||
AUXARGS_ENTRY(pos, LINUX_AT_SECURE, issetugid);
|
||||
AUXARGS_ENTRY(pos, AT_UID, imgp->proc->p_ucred->cr_ruid);
|
||||
AUXARGS_ENTRY(pos, AT_EUID, imgp->proc->p_ucred->cr_svuid);
|
||||
AUXARGS_ENTRY(pos, AT_GID, imgp->proc->p_ucred->cr_rgid);
|
||||
AUXARGS_ENTRY(pos, AT_EGID, imgp->proc->p_ucred->cr_svgid);
|
||||
AUXARGS_ENTRY(pos, LINUX_AT_PLATFORM, PTROUT(linux_platform));
|
||||
AUXARGS_ENTRY(pos, LINUX_AT_RANDOM, PTROUT(imgp->canary));
|
||||
if (imgp->execpathp != 0)
|
||||
AUXARGS_ENTRY(pos, LINUX_AT_EXECFN, PTROUT(imgp->execpathp));
|
||||
if (args->execfd != -1)
|
||||
AUXARGS_ENTRY_32(pos, AT_EXECFD, args->execfd);
|
||||
AUXARGS_ENTRY_32(pos, AT_NULL, 0);
|
||||
AUXARGS_ENTRY(pos, AT_EXECFD, args->execfd);
|
||||
AUXARGS_ENTRY(pos, AT_NULL, 0);
|
||||
|
||||
free(imgp->auxargs, M_TEMP);
|
||||
imgp->auxargs = NULL;
|
||||
KASSERT((pos - argarray) / sizeof(*pos) <= AT_COUNT,
|
||||
("Too many auxargs"));
|
||||
|
||||
error = copyout(&argarray[0], auxbase, sizeof(*argarray) * AT_COUNT);
|
||||
free(argarray, M_TEMP);
|
||||
if (error != 0)
|
||||
return (error);
|
||||
|
||||
base--;
|
||||
suword32(base, (uint32_t)imgp->args->argc);
|
||||
if (suword32(base, (uint32_t)imgp->args->argc) == -1)
|
||||
return (EFAULT);
|
||||
*stack_base = (register_t *)base;
|
||||
return (0);
|
||||
}
|
||||
|
@ -207,10 +207,10 @@ linux_fixup_elf(register_t **stack_base, struct image_params *imgp)
|
||||
{
|
||||
struct proc *p;
|
||||
Elf32_Auxargs *args;
|
||||
Elf32_Addr *uplatform;
|
||||
Elf32_Auxinfo *argarray, *pos;
|
||||
Elf32_Addr *auxbase, *uplatform;
|
||||
struct ps_strings *arginfo;
|
||||
register_t *pos;
|
||||
int issetugid;
|
||||
int error, issetugid;
|
||||
|
||||
KASSERT(curthread->td_proc == imgp->proc,
|
||||
("unsafe linux_fixup_elf(), should be curproc"));
|
||||
@ -220,7 +220,9 @@ linux_fixup_elf(register_t **stack_base, struct image_params *imgp)
|
||||
arginfo = (struct ps_strings *)p->p_sysent->sv_psstrings;
|
||||
uplatform = (Elf32_Addr *)((caddr_t)arginfo - linux_szplatform);
|
||||
args = (Elf32_Auxargs *)imgp->auxargs;
|
||||
pos = *stack_base + (imgp->args->argc + imgp->args->envc + 2);
|
||||
auxbase = *stack_base + imgp->args->argc + 1 + imgp->args->envc + 1;
|
||||
argarray = pos = malloc(LINUX_AT_COUNT * sizeof(*pos), M_TEMP,
|
||||
M_WAITOK | M_ZERO);
|
||||
|
||||
AUXARGS_ENTRY(pos, LINUX_AT_SYSINFO_EHDR,
|
||||
imgp->proc->p_sysent->sv_shared_page_base);
|
||||
@ -259,9 +261,17 @@ linux_fixup_elf(register_t **stack_base, struct image_params *imgp)
|
||||
|
||||
free(imgp->auxargs, M_TEMP);
|
||||
imgp->auxargs = NULL;
|
||||
KASSERT((pos - argarray) / sizeof(*pos) <= LINUX_AT_COUNT,
|
||||
("Too many auxargs"));
|
||||
|
||||
error = copyout(argarray, auxbase, sizeof(*argarray) * LINUX_AT_COUNT);
|
||||
free(argarray, M_TEMP);
|
||||
if (error != 0)
|
||||
return (error);
|
||||
|
||||
(*stack_base)--;
|
||||
suword(*stack_base, (register_t)imgp->args->argc);
|
||||
if (suword(*stack_base, (register_t)imgp->args->argc) == -1)
|
||||
return (EFAULT);
|
||||
return (0);
|
||||
}
|
||||
|
||||
|
@ -1098,11 +1098,14 @@ int
|
||||
__elfN(freebsd_fixup)(register_t **stack_base, struct image_params *imgp)
|
||||
{
|
||||
Elf_Auxargs *args = (Elf_Auxargs *)imgp->auxargs;
|
||||
Elf_Addr *base;
|
||||
Elf_Addr *pos;
|
||||
Elf_Auxinfo *argarray, *pos;
|
||||
Elf_Addr *base, *auxbase;
|
||||
int error;
|
||||
|
||||
base = (Elf_Addr *)*stack_base;
|
||||
pos = base + (imgp->args->argc + imgp->args->envc + 2);
|
||||
auxbase = base + imgp->args->argc + 1 + imgp->args->envc + 1;
|
||||
argarray = pos = malloc(AT_COUNT * sizeof(*pos), M_TEMP,
|
||||
M_WAITOK | M_ZERO);
|
||||
|
||||
if (args->execfd != -1)
|
||||
AUXARGS_ENTRY(pos, AT_EXECFD, args->execfd);
|
||||
@ -1142,9 +1145,17 @@ __elfN(freebsd_fixup)(register_t **stack_base, struct image_params *imgp)
|
||||
|
||||
free(imgp->auxargs, M_TEMP);
|
||||
imgp->auxargs = NULL;
|
||||
KASSERT((pos - argarray) / sizeof(*pos) <= AT_COUNT,
|
||||
("Too many auxargs"));
|
||||
|
||||
error = copyout(argarray, auxbase, sizeof(*argarray) * AT_COUNT);
|
||||
free(argarray, M_TEMP);
|
||||
if (error != 0)
|
||||
return (error);
|
||||
|
||||
base--;
|
||||
suword(base, (long)imgp->args->argc);
|
||||
if (suword(base, imgp->args->argc) == -1)
|
||||
return (EFAULT);
|
||||
*stack_base = (register_t *)base;
|
||||
return (0);
|
||||
}
|
||||
|
@ -691,9 +691,12 @@ interpret:
|
||||
* Else stuff argument count as first item on stack
|
||||
*/
|
||||
if (p->p_sysent->sv_fixup != NULL)
|
||||
(*p->p_sysent->sv_fixup)(&stack_base, imgp);
|
||||
error = (*p->p_sysent->sv_fixup)(&stack_base, imgp);
|
||||
else
|
||||
suword(--stack_base, imgp->args->argc);
|
||||
error = suword(--stack_base, imgp->args->argc) == 0 ?
|
||||
0 : EFAULT;
|
||||
if (error != 0)
|
||||
goto exec_fail_dealloc;
|
||||
|
||||
if (args->fdp != NULL) {
|
||||
/* Install a brand new file descriptor table. */
|
||||
|
@ -37,7 +37,8 @@
|
||||
|
||||
#ifdef _KERNEL
|
||||
|
||||
#define AUXARGS_ENTRY(pos, id, val) {suword(pos++, id); suword(pos++, val);}
|
||||
#define AUXARGS_ENTRY(pos, id, val) \
|
||||
{(pos)->a_type = (id); (pos)->a_un.a_val = (val); (pos)++;}
|
||||
|
||||
struct image_params;
|
||||
struct thread;
|
||||
|
Loading…
x
Reference in New Issue
Block a user