1ad2056f2SAlexander Leidinger /*- 2*023b850bSEd Maste * SPDX-License-Identifier: BSD-2-Clause-FreeBSD 37f2d13d6SPedro F. Giffuni * 4ad2056f2SAlexander Leidinger * Copyright (c) 2006 Roman Divacky 581338031SDmitry Chagin * Copyright (c) 2013 Dmitry Chagin 6ad2056f2SAlexander Leidinger * All rights reserved. 7ad2056f2SAlexander Leidinger * 8ad2056f2SAlexander Leidinger * Redistribution and use in source and binary forms, with or without 9ad2056f2SAlexander Leidinger * modification, are permitted provided that the following conditions 10ad2056f2SAlexander Leidinger * are met: 11ad2056f2SAlexander Leidinger * 1. Redistributions of source code must retain the above copyright 12*023b850bSEd Maste * notice, this list of conditions and the following disclaimer. 13ad2056f2SAlexander Leidinger * 2. Redistributions in binary form must reproduce the above copyright 14ad2056f2SAlexander Leidinger * notice, this list of conditions and the following disclaimer in the 15ad2056f2SAlexander Leidinger * documentation and/or other materials provided with the distribution. 16ad2056f2SAlexander Leidinger * 17*023b850bSEd Maste * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 18*023b850bSEd Maste * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 19*023b850bSEd Maste * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 20*023b850bSEd Maste * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 21*023b850bSEd Maste * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 22*023b850bSEd Maste * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 23*023b850bSEd Maste * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 24*023b850bSEd Maste * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 25*023b850bSEd Maste * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 26*023b850bSEd Maste * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 27*023b850bSEd Maste * 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> 4823e8912cSDmitry Chagin #include <compat/linux/linux_persona.h> 4981338031SDmitry Chagin #include <compat/linux/linux_util.h> 504732e446SRoman Divacky 5119e252baSAlexander Leidinger 5281338031SDmitry Chagin /* 53bc273677SDmitry Chagin * This returns reference to the thread emuldata entry (if found) 5481338031SDmitry Chagin * 5581338031SDmitry Chagin * Hold PROC_LOCK when referencing emuldata from other threads. 5681338031SDmitry Chagin */ 57ad2056f2SAlexander Leidinger struct linux_emuldata * 5881338031SDmitry Chagin em_find(struct thread *td) 59ad2056f2SAlexander Leidinger { 60ad2056f2SAlexander Leidinger struct linux_emuldata *em; 61ad2056f2SAlexander Leidinger 6281338031SDmitry Chagin em = td->td_emuldata; 63ad2056f2SAlexander Leidinger 64ad2056f2SAlexander Leidinger return (em); 65ad2056f2SAlexander Leidinger } 66ad2056f2SAlexander Leidinger 67bc273677SDmitry Chagin /* 68bc273677SDmitry Chagin * This returns reference to the proc pemuldata entry (if found) 69bc273677SDmitry Chagin * 70bc273677SDmitry Chagin * Hold PROC_LOCK when referencing proc pemuldata from other threads. 71bc273677SDmitry Chagin * Hold LINUX_PEM_LOCK wher referencing pemuldata members. 72bc273677SDmitry Chagin */ 73bc273677SDmitry Chagin struct linux_pemuldata * 74bc273677SDmitry Chagin pem_find(struct proc *p) 75bc273677SDmitry Chagin { 76bc273677SDmitry Chagin struct linux_pemuldata *pem; 77bc273677SDmitry Chagin 78bc273677SDmitry Chagin pem = p->p_emuldata; 79bc273677SDmitry Chagin 80bc273677SDmitry Chagin return (pem); 81bc273677SDmitry Chagin } 82bc273677SDmitry Chagin 8381338031SDmitry Chagin void 8481338031SDmitry Chagin linux_proc_init(struct thread *td, struct thread *newtd, int flags) 85ad2056f2SAlexander Leidinger { 8681338031SDmitry Chagin struct linux_emuldata *em; 87bc273677SDmitry Chagin struct linux_pemuldata *pem; 88e16fe1c7SDmitry Chagin struct epoll_emuldata *emd; 8968cf0367SDmitry Chagin struct proc *p; 9019e252baSAlexander Leidinger 9181338031SDmitry Chagin if (newtd != NULL) { 9268cf0367SDmitry Chagin p = newtd->td_proc; 9368cf0367SDmitry Chagin 9481338031SDmitry Chagin /* non-exec call */ 9581338031SDmitry Chagin em = malloc(sizeof(*em), M_TEMP, M_WAITOK | M_ZERO); 96a4e3bad7SJung-uk Kim if (flags & LINUX_CLONE_THREAD) { 97e16fe1c7SDmitry Chagin LINUX_CTR1(proc_init, "thread newtd(%d)", 98e16fe1c7SDmitry Chagin newtd->td_tid); 99e16fe1c7SDmitry Chagin 10081338031SDmitry Chagin em->em_tid = newtd->td_tid; 10181338031SDmitry Chagin } else { 10268cf0367SDmitry Chagin LINUX_CTR1(proc_init, "fork newtd(%d)", p->p_pid); 10319e252baSAlexander Leidinger 10468cf0367SDmitry Chagin em->em_tid = p->p_pid; 105bc273677SDmitry Chagin 106e0d3ea8cSDmitry Chagin pem = malloc(sizeof(*pem), M_LINUX, M_WAITOK | M_ZERO); 107bc273677SDmitry Chagin sx_init(&pem->pem_sx, "lpemlk"); 10868cf0367SDmitry Chagin p->p_emuldata = pem; 109ad2056f2SAlexander Leidinger } 11081338031SDmitry Chagin newtd->td_emuldata = em; 111ad2056f2SAlexander Leidinger } else { 11268cf0367SDmitry Chagin p = td->td_proc; 11368cf0367SDmitry Chagin 11419e252baSAlexander Leidinger /* exec */ 11568cf0367SDmitry Chagin LINUX_CTR1(proc_init, "exec newtd(%d)", p->p_pid); 11619e252baSAlexander Leidinger 117ad2056f2SAlexander Leidinger /* lookup the old one */ 11881338031SDmitry Chagin em = em_find(td); 119ad2056f2SAlexander Leidinger KASSERT(em != NULL, ("proc_init: emuldata not found in exec case.\n")); 12081338031SDmitry Chagin 12168cf0367SDmitry Chagin em->em_tid = p->p_pid; 12297cfa5c8SDmitry Chagin em->flags = 0; 12397cfa5c8SDmitry Chagin em->pdeath_signal = 0; 12497cfa5c8SDmitry Chagin em->robust_futexes = NULL; 12597cfa5c8SDmitry Chagin em->child_clear_tid = NULL; 12697cfa5c8SDmitry Chagin em->child_set_tid = NULL; 127e16fe1c7SDmitry Chagin 128e16fe1c7SDmitry Chagin /* epoll should be destroyed in a case of exec. */ 12968cf0367SDmitry Chagin pem = pem_find(p); 130e16fe1c7SDmitry Chagin KASSERT(pem != NULL, ("proc_exit: proc emuldata not found.\n")); 13123e8912cSDmitry Chagin pem->persona = 0; 132e16fe1c7SDmitry Chagin if (pem->epoll != NULL) { 133e16fe1c7SDmitry Chagin emd = pem->epoll; 134e16fe1c7SDmitry Chagin pem->epoll = NULL; 135e16fe1c7SDmitry Chagin free(emd, M_EPOLL); 136e16fe1c7SDmitry Chagin } 137ad2056f2SAlexander Leidinger } 138ad2056f2SAlexander Leidinger 139ad2056f2SAlexander Leidinger } 140ad2056f2SAlexander Leidinger 141ad2056f2SAlexander Leidinger void 142ad2056f2SAlexander Leidinger linux_proc_exit(void *arg __unused, struct proc *p) 143ad2056f2SAlexander Leidinger { 144bc273677SDmitry Chagin struct linux_pemuldata *pem; 145e16fe1c7SDmitry Chagin struct epoll_emuldata *emd; 14681338031SDmitry Chagin struct thread *td = curthread; 147ad2056f2SAlexander Leidinger 148bc273677SDmitry Chagin if (__predict_false(SV_CURPROC_ABI() != SV_ABI_LINUX)) 149bc273677SDmitry Chagin return; 150bc273677SDmitry Chagin 1517d96520bSDmitry Chagin LINUX_CTR3(proc_exit, "thread(%d) proc(%d) p %p", 1527d96520bSDmitry Chagin td->td_tid, p->p_pid, p); 1537d96520bSDmitry Chagin 154bc273677SDmitry Chagin pem = pem_find(p); 155bc273677SDmitry Chagin if (pem == NULL) 156bc273677SDmitry Chagin return; 15781338031SDmitry Chagin (p->p_sysent->sv_thread_detach)(td); 158bc273677SDmitry Chagin 159bc273677SDmitry Chagin p->p_emuldata = NULL; 160bc273677SDmitry Chagin 161e16fe1c7SDmitry Chagin if (pem->epoll != NULL) { 162e16fe1c7SDmitry Chagin emd = pem->epoll; 163e16fe1c7SDmitry Chagin pem->epoll = NULL; 164e16fe1c7SDmitry Chagin free(emd, M_EPOLL); 165e16fe1c7SDmitry Chagin } 166e16fe1c7SDmitry Chagin 167bc273677SDmitry Chagin sx_destroy(&pem->pem_sx); 168e0d3ea8cSDmitry Chagin free(pem, M_LINUX); 169e8b8b834SAlexander Leidinger } 170ad2056f2SAlexander Leidinger 17181338031SDmitry Chagin int 17281338031SDmitry Chagin linux_common_execve(struct thread *td, struct image_args *eargs) 17381338031SDmitry Chagin { 174bc273677SDmitry Chagin struct linux_pemuldata *pem; 175e16fe1c7SDmitry Chagin struct epoll_emuldata *emd; 176d707582fSDmitry Chagin struct vmspace *oldvmspace; 17781338031SDmitry Chagin struct linux_emuldata *em; 17881338031SDmitry Chagin struct proc *p; 17981338031SDmitry Chagin int error; 180ad2056f2SAlexander Leidinger 18181338031SDmitry Chagin p = td->td_proc; 182ad2056f2SAlexander Leidinger 183d707582fSDmitry Chagin error = pre_execve(td, &oldvmspace); 184d707582fSDmitry Chagin if (error != 0) 185d707582fSDmitry Chagin return (error); 18681338031SDmitry Chagin 18781338031SDmitry Chagin error = kern_execve(td, eargs, NULL); 188d707582fSDmitry Chagin post_execve(td, error, oldvmspace); 189814629ddSEd Schouten if (error != EJUSTRETURN) 19081338031SDmitry Chagin return (error); 19181338031SDmitry Chagin 19281338031SDmitry Chagin /* 19381338031SDmitry Chagin * In a case of transition from Linux binary execing to 194eae594f7SEd Maste * 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 207e16fe1c7SDmitry Chagin if (pem->epoll != NULL) { 208e16fe1c7SDmitry Chagin emd = pem->epoll; 209e16fe1c7SDmitry Chagin pem->epoll = NULL; 210e16fe1c7SDmitry Chagin free(emd, M_EPOLL); 211e16fe1c7SDmitry Chagin } 212e16fe1c7SDmitry Chagin 21381338031SDmitry Chagin free(em, M_TEMP); 214e0d3ea8cSDmitry Chagin free(pem, M_LINUX); 21581338031SDmitry Chagin } 216814629ddSEd Schouten return (EJUSTRETURN); 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; 22332ba368bSDmitry Chagin struct thread *othertd; 22423e8912cSDmitry Chagin #if defined(__amd64__) 22523e8912cSDmitry Chagin struct linux_pemuldata *pem; 22623e8912cSDmitry Chagin #endif 22732ba368bSDmitry Chagin 22832ba368bSDmitry Chagin /* 229eae594f7SEd Maste * In a case of execing from Linux binary properly detach 23032ba368bSDmitry Chagin * other threads from the user space. 23132ba368bSDmitry Chagin */ 23232ba368bSDmitry Chagin if (__predict_false(SV_PROC_ABI(p) == SV_ABI_LINUX)) { 23332ba368bSDmitry Chagin FOREACH_THREAD_IN_PROC(p, othertd) { 23432ba368bSDmitry Chagin if (td != othertd) 23532ba368bSDmitry Chagin (p->p_sysent->sv_thread_detach)(othertd); 23632ba368bSDmitry Chagin } 23732ba368bSDmitry Chagin } 23881338031SDmitry Chagin 23981338031SDmitry Chagin /* 240eae594f7SEd Maste * In a case of execing to Linux binary we create Linux 24181338031SDmitry Chagin * emuldata thread entry. 24281338031SDmitry Chagin */ 24381338031SDmitry Chagin if (__predict_false((imgp->sysent->sv_flags & SV_ABI_MASK) == 24481338031SDmitry Chagin SV_ABI_LINUX)) { 245e16fe1c7SDmitry Chagin 24681338031SDmitry Chagin if (SV_PROC_ABI(p) == SV_ABI_LINUX) 24781338031SDmitry Chagin linux_proc_init(td, NULL, 0); 24881338031SDmitry Chagin else 24981338031SDmitry Chagin linux_proc_init(td, td, 0); 25023e8912cSDmitry Chagin #if defined(__amd64__) 25123e8912cSDmitry Chagin /* 25223e8912cSDmitry Chagin * An IA32 executable which has executable stack will have the 25323e8912cSDmitry Chagin * READ_IMPLIES_EXEC personality flag set automatically. 25423e8912cSDmitry Chagin */ 25523e8912cSDmitry Chagin if (SV_PROC_FLAG(td->td_proc, SV_ILP32) && 25623e8912cSDmitry Chagin imgp->stack_prot & VM_PROT_EXECUTE) { 25723e8912cSDmitry Chagin pem = pem_find(p); 25823e8912cSDmitry Chagin pem->persona |= LINUX_READ_IMPLIES_EXEC; 25923e8912cSDmitry Chagin } 26023e8912cSDmitry Chagin #endif 26181338031SDmitry Chagin } 26281338031SDmitry Chagin } 26381338031SDmitry Chagin 26481338031SDmitry Chagin void 26581338031SDmitry Chagin linux_thread_dtor(void *arg __unused, struct thread *td) 266ad2056f2SAlexander Leidinger { 267ad2056f2SAlexander Leidinger struct linux_emuldata *em; 268ad2056f2SAlexander Leidinger 26981338031SDmitry Chagin em = em_find(td); 27081338031SDmitry Chagin if (em == NULL) 27181338031SDmitry Chagin return; 27281338031SDmitry Chagin td->td_emuldata = NULL; 273ad2056f2SAlexander Leidinger 2747d96520bSDmitry Chagin LINUX_CTR1(thread_dtor, "thread(%d)", em->em_tid); 275ad2056f2SAlexander Leidinger 27681338031SDmitry Chagin free(em, M_TEMP); 277ad2056f2SAlexander Leidinger } 278ad2056f2SAlexander Leidinger 279ad2056f2SAlexander Leidinger void 280e5d81ef1SDmitry Chagin linux_schedtail(struct thread *td) 281ad2056f2SAlexander Leidinger { 282ad2056f2SAlexander Leidinger struct linux_emuldata *em; 283e5d81ef1SDmitry Chagin struct proc *p; 284ad2056f2SAlexander Leidinger int error = 0; 285ad2056f2SAlexander Leidinger int *child_set_tid; 286ad2056f2SAlexander Leidinger 287e5d81ef1SDmitry Chagin p = td->td_proc; 288e5d81ef1SDmitry Chagin 28981338031SDmitry Chagin em = em_find(td); 290bc273677SDmitry Chagin KASSERT(em != NULL, ("linux_schedtail: thread emuldata not found.\n")); 291ad2056f2SAlexander Leidinger child_set_tid = em->child_set_tid; 292ad2056f2SAlexander Leidinger 29319e252baSAlexander Leidinger if (child_set_tid != NULL) { 294e0327ddbSDmitry Chagin error = copyout(&em->em_tid, child_set_tid, 29581338031SDmitry Chagin sizeof(em->em_tid)); 2967d96520bSDmitry Chagin LINUX_CTR4(schedtail, "thread(%d) %p stored %d error %d", 29781338031SDmitry Chagin td->td_tid, child_set_tid, em->em_tid, error); 29881338031SDmitry Chagin } else 2997d96520bSDmitry Chagin LINUX_CTR1(schedtail, "thread(%d)", em->em_tid); 300bb63fddeSAlexander Leidinger } 301