Changeset View
Changeset View
Standalone View
Standalone View
head/sys/arm64/linux/linux_sysvec.c
Show First 20 Lines • Show All 81 Lines • ▼ Show 20 Lines | |||||
static int linux_vsyscall(struct thread *td); | static int linux_vsyscall(struct thread *td); | ||||
/* DTrace init */ | /* DTrace init */ | ||||
LIN_SDT_PROVIDER_DECLARE(LINUX_DTRACE); | LIN_SDT_PROVIDER_DECLARE(LINUX_DTRACE); | ||||
/* DTrace probes */ | /* DTrace probes */ | ||||
LIN_SDT_PROBE_DEFINE2(sysvec, linux_translate_traps, todo, "int", "int"); | LIN_SDT_PROBE_DEFINE2(sysvec, linux_translate_traps, todo, "int", "int"); | ||||
LIN_SDT_PROBE_DEFINE0(sysvec, linux_exec_setregs, todo); | LIN_SDT_PROBE_DEFINE0(sysvec, linux_exec_setregs, todo); | ||||
LIN_SDT_PROBE_DEFINE0(sysvec, linux_copyout_auxargs, todo); | |||||
LIN_SDT_PROBE_DEFINE0(sysvec, linux_elf_fixup, todo); | LIN_SDT_PROBE_DEFINE0(sysvec, linux_elf_fixup, todo); | ||||
LIN_SDT_PROBE_DEFINE0(sysvec, linux_rt_sigreturn, todo); | LIN_SDT_PROBE_DEFINE0(sysvec, linux_rt_sigreturn, todo); | ||||
LIN_SDT_PROBE_DEFINE0(sysvec, linux_rt_sendsig, todo); | LIN_SDT_PROBE_DEFINE0(sysvec, linux_rt_sendsig, todo); | ||||
LIN_SDT_PROBE_DEFINE0(sysvec, linux_vsyscall, todo); | LIN_SDT_PROBE_DEFINE0(sysvec, linux_vsyscall, todo); | ||||
LIN_SDT_PROBE_DEFINE0(sysvec, linux_vdso_install, todo); | LIN_SDT_PROBE_DEFINE0(sysvec, linux_vdso_install, todo); | ||||
LIN_SDT_PROBE_DEFINE0(sysvec, linux_vdso_deinstall, todo); | LIN_SDT_PROBE_DEFINE0(sysvec, linux_vdso_deinstall, todo); | ||||
/* LINUXTODO: do we have traps to translate? */ | /* LINUXTODO: do we have traps to translate? */ | ||||
Show All 37 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 int | static void | ||||
linux_elf_fixup(register_t **stack_base, struct image_params *imgp) | linux_copyout_auxargs(struct image_params *imgp, u_long *base) | ||||
{ | { | ||||
Elf_Auxargs *args; | Elf_Auxargs *args; | ||||
Elf_Auxinfo *argarray, *pos; | Elf_Auxinfo *argarray, *pos; | ||||
Elf_Addr *auxbase, *base; | u_long auxlen; | ||||
struct ps_strings *arginfo; | |||||
struct proc *p; | struct proc *p; | ||||
int error, issetugid; | int issetugid; | ||||
LIN_SDT_PROBE0(sysvec, linux_elf_fixup, todo); | LIN_SDT_PROBE0(sysvec, linux_copyout_auxargs, todo); | ||||
p = imgp->proc; | p = imgp->proc; | ||||
arginfo = (struct ps_strings *)p->p_sysent->sv_psstrings; | |||||
KASSERT(curthread->td_proc == imgp->proc, | |||||
("unsafe linux_elf_fixup(), should be curproc")); | |||||
base = (Elf64_Addr *)*stack_base; | |||||
args = (Elf64_Auxargs *)imgp->auxargs; | args = (Elf64_Auxargs *)imgp->auxargs; | ||||
/* Auxargs after argc, and NULL-terminated argv and envv lists. */ | |||||
auxbase = base + 1 + imgp->args->argc + 1 + imgp->args->envc + 1; | |||||
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); | ||||
issetugid = p->p_flag & P_SUGID ? 1 : 0; | issetugid = p->p_flag & P_SUGID ? 1 : 0; | ||||
AUXARGS_ENTRY(pos, LINUX_AT_SYSINFO_EHDR, | AUXARGS_ENTRY(pos, LINUX_AT_SYSINFO_EHDR, | ||||
imgp->proc->p_sysent->sv_shared_page_base); | imgp->proc->p_sysent->sv_shared_page_base); | ||||
#if 0 /* LINUXTODO: implement arm64 LINUX_AT_HWCAP */ | #if 0 /* LINUXTODO: implement arm64 LINUX_AT_HWCAP */ | ||||
AUXARGS_ENTRY(pos, LINUX_AT_HWCAP, cpu_feature); | AUXARGS_ENTRY(pos, LINUX_AT_HWCAP, cpu_feature); | ||||
Show All 19 Lines | if (imgp->execpathp != 0) | ||||
AUXARGS_ENTRY(pos, LINUX_AT_EXECFN, imgp->execpathp); | AUXARGS_ENTRY(pos, LINUX_AT_EXECFN, imgp->execpathp); | ||||
if (args->execfd != -1) | 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")); | ||||
error = copyout(argarray, auxbase, sizeof(*argarray) * LINUX_AT_COUNT); | auxlen = sizeof(*argarray) * (pos - argarray); | ||||
*base -= auxlen; | |||||
copyout(argarray, (void *)*base, auxlen); | |||||
free(argarray, M_TEMP); | free(argarray, M_TEMP); | ||||
if (error != 0) | } | ||||
return (error); | |||||
static int | |||||
linux_elf_fixup(register_t **stack_base, struct image_params *imgp) | |||||
{ | |||||
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 | ||||
Show All 31 Lines | linux_copyout_strings(struct image_params *imgp) | ||||
/* 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)); | copyout(canary, (void *)imgp->canary, sizeof(canary)); | ||||
vectp = (char **)destp; | vectp = (char **)destp; | ||||
if (imgp->auxargs) { | if (imgp->auxargs) | ||||
/* | imgp->sysent->sv_copyout_auxargs(imgp, (u_long *)&vectp); | ||||
* Allocate room on the stack for the ELF auxargs | |||||
* array. It has up to LINUX_AT_COUNT entries. | |||||
*/ | |||||
vectp -= howmany(LINUX_AT_COUNT * sizeof(Elf64_Auxinfo), | |||||
sizeof(*vectp)); | |||||
} | |||||
/* | /* | ||||
* 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); | copyout(stringp, destp, ARG_MAX - imgp->args->stringspace); | ||||
/* 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); | suword(&arginfo->ps_argvstr, (long)(intptr_t)vectp); | ||||
suword(&arginfo->ps_nargvstr, argc); | suword(&arginfo->ps_nargvstr, argc); | ||||
suword(vectp++, argc); | suword(vectp++, argc); | ||||
jhb: While adding error checking for a followup for @kib, I noticed this line. This is almost… | |||||
/* 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); | suword(vectp++, (long)(intptr_t)destp); | ||||
while (*stringp++ != 0) | while (*stringp++ != 0) | ||||
destp++; | destp++; | ||||
destp++; | destp++; | ||||
} | } | ||||
▲ Show 20 Lines • Show All 78 Lines • ▼ Show 20 Lines | struct sysentvec elf_linux_sysvec = { | ||||
.sv_coredump = elf64_coredump, | .sv_coredump = elf64_coredump, | ||||
.sv_imgact_try = linux_exec_imgact_try, | .sv_imgact_try = linux_exec_imgact_try, | ||||
.sv_minsigstksz = LINUX_MINSIGSTKSZ, | .sv_minsigstksz = LINUX_MINSIGSTKSZ, | ||||
.sv_minuser = VM_MIN_ADDRESS, | .sv_minuser = VM_MIN_ADDRESS, | ||||
.sv_maxuser = VM_MAXUSER_ADDRESS, | .sv_maxuser = VM_MAXUSER_ADDRESS, | ||||
.sv_usrstack = USRSTACK, | .sv_usrstack = USRSTACK, | ||||
.sv_psstrings = PS_STRINGS, /* XXX */ | .sv_psstrings = PS_STRINGS, /* XXX */ | ||||
.sv_stackprot = VM_PROT_READ | VM_PROT_WRITE, | .sv_stackprot = VM_PROT_READ | VM_PROT_WRITE, | ||||
.sv_copyout_auxargs = linux_copyout_auxargs, | |||||
.sv_copyout_strings = linux_copyout_strings, | .sv_copyout_strings = linux_copyout_strings, | ||||
.sv_setregs = linux_exec_setregs, | .sv_setregs = linux_exec_setregs, | ||||
.sv_fixlimit = NULL, | .sv_fixlimit = NULL, | ||||
.sv_maxssiz = NULL, | .sv_maxssiz = NULL, | ||||
.sv_flags = SV_ABI_LINUX | SV_LP64 | SV_SHP, | .sv_flags = SV_ABI_LINUX | SV_LP64 | SV_SHP, | ||||
.sv_set_syscall_retval = linux_set_syscall_retval, | .sv_set_syscall_retval = linux_set_syscall_retval, | ||||
.sv_fetch_syscall_args = linux_fetch_syscall_args, | .sv_fetch_syscall_args = linux_fetch_syscall_args, | ||||
.sv_syscallnames = NULL, | .sv_syscallnames = NULL, | ||||
▲ Show 20 Lines • Show All 152 Lines • Show Last 20 Lines |
While adding error checking for a followup for @kib, I noticed this line. This is almost certainly going to cause breakage on arm64 with this change. Previously this was overwritten because we recalculated the location of auxargs and the first auxarg overwrote this duplicate argc, but now this argc will be "real", so if arm64 Linux binaries fail, the first thing I'd try is to remove this line. Note that ps_argvstr is also currently wrong (it points at this argc value instead of argv[0]) due to this.