Changeset View
Changeset View
Standalone View
Standalone View
head/sys/i386/linux/linux_sysvec.c
Show First 20 Lines • Show All 82 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 int linux_fixup(register_t **stack_base, | static int linux_fixup(uintptr_t *stack_base, | ||||
struct image_params *iparams); | struct image_params *iparams); | ||||
static int linux_fixup_elf(register_t **stack_base, | static int linux_fixup_elf(uintptr_t *stack_base, | ||||
struct image_params *iparams); | struct image_params *iparams); | ||||
static void linux_sendsig(sig_t catcher, ksiginfo_t *ksi, sigset_t *mask); | static void linux_sendsig(sig_t catcher, ksiginfo_t *ksi, sigset_t *mask); | ||||
static void linux_exec_setregs(struct thread *td, | static void linux_exec_setregs(struct thread *td, | ||||
struct image_params *imgp, u_long stack); | struct image_params *imgp, uintptr_t stack); | ||||
static int linux_copyout_strings(struct image_params *imgp, | static int linux_copyout_strings(struct image_params *imgp, | ||||
register_t **stack_base); | uintptr_t *stack_base); | ||||
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(void *param); | static void linux_vdso_install(void *param); | ||||
static void linux_vdso_deinstall(void *param); | static void linux_vdso_deinstall(void *param); | ||||
static int linux_szplatform; | static int linux_szplatform; | ||||
const char *linux_kplatform; | const char *linux_kplatform; | ||||
static eventhandler_tag linux_exit_tag; | static eventhandler_tag linux_exit_tag; | ||||
▲ Show 20 Lines • Show All 61 Lines • ▼ Show 20 Lines | linux_translate_traps(int signal, int trap_code) | ||||
case T_PAGEFLT: | case T_PAGEFLT: | ||||
return (SIGSEGV); | return (SIGSEGV); | ||||
default: | default: | ||||
return (signal); | return (signal); | ||||
} | } | ||||
} | } | ||||
static int | static int | ||||
linux_fixup(register_t **stack_base, struct image_params *imgp) | linux_fixup(uintptr_t *stack_base, struct image_params *imgp) | ||||
{ | { | ||||
register_t *argv, *envp; | register_t *base, *argv, *envp; | ||||
argv = *stack_base; | base = (register_t *)*stack_base; | ||||
envp = *stack_base + (imgp->args->argc + 1); | argv = base; | ||||
(*stack_base)--; | envp = base + (imgp->args->argc + 1); | ||||
suword(*stack_base, (intptr_t)(void *)envp); | base--; | ||||
(*stack_base)--; | suword(base, (intptr_t)envp); | ||||
suword(*stack_base, (intptr_t)(void *)argv); | base--; | ||||
(*stack_base)--; | suword(base, (intptr_t)argv); | ||||
suword(*stack_base, imgp->args->argc); | base--; | ||||
suword(base, imgp->args->argc); | |||||
*stack_base = (uintptr_t)base; | |||||
return (0); | return (0); | ||||
} | } | ||||
static int | static int | ||||
linux_copyout_auxargs(struct image_params *imgp, u_long *base) | linux_copyout_auxargs(struct image_params *imgp, uintptr_t *base) | ||||
{ | { | ||||
struct proc *p; | struct proc *p; | ||||
Elf32_Auxargs *args; | Elf32_Auxargs *args; | ||||
Elf32_Auxinfo *argarray, *pos; | Elf32_Auxinfo *argarray, *pos; | ||||
Elf32_Addr *uplatform; | Elf32_Addr *uplatform; | ||||
struct ps_strings *arginfo; | struct ps_strings *arginfo; | ||||
u_long auxlen; | u_long auxlen; | ||||
int error, issetugid; | int error, issetugid; | ||||
▲ Show 20 Lines • Show All 48 Lines • ▼ Show 20 Lines | linux_copyout_auxargs(struct image_params *imgp, uintptr_t *base) | ||||
auxlen = sizeof(*argarray) * (pos - argarray); | auxlen = sizeof(*argarray) * (pos - argarray); | ||||
*base -= auxlen; | *base -= auxlen; | ||||
error = copyout(argarray, (void *)*base, auxlen); | error = copyout(argarray, (void *)*base, auxlen); | ||||
free(argarray, M_TEMP); | free(argarray, M_TEMP); | ||||
return (error); | return (error); | ||||
} | } | ||||
static int | static int | ||||
linux_fixup_elf(register_t **stack_base, struct image_params *imgp) | linux_fixup_elf(uintptr_t *stack_base, struct image_params *imgp) | ||||
{ | { | ||||
register_t *base; | |||||
(*stack_base)--; | base = (register_t *)*stack_base; | ||||
if (suword(*stack_base, (register_t)imgp->args->argc) == -1) | base--; | ||||
if (suword(base, (register_t)imgp->args->argc) == -1) | |||||
return (EFAULT); | return (EFAULT); | ||||
*stack_base = (uintptr_t)base; | |||||
return (0); | return (0); | ||||
} | } | ||||
/* | /* | ||||
* Copied from kern/kern_exec.c | * Copied from kern/kern_exec.c | ||||
*/ | */ | ||||
static int | static int | ||||
linux_copyout_strings(struct image_params *imgp, register_t **stack_base) | linux_copyout_strings(struct image_params *imgp, uintptr_t *stack_base) | ||||
{ | { | ||||
int argc, envc, error; | int argc, envc, error; | ||||
char **vectp; | char **vectp; | ||||
char *stringp, *destp; | char *stringp; | ||||
uintptr_t destp, ustringp; | |||||
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; | ||||
/* Calculate string base and vector table pointers. */ | /* Calculate string base and vector table pointers. */ | ||||
p = imgp->proc; | p = imgp->proc; | ||||
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; | ||||
arginfo = (struct ps_strings *)p->p_sysent->sv_psstrings; | arginfo = (struct ps_strings *)p->p_sysent->sv_psstrings; | ||||
destp = (caddr_t)arginfo - SPARE_USRSPACE - linux_szplatform - | destp = (uintptr_t)arginfo; | ||||
roundup(sizeof(canary), sizeof(char *)) - | |||||
roundup(execpath_len, sizeof(char *)) - | |||||
roundup(ARG_MAX - imgp->args->stringspace, sizeof(char *)); | |||||
/* Install LINUX_PLATFORM. */ | /* Install LINUX_PLATFORM. */ | ||||
error = copyout(linux_kplatform, ((caddr_t)arginfo - linux_szplatform), | destp -= linux_szplatform; | ||||
linux_szplatform); | destp = rounddown2(destp, sizeof(void *)); | ||||
error = copyout(linux_kplatform, (void *)destp, linux_szplatform); | |||||
if (error != 0) | if (error != 0) | ||||
return (error); | return (error); | ||||
if (execpath_len != 0) { | if (execpath_len != 0) { | ||||
imgp->execpathp = (uintptr_t)arginfo - | destp -= execpath_len; | ||||
linux_szplatform - execpath_len; | destp = rounddown2(destp, sizeof(void *)); | ||||
error = copyout(imgp->execpath, (void *)imgp->execpathp, | imgp->execpathp = destp; | ||||
execpath_len); | error = copyout(imgp->execpath, (void *)destp, execpath_len); | ||||
if (error != 0) | if (error != 0) | ||||
return (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 - linux_szplatform - | destp -= roundup(sizeof(canary), sizeof(void *)); | ||||
roundup(execpath_len, sizeof(char *)) - | imgp->canary = destp; | ||||
roundup(sizeof(canary), sizeof(char *)); | error = copyout(canary, (void *)destp, sizeof(canary)); | ||||
error = copyout(canary, (void *)imgp->canary, sizeof(canary)); | |||||
if (error != 0) | if (error != 0) | ||||
return (error); | return (error); | ||||
vectp = (char **)destp; | /* Allocate room for the argument and environment strings. */ | ||||
destp -= ARG_MAX - imgp->args->stringspace; | |||||
destp = rounddown2(destp, sizeof(void *)); | |||||
ustringp = destp; | |||||
if (imgp->auxargs) { | if (imgp->auxargs) { | ||||
error = imgp->sysent->sv_copyout_auxargs(imgp, | error = imgp->sysent->sv_copyout_auxargs(imgp, &destp); | ||||
(u_long *)&vectp); | |||||
if (error != 0) | if (error != 0) | ||||
return (error); | return (error); | ||||
} | } | ||||
vectp = (char **)destp; | |||||
/* | /* | ||||
* Allocate room for the argv[] and env vectors including the | * Allocate room for the argv[] and env vectors including the | ||||
* terminating NULL pointers. | * terminating NULL pointers. | ||||
*/ | */ | ||||
vectp -= imgp->args->argc + 1 + imgp->args->envc + 1; | vectp -= imgp->args->argc + 1 + imgp->args->envc + 1; | ||||
/* vectp also becomes our initial stack base. */ | /* vectp also becomes our initial stack base. */ | ||||
*stack_base = (register_t *)vectp; | *stack_base = (uintptr_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. */ | ||||
error = copyout(stringp, destp, ARG_MAX - imgp->args->stringspace); | error = copyout(stringp, (void *)ustringp, | ||||
ARG_MAX - imgp->args->stringspace); | |||||
if (error != 0) | if (error != 0) | ||||
return (error); | return (error); | ||||
/* Fill in "ps_strings" struct for ps, w, etc. */ | /* Fill in "ps_strings" struct for ps, w, etc. */ | ||||
if (suword(&arginfo->ps_argvstr, (long)(intptr_t)vectp) != 0 || | if (suword(&arginfo->ps_argvstr, (long)(intptr_t)vectp) != 0 || | ||||
suword(&arginfo->ps_nargvstr, argc) != 0) | suword(&arginfo->ps_nargvstr, argc) != 0) | ||||
return (EFAULT); | return (EFAULT); | ||||
/* Fill in argument portion of vector table. */ | /* Fill in argument portion of vector table. */ | ||||
for (; argc > 0; --argc) { | for (; argc > 0; --argc) { | ||||
if (suword(vectp++, (long)(intptr_t)destp) != 0) | if (suword(vectp++, ustringp) != 0) | ||||
return (EFAULT); | return (EFAULT); | ||||
while (*stringp++ != 0) | while (*stringp++ != 0) | ||||
destp++; | ustringp++; | ||||
destp++; | ustringp++; | ||||
} | } | ||||
/* 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. */ | ||||
if (suword(vectp++, 0) != 0) | if (suword(vectp++, 0) != 0) | ||||
return (EFAULT); | return (EFAULT); | ||||
if (suword(&arginfo->ps_envstr, (long)(intptr_t)vectp) != 0 || | if (suword(&arginfo->ps_envstr, (long)(intptr_t)vectp) != 0 || | ||||
suword(&arginfo->ps_nenvstr, envc) != 0) | suword(&arginfo->ps_nenvstr, envc) != 0) | ||||
return (EFAULT); | return (EFAULT); | ||||
/* Fill in environment portion of vector table. */ | /* Fill in environment portion of vector table. */ | ||||
for (; envc > 0; --envc) { | for (; envc > 0; --envc) { | ||||
if (suword(vectp++, (long)(intptr_t)destp) != 0) | if (suword(vectp++, ustringp) != 0) | ||||
return (EFAULT); | return (EFAULT); | ||||
while (*stringp++ != 0) | while (*stringp++ != 0) | ||||
destp++; | ustringp++; | ||||
destp++; | ustringp++; | ||||
} | } | ||||
/* The end of the vector table is a null pointer. */ | /* The end of the vector table is a null pointer. */ | ||||
if (suword(vectp, 0) != 0) | if (suword(vectp, 0) != 0) | ||||
return (EFAULT); | return (EFAULT); | ||||
return (0); | return (0); | ||||
} | } | ||||
▲ Show 20 Lines • Show All 396 Lines • ▼ Show 20 Lines | |||||
} | } | ||||
/* | /* | ||||
* exec_setregs may initialize some registers differently than Linux | * exec_setregs may initialize some registers differently than Linux | ||||
* does, thus potentially confusing Linux binaries. If necessary, we | * does, thus potentially confusing Linux binaries. If necessary, we | ||||
* override the exec_setregs default(s) here. | * override the exec_setregs default(s) here. | ||||
*/ | */ | ||||
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, | ||||
uintptr_t stack) | |||||
{ | { | ||||
struct pcb *pcb = td->td_pcb; | struct pcb *pcb = td->td_pcb; | ||||
exec_setregs(td, imgp, stack); | exec_setregs(td, imgp, stack); | ||||
/* Linux sets %gs to 0, we default to _udatasel. */ | /* Linux sets %gs to 0, we default to _udatasel. */ | ||||
pcb->pcb_gs = 0; | pcb->pcb_gs = 0; | ||||
load_gs(0); | load_gs(0); | ||||
▲ Show 20 Lines • Show All 280 Lines • Show Last 20 Lines |