1ad2056f2SAlexander Leidinger /*- 2ad2056f2SAlexander Leidinger * Copyright (c) 2006 Roman Divacky 381338031SDmitry Chagin * Copyright (c) 2013 Dmitry Chagin 4ad2056f2SAlexander Leidinger * All rights reserved. 5ad2056f2SAlexander Leidinger * 6ad2056f2SAlexander Leidinger * Redistribution and use in source and binary forms, with or without 7ad2056f2SAlexander Leidinger * modification, are permitted provided that the following conditions 8ad2056f2SAlexander Leidinger * are met: 9ad2056f2SAlexander Leidinger * 1. Redistributions of source code must retain the above copyright 10ad2056f2SAlexander Leidinger * notice, this list of conditions and the following disclaimer 11ad2056f2SAlexander Leidinger * in this position and unchanged. 12ad2056f2SAlexander Leidinger * 2. Redistributions in binary form must reproduce the above copyright 13ad2056f2SAlexander Leidinger * notice, this list of conditions and the following disclaimer in the 14ad2056f2SAlexander Leidinger * documentation and/or other materials provided with the distribution. 15ad2056f2SAlexander Leidinger * 3. The name of the author may not be used to endorse or promote products 16ad2056f2SAlexander Leidinger * derived from this software without specific prior written permission 17ad2056f2SAlexander Leidinger * 18ad2056f2SAlexander Leidinger * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 19ad2056f2SAlexander Leidinger * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 20ad2056f2SAlexander Leidinger * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 21ad2056f2SAlexander Leidinger * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 22ad2056f2SAlexander Leidinger * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 23ad2056f2SAlexander Leidinger * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 24ad2056f2SAlexander Leidinger * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 25ad2056f2SAlexander Leidinger * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 26ad2056f2SAlexander Leidinger * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 27ad2056f2SAlexander Leidinger * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 28ad2056f2SAlexander Leidinger */ 29ad2056f2SAlexander Leidinger 30ad2056f2SAlexander Leidinger #include <sys/cdefs.h> 31ad2056f2SAlexander Leidinger __FBSDID("$FreeBSD$"); 32ad2056f2SAlexander Leidinger 33ad2056f2SAlexander Leidinger #include <sys/param.h> 34ad2056f2SAlexander Leidinger #include <sys/systm.h> 35ad2056f2SAlexander Leidinger #include <sys/imgact.h> 36b4bb5154SKonstantin Belousov #include <sys/kernel.h> 3781338031SDmitry Chagin #include <sys/ktr.h> 38ad2056f2SAlexander Leidinger #include <sys/lock.h> 39ad2056f2SAlexander Leidinger #include <sys/malloc.h> 40ad2056f2SAlexander Leidinger #include <sys/mutex.h> 41ad2056f2SAlexander Leidinger #include <sys/sx.h> 42ad2056f2SAlexander Leidinger #include <sys/proc.h> 43ad2056f2SAlexander Leidinger #include <sys/syscallsubr.h> 4495353459SDimitry Andric #include <sys/sysent.h> 45ad2056f2SAlexander Leidinger 464732e446SRoman Divacky #include <compat/linux/linux_emul.h> 47d825ce0aSJohn Baldwin #include <compat/linux/linux_misc.h> 4881338031SDmitry Chagin #include <compat/linux/linux_util.h> 494732e446SRoman Divacky 5019e252baSAlexander Leidinger 5181338031SDmitry Chagin /* 52bc273677SDmitry Chagin * This returns reference to the thread emuldata entry (if found) 5381338031SDmitry Chagin * 5481338031SDmitry Chagin * Hold PROC_LOCK when referencing emuldata from other threads. 5581338031SDmitry Chagin */ 56ad2056f2SAlexander Leidinger struct linux_emuldata * 5781338031SDmitry Chagin em_find(struct thread *td) 58ad2056f2SAlexander Leidinger { 59ad2056f2SAlexander Leidinger struct linux_emuldata *em; 60ad2056f2SAlexander Leidinger 6181338031SDmitry Chagin em = td->td_emuldata; 62ad2056f2SAlexander Leidinger 63ad2056f2SAlexander Leidinger return (em); 64ad2056f2SAlexander Leidinger } 65ad2056f2SAlexander Leidinger 66bc273677SDmitry Chagin /* 67bc273677SDmitry Chagin * This returns reference to the proc pemuldata entry (if found) 68bc273677SDmitry Chagin * 69bc273677SDmitry Chagin * Hold PROC_LOCK when referencing proc pemuldata from other threads. 70bc273677SDmitry Chagin * Hold LINUX_PEM_LOCK wher referencing pemuldata members. 71bc273677SDmitry Chagin */ 72bc273677SDmitry Chagin struct linux_pemuldata * 73bc273677SDmitry Chagin pem_find(struct proc *p) 74bc273677SDmitry Chagin { 75bc273677SDmitry Chagin struct linux_pemuldata *pem; 76bc273677SDmitry Chagin 77bc273677SDmitry Chagin pem = p->p_emuldata; 78bc273677SDmitry Chagin 79bc273677SDmitry Chagin return (pem); 80bc273677SDmitry Chagin } 81bc273677SDmitry Chagin 8281338031SDmitry Chagin void 8381338031SDmitry Chagin linux_proc_init(struct thread *td, struct thread *newtd, int flags) 84ad2056f2SAlexander Leidinger { 8581338031SDmitry Chagin struct linux_emuldata *em; 86bc273677SDmitry Chagin struct linux_pemuldata *pem; 87*e16fe1c7SDmitry Chagin struct epoll_emuldata *emd; 8819e252baSAlexander Leidinger 8981338031SDmitry Chagin if (newtd != NULL) { 9081338031SDmitry Chagin /* non-exec call */ 9181338031SDmitry Chagin em = malloc(sizeof(*em), M_TEMP, M_WAITOK | M_ZERO); 92955d762aSAlexander Leidinger em->pdeath_signal = 0; 934732e446SRoman Divacky em->robust_futexes = NULL; 94a4e3bad7SJung-uk Kim if (flags & LINUX_CLONE_THREAD) { 95*e16fe1c7SDmitry Chagin LINUX_CTR1(proc_init, "thread newtd(%d)", 96*e16fe1c7SDmitry Chagin newtd->td_tid); 97*e16fe1c7SDmitry Chagin 9881338031SDmitry Chagin em->em_tid = newtd->td_tid; 9981338031SDmitry Chagin } else { 100*e16fe1c7SDmitry Chagin LINUX_CTR1(proc_init, "fork newtd(%d)", 101*e16fe1c7SDmitry Chagin newtd->td_proc->p_pid); 10219e252baSAlexander Leidinger 10381338031SDmitry Chagin em->em_tid = newtd->td_proc->p_pid; 104bc273677SDmitry Chagin 105e0d3ea8cSDmitry Chagin pem = malloc(sizeof(*pem), M_LINUX, M_WAITOK | M_ZERO); 106bc273677SDmitry Chagin sx_init(&pem->pem_sx, "lpemlk"); 107bc273677SDmitry Chagin newtd->td_proc->p_emuldata = pem; 108ad2056f2SAlexander Leidinger } 10981338031SDmitry Chagin newtd->td_emuldata = em; 110ad2056f2SAlexander Leidinger } else { 11119e252baSAlexander Leidinger /* exec */ 112*e16fe1c7SDmitry Chagin LINUX_CTR1(proc_init, "exec newtd(%d)", 113*e16fe1c7SDmitry Chagin td->td_proc->p_pid); 11419e252baSAlexander Leidinger 115ad2056f2SAlexander Leidinger /* lookup the old one */ 11681338031SDmitry Chagin em = em_find(td); 117ad2056f2SAlexander Leidinger KASSERT(em != NULL, ("proc_init: emuldata not found in exec case.\n")); 11881338031SDmitry Chagin 11981338031SDmitry Chagin em->em_tid = td->td_proc->p_pid; 120*e16fe1c7SDmitry Chagin 121*e16fe1c7SDmitry Chagin /* epoll should be destroyed in a case of exec. */ 122*e16fe1c7SDmitry Chagin pem = pem_find(td->td_proc); 123*e16fe1c7SDmitry Chagin KASSERT(pem != NULL, ("proc_exit: proc emuldata not found.\n")); 124*e16fe1c7SDmitry Chagin 125*e16fe1c7SDmitry Chagin if (pem->epoll != NULL) { 126*e16fe1c7SDmitry Chagin emd = pem->epoll; 127*e16fe1c7SDmitry Chagin pem->epoll = NULL; 128*e16fe1c7SDmitry Chagin free(emd, M_EPOLL); 129*e16fe1c7SDmitry Chagin } 130ad2056f2SAlexander Leidinger } 131ad2056f2SAlexander Leidinger 132ad2056f2SAlexander Leidinger em->child_clear_tid = NULL; 133ad2056f2SAlexander Leidinger em->child_set_tid = NULL; 134ad2056f2SAlexander Leidinger } 135ad2056f2SAlexander Leidinger 136ad2056f2SAlexander Leidinger void 137ad2056f2SAlexander Leidinger linux_proc_exit(void *arg __unused, struct proc *p) 138ad2056f2SAlexander Leidinger { 139bc273677SDmitry Chagin struct linux_pemuldata *pem; 140*e16fe1c7SDmitry Chagin struct epoll_emuldata *emd; 14181338031SDmitry Chagin struct thread *td = curthread; 142ad2056f2SAlexander Leidinger 143bc273677SDmitry Chagin if (__predict_false(SV_CURPROC_ABI() != SV_ABI_LINUX)) 144bc273677SDmitry Chagin return; 145bc273677SDmitry Chagin 146bc273677SDmitry Chagin pem = pem_find(p); 147bc273677SDmitry Chagin if (pem == NULL) 148bc273677SDmitry Chagin return; 14981338031SDmitry Chagin (p->p_sysent->sv_thread_detach)(td); 150bc273677SDmitry Chagin 151bc273677SDmitry Chagin p->p_emuldata = NULL; 152bc273677SDmitry Chagin 153*e16fe1c7SDmitry Chagin if (pem->epoll != NULL) { 154*e16fe1c7SDmitry Chagin emd = pem->epoll; 155*e16fe1c7SDmitry Chagin pem->epoll = NULL; 156*e16fe1c7SDmitry Chagin free(emd, M_EPOLL); 157*e16fe1c7SDmitry Chagin } 158*e16fe1c7SDmitry Chagin 159bc273677SDmitry Chagin sx_destroy(&pem->pem_sx); 160e0d3ea8cSDmitry Chagin free(pem, M_LINUX); 161e8b8b834SAlexander Leidinger } 162ad2056f2SAlexander Leidinger 16381338031SDmitry Chagin int 16481338031SDmitry Chagin linux_common_execve(struct thread *td, struct image_args *eargs) 16581338031SDmitry Chagin { 166bc273677SDmitry Chagin struct linux_pemuldata *pem; 167*e16fe1c7SDmitry Chagin struct epoll_emuldata *emd; 16881338031SDmitry Chagin struct linux_emuldata *em; 16981338031SDmitry Chagin struct proc *p; 17081338031SDmitry Chagin int error; 171ad2056f2SAlexander Leidinger 17281338031SDmitry Chagin p = td->td_proc; 173ad2056f2SAlexander Leidinger 17481338031SDmitry Chagin /* 17581338031SDmitry Chagin * Unlike FreeBSD abort all other threads before 17681338031SDmitry Chagin * proceeding exec. 17781338031SDmitry Chagin */ 17881338031SDmitry Chagin PROC_LOCK(p); 17981338031SDmitry Chagin /* See exit1() comments. */ 18081338031SDmitry Chagin thread_suspend_check(0); 18181338031SDmitry Chagin while (p->p_flag & P_HADTHREADS) { 18281338031SDmitry Chagin if (!thread_single(p, SINGLE_EXIT)) 18381338031SDmitry Chagin break; 18481338031SDmitry Chagin thread_suspend_check(0); 18581338031SDmitry Chagin } 18681338031SDmitry Chagin PROC_UNLOCK(p); 18781338031SDmitry Chagin 18881338031SDmitry Chagin error = kern_execve(td, eargs, NULL); 18981338031SDmitry Chagin if (error != 0) 19081338031SDmitry Chagin return (error); 19181338031SDmitry Chagin 19281338031SDmitry Chagin /* 19381338031SDmitry Chagin * In a case of transition from Linux binary execing to 194bc273677SDmitry Chagin * FreeBSD binary we destroy linux emuldata thread & proc entries. 19581338031SDmitry Chagin */ 19681338031SDmitry Chagin if (SV_CURPROC_ABI() != SV_ABI_LINUX) { 19781338031SDmitry Chagin PROC_LOCK(p); 19881338031SDmitry Chagin em = em_find(td); 199bc273677SDmitry Chagin KASSERT(em != NULL, ("proc_exec: thread emuldata not found.\n")); 20081338031SDmitry Chagin td->td_emuldata = NULL; 201bc273677SDmitry Chagin 202bc273677SDmitry Chagin pem = pem_find(p); 203bc273677SDmitry Chagin KASSERT(pem != NULL, ("proc_exec: proc pemuldata not found.\n")); 204bc273677SDmitry Chagin p->p_emuldata = NULL; 20581338031SDmitry Chagin PROC_UNLOCK(p); 20681338031SDmitry Chagin 207*e16fe1c7SDmitry Chagin if (pem->epoll != NULL) { 208*e16fe1c7SDmitry Chagin emd = pem->epoll; 209*e16fe1c7SDmitry Chagin pem->epoll = NULL; 210*e16fe1c7SDmitry Chagin free(emd, M_EPOLL); 211*e16fe1c7SDmitry Chagin } 212*e16fe1c7SDmitry Chagin 21381338031SDmitry Chagin free(em, M_TEMP); 214e0d3ea8cSDmitry Chagin free(pem, M_LINUX); 21581338031SDmitry Chagin } 21681338031SDmitry Chagin return (0); 21781338031SDmitry Chagin } 21881338031SDmitry Chagin 21981338031SDmitry Chagin void 22081338031SDmitry Chagin linux_proc_exec(void *arg __unused, struct proc *p, struct image_params *imgp) 22181338031SDmitry Chagin { 22281338031SDmitry Chagin struct thread *td = curthread; 22381338031SDmitry Chagin 22481338031SDmitry Chagin /* 22581338031SDmitry Chagin * In a case of execing to linux binary we create linux 22681338031SDmitry Chagin * emuldata thread entry. 22781338031SDmitry Chagin */ 22881338031SDmitry Chagin if (__predict_false((imgp->sysent->sv_flags & SV_ABI_MASK) == 22981338031SDmitry Chagin SV_ABI_LINUX)) { 230*e16fe1c7SDmitry Chagin 23181338031SDmitry Chagin if (SV_PROC_ABI(p) == SV_ABI_LINUX) 23281338031SDmitry Chagin linux_proc_init(td, NULL, 0); 23381338031SDmitry Chagin else 23481338031SDmitry Chagin linux_proc_init(td, td, 0); 23581338031SDmitry Chagin } 23681338031SDmitry Chagin } 23781338031SDmitry Chagin 23881338031SDmitry Chagin void 23981338031SDmitry Chagin linux_thread_dtor(void *arg __unused, struct thread *td) 240ad2056f2SAlexander Leidinger { 241ad2056f2SAlexander Leidinger struct linux_emuldata *em; 242ad2056f2SAlexander Leidinger 24381338031SDmitry Chagin em = em_find(td); 24481338031SDmitry Chagin if (em == NULL) 24581338031SDmitry Chagin return; 24681338031SDmitry Chagin td->td_emuldata = NULL; 247ad2056f2SAlexander Leidinger 24881338031SDmitry Chagin LINUX_CTR1(exit, "thread dtor(%d)", em->em_tid); 249ad2056f2SAlexander Leidinger 25081338031SDmitry Chagin free(em, M_TEMP); 251ad2056f2SAlexander Leidinger } 252ad2056f2SAlexander Leidinger 253ad2056f2SAlexander Leidinger void 254e5d81ef1SDmitry Chagin linux_schedtail(struct thread *td) 255ad2056f2SAlexander Leidinger { 256ad2056f2SAlexander Leidinger struct linux_emuldata *em; 257e5d81ef1SDmitry Chagin struct proc *p; 258ad2056f2SAlexander Leidinger int error = 0; 259ad2056f2SAlexander Leidinger int *child_set_tid; 260ad2056f2SAlexander Leidinger 261e5d81ef1SDmitry Chagin p = td->td_proc; 262e5d81ef1SDmitry Chagin 26381338031SDmitry Chagin em = em_find(td); 264bc273677SDmitry Chagin KASSERT(em != NULL, ("linux_schedtail: thread emuldata not found.\n")); 265ad2056f2SAlexander Leidinger child_set_tid = em->child_set_tid; 266ad2056f2SAlexander Leidinger 26719e252baSAlexander Leidinger if (child_set_tid != NULL) { 26881338031SDmitry Chagin error = copyout(&em->em_tid, (int *)child_set_tid, 26981338031SDmitry Chagin sizeof(em->em_tid)); 27081338031SDmitry Chagin LINUX_CTR4(clone, "schedtail(%d) %p stored %d error %d", 27181338031SDmitry Chagin td->td_tid, child_set_tid, em->em_tid, error); 27281338031SDmitry Chagin } else 27381338031SDmitry Chagin LINUX_CTR1(clone, "schedtail(%d)", em->em_tid); 274bb63fddeSAlexander Leidinger } 275