xref: /netbsd-src/sys/compat/linux/common/linux_mod.c (revision eab380320695b8901777f834601151f48dd29933)
1*eab38032Sriastradh /*	$NetBSD: linux_mod.c,v 1.17 2024/10/01 16:41:29 riastradh Exp $	*/
292ce8c6aSad 
392ce8c6aSad /*-
492ce8c6aSad  * Copyright (c) 2008 The NetBSD Foundation, Inc.
592ce8c6aSad  * All rights reserved.
692ce8c6aSad  *
792ce8c6aSad  * This code is derived from software developed for The NetBSD Foundation
892ce8c6aSad  * by Andrew Doran.
992ce8c6aSad  *
1092ce8c6aSad  * Redistribution and use in source and binary forms, with or without
1192ce8c6aSad  * modification, are permitted provided that the following conditions
1292ce8c6aSad  * are met:
1392ce8c6aSad  * 1. Redistributions of source code must retain the above copyright
1492ce8c6aSad  *    notice, this list of conditions and the following disclaimer.
1592ce8c6aSad  * 2. Redistributions in binary form must reproduce the above copyright
1692ce8c6aSad  *    notice, this list of conditions and the following disclaimer in the
1792ce8c6aSad  *    documentation and/or other materials provided with the distribution.
1892ce8c6aSad  *
1992ce8c6aSad  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
2092ce8c6aSad  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
2192ce8c6aSad  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
2292ce8c6aSad  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
2392ce8c6aSad  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
2492ce8c6aSad  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
2592ce8c6aSad  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
2692ce8c6aSad  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
2792ce8c6aSad  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
2892ce8c6aSad  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
2992ce8c6aSad  * POSSIBILITY OF SUCH DAMAGE.
3092ce8c6aSad  */
3192ce8c6aSad 
3292ce8c6aSad #include <sys/cdefs.h>
33*eab38032Sriastradh __KERNEL_RCSID(0, "$NetBSD: linux_mod.c,v 1.17 2024/10/01 16:41:29 riastradh Exp $");
3492ce8c6aSad 
3592ce8c6aSad #ifdef _KERNEL_OPT
3692ce8c6aSad #include "opt_execfmt.h"
3792ce8c6aSad #endif
3892ce8c6aSad 
3992ce8c6aSad #ifndef ELFSIZE
4092ce8c6aSad #define ELFSIZE ARCH_ELFSIZE
4192ce8c6aSad #endif
4292ce8c6aSad 
4392ce8c6aSad #include <sys/param.h>
4492ce8c6aSad #include <sys/module.h>
4592ce8c6aSad #include <sys/exec.h>
4692ce8c6aSad #include <sys/signalvar.h>
47aef145ddSmaxv #include <sys/sysctl.h>
4892ce8c6aSad 
498575c986Schristos #include <compat/linux/common/linux_inotify.h>
5092ce8c6aSad #include <compat/linux/common/linux_sysctl.h>
5192ce8c6aSad #include <compat/linux/common/linux_exec.h>
5292ce8c6aSad 
5392ce8c6aSad #if defined(EXEC_ELF32) && ELFSIZE == 32
5492ce8c6aSad # define	MD1	",exec_elf32"
5592ce8c6aSad #else
5692ce8c6aSad # define	MD1	""
5792ce8c6aSad #endif
5892ce8c6aSad #if defined(EXEC_ELF64)
5992ce8c6aSad # define	MD2	",exec_elf64"
6092ce8c6aSad #else
6192ce8c6aSad # define	MD2	""
6292ce8c6aSad #endif
6392ce8c6aSad #if defined(EXEC_AOUT)
6492ce8c6aSad #  define	MD3	",exec_aout"
6592ce8c6aSad #else
6692ce8c6aSad # define	MD3	""
6792ce8c6aSad #endif
6892ce8c6aSad 
690124a941Schristos #define REQ1    "compat_ossaudio,sysv_ipc,mqueue,compat_util"
70d91f98a8Spgoyette #define REQ2    ",compat_50,compat_43"
71d91f98a8Spgoyette 
72d91f98a8Spgoyette MODULE(MODULE_CLASS_EXEC, compat_linux, REQ1 REQ2 MD1 MD2 MD3);
7392ce8c6aSad 
7492ce8c6aSad static struct execsw linux_execsw[] = {
7592ce8c6aSad #if defined(EXEC_ELF32) && ELFSIZE == 32
7654b7adb1Schristos 	{
7754b7adb1Schristos 		.es_hdrsz = sizeof (Elf32_Ehdr),
7854b7adb1Schristos 		.es_makecmds = exec_elf32_makecmds,
7954b7adb1Schristos 		.u = {
8054b7adb1Schristos 			.elf_probe_func = linux_elf32_probe,
8154b7adb1Schristos 		},
8254b7adb1Schristos 		.es_emul = &emul_linux,
8354b7adb1Schristos 		.es_prio = EXECSW_PRIO_ANY,
8454b7adb1Schristos 		.es_arglen = LINUX_ELF_AUX_ARGSIZ,
8554b7adb1Schristos 		.es_copyargs = linux_elf32_copyargs,
8654b7adb1Schristos 		.es_setregs = NULL,
8754b7adb1Schristos 		.es_coredump = coredump_elf32,
8854b7adb1Schristos 		.es_setup_stack = linux_exec_setup_stack,
8954b7adb1Schristos 	},
9092ce8c6aSad #elif defined(EXEC_ELF64)
9154b7adb1Schristos 	{
9254b7adb1Schristos 		.es_hdrsz = sizeof (Elf64_Ehdr),
9354b7adb1Schristos 		.es_makecmds = exec_elf64_makecmds,
9454b7adb1Schristos 		.u = {
9554b7adb1Schristos 			.elf_probe_func = linux_elf64_probe,
9654b7adb1Schristos 		},
9754b7adb1Schristos 		.es_emul = &emul_linux,
9854b7adb1Schristos 		.es_prio = EXECSW_PRIO_ANY,
9954b7adb1Schristos 		.es_arglen = LINUX_ELF_AUX_ARGSIZ,
10054b7adb1Schristos 		.es_copyargs = linux_elf64_copyargs,
10154b7adb1Schristos 		.es_setregs = NULL,
10254b7adb1Schristos  		.es_coredump = coredump_elf64,
10354b7adb1Schristos 		.es_setup_stack = linux_exec_setup_stack,
10454b7adb1Schristos 	},
10592ce8c6aSad #endif
10692ce8c6aSad #ifdef EXEC_AOUT
10754b7adb1Schristos 	{
10854b7adb1Schristos 		.es_hdrsz = LINUX_AOUT_HDR_SIZE,
10954b7adb1Schristos 		.es_makecmds = exec_linux_aout_makecmds,
11054b7adb1Schristos 		.u = {
11154b7adb1Schristos 			.elf_probe_func = NULL,
11254b7adb1Schristos 		},
11354b7adb1Schristos 		.es_emul = &emul_linux,
11454b7adb1Schristos 		.es_prio = EXECSW_PRIO_LAST,
11554b7adb1Schristos 		.es_arglen = LINUX_AOUT_AUX_ARGSIZ,
11654b7adb1Schristos 		.es_copyargs = linux_aout_copyargs,
11754b7adb1Schristos 		.es_setregs = NULL,
11854b7adb1Schristos 		.es_coredump = coredump_netbsd,
11954b7adb1Schristos 		.es_setup_stack = linux_exec_setup_stack,
12054b7adb1Schristos 	},
12192ce8c6aSad #endif
12292ce8c6aSad };
12392ce8c6aSad 
124c08407ddSjoerg int linux_enabled = 1;
125aef145ddSmaxv 
126aef145ddSmaxv int
127aef145ddSmaxv linux_sysctl_enable(SYSCTLFN_ARGS)
128aef145ddSmaxv {
129aef145ddSmaxv 	struct sysctlnode node;
130aef145ddSmaxv 	int error, val;
131aef145ddSmaxv 
132aef145ddSmaxv 	val = *(int *)rnode->sysctl_data;
133aef145ddSmaxv 
134aef145ddSmaxv 	node = *rnode;
135aef145ddSmaxv 	node.sysctl_data = &val;
136aef145ddSmaxv 
137aef145ddSmaxv 	error = sysctl_lookup(SYSCTLFN_CALL(&node));
138aef145ddSmaxv 	if (error != 0 || newp == NULL)
139aef145ddSmaxv 		return error;
140aef145ddSmaxv 
141a2da047fSkre 	if (val == *(int *)rnode->sysctl_data)
142a2da047fSkre 		return 0;
143a2da047fSkre 
144a2da047fSkre 	if (val == 1)
145aef145ddSmaxv 		error = exec_add(linux_execsw, __arraycount(linux_execsw));
146a2da047fSkre 	else if (val == 0)
147aef145ddSmaxv 		error = exec_remove(linux_execsw, __arraycount(linux_execsw));
148a2da047fSkre 	else
149aef145ddSmaxv 		error = EINVAL;
150a2da047fSkre 
151aef145ddSmaxv 	if (error)
152aef145ddSmaxv 		return error;
153aef145ddSmaxv 
154aef145ddSmaxv 	*(int *)rnode->sysctl_data = val;
155aef145ddSmaxv 
156aef145ddSmaxv 	return 0;
157aef145ddSmaxv }
158aef145ddSmaxv 
15992ce8c6aSad static int
16092ce8c6aSad compat_linux_modcmd(modcmd_t cmd, void *arg)
16192ce8c6aSad {
16292ce8c6aSad 	int error;
16392ce8c6aSad 
16492ce8c6aSad 	switch (cmd) {
16592ce8c6aSad 	case MODULE_CMD_INIT:
1668575c986Schristos 		error = linux_inotify_init();
1678575c986Schristos 		if (error != 0)
1688575c986Schristos 			return error;
169a2da047fSkre 		error = exec_add(linux_execsw, __arraycount(linux_execsw));
1708575c986Schristos 		if (error)
1718575c986Schristos 			linux_inotify_fini();
172a2da047fSkre 		return error;
17392ce8c6aSad 
17492ce8c6aSad 	case MODULE_CMD_FINI:
175aef145ddSmaxv 		error = exec_remove(linux_execsw, __arraycount(linux_execsw));
176aef145ddSmaxv 		if (error)
177aef145ddSmaxv 			return error;
1784af030e5Spgoyette 		linux_sysctl_fini();
1798575c986Schristos 		linux_inotify_fini();
180aef145ddSmaxv 		return 0;
18192ce8c6aSad 
18292ce8c6aSad 	default:
18392ce8c6aSad 		return ENOTTY;
18492ce8c6aSad 	}
18592ce8c6aSad }
186