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 #include <sys/sysproto.h> 46ad2056f2SAlexander Leidinger #include <sys/unistd.h> 47ad2056f2SAlexander Leidinger 484732e446SRoman Divacky #include <compat/linux/linux_emul.h> 49d825ce0aSJohn Baldwin #include <compat/linux/linux_misc.h> 5081338031SDmitry Chagin #include <compat/linux/linux_util.h> 514732e446SRoman Divacky 5219e252baSAlexander Leidinger 5381338031SDmitry Chagin /* 54*bc273677SDmitry Chagin * This returns reference to the thread emuldata entry (if found) 5581338031SDmitry Chagin * 5681338031SDmitry Chagin * Hold PROC_LOCK when referencing emuldata from other threads. 5781338031SDmitry Chagin */ 58ad2056f2SAlexander Leidinger struct linux_emuldata * 5981338031SDmitry Chagin em_find(struct thread *td) 60ad2056f2SAlexander Leidinger { 61ad2056f2SAlexander Leidinger struct linux_emuldata *em; 62ad2056f2SAlexander Leidinger 6381338031SDmitry Chagin em = td->td_emuldata; 64ad2056f2SAlexander Leidinger 65ad2056f2SAlexander Leidinger return (em); 66ad2056f2SAlexander Leidinger } 67ad2056f2SAlexander Leidinger 68*bc273677SDmitry Chagin /* 69*bc273677SDmitry Chagin * This returns reference to the proc pemuldata entry (if found) 70*bc273677SDmitry Chagin * 71*bc273677SDmitry Chagin * Hold PROC_LOCK when referencing proc pemuldata from other threads. 72*bc273677SDmitry Chagin * Hold LINUX_PEM_LOCK wher referencing pemuldata members. 73*bc273677SDmitry Chagin */ 74*bc273677SDmitry Chagin struct linux_pemuldata * 75*bc273677SDmitry Chagin pem_find(struct proc *p) 76*bc273677SDmitry Chagin { 77*bc273677SDmitry Chagin struct linux_pemuldata *pem; 78*bc273677SDmitry Chagin 79*bc273677SDmitry Chagin pem = p->p_emuldata; 80*bc273677SDmitry Chagin 81*bc273677SDmitry Chagin return (pem); 82*bc273677SDmitry Chagin } 83*bc273677SDmitry Chagin 8481338031SDmitry Chagin void 8581338031SDmitry Chagin linux_proc_init(struct thread *td, struct thread *newtd, int flags) 86ad2056f2SAlexander Leidinger { 8781338031SDmitry Chagin struct linux_emuldata *em; 88*bc273677SDmitry Chagin struct linux_pemuldata *pem; 8919e252baSAlexander Leidinger 9081338031SDmitry Chagin if (newtd != NULL) { 9181338031SDmitry Chagin /* non-exec call */ 9281338031SDmitry Chagin em = malloc(sizeof(*em), M_TEMP, M_WAITOK | M_ZERO); 93955d762aSAlexander Leidinger em->pdeath_signal = 0; 944732e446SRoman Divacky em->robust_futexes = NULL; 95a4e3bad7SJung-uk Kim if (flags & LINUX_CLONE_THREAD) { 9681338031SDmitry Chagin em->em_tid = newtd->td_tid; 9781338031SDmitry Chagin } else { 9819e252baSAlexander Leidinger 9981338031SDmitry Chagin em->em_tid = newtd->td_proc->p_pid; 100*bc273677SDmitry Chagin 101*bc273677SDmitry Chagin pem = malloc(sizeof(*pem), M_TEMP, M_WAITOK | M_ZERO); 102*bc273677SDmitry Chagin sx_init(&pem->pem_sx, "lpemlk"); 103*bc273677SDmitry Chagin newtd->td_proc->p_emuldata = pem; 104ad2056f2SAlexander Leidinger } 10581338031SDmitry Chagin newtd->td_emuldata = em; 106ad2056f2SAlexander Leidinger } else { 10719e252baSAlexander Leidinger /* exec */ 10819e252baSAlexander Leidinger 109ad2056f2SAlexander Leidinger /* lookup the old one */ 11081338031SDmitry Chagin em = em_find(td); 111ad2056f2SAlexander Leidinger KASSERT(em != NULL, ("proc_init: emuldata not found in exec case.\n")); 11281338031SDmitry Chagin 11381338031SDmitry Chagin em->em_tid = td->td_proc->p_pid; 114ad2056f2SAlexander Leidinger } 115ad2056f2SAlexander Leidinger 116ad2056f2SAlexander Leidinger em->child_clear_tid = NULL; 117ad2056f2SAlexander Leidinger em->child_set_tid = NULL; 118ad2056f2SAlexander Leidinger } 119ad2056f2SAlexander Leidinger 120ad2056f2SAlexander Leidinger void 121ad2056f2SAlexander Leidinger linux_proc_exit(void *arg __unused, struct proc *p) 122ad2056f2SAlexander Leidinger { 123*bc273677SDmitry Chagin struct linux_pemuldata *pem; 12481338031SDmitry Chagin struct thread *td = curthread; 125ad2056f2SAlexander Leidinger 126*bc273677SDmitry Chagin if (__predict_false(SV_CURPROC_ABI() != SV_ABI_LINUX)) 127*bc273677SDmitry Chagin return; 128*bc273677SDmitry Chagin 129*bc273677SDmitry Chagin pem = pem_find(p); 130*bc273677SDmitry Chagin if (pem == NULL) 131*bc273677SDmitry Chagin return; 13281338031SDmitry Chagin (p->p_sysent->sv_thread_detach)(td); 133*bc273677SDmitry Chagin 134*bc273677SDmitry Chagin p->p_emuldata = NULL; 135*bc273677SDmitry Chagin 136*bc273677SDmitry Chagin sx_destroy(&pem->pem_sx); 137*bc273677SDmitry Chagin free(pem, M_TEMP); 138e8b8b834SAlexander Leidinger } 139ad2056f2SAlexander Leidinger 14081338031SDmitry Chagin int 14181338031SDmitry Chagin linux_common_execve(struct thread *td, struct image_args *eargs) 14281338031SDmitry Chagin { 143*bc273677SDmitry Chagin struct linux_pemuldata *pem; 14481338031SDmitry Chagin struct linux_emuldata *em; 14581338031SDmitry Chagin struct proc *p; 14681338031SDmitry Chagin int error; 147ad2056f2SAlexander Leidinger 14881338031SDmitry Chagin p = td->td_proc; 149ad2056f2SAlexander Leidinger 15081338031SDmitry Chagin /* 15181338031SDmitry Chagin * Unlike FreeBSD abort all other threads before 15281338031SDmitry Chagin * proceeding exec. 15381338031SDmitry Chagin */ 15481338031SDmitry Chagin PROC_LOCK(p); 15581338031SDmitry Chagin /* See exit1() comments. */ 15681338031SDmitry Chagin thread_suspend_check(0); 15781338031SDmitry Chagin while (p->p_flag & P_HADTHREADS) { 15881338031SDmitry Chagin if (!thread_single(p, SINGLE_EXIT)) 15981338031SDmitry Chagin break; 16081338031SDmitry Chagin thread_suspend_check(0); 16181338031SDmitry Chagin } 16281338031SDmitry Chagin PROC_UNLOCK(p); 16381338031SDmitry Chagin 16481338031SDmitry Chagin error = kern_execve(td, eargs, NULL); 16581338031SDmitry Chagin if (error != 0) 16681338031SDmitry Chagin return (error); 16781338031SDmitry Chagin 16881338031SDmitry Chagin /* 16981338031SDmitry Chagin * In a case of transition from Linux binary execing to 170*bc273677SDmitry Chagin * FreeBSD binary we destroy linux emuldata thread & proc entries. 17181338031SDmitry Chagin */ 17281338031SDmitry Chagin if (SV_CURPROC_ABI() != SV_ABI_LINUX) { 17381338031SDmitry Chagin PROC_LOCK(p); 17481338031SDmitry Chagin em = em_find(td); 175*bc273677SDmitry Chagin KASSERT(em != NULL, ("proc_exec: thread emuldata not found.\n")); 17681338031SDmitry Chagin td->td_emuldata = NULL; 177*bc273677SDmitry Chagin 178*bc273677SDmitry Chagin pem = pem_find(p); 179*bc273677SDmitry Chagin KASSERT(pem != NULL, ("proc_exec: proc pemuldata not found.\n")); 180*bc273677SDmitry Chagin p->p_emuldata = NULL; 18181338031SDmitry Chagin PROC_UNLOCK(p); 18281338031SDmitry Chagin 18381338031SDmitry Chagin free(em, M_TEMP); 184*bc273677SDmitry Chagin free(pem, M_TEMP); 18581338031SDmitry Chagin } 18681338031SDmitry Chagin return (0); 18781338031SDmitry Chagin } 18881338031SDmitry Chagin 18981338031SDmitry Chagin void 19081338031SDmitry Chagin linux_proc_exec(void *arg __unused, struct proc *p, struct image_params *imgp) 19181338031SDmitry Chagin { 19281338031SDmitry Chagin struct thread *td = curthread; 19381338031SDmitry Chagin 19481338031SDmitry Chagin /* 19581338031SDmitry Chagin * In a case of execing to linux binary we create linux 19681338031SDmitry Chagin * emuldata thread entry. 19781338031SDmitry Chagin */ 19881338031SDmitry Chagin if (__predict_false((imgp->sysent->sv_flags & SV_ABI_MASK) == 19981338031SDmitry Chagin SV_ABI_LINUX)) { 20081338031SDmitry Chagin if (SV_PROC_ABI(p) == SV_ABI_LINUX) 20181338031SDmitry Chagin linux_proc_init(td, NULL, 0); 20281338031SDmitry Chagin else 20381338031SDmitry Chagin linux_proc_init(td, td, 0); 20481338031SDmitry Chagin } 20581338031SDmitry Chagin } 20681338031SDmitry Chagin 20781338031SDmitry Chagin void 20881338031SDmitry Chagin linux_thread_dtor(void *arg __unused, struct thread *td) 209ad2056f2SAlexander Leidinger { 210ad2056f2SAlexander Leidinger struct linux_emuldata *em; 211ad2056f2SAlexander Leidinger 21281338031SDmitry Chagin em = em_find(td); 21381338031SDmitry Chagin if (em == NULL) 21481338031SDmitry Chagin return; 21581338031SDmitry Chagin td->td_emuldata = NULL; 216ad2056f2SAlexander Leidinger 21781338031SDmitry Chagin LINUX_CTR1(exit, "thread dtor(%d)", em->em_tid); 218ad2056f2SAlexander Leidinger 21981338031SDmitry Chagin free(em, M_TEMP); 220ad2056f2SAlexander Leidinger } 221ad2056f2SAlexander Leidinger 222ad2056f2SAlexander Leidinger void 223e5d81ef1SDmitry Chagin linux_schedtail(struct thread *td) 224ad2056f2SAlexander Leidinger { 225ad2056f2SAlexander Leidinger struct linux_emuldata *em; 226e5d81ef1SDmitry Chagin struct proc *p; 227ad2056f2SAlexander Leidinger int error = 0; 228ad2056f2SAlexander Leidinger int *child_set_tid; 229ad2056f2SAlexander Leidinger 230e5d81ef1SDmitry Chagin p = td->td_proc; 231e5d81ef1SDmitry Chagin 23281338031SDmitry Chagin em = em_find(td); 233*bc273677SDmitry Chagin KASSERT(em != NULL, ("linux_schedtail: thread emuldata not found.\n")); 234ad2056f2SAlexander Leidinger child_set_tid = em->child_set_tid; 235ad2056f2SAlexander Leidinger 23619e252baSAlexander Leidinger if (child_set_tid != NULL) { 23781338031SDmitry Chagin error = copyout(&em->em_tid, (int *)child_set_tid, 23881338031SDmitry Chagin sizeof(em->em_tid)); 23981338031SDmitry Chagin LINUX_CTR4(clone, "schedtail(%d) %p stored %d error %d", 24081338031SDmitry Chagin td->td_tid, child_set_tid, em->em_tid, error); 24181338031SDmitry Chagin } else 24281338031SDmitry Chagin LINUX_CTR1(clone, "schedtail(%d)", em->em_tid); 243bb63fddeSAlexander Leidinger } 244