Changeset View
Changeset View
Standalone View
Standalone View
head/sys/amd64/linux32/linux32_sysvec.c
Show First 20 Lines • Show All 95 Lines • ▼ Show 20 Lines | |||||
static char *linux_shared_page_mapping; | static char *linux_shared_page_mapping; | ||||
extern char _binary_linux32_locore_o_start; | extern char _binary_linux32_locore_o_start; | ||||
extern char _binary_linux32_locore_o_end; | extern char _binary_linux32_locore_o_end; | ||||
extern struct sysent linux32_sysent[LINUX32_SYS_MAXSYSCALL]; | extern struct sysent linux32_sysent[LINUX32_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_elf(register_t **stack_base, | static int linux_fixup_elf(uintptr_t *stack_base, | ||||
struct image_params *iparams); | struct image_params *iparams); | ||||
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 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 void linux32_fixlimit(struct rlimit *rl, int which); | static void linux32_fixlimit(struct rlimit *rl, int which); | ||||
static bool linux32_trans_osrel(const Elf_Note *note, int32_t *osrel); | static bool linux32_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); | ||||
#define LINUX_T_UNKNOWN 255 | #define LINUX_T_UNKNOWN 255 | ||||
static int _bsd_to_linux_trapcode[] = { | static int _bsd_to_linux_trapcode[] = { | ||||
LINUX_T_UNKNOWN, /* 0 */ | LINUX_T_UNKNOWN, /* 0 */ | ||||
▲ Show 20 Lines • Show All 122 Lines • ▼ Show 20 Lines | linux_copyout_auxargs(struct image_params *imgp, u_long *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) | ||||
{ | { | ||||
Elf32_Addr *base; | Elf32_Addr *base; | ||||
base = (Elf32_Addr *)*stack_base; | base = (Elf32_Addr *)*stack_base; | ||||
base--; | base--; | ||||
if (suword32(base, (uint32_t)imgp->args->argc) == -1) | if (suword32(base, (uint32_t)imgp->args->argc) == -1) | ||||
return (EFAULT); | return (EFAULT); | ||||
*stack_base = (register_t *)base; | *stack_base = (uintptr_t)base; | ||||
return (0); | return (0); | ||||
} | } | ||||
static void | static void | ||||
linux_rt_sendsig(sig_t catcher, ksiginfo_t *ksi, sigset_t *mask) | linux_rt_sendsig(sig_t catcher, ksiginfo_t *ksi, sigset_t *mask) | ||||
{ | { | ||||
struct thread *td = curthread; | struct thread *td = curthread; | ||||
struct proc *p = td->td_proc; | struct proc *p = td->td_proc; | ||||
▲ Show 20 Lines • Show All 406 Lines • ▼ Show 20 Lines | linux32_fetch_syscall_args(struct thread *td) | ||||
return (0); | return (0); | ||||
} | } | ||||
/* | /* | ||||
* Clear registers on exec | * Clear registers on exec | ||||
* XXX copied from ia32_signal.c. | * XXX copied from ia32_signal.c. | ||||
*/ | */ | ||||
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 trapframe *regs = td->td_frame; | struct trapframe *regs = td->td_frame; | ||||
struct pcb *pcb = td->td_pcb; | struct pcb *pcb = td->td_pcb; | ||||
register_t saved_rflags; | register_t saved_rflags; | ||||
regs = td->td_frame; | regs = td->td_frame; | ||||
pcb = td->td_pcb; | pcb = td->td_pcb; | ||||
Show All 27 Lines | linux_exec_setregs(struct thread *td, struct image_params *imgp, | ||||
/* Do full restore on return so that we can change to a different %cs */ | /* Do full restore on return so that we can change to a different %cs */ | ||||
set_pcb_flags(pcb, PCB_32BIT | PCB_FULL_IRET); | set_pcb_flags(pcb, PCB_32BIT | PCB_FULL_IRET); | ||||
} | } | ||||
/* | /* | ||||
* XXX copied from ia32_sysvec.c. | * XXX copied from ia32_sysvec.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; | ||||
u_int32_t *vectp; | u_int32_t *vectp; | ||||
char *stringp, *destp; | char *stringp; | ||||
uintptr_t destp, ustringp; | |||||
struct linux32_ps_strings *arginfo; | struct linux32_ps_strings *arginfo; | ||||
char canary[LINUX_AT_RANDOM_LEN]; | char canary[LINUX_AT_RANDOM_LEN]; | ||||
size_t execpath_len; | size_t execpath_len; | ||||
/* 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; | ||||
arginfo = (struct linux32_ps_strings *)LINUX32_PS_STRINGS; | arginfo = (struct linux32_ps_strings *)LINUX32_PS_STRINGS; | ||||
destp = (caddr_t)arginfo - SPARE_USRSPACE - | destp = (uintptr_t)arginfo; | ||||
roundup(sizeof(canary), sizeof(char *)) - | |||||
roundup(execpath_len, 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; | destp -= execpath_len; | ||||
error = copyout(imgp->execpath, (void *)imgp->execpathp, | destp = rounddown2(destp, sizeof(void *)); | ||||
execpath_len); | imgp->execpathp = destp; | ||||
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 - | 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 = (uint32_t *)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 = (uint32_t *)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 (suword32(&arginfo->ps_argvstr, (uint32_t)(intptr_t)vectp) != 0 || | if (suword32(&arginfo->ps_argvstr, (uint32_t)(intptr_t)vectp) != 0 || | ||||
suword32(&arginfo->ps_nargvstr, argc) != 0) | suword32(&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 (suword32(vectp++, (uint32_t)(intptr_t)destp) != 0) | if (suword32(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 (suword32(vectp++, 0) != 0) | if (suword32(vectp++, 0) != 0) | ||||
return (EFAULT); | return (EFAULT); | ||||
if (suword32(&arginfo->ps_envstr, (uint32_t)(intptr_t)vectp) != 0 || | if (suword32(&arginfo->ps_envstr, (uint32_t)(intptr_t)vectp) != 0 || | ||||
suword32(&arginfo->ps_nenvstr, envc) != 0) | suword32(&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 (suword32(vectp++, (uint32_t)(intptr_t)destp) != 0) | if (suword32(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 (suword32(vectp, 0) != 0) | if (suword32(vectp, 0) != 0) | ||||
return (EFAULT); | return (EFAULT); | ||||
return (0); | return (0); | ||||
} | } | ||||
▲ Show 20 Lines • Show All 253 Lines • Show Last 20 Lines |