Changeset View
Changeset View
Standalone View
Standalone View
sys/arm64/linux/linux_sysvec.c
Show First 20 Lines • Show All 63 Lines • ▼ Show 20 Lines | |||||
static char *linux_shared_page_mapping; | static char *linux_shared_page_mapping; | ||||
extern char _binary_linux_locore_o_start; | extern char _binary_linux_locore_o_start; | ||||
extern char _binary_linux_locore_o_end; | extern char _binary_linux_locore_o_end; | ||||
extern struct sysent linux_sysent[LINUX_SYS_MAXSYSCALL]; | extern struct sysent linux_sysent[LINUX_SYS_MAXSYSCALL]; | ||||
SET_DECLARE(linux_ioctl_handler_set, struct linux_ioctl_handler); | SET_DECLARE(linux_ioctl_handler_set, struct linux_ioctl_handler); | ||||
static register_t *linux_copyout_strings(struct image_params *imgp); | static int linux_copyout_strings(struct image_params *imgp, | ||||
register_t **stack_base); | |||||
static int linux_elf_fixup(register_t **stack_base, | static int linux_elf_fixup(register_t **stack_base, | ||||
struct image_params *iparams); | struct image_params *iparams); | ||||
static bool linux_trans_osrel(const Elf_Note *note, int32_t *osrel); | static bool linux_trans_osrel(const Elf_Note *note, int32_t *osrel); | ||||
static void linux_vdso_install(const void *param); | static void linux_vdso_install(const void *param); | ||||
static void linux_vdso_deinstall(const void *param); | static void linux_vdso_deinstall(const void *param); | ||||
static void linux_set_syscall_retval(struct thread *td, int error); | static void linux_set_syscall_retval(struct thread *td, int error); | ||||
static int linux_fetch_syscall_args(struct thread *td); | static int linux_fetch_syscall_args(struct thread *td); | ||||
static void linux_exec_setregs(struct thread *td, struct image_params *imgp, | static void linux_exec_setregs(struct thread *td, struct image_params *imgp, | ||||
▲ Show 20 Lines • Show All 55 Lines • ▼ Show 20 Lines | |||||
static void | static void | ||||
linux_set_syscall_retval(struct thread *td, int error) | linux_set_syscall_retval(struct thread *td, int error) | ||||
{ | { | ||||
td->td_retval[1] = td->td_frame->tf_x[1]; | td->td_retval[1] = td->td_frame->tf_x[1]; | ||||
cpu_set_syscall_retval(td, error); | cpu_set_syscall_retval(td, error); | ||||
} | } | ||||
static void | static int | ||||
linux_copyout_auxargs(struct image_params *imgp, u_long *base) | linux_copyout_auxargs(struct image_params *imgp, u_long *base) | ||||
{ | { | ||||
Elf_Auxargs *args; | Elf_Auxargs *args; | ||||
Elf_Auxinfo *argarray, *pos; | Elf_Auxinfo *argarray, *pos; | ||||
u_long auxlen; | u_long auxlen; | ||||
struct proc *p; | struct proc *p; | ||||
int issetugid; | int error, issetugid; | ||||
LIN_SDT_PROBE0(sysvec, linux_copyout_auxargs, todo); | LIN_SDT_PROBE0(sysvec, linux_copyout_auxargs, todo); | ||||
p = imgp->proc; | p = imgp->proc; | ||||
args = (Elf64_Auxargs *)imgp->auxargs; | args = (Elf64_Auxargs *)imgp->auxargs; | ||||
argarray = pos = malloc(LINUX_AT_COUNT * sizeof(*pos), M_TEMP, | argarray = pos = malloc(LINUX_AT_COUNT * sizeof(*pos), M_TEMP, | ||||
M_WAITOK | M_ZERO); | M_WAITOK | M_ZERO); | ||||
Show All 26 Lines | if (args->execfd != -1) | ||||
AUXARGS_ENTRY(pos, AT_EXECFD, args->execfd); | AUXARGS_ENTRY(pos, AT_EXECFD, args->execfd); | ||||
AUXARGS_ENTRY(pos, AT_NULL, 0); | AUXARGS_ENTRY(pos, AT_NULL, 0); | ||||
free(imgp->auxargs, M_TEMP); | free(imgp->auxargs, M_TEMP); | ||||
imgp->auxargs = NULL; | imgp->auxargs = NULL; | ||||
KASSERT(pos - argarray <= LINUX_AT_COUNT, ("Too many auxargs")); | KASSERT(pos - argarray <= LINUX_AT_COUNT, ("Too many auxargs")); | ||||
auxlen = sizeof(*argarray) * (pos - argarray); | auxlen = sizeof(*argarray) * (pos - argarray); | ||||
*base -= auxlen; | *base -= auxlen; | ||||
copyout(argarray, (void *)*base, auxlen); | error = copyout(argarray, (void *)*base, auxlen); | ||||
free(argarray, M_TEMP); | free(argarray, M_TEMP); | ||||
return (error); | |||||
} | } | ||||
static int | static int | ||||
linux_elf_fixup(register_t **stack_base, struct image_params *imgp) | linux_elf_fixup(register_t **stack_base, struct image_params *imgp) | ||||
{ | { | ||||
LIN_SDT_PROBE0(sysvec, linux_elf_fixup, todo); | LIN_SDT_PROBE0(sysvec, linux_elf_fixup, todo); | ||||
return (0); | return (0); | ||||
} | } | ||||
/* | /* | ||||
* Copy strings out to the new process address space, constructing new arg | * Copy strings out to the new process address space, constructing new arg | ||||
* and env vector tables. Return a pointer to the base so that it can be used | * and env vector tables. Return a pointer to the base so that it can be used | ||||
* as the initial stack pointer. | * as the initial stack pointer. | ||||
* LINUXTODO: deduplicate against other linuxulator archs | * LINUXTODO: deduplicate against other linuxulator archs | ||||
*/ | */ | ||||
static register_t * | static int | ||||
linux_copyout_strings(struct image_params *imgp) | linux_copyout_strings(struct image_params *imgp, register_t **stack_base) | ||||
{ | { | ||||
char **vectp; | char **vectp; | ||||
char *stringp, *destp; | char *stringp, *destp; | ||||
register_t *stack_base; | |||||
struct ps_strings *arginfo; | struct ps_strings *arginfo; | ||||
char canary[LINUX_AT_RANDOM_LEN]; | char canary[LINUX_AT_RANDOM_LEN]; | ||||
size_t execpath_len; | size_t execpath_len; | ||||
struct proc *p; | struct proc *p; | ||||
int argc, envc; | int argc, envc, error; | ||||
/* Calculate string base and vector table pointers. */ | /* Calculate string base and vector table pointers. */ | ||||
if (imgp->execpath != NULL && imgp->auxargs != NULL) | if (imgp->execpath != NULL && imgp->auxargs != NULL) | ||||
execpath_len = strlen(imgp->execpath) + 1; | execpath_len = strlen(imgp->execpath) + 1; | ||||
else | else | ||||
execpath_len = 0; | execpath_len = 0; | ||||
p = imgp->proc; | p = imgp->proc; | ||||
arginfo = (struct ps_strings *)p->p_sysent->sv_psstrings; | arginfo = (struct ps_strings *)p->p_sysent->sv_psstrings; | ||||
destp = (caddr_t)arginfo - SPARE_USRSPACE - | destp = (caddr_t)arginfo - SPARE_USRSPACE - | ||||
roundup(sizeof(canary), sizeof(char *)) - | roundup(sizeof(canary), sizeof(char *)) - | ||||
roundup(execpath_len, sizeof(char *)) - | roundup(execpath_len, sizeof(char *)) - | ||||
roundup(ARG_MAX - imgp->args->stringspace, sizeof(char *)); | roundup(ARG_MAX - imgp->args->stringspace, sizeof(char *)); | ||||
if (execpath_len != 0) { | if (execpath_len != 0) { | ||||
imgp->execpathp = (uintptr_t)arginfo - execpath_len; | imgp->execpathp = (uintptr_t)arginfo - execpath_len; | ||||
copyout(imgp->execpath, (void *)imgp->execpathp, execpath_len); | error = copyout(imgp->execpath, (void *)imgp->execpathp, | ||||
execpath_len); | |||||
if (error) | |||||
return (error); | |||||
} | } | ||||
/* Prepare the canary for SSP. */ | /* Prepare the canary for SSP. */ | ||||
arc4rand(canary, sizeof(canary), 0); | arc4rand(canary, sizeof(canary), 0); | ||||
imgp->canary = (uintptr_t)arginfo - | imgp->canary = (uintptr_t)arginfo - | ||||
roundup(execpath_len, sizeof(char *)) - | roundup(execpath_len, sizeof(char *)) - | ||||
roundup(sizeof(canary), sizeof(char *)); | roundup(sizeof(canary), sizeof(char *)); | ||||
copyout(canary, (void *)imgp->canary, sizeof(canary)); | error = copyout(canary, (void *)imgp->canary, sizeof(canary)); | ||||
if (error) | |||||
return (error); | |||||
vectp = (char **)destp; | vectp = (char **)destp; | ||||
if (imgp->auxargs) | if (imgp->auxargs) { | ||||
imgp->sysent->sv_copyout_auxargs(imgp, (u_long *)&vectp); | error = imgp->sysent->sv_copyout_auxargs(imgp, | ||||
(u_long *)&vectp); | |||||
if (error) | |||||
return (error); | |||||
} | |||||
/* | /* | ||||
* Allocate room for argc and the argv[] and env vectors including the | * Allocate room for argc and the argv[] and env vectors including the | ||||
* terminating NULL pointers. | * terminating NULL pointers. | ||||
*/ | */ | ||||
vectp -= 1 + imgp->args->argc + 1 + imgp->args->envc + 1; | vectp -= 1 + imgp->args->argc + 1 + imgp->args->envc + 1; | ||||
vectp = (char **)STACKALIGN(vectp); | vectp = (char **)STACKALIGN(vectp); | ||||
/* vectp also becomes our initial stack base. */ | /* vectp also becomes our initial stack base. */ | ||||
stack_base = (register_t *)vectp; | *stack_base = (register_t *)vectp; | ||||
stringp = imgp->args->begin_argv; | stringp = imgp->args->begin_argv; | ||||
argc = imgp->args->argc; | argc = imgp->args->argc; | ||||
envc = imgp->args->envc; | envc = imgp->args->envc; | ||||
/* Copy out strings - arguments and environment. */ | /* Copy out strings - arguments and environment. */ | ||||
copyout(stringp, destp, ARG_MAX - imgp->args->stringspace); | error = copyout(stringp, destp, ARG_MAX - imgp->args->stringspace); | ||||
if (error) | |||||
return (error); | |||||
/* Fill in "ps_strings" struct for ps, w, etc. */ | /* Fill in "ps_strings" struct for ps, w, etc. */ | ||||
suword(&arginfo->ps_argvstr, (long)(intptr_t)vectp); | if (suword(&arginfo->ps_argvstr, (long)(intptr_t)vectp) != 0 || | ||||
suword(&arginfo->ps_nargvstr, argc); | suword(&arginfo->ps_nargvstr, argc) != 0) | ||||
return (EFAULT); | |||||
suword(vectp++, argc); | if (suword(vectp++, argc) != 0) | ||||
return (EFAULT); | |||||
/* Fill in argument portion of vector table. */ | /* Fill in argument portion of vector table. */ | ||||
for (; argc > 0; --argc) { | for (; argc > 0; --argc) { | ||||
suword(vectp++, (long)(intptr_t)destp); | if (suword(vectp++, (long)(intptr_t)destp) != 0) | ||||
return (EFAULT); | |||||
while (*stringp++ != 0) | while (*stringp++ != 0) | ||||
destp++; | destp++; | ||||
destp++; | destp++; | ||||
} | } | ||||
/* A null vector table pointer separates the argp's from the envp's. */ | /* A null vector table pointer separates the argp's from the envp's. */ | ||||
suword(vectp++, 0); | if (suword(vectp++, 0) != 0) | ||||
return (EFAULT); | |||||
suword(&arginfo->ps_envstr, (long)(intptr_t)vectp); | if (suword(&arginfo->ps_envstr, (long)(intptr_t)vectp) != 0 || | ||||
suword(&arginfo->ps_nenvstr, envc); | suword(&arginfo->ps_nenvstr, envc) != 0) | ||||
return (EFAULT); | |||||
/* Fill in environment portion of vector table. */ | /* Fill in environment portion of vector table. */ | ||||
for (; envc > 0; --envc) { | for (; envc > 0; --envc) { | ||||
suword(vectp++, (long)(intptr_t)destp); | if (suword(vectp++, (long)(intptr_t)destp) != 0) | ||||
return (EFAULT); | |||||
while (*stringp++ != 0) | while (*stringp++ != 0) | ||||
destp++; | destp++; | ||||
destp++; | destp++; | ||||
} | } | ||||
/* The end of the vector table is a null pointer. */ | /* The end of the vector table is a null pointer. */ | ||||
suword(vectp, 0); | if (suword(vectp, 0) != 0) | ||||
return (stack_base); | return (EFAULT); | ||||
return (0); | |||||
} | } | ||||
/* | /* | ||||
* Reset registers to default values on exec. | * Reset registers to default values on exec. | ||||
*/ | */ | ||||
static void | static void | ||||
linux_exec_setregs(struct thread *td, struct image_params *imgp, u_long stack) | linux_exec_setregs(struct thread *td, struct image_params *imgp, u_long stack) | ||||
{ | { | ||||
▲ Show 20 Lines • Show All 222 Lines • Show Last 20 Lines |