xref: /freebsd/sys/compat/linux/linux_emul.c (revision 4815f175d0324b851509adff0e82500cdf979c73)
1ad2056f2SAlexander Leidinger /*-
2023b850bSEd Maste  * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
37f2d13d6SPedro F. Giffuni  *
4b267239dSEd Maste  * Copyright (c) 1994-1996 Søren Schmidt
5ad2056f2SAlexander Leidinger  * Copyright (c) 2006 Roman Divacky
681338031SDmitry Chagin  * Copyright (c) 2013 Dmitry Chagin
7ad2056f2SAlexander Leidinger  * All rights reserved.
8ad2056f2SAlexander Leidinger  *
9ad2056f2SAlexander Leidinger  * Redistribution and use in source and binary forms, with or without
10ad2056f2SAlexander Leidinger  * modification, are permitted provided that the following conditions
11ad2056f2SAlexander Leidinger  * are met:
12ad2056f2SAlexander Leidinger  * 1. Redistributions of source code must retain the above copyright
13023b850bSEd Maste  *    notice, this list of conditions and the following disclaimer.
14ad2056f2SAlexander Leidinger  * 2. Redistributions in binary form must reproduce the above copyright
15ad2056f2SAlexander Leidinger  *    notice, this list of conditions and the following disclaimer in the
16ad2056f2SAlexander Leidinger  *    documentation and/or other materials provided with the distribution.
17ad2056f2SAlexander Leidinger  *
18023b850bSEd Maste  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
19023b850bSEd Maste  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20023b850bSEd Maste  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
21023b850bSEd Maste  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
22023b850bSEd Maste  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
23023b850bSEd Maste  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
24023b850bSEd Maste  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
25023b850bSEd Maste  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
26023b850bSEd Maste  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
27023b850bSEd Maste  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
28023b850bSEd Maste  * SUCH DAMAGE.
29ad2056f2SAlexander Leidinger  */
30ad2056f2SAlexander Leidinger 
31ad2056f2SAlexander Leidinger #include <sys/cdefs.h>
32ad2056f2SAlexander Leidinger __FBSDID("$FreeBSD$");
33ad2056f2SAlexander Leidinger 
34ad2056f2SAlexander Leidinger #include <sys/param.h>
35ad2056f2SAlexander Leidinger #include <sys/systm.h>
36b267239dSEd Maste #include <sys/fcntl.h>
37ad2056f2SAlexander Leidinger #include <sys/imgact.h>
38b4bb5154SKonstantin Belousov #include <sys/kernel.h>
3981338031SDmitry Chagin #include <sys/ktr.h>
40ad2056f2SAlexander Leidinger #include <sys/lock.h>
41ad2056f2SAlexander Leidinger #include <sys/malloc.h>
42ad2056f2SAlexander Leidinger #include <sys/mutex.h>
43ad2056f2SAlexander Leidinger #include <sys/sx.h>
44ad2056f2SAlexander Leidinger #include <sys/proc.h>
458c5059e9SEdward Tomasz Napierala #include <sys/resourcevar.h>
46ad2056f2SAlexander Leidinger #include <sys/syscallsubr.h>
4795353459SDimitry Andric #include <sys/sysent.h>
48ad2056f2SAlexander Leidinger 
494732e446SRoman Divacky #include <compat/linux/linux_emul.h>
508c5059e9SEdward Tomasz Napierala #include <compat/linux/linux_mib.h>
51d825ce0aSJohn Baldwin #include <compat/linux/linux_misc.h>
5223e8912cSDmitry Chagin #include <compat/linux/linux_persona.h>
5381338031SDmitry Chagin #include <compat/linux/linux_util.h>
544732e446SRoman Divacky 
55b267239dSEd Maste #if BYTE_ORDER == LITTLE_ENDIAN
56b267239dSEd Maste #define SHELLMAGIC	0x2123 /* #! */
57b267239dSEd Maste #else
58b267239dSEd Maste #define SHELLMAGIC	0x2321
59b267239dSEd Maste #endif
6019e252baSAlexander Leidinger 
6181338031SDmitry Chagin /*
62bc273677SDmitry Chagin  * This returns reference to the thread emuldata entry (if found)
6381338031SDmitry Chagin  *
6481338031SDmitry Chagin  * Hold PROC_LOCK when referencing emuldata from other threads.
6581338031SDmitry Chagin  */
66ad2056f2SAlexander Leidinger struct linux_emuldata *
6781338031SDmitry Chagin em_find(struct thread *td)
68ad2056f2SAlexander Leidinger {
69ad2056f2SAlexander Leidinger 	struct linux_emuldata *em;
70ad2056f2SAlexander Leidinger 
7181338031SDmitry Chagin 	em = td->td_emuldata;
72ad2056f2SAlexander Leidinger 
73ad2056f2SAlexander Leidinger 	return (em);
74ad2056f2SAlexander Leidinger }
75ad2056f2SAlexander Leidinger 
76bc273677SDmitry Chagin /*
77bc273677SDmitry Chagin  * This returns reference to the proc pemuldata entry (if found)
78bc273677SDmitry Chagin  *
79bc273677SDmitry Chagin  * Hold PROC_LOCK when referencing proc pemuldata from other threads.
80bc273677SDmitry Chagin  * Hold LINUX_PEM_LOCK wher referencing pemuldata members.
81bc273677SDmitry Chagin  */
82bc273677SDmitry Chagin struct linux_pemuldata *
83bc273677SDmitry Chagin pem_find(struct proc *p)
84bc273677SDmitry Chagin {
85bc273677SDmitry Chagin 	struct linux_pemuldata *pem;
86bc273677SDmitry Chagin 
87bc273677SDmitry Chagin 	pem = p->p_emuldata;
88bc273677SDmitry Chagin 
89bc273677SDmitry Chagin 	return (pem);
90bc273677SDmitry Chagin }
91bc273677SDmitry Chagin 
928c5059e9SEdward Tomasz Napierala /*
938c5059e9SEdward Tomasz Napierala  * Linux apps generally expect the soft open file limit to be set
948c5059e9SEdward Tomasz Napierala  * to 1024, often iterating over all the file descriptors up to that
958c5059e9SEdward Tomasz Napierala  * limit instead of using closefrom(2).  Give them what they want,
968c5059e9SEdward Tomasz Napierala  * unless there already is a resource limit in place.
978c5059e9SEdward Tomasz Napierala  */
988c5059e9SEdward Tomasz Napierala static void
998c5059e9SEdward Tomasz Napierala linux_set_default_openfiles(struct thread *td, struct proc *p)
1008c5059e9SEdward Tomasz Napierala {
1018c5059e9SEdward Tomasz Napierala 	struct rlimit rlim;
1028c5059e9SEdward Tomasz Napierala 	int error;
1038c5059e9SEdward Tomasz Napierala 
1048c5059e9SEdward Tomasz Napierala 	if (linux_default_openfiles < 0)
1058c5059e9SEdward Tomasz Napierala 		return;
1068c5059e9SEdward Tomasz Napierala 
1078c5059e9SEdward Tomasz Napierala 	PROC_LOCK(p);
1088c5059e9SEdward Tomasz Napierala 	lim_rlimit_proc(p, RLIMIT_NOFILE, &rlim);
1098c5059e9SEdward Tomasz Napierala 	PROC_UNLOCK(p);
1108c5059e9SEdward Tomasz Napierala 	if (rlim.rlim_cur != rlim.rlim_max ||
1118c5059e9SEdward Tomasz Napierala 	    rlim.rlim_cur <= linux_default_openfiles)
1128c5059e9SEdward Tomasz Napierala 		return;
1138c5059e9SEdward Tomasz Napierala 	rlim.rlim_cur = linux_default_openfiles;
1148c5059e9SEdward Tomasz Napierala 	error = kern_proc_setrlimit(td, p, RLIMIT_NOFILE, &rlim);
1158c5059e9SEdward Tomasz Napierala 	KASSERT(error == 0, ("kern_proc_setrlimit failed"));
1168c5059e9SEdward Tomasz Napierala }
1178c5059e9SEdward Tomasz Napierala 
1181c34dcb5SEdward Tomasz Napierala /*
1191c34dcb5SEdward Tomasz Napierala  * The default stack size limit in Linux is 8MB.
1201c34dcb5SEdward Tomasz Napierala  */
1211c34dcb5SEdward Tomasz Napierala static void
1221c34dcb5SEdward Tomasz Napierala linux_set_default_stacksize(struct thread *td, struct proc *p)
1231c34dcb5SEdward Tomasz Napierala {
1241c34dcb5SEdward Tomasz Napierala 	struct rlimit rlim;
1251c34dcb5SEdward Tomasz Napierala 	int error;
1261c34dcb5SEdward Tomasz Napierala 
1271c34dcb5SEdward Tomasz Napierala 	if (linux_default_stacksize < 0)
1281c34dcb5SEdward Tomasz Napierala 		return;
1291c34dcb5SEdward Tomasz Napierala 
1301c34dcb5SEdward Tomasz Napierala 	PROC_LOCK(p);
1311c34dcb5SEdward Tomasz Napierala 	lim_rlimit_proc(p, RLIMIT_STACK, &rlim);
1321c34dcb5SEdward Tomasz Napierala 	PROC_UNLOCK(p);
1331c34dcb5SEdward Tomasz Napierala 	if (rlim.rlim_cur != rlim.rlim_max ||
1341c34dcb5SEdward Tomasz Napierala 	    rlim.rlim_cur <= linux_default_stacksize)
1351c34dcb5SEdward Tomasz Napierala 		return;
1361c34dcb5SEdward Tomasz Napierala 	rlim.rlim_cur = linux_default_stacksize;
1371c34dcb5SEdward Tomasz Napierala 	error = kern_proc_setrlimit(td, p, RLIMIT_STACK, &rlim);
1381c34dcb5SEdward Tomasz Napierala 	KASSERT(error == 0, ("kern_proc_setrlimit failed"));
1391c34dcb5SEdward Tomasz Napierala }
1401c34dcb5SEdward Tomasz Napierala 
14181338031SDmitry Chagin void
14281338031SDmitry Chagin linux_proc_init(struct thread *td, struct thread *newtd, int flags)
143ad2056f2SAlexander Leidinger {
14481338031SDmitry Chagin 	struct linux_emuldata *em;
145bc273677SDmitry Chagin 	struct linux_pemuldata *pem;
146e16fe1c7SDmitry Chagin 	struct epoll_emuldata *emd;
14768cf0367SDmitry Chagin 	struct proc *p;
14819e252baSAlexander Leidinger 
14981338031SDmitry Chagin 	if (newtd != NULL) {
15068cf0367SDmitry Chagin 		p = newtd->td_proc;
15168cf0367SDmitry Chagin 
15281338031SDmitry Chagin 		/* non-exec call */
15381338031SDmitry Chagin 		em = malloc(sizeof(*em), M_TEMP, M_WAITOK | M_ZERO);
154a4e3bad7SJung-uk Kim 		if (flags & LINUX_CLONE_THREAD) {
155e16fe1c7SDmitry Chagin 			LINUX_CTR1(proc_init, "thread newtd(%d)",
156e16fe1c7SDmitry Chagin 			    newtd->td_tid);
157e16fe1c7SDmitry Chagin 
15881338031SDmitry Chagin 			em->em_tid = newtd->td_tid;
15981338031SDmitry Chagin 		} else {
16068cf0367SDmitry Chagin 			LINUX_CTR1(proc_init, "fork newtd(%d)", p->p_pid);
16119e252baSAlexander Leidinger 
16268cf0367SDmitry Chagin 			em->em_tid = p->p_pid;
163bc273677SDmitry Chagin 
164e0d3ea8cSDmitry Chagin 			pem = malloc(sizeof(*pem), M_LINUX, M_WAITOK | M_ZERO);
165bc273677SDmitry Chagin 			sx_init(&pem->pem_sx, "lpemlk");
16668cf0367SDmitry Chagin 			p->p_emuldata = pem;
167ad2056f2SAlexander Leidinger 		}
16881338031SDmitry Chagin 		newtd->td_emuldata = em;
1698c5059e9SEdward Tomasz Napierala 
1708c5059e9SEdward Tomasz Napierala 		linux_set_default_openfiles(td, p);
1711c34dcb5SEdward Tomasz Napierala 		linux_set_default_stacksize(td, p);
172ad2056f2SAlexander Leidinger 	} else {
17368cf0367SDmitry Chagin 		p = td->td_proc;
17468cf0367SDmitry Chagin 
17519e252baSAlexander Leidinger 		/* exec */
17668cf0367SDmitry Chagin 		LINUX_CTR1(proc_init, "exec newtd(%d)", p->p_pid);
17719e252baSAlexander Leidinger 
178ad2056f2SAlexander Leidinger 		/* lookup the old one */
17981338031SDmitry Chagin 		em = em_find(td);
180ad2056f2SAlexander Leidinger 		KASSERT(em != NULL, ("proc_init: emuldata not found in exec case.\n"));
18181338031SDmitry Chagin 
18268cf0367SDmitry Chagin 		em->em_tid = p->p_pid;
18397cfa5c8SDmitry Chagin 		em->flags = 0;
18497cfa5c8SDmitry Chagin 		em->robust_futexes = NULL;
18597cfa5c8SDmitry Chagin 		em->child_clear_tid = NULL;
18697cfa5c8SDmitry Chagin 		em->child_set_tid = NULL;
187e16fe1c7SDmitry Chagin 
188e16fe1c7SDmitry Chagin 		 /* epoll should be destroyed in a case of exec. */
18968cf0367SDmitry Chagin 		pem = pem_find(p);
190e16fe1c7SDmitry Chagin 		KASSERT(pem != NULL, ("proc_exit: proc emuldata not found.\n"));
19123e8912cSDmitry Chagin 		pem->persona = 0;
192e16fe1c7SDmitry Chagin 		if (pem->epoll != NULL) {
193e16fe1c7SDmitry Chagin 			emd = pem->epoll;
194e16fe1c7SDmitry Chagin 			pem->epoll = NULL;
195e16fe1c7SDmitry Chagin 			free(emd, M_EPOLL);
196e16fe1c7SDmitry Chagin 		}
197ad2056f2SAlexander Leidinger 	}
198ad2056f2SAlexander Leidinger 
199ad2056f2SAlexander Leidinger }
200ad2056f2SAlexander Leidinger 
201ad2056f2SAlexander Leidinger void
202*4815f175SKonstantin Belousov linux_on_exit(struct proc *p)
203ad2056f2SAlexander Leidinger {
204bc273677SDmitry Chagin 	struct linux_pemuldata *pem;
205e16fe1c7SDmitry Chagin 	struct epoll_emuldata *emd;
20681338031SDmitry Chagin 	struct thread *td = curthread;
207ad2056f2SAlexander Leidinger 
208*4815f175SKonstantin Belousov 	MPASS(SV_CURPROC_ABI() == SV_ABI_LINUX);
209bc273677SDmitry Chagin 
2107d96520bSDmitry Chagin 	LINUX_CTR3(proc_exit, "thread(%d) proc(%d) p %p",
2117d96520bSDmitry Chagin 	    td->td_tid, p->p_pid, p);
2127d96520bSDmitry Chagin 
213bc273677SDmitry Chagin 	pem = pem_find(p);
214bc273677SDmitry Chagin 	if (pem == NULL)
215bc273677SDmitry Chagin 		return;
21681338031SDmitry Chagin 	(p->p_sysent->sv_thread_detach)(td);
217bc273677SDmitry Chagin 
218bc273677SDmitry Chagin 	p->p_emuldata = NULL;
219bc273677SDmitry Chagin 
220e16fe1c7SDmitry Chagin 	if (pem->epoll != NULL) {
221e16fe1c7SDmitry Chagin 		emd = pem->epoll;
222e16fe1c7SDmitry Chagin 		pem->epoll = NULL;
223e16fe1c7SDmitry Chagin 		free(emd, M_EPOLL);
224e16fe1c7SDmitry Chagin 	}
225e16fe1c7SDmitry Chagin 
226bc273677SDmitry Chagin 	sx_destroy(&pem->pem_sx);
227e0d3ea8cSDmitry Chagin 	free(pem, M_LINUX);
228e8b8b834SAlexander Leidinger }
229ad2056f2SAlexander Leidinger 
230b267239dSEd Maste /*
231b267239dSEd Maste  * If a Linux binary is exec'ing something, try this image activator
232b267239dSEd Maste  * first.  We override standard shell script execution in order to
233b267239dSEd Maste  * be able to modify the interpreter path.  We only do this if a Linux
234b267239dSEd Maste  * binary is doing the exec, so we do not create an EXEC module for it.
235b267239dSEd Maste  */
236b267239dSEd Maste int
237b267239dSEd Maste linux_exec_imgact_try(struct image_params *imgp)
238b267239dSEd Maste {
239b267239dSEd Maste 	const char *head = (const char *)imgp->image_header;
240b267239dSEd Maste 	char *rpath;
241b267239dSEd Maste 	int error = -1;
242b267239dSEd Maste 
243b267239dSEd Maste 	/*
244b267239dSEd Maste 	 * The interpreter for shell scripts run from a Linux binary needs
245b267239dSEd Maste 	 * to be located in /compat/linux if possible in order to recursively
246b267239dSEd Maste 	 * maintain Linux path emulation.
247b267239dSEd Maste 	 */
248b267239dSEd Maste 	if (((const short *)head)[0] == SHELLMAGIC) {
249b267239dSEd Maste 		/*
250b267239dSEd Maste 		 * Run our normal shell image activator.  If it succeeds attempt
251b267239dSEd Maste 		 * to use the alternate path for the interpreter.  If an
252b267239dSEd Maste 		 * alternate path is found, use our stringspace to store it.
253b267239dSEd Maste 		 */
254b267239dSEd Maste 		if ((error = exec_shell_imgact(imgp)) == 0) {
255b267239dSEd Maste 			linux_emul_convpath(FIRST_THREAD_IN_PROC(imgp->proc),
256b267239dSEd Maste 			    imgp->interpreter_name, UIO_SYSSPACE, &rpath, 0,
257b267239dSEd Maste 			    AT_FDCWD);
258b267239dSEd Maste 			if (rpath != NULL)
259b267239dSEd Maste 				imgp->args->fname_buf =
260b267239dSEd Maste 				    imgp->interpreter_name = rpath;
261b267239dSEd Maste 		}
262b267239dSEd Maste 	}
263b267239dSEd Maste 	return (error);
264b267239dSEd Maste }
265b267239dSEd Maste 
26681338031SDmitry Chagin int
26781338031SDmitry Chagin linux_common_execve(struct thread *td, struct image_args *eargs)
26881338031SDmitry Chagin {
269bc273677SDmitry Chagin 	struct linux_pemuldata *pem;
270e16fe1c7SDmitry Chagin 	struct epoll_emuldata *emd;
271d707582fSDmitry Chagin 	struct vmspace *oldvmspace;
27281338031SDmitry Chagin 	struct linux_emuldata *em;
27381338031SDmitry Chagin 	struct proc *p;
27481338031SDmitry Chagin 	int error;
275ad2056f2SAlexander Leidinger 
27681338031SDmitry Chagin 	p = td->td_proc;
277ad2056f2SAlexander Leidinger 
278d707582fSDmitry Chagin 	error = pre_execve(td, &oldvmspace);
279d707582fSDmitry Chagin 	if (error != 0)
280d707582fSDmitry Chagin 		return (error);
28181338031SDmitry Chagin 
282aaf78c16SKonstantin Belousov 	error = kern_execve(td, eargs, NULL, oldvmspace);
283d707582fSDmitry Chagin 	post_execve(td, error, oldvmspace);
284814629ddSEd Schouten 	if (error != EJUSTRETURN)
28581338031SDmitry Chagin 		return (error);
28681338031SDmitry Chagin 
28781338031SDmitry Chagin 	/*
28881338031SDmitry Chagin 	 * In a case of transition from Linux binary execing to
289eae594f7SEd Maste 	 * FreeBSD binary we destroy Linux emuldata thread & proc entries.
29081338031SDmitry Chagin 	 */
29181338031SDmitry Chagin 	if (SV_CURPROC_ABI() != SV_ABI_LINUX) {
29281338031SDmitry Chagin 		PROC_LOCK(p);
29381338031SDmitry Chagin 		em = em_find(td);
294bc273677SDmitry Chagin 		KASSERT(em != NULL, ("proc_exec: thread emuldata not found.\n"));
29581338031SDmitry Chagin 		td->td_emuldata = NULL;
296bc273677SDmitry Chagin 
297bc273677SDmitry Chagin 		pem = pem_find(p);
298bc273677SDmitry Chagin 		KASSERT(pem != NULL, ("proc_exec: proc pemuldata not found.\n"));
299bc273677SDmitry Chagin 		p->p_emuldata = NULL;
30081338031SDmitry Chagin 		PROC_UNLOCK(p);
30181338031SDmitry Chagin 
302e16fe1c7SDmitry Chagin 		if (pem->epoll != NULL) {
303e16fe1c7SDmitry Chagin 			emd = pem->epoll;
304e16fe1c7SDmitry Chagin 			pem->epoll = NULL;
305e16fe1c7SDmitry Chagin 			free(emd, M_EPOLL);
306e16fe1c7SDmitry Chagin 		}
307e16fe1c7SDmitry Chagin 
30881338031SDmitry Chagin 		free(em, M_TEMP);
309e0d3ea8cSDmitry Chagin 		free(pem, M_LINUX);
31081338031SDmitry Chagin 	}
311814629ddSEd Schouten 	return (EJUSTRETURN);
31281338031SDmitry Chagin }
31381338031SDmitry Chagin 
31481338031SDmitry Chagin void
315*4815f175SKonstantin Belousov linux_on_exec(struct proc *p, struct image_params *imgp)
31681338031SDmitry Chagin {
3178a15ac83SKonstantin Belousov 	struct thread *td;
31832ba368bSDmitry Chagin 	struct thread *othertd;
31923e8912cSDmitry Chagin #if defined(__amd64__)
32023e8912cSDmitry Chagin 	struct linux_pemuldata *pem;
32123e8912cSDmitry Chagin #endif
32232ba368bSDmitry Chagin 
3238a15ac83SKonstantin Belousov 	td = curthread;
324*4815f175SKonstantin Belousov 	MPASS((imgp->sysent->sv_flags & SV_ABI_MASK) == SV_ABI_LINUX);
32581338031SDmitry Chagin 
32681338031SDmitry Chagin 	/*
327*4815f175SKonstantin Belousov 	 * When execing to Linux binary, we create Linux emuldata
328*4815f175SKonstantin Belousov 	 * thread entry.
32981338031SDmitry Chagin 	 */
3308a15ac83SKonstantin Belousov 	if (SV_PROC_ABI(p) == SV_ABI_LINUX) {
3318a15ac83SKonstantin Belousov 		/*
3328a15ac83SKonstantin Belousov 		 * Process already was under Linuxolator
3338a15ac83SKonstantin Belousov 		 * before exec.  Update emuldata to reflect
3348a15ac83SKonstantin Belousov 		 * single-threaded cleaned state after exec.
3358a15ac83SKonstantin Belousov 		 */
33681338031SDmitry Chagin 		linux_proc_init(td, NULL, 0);
3378a15ac83SKonstantin Belousov 	} else {
3388a15ac83SKonstantin Belousov 		/*
3398a15ac83SKonstantin Belousov 		 * We are switching the process to Linux emulator.
3408a15ac83SKonstantin Belousov 		 */
34181338031SDmitry Chagin 		linux_proc_init(td, td, 0);
3428a15ac83SKonstantin Belousov 
3438a15ac83SKonstantin Belousov 		/*
3448a15ac83SKonstantin Belousov 		 * Create a transient td_emuldata for all suspended
3458a15ac83SKonstantin Belousov 		 * threads, so that p->p_sysent->sv_thread_detach() ==
3468a15ac83SKonstantin Belousov 		 * linux_thread_detach() can find expected but unused
3478a15ac83SKonstantin Belousov 		 * emuldata.
3488a15ac83SKonstantin Belousov 		 */
3498a15ac83SKonstantin Belousov 		FOREACH_THREAD_IN_PROC(td->td_proc, othertd) {
350*4815f175SKonstantin Belousov 			if (othertd == td)
351*4815f175SKonstantin Belousov 				continue;
352*4815f175SKonstantin Belousov 			linux_proc_init(td, othertd, LINUX_CLONE_THREAD);
3538a15ac83SKonstantin Belousov 		}
3548a15ac83SKonstantin Belousov 	}
35523e8912cSDmitry Chagin #if defined(__amd64__)
35623e8912cSDmitry Chagin 	/*
35723e8912cSDmitry Chagin 	 * An IA32 executable which has executable stack will have the
35823e8912cSDmitry Chagin 	 * READ_IMPLIES_EXEC personality flag set automatically.
35923e8912cSDmitry Chagin 	 */
36023e8912cSDmitry Chagin 	if (SV_PROC_FLAG(td->td_proc, SV_ILP32) &&
36123e8912cSDmitry Chagin 	    imgp->stack_prot & VM_PROT_EXECUTE) {
36223e8912cSDmitry Chagin 		pem = pem_find(p);
36323e8912cSDmitry Chagin 		pem->persona |= LINUX_READ_IMPLIES_EXEC;
36423e8912cSDmitry Chagin 	}
36523e8912cSDmitry Chagin #endif
36681338031SDmitry Chagin }
36781338031SDmitry Chagin 
36881338031SDmitry Chagin void
369*4815f175SKonstantin Belousov linux_thread_dtor(struct thread *td)
370ad2056f2SAlexander Leidinger {
371ad2056f2SAlexander Leidinger 	struct linux_emuldata *em;
372ad2056f2SAlexander Leidinger 
37381338031SDmitry Chagin 	em = em_find(td);
37481338031SDmitry Chagin 	if (em == NULL)
37581338031SDmitry Chagin 		return;
37681338031SDmitry Chagin 	td->td_emuldata = NULL;
377ad2056f2SAlexander Leidinger 
3787d96520bSDmitry Chagin 	LINUX_CTR1(thread_dtor, "thread(%d)", em->em_tid);
379ad2056f2SAlexander Leidinger 
38081338031SDmitry Chagin 	free(em, M_TEMP);
381ad2056f2SAlexander Leidinger }
382ad2056f2SAlexander Leidinger 
383ad2056f2SAlexander Leidinger void
384e5d81ef1SDmitry Chagin linux_schedtail(struct thread *td)
385ad2056f2SAlexander Leidinger {
386ad2056f2SAlexander Leidinger 	struct linux_emuldata *em;
387e5d81ef1SDmitry Chagin 	struct proc *p;
388ad2056f2SAlexander Leidinger 	int error = 0;
389ad2056f2SAlexander Leidinger 	int *child_set_tid;
390ad2056f2SAlexander Leidinger 
391e5d81ef1SDmitry Chagin 	p = td->td_proc;
392e5d81ef1SDmitry Chagin 
39381338031SDmitry Chagin 	em = em_find(td);
394bc273677SDmitry Chagin 	KASSERT(em != NULL, ("linux_schedtail: thread emuldata not found.\n"));
395ad2056f2SAlexander Leidinger 	child_set_tid = em->child_set_tid;
396ad2056f2SAlexander Leidinger 
39719e252baSAlexander Leidinger 	if (child_set_tid != NULL) {
398e0327ddbSDmitry Chagin 		error = copyout(&em->em_tid, child_set_tid,
39981338031SDmitry Chagin 		    sizeof(em->em_tid));
4007d96520bSDmitry Chagin 		LINUX_CTR4(schedtail, "thread(%d) %p stored %d error %d",
40181338031SDmitry Chagin 		    td->td_tid, child_set_tid, em->em_tid, error);
40281338031SDmitry Chagin 	} else
4037d96520bSDmitry Chagin 		LINUX_CTR1(schedtail, "thread(%d)", em->em_tid);
404bb63fddeSAlexander Leidinger }
405