| 1 | /*- |
| 2 | * SPDX-License-Identifier: BSD-2-Clause |
| 3 | * |
| 4 | * Copyright (c) 2013 Stacey D. Son |
| 5 | * |
| 6 | * Redistribution and use in source and binary forms, with or without |
| 7 | * modification, are permitted provided that the following conditions |
| 8 | * are met: |
| 9 | * 1. Redistributions of source code must retain the above copyright |
| 10 | * notice, this list of conditions and the following disclaimer. |
| 11 | * 2. Redistributions in binary form must reproduce the above copyright |
| 12 | * notice, this list of conditions and the following disclaimer in the |
| 13 | * documentation and/or other materials provided with the distribution. |
| 14 | * |
| 15 | * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND |
| 16 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
| 17 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE |
| 18 | * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE |
| 19 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL |
| 20 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS |
| 21 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) |
| 22 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT |
| 23 | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY |
| 24 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF |
| 25 | * SUCH DAMAGE. |
| 26 | */ |
| 27 | |
| 28 | #ifndef	_IMGACT_BINMISC_H_ |
| 29 | #define	_IMGACT_BINMISC_H_ |
| 30 | |
| 31 | /** |
| 32 | * Miscellaneous binary interpreter image activator. |
| 33 | */ |
| 34 | |
| 35 | #include <sys/param.h>	/* for MAXPATHLEN */ |
| 36 | |
| 37 | /* |
| 38 | * Imgact bin misc parameters. |
| 39 | */ |
| 40 | #define	IBE_VERSION	1	/* struct ximgact_binmisc_entry version. */ |
| 41 | #define	IBE_NAME_MAX	32	/* Max size for entry name. */ |
| 42 | #define	IBE_MAGIC_MAX	256	/* Max size for header magic and mask. */ |
| 43 | #define	IBE_ARG_LEN_MAX	256	/* Max space for optional interpreter command- |
| 44 | 				 line arguments separated by white space */ |
| 45 | #define	IBE_INTERP_LEN_MAX	(MAXPATHLEN + IBE_ARG_LEN_MAX) |
| 46 | #define	IBE_MAX_ENTRIES	64	/* Max number of interpreter entries. */ |
| 47 | |
| 48 | /* We only map the first page for identification purposes. */ |
| 49 | #define	IBE_MATCH_MAX	PAGE_SIZE |
| 50 | _Static_assert(IBE_MAGIC_MAX <= IBE_MATCH_MAX, |
| 51 | "Cannot identify binaries past the first page."); |
| 52 | |
| 53 | /* |
| 54 | * Imgact bin misc interpreter entry flags. |
| 55 | */ |
| 56 | #define	IBF_ENABLED	0x0001	/* Entry is active. */ |
| 57 | #define	IBF_USE_MASK	0x0002	/* Use mask on header magic field. */ |
| 58 | #define	IBF_PRE_OPEN	0x0004	/* Cache the vnode for interpreter */ |
| 59 | |
| 60 | #define	IBF_VALID_UFLAGS	0x0007	/* Bits allowed from userland. */ |
| 61 | |
| 62 | /* |
| 63 | * Used with sysctlbyname() to pass imgact bin misc entries in and out of the |
| 64 | * kernel. |
| 65 | */ |
| 66 | typedef struct ximgact_binmisc_entry { |
| 67 | 	uint32_t xbe_version;	/* Struct version(IBE_VERSION) */ |
| 68 | 	uint32_t xbe_flags;	/* Entry flags (IBF_*) */ |
| 69 | 	uint32_t xbe_moffset;	/* Magic offset in header */ |
| 70 | 	uint32_t xbe_msize;	/* Magic size */ |
| 71 | 	uint32_t spare[3];	/* Spare fields for future use */ |
| 72 | 	char xbe_name[IBE_NAME_MAX];	/* Unique interpreter name */ |
| 73 | 	char xbe_interpreter[IBE_INTERP_LEN_MAX]; /* Interpreter path + args */ |
| 74 | 	uint8_t xbe_magic[IBE_MAGIC_MAX]; /* Header Magic */ |
| 75 | 	uint8_t xbe_mask[IBE_MAGIC_MAX]; /* Magic Mask */ |
| 76 | } ximgact_binmisc_entry_t; |
| 77 | |
| 78 | /* |
| 79 | * sysctl() command names. |
| 80 | */ |
| 81 | #define	IBE_SYSCTL_NAME		"kern.binmisc" |
| 82 | |
| 83 | #define	IBE_SYSCTL_NAME_ADD	IBE_SYSCTL_NAME ".add" |
| 84 | #define	IBE_SYSCTL_NAME_REMOVE	IBE_SYSCTL_NAME ".remove" |
| 85 | #define	IBE_SYSCTL_NAME_DISABLE	IBE_SYSCTL_NAME ".disable" |
| 86 | #define	IBE_SYSCTL_NAME_ENABLE	IBE_SYSCTL_NAME ".enable" |
| 87 | #define	IBE_SYSCTL_NAME_LOOKUP	IBE_SYSCTL_NAME ".lookup" |
| 88 | #define	IBE_SYSCTL_NAME_LIST	IBE_SYSCTL_NAME ".list" |
| 89 | |
| 90 | #define	KMOD_NAME	"imgact_binmisc" |
| 91 | |
| 92 | /* |
| 93 | * Examples of manipulating the interpreter table using sysctlbyname(3): |
| 94 | * |
| 95 | * #include <sys/imgact_binmisc.h> |
| 96 | * |
| 97 | * #define LLVM_MAGIC "BC\xc0\xde" |
| 98 | * |
| 99 | * #define MIPS64_ELF_MAGIC	"\x7f\x45\x4c\x46\x02\x02\x01\x00\x00\x00" \ |
| 100 | *				"\x00\x00\x00\x00\x00\x00\x00\x02\x00\x08" |
| 101 | * #define MIPS64_ELF_MASK	"\xff\xff\xff\xff\xff\xff\xff\x00\xff\xff" \ |
| 102 | *				"\xff\xff\xff\xff\xff\xff\xff\xfe\xff\xff" |
| 103 | * |
| 104 | * ximgact_binmisc_entry_t xbe, *xbep, out_xbe; |
| 105 | * size_t size = 0, osize; |
| 106 | * int error, i; |
| 107 | * |
| 108 | * // Add image activator for LLVM byte code |
| 109 | * bzero(&xbe, sizeof(xbe)); |
| 110 | * xbe.xbe_version = IBE_VERSION; |
| 111 | * xbe.xbe_flags = IBF_ENABLED; |
| 112 | * strlcpy(xbe.xbe_name, "llvm_bc", IBE_NAME_MAX); |
| 113 | * strlcpy(xbe.xbe_interpreter, "/usr/bin/lli --fake-arg0=#a", |
| 114 | * IBE_INTERP_LEN_MAX); |
| 115 | * xbe.xbe_moffset = 0; |
| 116 | * xbe.xbe_msize = 4; |
| 117 | * memcpy(xbe.xbe_magic, LLVM_MAGIC, xbe.xbe_msize); |
| 118 | * error = sysctlbyname(IBE_SYSCTL_NAME_ADD, NULL, NULL, &xbe, sizeof(xbe)); |
| 119 | * |
| 120 | * // Add image activator for mips64 ELF binaries to use qemu user mode |
| 121 | * bzero(&xbe, sizeof(xbe)); |
| 122 | * xbe.xbe_version = IBE_VERSION; |
| 123 | * xbe.xbe_flags = IBF_ENABLED | IBF_USE_MASK; |
| 124 | * strlcpy(xbe.xbe_name, "mips64elf", IBE_NAME_MAX); |
| 125 | * strlcpy(xbe.xbe_interpreter, "/usr/local/bin/qemu-mips64", |
| 126 | *	IBE_INTERP_LEN_MAX); |
| 127 | * xbe.xbe_moffset = 0; |
| 128 | * xbe.xbe_msize = 20; |
| 129 | * memcpy(xbe.xbe_magic, MIPS64_ELF_MAGIC, xbe.xbe_msize); |
| 130 | * memcpy(xbe.xbe_mask, MIPS64_ELF_MASK, xbe.xbe_msize); |
| 131 | * sysctlbyname(IBE_SYSCTL_NAME_ADD, NULL, NULL, &xbe, sizeof(xbe)); |
| 132 | * |
| 133 | * // Disable (OR Enable OR Remove) image activator for LLVM byte code |
| 134 | * bzero(&xbe, sizeof(xbe)); |
| 135 | * xbe.xbe_version = IBE_VERSION; |
| 136 | * strlcpy(xbe.xbe_name, "llvm_bc", IBE_NAME_MAX); |
| 137 | * error = sysctlbyname(IBE_SYSCTL_NAME_DISABLE, NULL, NULL, &xbe, sizeof(xbe)); |
| 138 | * // OR sysctlbyname(IBE_SYSCTL_NAME_ENABLE, NULL, NULL, &xbe, sizeof(xbe)); |
| 139 | * // OR sysctlbyname(IBE_SYSCTL_NAME_REMOVE, NULL, NULL, &xbe, sizeof(xbe)); |
| 140 | * |
| 141 | * // Lookup image activator "llvm_bc" |
| 142 | * bzero(&xbe, sizeof(xbe)); |
| 143 | * xbe.xbe_version = IBE_VERSION; |
| 144 | * strlcpy(xbe.xbe_name, "llvm_bc", IBE_NAME_MAX); |
| 145 | * size = sizeof(out_xbe); |
| 146 | * error = sysctlbyname(IBE_SYSCTL_NAME_LOOKUP, &out_xbe, &size, &xbe, |
| 147 | *	sizeof(xbe)); |
| 148 | * |
| 149 | * // Get all the currently configured image activators and report |
| 150 | * error = sysctlbyname(IBE_SYSCTL_NAME_LIST, NULL, &size, NULL, 0); |
| 151 | * if (0 == error && size > 0) { |
| 152 | *	xbep = malloc(size); |
| 153 | *	while(1) { |
| 154 | *	 osize = size; |
| 155 | *	 error = sysctlbyname("kern.binmisc.list", xbep, &size, NULL, 0); |
| 156 | *	 if (-1 == error && ENOMEM == errno && size == osize) { |
| 157 | *		// The buffer too small and needs to grow |
| 158 | *		size += sizeof(xbe); |
| 159 | *		xbep = realloc(xbep, size); |
| 160 | *	 } else |
| 161 | *		break; |
| 162 | *	} |
| 163 | * } |
| 164 | * for(i = 0; i < (size / sizeof(xbe)); i++, xbep++) |
| 165 | *	printf("name: %s interpreter: %s flags: %s %s\n", xbep->xbe_name, |
| 166 | *	 xbep->xbe_interpreter, (xbep->xbe_flags & IBF_ENABLED) ? |
| 167 | *	 "ENABLED" : "", (xbep->xbe_flags & IBF_ENABLED) ? "USE_MASK" : ""); |
| 168 | * |
| 169 | * The sysctlbyname() calls above may return the following errors in addition |
| 170 | * to the standard ones: |
| 171 | * |
| 172 | * [EINVAL] Invalid argument in the input ximgact_binmisc_entry_t structure. |
| 173 | * [EEXIST] Interpreter entry for given name already exist in kernel list. |
| 174 | * [ENOMEM] Allocating memory in the kernel failed or, in the case of |
| 175 | * kern.binmisc.list, the user buffer is too small. |
| 176 | * [ENOENT] Interpreter entry for given name is not found. |
| 177 | * [ENOSPC] Attempted to exceed maximum number of entries (IBE_MAX_ENTRIES). |
| 178 | */ |
| 179 | |
| 180 | #endif /* !_IMGACT_BINMISC_H_ */ |