1*6430fcd5Sthorpej /* $NetBSD: linux_exec.c,v 1.124 2020/05/03 01:06:56 thorpej Exp $ */
28fb507a3Schristos
38fb507a3Schristos /*-
4980ef212Sad * Copyright (c) 1994, 1995, 1998, 2000, 2007, 2008, 2020
5980ef212Sad * The NetBSD Foundation, Inc.
68fb507a3Schristos * All rights reserved.
78fb507a3Schristos *
88fb507a3Schristos * This code is derived from software contributed to The NetBSD Foundation
98096c25aSfvdl * by Christos Zoulas, Frank van der Linden, Eric Haszlakiewicz and
108096c25aSfvdl * Thor Lancelot Simon.
118fb507a3Schristos *
128fb507a3Schristos * Redistribution and use in source and binary forms, with or without
138fb507a3Schristos * modification, are permitted provided that the following conditions
148fb507a3Schristos * are met:
158fb507a3Schristos * 1. Redistributions of source code must retain the above copyright
168fb507a3Schristos * notice, this list of conditions and the following disclaimer.
178fb507a3Schristos * 2. Redistributions in binary form must reproduce the above copyright
188fb507a3Schristos * notice, this list of conditions and the following disclaimer in the
198fb507a3Schristos * documentation and/or other materials provided with the distribution.
208fb507a3Schristos *
218fb507a3Schristos * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
228fb507a3Schristos * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
238fb507a3Schristos * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
248fb507a3Schristos * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
258fb507a3Schristos * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
268fb507a3Schristos * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
278fb507a3Schristos * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
288fb507a3Schristos * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
298fb507a3Schristos * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
308fb507a3Schristos * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
318fb507a3Schristos * POSSIBILITY OF SUCH DAMAGE.
328fb507a3Schristos */
333bf459f3Sfvdl
34dab6ef8bSlukem #include <sys/cdefs.h>
35*6430fcd5Sthorpej __KERNEL_RCSID(0, "$NetBSD: linux_exec.c,v 1.124 2020/05/03 01:06:56 thorpej Exp $");
36dab6ef8bSlukem
373bf459f3Sfvdl #include <sys/param.h>
383bf459f3Sfvdl #include <sys/systm.h>
393bf459f3Sfvdl #include <sys/kernel.h>
40980ef212Sad #include <sys/lwp.h>
413bf459f3Sfvdl #include <sys/proc.h>
423bf459f3Sfvdl #include <sys/namei.h>
433bf459f3Sfvdl #include <sys/vnode.h>
44151fa70fSchristos #include <sys/mount.h>
45d551a4edSchristos #include <sys/exec.h>
46c4aaa600Sfvdl #include <sys/exec_elf.h>
47276ef223Sthorpej #include <sys/futex.h>
483bf459f3Sfvdl
493bf459f3Sfvdl #include <sys/mman.h>
50151fa70fSchristos #include <sys/syscallargs.h>
51151fa70fSchristos
5281c909ddSmanu #include <sys/ptrace.h> /* For proc_reparent() */
5381c909ddSmanu
54c487efe4Sfvdl #include <uvm/uvm_extern.h>
55c487efe4Sfvdl
56a2a38285Sad #include <sys/cpu.h>
573bf459f3Sfvdl #include <machine/reg.h>
583bf459f3Sfvdl
59908291d2Schristos #include <compat/linux/common/linux_types.h>
60908291d2Schristos #include <compat/linux/common/linux_signal.h>
61908291d2Schristos #include <compat/linux/common/linux_util.h>
6281c909ddSmanu #include <compat/linux/common/linux_sched.h>
63908291d2Schristos #include <compat/linux/common/linux_machdep.h>
64*6430fcd5Sthorpej #include <compat/linux/common/linux_misc.h>
6581c909ddSmanu #include <compat/linux/common/linux_exec.h>
66a478f23bSnjoly #include <compat/linux/common/linux_ipc.h>
67a478f23bSnjoly #include <compat/linux/common/linux_sem.h>
683bf459f3Sfvdl
69908291d2Schristos #include <compat/linux/linux_syscallargs.h>
70908291d2Schristos #include <compat/linux/linux_syscall.h>
71baae0324Sjdolecek #include <compat/linux/common/linux_misc.h>
72baae0324Sjdolecek #include <compat/linux/common/linux_errno.h>
73a53687b1Sjdolecek #include <compat/linux/common/linux_emuldata.h>
7444eef7c2Schristos
75baae0324Sjdolecek extern struct sysent linux_sysent[];
763cd7406aSpgoyette extern const uint32_t linux_sysent_nomodbits[];
77baae0324Sjdolecek extern const char * const linux_syscallnames[];
78baae0324Sjdolecek extern char linux_sigcode[], linux_esigcode[];
79baae0324Sjdolecek
803bf459f3Sfvdl /*
81baae0324Sjdolecek * Emulation switch.
82baae0324Sjdolecek */
83939df36eSchs
84939df36eSchs struct uvm_object *emul_linux_object;
85939df36eSchs
8692ce8c6aSad struct emul emul_linux = {
87554a0142Srmind .e_name = "linux",
88554a0142Srmind .e_path = "/emul/linux",
89f495cd9dSmycroft #ifndef __HAVE_MINIMAL_EMUL
90554a0142Srmind .e_flags = 0,
9133fa5ccbSchs .e_errno = native_to_linux_errno,
92554a0142Srmind .e_nosys = LINUX_SYS_syscall,
93554a0142Srmind .e_nsysent = LINUX_SYS_NSYSENT,
94f495cd9dSmycroft #endif
95554a0142Srmind .e_sysent = linux_sysent,
963cd7406aSpgoyette .e_nomodbits = linux_sysent_nomodbits,
97554a0142Srmind .e_syscallnames = linux_syscallnames,
98554a0142Srmind .e_sendsig = linux_sendsig,
99554a0142Srmind .e_trapsignal = linux_trapsignal,
100554a0142Srmind .e_sigcode = linux_sigcode,
101554a0142Srmind .e_esigcode = linux_esigcode,
102554a0142Srmind .e_sigobject = &emul_linux_object,
103554a0142Srmind .e_setregs = linux_setregs,
104554a0142Srmind .e_proc_exec = linux_e_proc_exec,
105554a0142Srmind .e_proc_fork = linux_e_proc_fork,
106554a0142Srmind .e_proc_exit = linux_e_proc_exit,
10733fa5ccbSchs .e_lwp_fork = linux_e_lwp_fork,
10833fa5ccbSchs .e_lwp_exit = linux_e_lwp_exit,
109f495cd9dSmycroft #ifdef __HAVE_SYSCALL_INTERN
110554a0142Srmind .e_syscall_intern = linux_syscall_intern,
111da1aefe9Sjdolecek #else
1125afa6838Sthorpej #error Implement __HAVE_SYSCALL_INTERN for this platform
113da1aefe9Sjdolecek #endif
114554a0142Srmind .e_sysctlovly = NULL,
115554a0142Srmind .e_vm_default_addr = uvm_default_mapaddr,
116554a0142Srmind .e_usertrap = linux_usertrap,
117554a0142Srmind .e_ucsize = 0,
118554a0142Srmind .e_startlwp = NULL
119baae0324Sjdolecek };
120a53687b1Sjdolecek
12133fa5ccbSchs void
linux_e_proc_exec(struct proc * p,struct exec_package * epp)122168cd830Schristos linux_e_proc_exec(struct proc *p, struct exec_package *epp)
123569cf4b7Sjdolecek {
12433fa5ccbSchs struct lwp *l;
125a87ccd22Sad
12633fa5ccbSchs l = LIST_FIRST(&p->p_lwps);
12733fa5ccbSchs if (l->l_emuldata == NULL) {
12833fa5ccbSchs l->l_emuldata = kmem_zalloc(sizeof(struct linux_emuldata), KM_SLEEP);
12933fa5ccbSchs } else {
13033fa5ccbSchs memset(l->l_emuldata, 0, sizeof (struct linux_emuldata));
131c35e5ed1Sitojun }
132a53687b1Sjdolecek
13333fa5ccbSchs KASSERT(p->p_nlwps == 1);
13433fa5ccbSchs }
13533fa5ccbSchs
13633fa5ccbSchs void
linux_e_proc_exit(struct proc * p)13728bae79bSdsl linux_e_proc_exit(struct proc *p)
138a53687b1Sjdolecek {
13933fa5ccbSchs struct lwp *l;
140a714ac82Sjdolecek
14133fa5ccbSchs KASSERT(p->p_nlwps == 1);
14233fa5ccbSchs l = LIST_FIRST(&p->p_lwps);
14333fa5ccbSchs linux_e_lwp_exit(l);
144a53687b1Sjdolecek }
14581c909ddSmanu
14681c909ddSmanu void
linux_e_proc_fork(struct proc * p2,struct lwp * l1,int flags)14733fa5ccbSchs linux_e_proc_fork(struct proc *p2, struct lwp *l1, int flags)
14881c909ddSmanu {
14933fa5ccbSchs struct linux_emuldata *led1, *led2;
15033fa5ccbSchs struct lwp *l2;
151d0a51fd2Sad
15233fa5ccbSchs KASSERT(p2->p_nlwps == 1);
15333fa5ccbSchs l2 = LIST_FIRST(&p2->p_lwps);
15433fa5ccbSchs led1 = l1->l_emuldata;
15533fa5ccbSchs led2 = l2->l_emuldata;
15633fa5ccbSchs led2->led_child_tidptr = led1->led_child_tidptr;
15781c909ddSmanu }
15881c909ddSmanu
15933fa5ccbSchs void
linux_e_lwp_fork(struct lwp * l1,struct lwp * l2)16033fa5ccbSchs linux_e_lwp_fork(struct lwp *l1, struct lwp *l2)
16133fa5ccbSchs {
16233fa5ccbSchs struct linux_emuldata *led2;
16333fa5ccbSchs
164c2480dc3Schristos led2 = kmem_zalloc(sizeof(*led2), KM_SLEEP);
16533fa5ccbSchs l2->l_emuldata = led2;
16681c909ddSmanu }
16781c909ddSmanu
16833fa5ccbSchs void
linux_e_lwp_exit(struct lwp * l)16933fa5ccbSchs linux_e_lwp_exit(struct lwp *l)
17033fa5ccbSchs {
17133fa5ccbSchs struct linux_emuldata *led;
17281c909ddSmanu register_t retval;
17333fa5ccbSchs int error, zero = 0;
17481c909ddSmanu
17533fa5ccbSchs led = l->l_emuldata;
17633fa5ccbSchs
177276ef223Sthorpej if (led->led_clear_tid != NULL) {
17833fa5ccbSchs /* Emulate LINUX_CLONE_CHILD_CLEARTID */
17933fa5ccbSchs error = copyout(&zero, led->led_clear_tid, sizeof(zero));
18081c909ddSmanu #ifdef DEBUG_LINUX
18181c909ddSmanu if (error != 0)
18281c909ddSmanu printf("%s: cannot clear TID\n", __func__);
18381c909ddSmanu #endif
18481c909ddSmanu
185*6430fcd5Sthorpej error = linux_do_futex((int *)led->led_clear_tid, FUTEX_WAKE,
186276ef223Sthorpej INT_MAX, NULL, NULL, 0, 0, &retval);
187276ef223Sthorpej if (error)
18881c909ddSmanu printf("%s: linux_sys_futex failed\n", __func__);
189276ef223Sthorpej }
19033fa5ccbSchs
19133fa5ccbSchs led = l->l_emuldata;
19233fa5ccbSchs l->l_emuldata = NULL;
193c2480dc3Schristos kmem_free(led, sizeof(*led));
19481c909ddSmanu }
195