xref: /freebsd/sys/compat/linux/linux_emul.c (revision 74a0e24f07974b4d51c57afa7525b5f88574ad31)
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
6ad2056f2SAlexander Leidinger  * All rights reserved.
71ca6b15bSDmitry Chagin  * Copyright (c) 2013 Dmitry Chagin <dchagin@FreeBSD.org>
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
1420a4b664aSDmitry Chagin linux_proc_init(struct thread *td, struct thread *newtd, bool init_thread)
143ad2056f2SAlexander Leidinger {
14481338031SDmitry Chagin 	struct linux_emuldata *em;
145bc273677SDmitry Chagin 	struct linux_pemuldata *pem;
14668cf0367SDmitry Chagin 	struct proc *p;
14719e252baSAlexander Leidinger 
14881338031SDmitry Chagin 	if (newtd != NULL) {
14968cf0367SDmitry Chagin 		p = newtd->td_proc;
15068cf0367SDmitry Chagin 
15181338031SDmitry Chagin 		/* non-exec call */
15281338031SDmitry Chagin 		em = malloc(sizeof(*em), M_TEMP, M_WAITOK | M_ZERO);
1530a4b664aSDmitry Chagin 		if (init_thread) {
154e16fe1c7SDmitry Chagin 			LINUX_CTR1(proc_init, "thread newtd(%d)",
155e16fe1c7SDmitry Chagin 			    newtd->td_tid);
156e16fe1c7SDmitry Chagin 
15781338031SDmitry Chagin 			em->em_tid = newtd->td_tid;
15881338031SDmitry Chagin 		} else {
15968cf0367SDmitry Chagin 			LINUX_CTR1(proc_init, "fork newtd(%d)", p->p_pid);
16019e252baSAlexander Leidinger 
16168cf0367SDmitry Chagin 			em->em_tid = p->p_pid;
162bc273677SDmitry Chagin 
163e0d3ea8cSDmitry Chagin 			pem = malloc(sizeof(*pem), M_LINUX, M_WAITOK | M_ZERO);
164bc273677SDmitry Chagin 			sx_init(&pem->pem_sx, "lpemlk");
16568cf0367SDmitry Chagin 			p->p_emuldata = pem;
166ad2056f2SAlexander Leidinger 		}
16781338031SDmitry Chagin 		newtd->td_emuldata = em;
1688c5059e9SEdward Tomasz Napierala 
1698c5059e9SEdward Tomasz Napierala 		linux_set_default_openfiles(td, p);
1701c34dcb5SEdward Tomasz Napierala 		linux_set_default_stacksize(td, p);
171ad2056f2SAlexander Leidinger 	} else {
17268cf0367SDmitry Chagin 		p = td->td_proc;
17368cf0367SDmitry Chagin 
17419e252baSAlexander Leidinger 		/* exec */
17568cf0367SDmitry Chagin 		LINUX_CTR1(proc_init, "exec newtd(%d)", p->p_pid);
17619e252baSAlexander Leidinger 
177ad2056f2SAlexander Leidinger 		/* lookup the old one */
17881338031SDmitry Chagin 		em = em_find(td);
179ad2056f2SAlexander Leidinger 		KASSERT(em != NULL, ("proc_init: emuldata not found in exec case.\n"));
18081338031SDmitry Chagin 
18168cf0367SDmitry Chagin 		em->em_tid = p->p_pid;
18297cfa5c8SDmitry Chagin 		em->flags = 0;
18397cfa5c8SDmitry Chagin 		em->robust_futexes = NULL;
18497cfa5c8SDmitry Chagin 		em->child_clear_tid = NULL;
18597cfa5c8SDmitry Chagin 		em->child_set_tid = NULL;
186e16fe1c7SDmitry Chagin 
18768cf0367SDmitry Chagin 		pem = pem_find(p);
188e16fe1c7SDmitry Chagin 		KASSERT(pem != NULL, ("proc_exit: proc emuldata not found.\n"));
18923e8912cSDmitry Chagin 		pem->persona = 0;
190ad2056f2SAlexander Leidinger 	}
191ad2056f2SAlexander Leidinger 
192ad2056f2SAlexander Leidinger }
193ad2056f2SAlexander Leidinger 
194ad2056f2SAlexander Leidinger void
1954815f175SKonstantin Belousov linux_on_exit(struct proc *p)
196ad2056f2SAlexander Leidinger {
197bc273677SDmitry Chagin 	struct linux_pemuldata *pem;
19881338031SDmitry Chagin 	struct thread *td = curthread;
199ad2056f2SAlexander Leidinger 
2004815f175SKonstantin Belousov 	MPASS(SV_CURPROC_ABI() == SV_ABI_LINUX);
201bc273677SDmitry Chagin 
2027d96520bSDmitry Chagin 	LINUX_CTR3(proc_exit, "thread(%d) proc(%d) p %p",
2037d96520bSDmitry Chagin 	    td->td_tid, p->p_pid, p);
2047d96520bSDmitry Chagin 
205bc273677SDmitry Chagin 	pem = pem_find(p);
206bc273677SDmitry Chagin 	if (pem == NULL)
207bc273677SDmitry Chagin 		return;
20881338031SDmitry Chagin 	(p->p_sysent->sv_thread_detach)(td);
209bc273677SDmitry Chagin 
210bc273677SDmitry Chagin 	p->p_emuldata = NULL;
211bc273677SDmitry Chagin 
212bc273677SDmitry Chagin 	sx_destroy(&pem->pem_sx);
213e0d3ea8cSDmitry Chagin 	free(pem, M_LINUX);
214e8b8b834SAlexander Leidinger }
215ad2056f2SAlexander Leidinger 
216b267239dSEd Maste /*
217b267239dSEd Maste  * If a Linux binary is exec'ing something, try this image activator
218b267239dSEd Maste  * first.  We override standard shell script execution in order to
219b267239dSEd Maste  * be able to modify the interpreter path.  We only do this if a Linux
220b267239dSEd Maste  * binary is doing the exec, so we do not create an EXEC module for it.
221b267239dSEd Maste  */
222b267239dSEd Maste int
223b267239dSEd Maste linux_exec_imgact_try(struct image_params *imgp)
224b267239dSEd Maste {
225b267239dSEd Maste 	const char *head = (const char *)imgp->image_header;
226b267239dSEd Maste 	char *rpath;
227b267239dSEd Maste 	int error = -1;
228b267239dSEd Maste 
229b267239dSEd Maste 	/*
230b267239dSEd Maste 	 * The interpreter for shell scripts run from a Linux binary needs
231b267239dSEd Maste 	 * to be located in /compat/linux if possible in order to recursively
232b267239dSEd Maste 	 * maintain Linux path emulation.
233b267239dSEd Maste 	 */
234b267239dSEd Maste 	if (((const short *)head)[0] == SHELLMAGIC) {
235b267239dSEd Maste 		/*
236b267239dSEd Maste 		 * Run our normal shell image activator.  If it succeeds attempt
237b267239dSEd Maste 		 * to use the alternate path for the interpreter.  If an
238b267239dSEd Maste 		 * alternate path is found, use our stringspace to store it.
239b267239dSEd Maste 		 */
240b267239dSEd Maste 		if ((error = exec_shell_imgact(imgp)) == 0) {
241b267239dSEd Maste 			linux_emul_convpath(FIRST_THREAD_IN_PROC(imgp->proc),
242b267239dSEd Maste 			    imgp->interpreter_name, UIO_SYSSPACE, &rpath, 0,
243b267239dSEd Maste 			    AT_FDCWD);
244b267239dSEd Maste 			if (rpath != NULL)
245b267239dSEd Maste 				imgp->args->fname_buf =
246b267239dSEd Maste 				    imgp->interpreter_name = rpath;
247b267239dSEd Maste 		}
248b267239dSEd Maste 	}
249b267239dSEd Maste 	return (error);
250b267239dSEd Maste }
251b267239dSEd Maste 
25281338031SDmitry Chagin int
25381338031SDmitry Chagin linux_common_execve(struct thread *td, struct image_args *eargs)
25481338031SDmitry Chagin {
255bc273677SDmitry Chagin 	struct linux_pemuldata *pem;
256d707582fSDmitry Chagin 	struct vmspace *oldvmspace;
25781338031SDmitry Chagin 	struct linux_emuldata *em;
25881338031SDmitry Chagin 	struct proc *p;
25981338031SDmitry Chagin 	int error;
260ad2056f2SAlexander Leidinger 
26181338031SDmitry Chagin 	p = td->td_proc;
262ad2056f2SAlexander Leidinger 
263d707582fSDmitry Chagin 	error = pre_execve(td, &oldvmspace);
264d707582fSDmitry Chagin 	if (error != 0)
265d707582fSDmitry Chagin 		return (error);
26681338031SDmitry Chagin 
267aaf78c16SKonstantin Belousov 	error = kern_execve(td, eargs, NULL, oldvmspace);
268d707582fSDmitry Chagin 	post_execve(td, error, oldvmspace);
269814629ddSEd Schouten 	if (error != EJUSTRETURN)
27081338031SDmitry Chagin 		return (error);
27181338031SDmitry Chagin 
27281338031SDmitry Chagin 	/*
27381338031SDmitry Chagin 	 * In a case of transition from Linux binary execing to
274eae594f7SEd Maste 	 * FreeBSD binary we destroy Linux emuldata thread & proc entries.
27581338031SDmitry Chagin 	 */
27681338031SDmitry Chagin 	if (SV_CURPROC_ABI() != SV_ABI_LINUX) {
27781338031SDmitry Chagin 		PROC_LOCK(p);
27881338031SDmitry Chagin 		em = em_find(td);
279bc273677SDmitry Chagin 		KASSERT(em != NULL, ("proc_exec: thread emuldata not found.\n"));
28081338031SDmitry Chagin 		td->td_emuldata = NULL;
281bc273677SDmitry Chagin 
282bc273677SDmitry Chagin 		pem = pem_find(p);
283bc273677SDmitry Chagin 		KASSERT(pem != NULL, ("proc_exec: proc pemuldata not found.\n"));
284bc273677SDmitry Chagin 		p->p_emuldata = NULL;
28581338031SDmitry Chagin 		PROC_UNLOCK(p);
28681338031SDmitry Chagin 
28781338031SDmitry Chagin 		free(em, M_TEMP);
288e0d3ea8cSDmitry Chagin 		free(pem, M_LINUX);
28981338031SDmitry Chagin 	}
290814629ddSEd Schouten 	return (EJUSTRETURN);
29181338031SDmitry Chagin }
29281338031SDmitry Chagin 
29381338031SDmitry Chagin void
2944815f175SKonstantin Belousov linux_on_exec(struct proc *p, struct image_params *imgp)
29581338031SDmitry Chagin {
2968a15ac83SKonstantin Belousov 	struct thread *td;
29732ba368bSDmitry Chagin 	struct thread *othertd;
29823e8912cSDmitry Chagin #if defined(__amd64__)
29923e8912cSDmitry Chagin 	struct linux_pemuldata *pem;
30023e8912cSDmitry Chagin #endif
30132ba368bSDmitry Chagin 
3028a15ac83SKonstantin Belousov 	td = curthread;
3034815f175SKonstantin Belousov 	MPASS((imgp->sysent->sv_flags & SV_ABI_MASK) == SV_ABI_LINUX);
30481338031SDmitry Chagin 
30581338031SDmitry Chagin 	/*
3064815f175SKonstantin Belousov 	 * When execing to Linux binary, we create Linux emuldata
3074815f175SKonstantin Belousov 	 * thread entry.
30881338031SDmitry Chagin 	 */
3098a15ac83SKonstantin Belousov 	if (SV_PROC_ABI(p) == SV_ABI_LINUX) {
3108a15ac83SKonstantin Belousov 		/*
3118a15ac83SKonstantin Belousov 		 * Process already was under Linuxolator
3128a15ac83SKonstantin Belousov 		 * before exec.  Update emuldata to reflect
3138a15ac83SKonstantin Belousov 		 * single-threaded cleaned state after exec.
3148a15ac83SKonstantin Belousov 		 */
3150a4b664aSDmitry Chagin 		linux_proc_init(td, NULL, false);
3168a15ac83SKonstantin Belousov 	} else {
3178a15ac83SKonstantin Belousov 		/*
3188a15ac83SKonstantin Belousov 		 * We are switching the process to Linux emulator.
3198a15ac83SKonstantin Belousov 		 */
3200a4b664aSDmitry Chagin 		linux_proc_init(td, td, false);
3218a15ac83SKonstantin Belousov 
3228a15ac83SKonstantin Belousov 		/*
3238a15ac83SKonstantin Belousov 		 * Create a transient td_emuldata for all suspended
3248a15ac83SKonstantin Belousov 		 * threads, so that p->p_sysent->sv_thread_detach() ==
3258a15ac83SKonstantin Belousov 		 * linux_thread_detach() can find expected but unused
3268a15ac83SKonstantin Belousov 		 * emuldata.
3278a15ac83SKonstantin Belousov 		 */
3288a15ac83SKonstantin Belousov 		FOREACH_THREAD_IN_PROC(td->td_proc, othertd) {
3294815f175SKonstantin Belousov 			if (othertd == td)
3304815f175SKonstantin Belousov 				continue;
3310a4b664aSDmitry Chagin 			linux_proc_init(td, othertd, true);
3328a15ac83SKonstantin Belousov 		}
3338a15ac83SKonstantin Belousov 	}
33423e8912cSDmitry Chagin #if defined(__amd64__)
33523e8912cSDmitry Chagin 	/*
33623e8912cSDmitry Chagin 	 * An IA32 executable which has executable stack will have the
33723e8912cSDmitry Chagin 	 * READ_IMPLIES_EXEC personality flag set automatically.
33823e8912cSDmitry Chagin 	 */
33923e8912cSDmitry Chagin 	if (SV_PROC_FLAG(td->td_proc, SV_ILP32) &&
34023e8912cSDmitry Chagin 	    imgp->stack_prot & VM_PROT_EXECUTE) {
34123e8912cSDmitry Chagin 		pem = pem_find(p);
34223e8912cSDmitry Chagin 		pem->persona |= LINUX_READ_IMPLIES_EXEC;
34323e8912cSDmitry Chagin 	}
34423e8912cSDmitry Chagin #endif
34581338031SDmitry Chagin }
34681338031SDmitry Chagin 
34781338031SDmitry Chagin void
3484815f175SKonstantin Belousov linux_thread_dtor(struct thread *td)
349ad2056f2SAlexander Leidinger {
350ad2056f2SAlexander Leidinger 	struct linux_emuldata *em;
351ad2056f2SAlexander Leidinger 
35281338031SDmitry Chagin 	em = em_find(td);
35381338031SDmitry Chagin 	if (em == NULL)
35481338031SDmitry Chagin 		return;
35581338031SDmitry Chagin 	td->td_emuldata = NULL;
356ad2056f2SAlexander Leidinger 
3577d96520bSDmitry Chagin 	LINUX_CTR1(thread_dtor, "thread(%d)", em->em_tid);
358ad2056f2SAlexander Leidinger 
35981338031SDmitry Chagin 	free(em, M_TEMP);
360ad2056f2SAlexander Leidinger }
361ad2056f2SAlexander Leidinger 
362ad2056f2SAlexander Leidinger void
363e5d81ef1SDmitry Chagin linux_schedtail(struct thread *td)
364ad2056f2SAlexander Leidinger {
365ad2056f2SAlexander Leidinger 	struct linux_emuldata *em;
366*74a0e24fSMateusz Guzik #ifdef KTR
367*74a0e24fSMateusz Guzik 	int error;
368*74a0e24fSMateusz Guzik #else
369*74a0e24fSMateusz Guzik 	int error __unused;
370*74a0e24fSMateusz Guzik #endif
371ad2056f2SAlexander Leidinger 	int *child_set_tid;
372ad2056f2SAlexander Leidinger 
37381338031SDmitry Chagin 	em = em_find(td);
374bc273677SDmitry Chagin 	KASSERT(em != NULL, ("linux_schedtail: thread emuldata not found.\n"));
375ad2056f2SAlexander Leidinger 	child_set_tid = em->child_set_tid;
376ad2056f2SAlexander Leidinger 
37719e252baSAlexander Leidinger 	if (child_set_tid != NULL) {
378e0327ddbSDmitry Chagin 		error = copyout(&em->em_tid, child_set_tid,
37981338031SDmitry Chagin 		    sizeof(em->em_tid));
3807d96520bSDmitry Chagin 		LINUX_CTR4(schedtail, "thread(%d) %p stored %d error %d",
38181338031SDmitry Chagin 		    td->td_tid, child_set_tid, em->em_tid, error);
38281338031SDmitry Chagin 	} else
3837d96520bSDmitry Chagin 		LINUX_CTR1(schedtail, "thread(%d)", em->em_tid);
384bb63fddeSAlexander Leidinger }
385