Changeset View
Changeset View
Standalone View
Standalone View
sys/compat/linux/linux_emul.c
Show First 20 Lines • Show All 205 Lines • ▼ Show 20 Lines | linux_on_exit(struct proc *p) | ||||
(p->p_sysent->sv_thread_detach)(td); | (p->p_sysent->sv_thread_detach)(td); | ||||
p->p_emuldata = NULL; | p->p_emuldata = NULL; | ||||
sx_destroy(&pem->pem_sx); | sx_destroy(&pem->pem_sx); | ||||
free(pem, M_LINUX); | free(pem, M_LINUX); | ||||
} | } | ||||
/* | |||||
* If a Linux binary is exec'ing something, try this image activator | |||||
* first. We override standard shell script execution in order to | |||||
* be able to modify the interpreter path. We only do this if a Linux | |||||
* binary is doing the exec, so we do not create an EXEC module for it. | |||||
*/ | |||||
int | int | ||||
linux_exec_imgact_try(struct image_params *imgp) | |||||
{ | |||||
const char *head = (const char *)imgp->image_header; | |||||
char *rpath; | |||||
int error = -1; | |||||
/* | |||||
* The interpreter for shell scripts run from a Linux binary needs | |||||
* to be located in /compat/linux if possible in order to recursively | |||||
* maintain Linux path emulation. | |||||
*/ | |||||
if (((const short *)head)[0] == SHELLMAGIC) { | |||||
/* | |||||
* Run our normal shell image activator. If it succeeds attempt | |||||
* to use the alternate path for the interpreter. If an | |||||
* alternate path is found, use our stringspace to store it. | |||||
*/ | |||||
if ((error = exec_shell_imgact(imgp)) == 0) { | |||||
linux_emul_convpath(imgp->interpreter_name, UIO_SYSSPACE, | |||||
&rpath, 0, AT_FDCWD); | |||||
if (rpath != NULL) | |||||
imgp->args->fname_buf = | |||||
imgp->interpreter_name = rpath; | |||||
} | |||||
} | |||||
return (error); | |||||
} | |||||
int | |||||
linux_common_execve(struct thread *td, struct image_args *eargs) | linux_common_execve(struct thread *td, struct image_args *eargs) | ||||
{ | { | ||||
struct linux_pemuldata *pem; | struct linux_pemuldata *pem; | ||||
struct vmspace *oldvmspace; | struct vmspace *oldvmspace; | ||||
struct linux_emuldata *em; | struct linux_emuldata *em; | ||||
struct proc *p; | struct proc *p; | ||||
int error; | int error; | ||||
p = td->td_proc; | p = td->td_proc; | ||||
error = pre_execve(td, &oldvmspace); | error = pre_execve(td, &oldvmspace); | ||||
if (error != 0) | if (error != 0) | ||||
return (error); | return (error); | ||||
error = kern_execve(td, eargs, NULL, oldvmspace); | error = kern_execve(td, eargs, NULL, oldvmspace); | ||||
post_execve(td, error, oldvmspace); | post_execve(td, error, oldvmspace); | ||||
if (error != EJUSTRETURN) | if (error != EJUSTRETURN) | ||||
return (error); | return (error); | ||||
/* | /* | ||||
* In a case of transition from Linux binary execing to | * In a case of transition from Linux binary execing to | ||||
* FreeBSD binary we destroy Linux emuldata thread & proc entries. | * FreeBSD binary we destroy Linux emuldata thread & proc entries. | ||||
*/ | */ | ||||
if (SV_CURPROC_ABI() != SV_ABI_LINUX) { | if (SV_CURPROC_ABI() != SV_ABI_LINUX) { | ||||
/* Clear ABI root directory if set. */ | |||||
linux_pwd_onexec_native(td); | |||||
PROC_LOCK(p); | PROC_LOCK(p); | ||||
em = em_find(td); | em = em_find(td); | ||||
KASSERT(em != NULL, ("proc_exec: thread emuldata not found.\n")); | KASSERT(em != NULL, ("proc_exec: thread emuldata not found.\n")); | ||||
td->td_emuldata = NULL; | td->td_emuldata = NULL; | ||||
pem = pem_find(p); | pem = pem_find(p); | ||||
KASSERT(pem != NULL, ("proc_exec: proc pemuldata not found.\n")); | KASSERT(pem != NULL, ("proc_exec: proc pemuldata not found.\n")); | ||||
p->p_emuldata = NULL; | p->p_emuldata = NULL; | ||||
PROC_UNLOCK(p); | PROC_UNLOCK(p); | ||||
free(em, M_TEMP); | free(em, M_TEMP); | ||||
free(pem, M_LINUX); | free(pem, M_LINUX); | ||||
} | } | ||||
return (EJUSTRETURN); | return (EJUSTRETURN); | ||||
} | } | ||||
void | int | ||||
linux_on_exec(struct proc *p, struct image_params *imgp) | linux_on_exec(struct proc *p, struct image_params *imgp) | ||||
{ | { | ||||
struct thread *td; | struct thread *td; | ||||
struct thread *othertd; | struct thread *othertd; | ||||
#if defined(__amd64__) | #if defined(__amd64__) | ||||
struct linux_pemuldata *pem; | struct linux_pemuldata *pem; | ||||
#endif | #endif | ||||
int error; | |||||
td = curthread; | td = curthread; | ||||
MPASS((imgp->sysent->sv_flags & SV_ABI_MASK) == SV_ABI_LINUX); | MPASS((imgp->sysent->sv_flags & SV_ABI_MASK) == SV_ABI_LINUX); | ||||
/* | /* | ||||
* When execing to Linux binary, we create Linux emuldata | * When execing to Linux binary, we create Linux emuldata | ||||
* thread entry. | * thread entry. | ||||
*/ | */ | ||||
Show All 16 Lines | if (SV_PROC_ABI(p) == SV_ABI_LINUX) { | ||||
* linux_thread_detach() can find expected but unused | * linux_thread_detach() can find expected but unused | ||||
* emuldata. | * emuldata. | ||||
*/ | */ | ||||
FOREACH_THREAD_IN_PROC(td->td_proc, othertd) { | FOREACH_THREAD_IN_PROC(td->td_proc, othertd) { | ||||
if (othertd == td) | if (othertd == td) | ||||
continue; | continue; | ||||
linux_proc_init(td, othertd, true); | linux_proc_init(td, othertd, true); | ||||
} | } | ||||
/* Set ABI root directory. */ | |||||
if ((error = linux_pwd_onexec(td)) != 0) | |||||
return (error); | |||||
} | } | ||||
#if defined(__amd64__) | #if defined(__amd64__) | ||||
/* | /* | ||||
* An IA32 executable which has executable stack will have the | * An IA32 executable which has executable stack will have the | ||||
* READ_IMPLIES_EXEC personality flag set automatically. | * READ_IMPLIES_EXEC personality flag set automatically. | ||||
*/ | */ | ||||
if (SV_PROC_FLAG(td->td_proc, SV_ILP32) && | if (SV_PROC_FLAG(td->td_proc, SV_ILP32) && | ||||
imgp->stack_prot & VM_PROT_EXECUTE) { | imgp->stack_prot & VM_PROT_EXECUTE) { | ||||
pem = pem_find(p); | pem = pem_find(p); | ||||
pem->persona |= LINUX_READ_IMPLIES_EXEC; | pem->persona |= LINUX_READ_IMPLIES_EXEC; | ||||
} | } | ||||
#endif | #endif | ||||
return (0); | |||||
} | } | ||||
void | void | ||||
linux_thread_dtor(struct thread *td) | linux_thread_dtor(struct thread *td) | ||||
{ | { | ||||
struct linux_emuldata *em; | struct linux_emuldata *em; | ||||
em = em_find(td); | em = em_find(td); | ||||
Show All 32 Lines |