diff options
Diffstat (limited to 'usr.sbin/binmiscctl')
| -rw-r--r-- | usr.sbin/binmiscctl/Makefile | 9 | ||||
| -rw-r--r-- | usr.sbin/binmiscctl/Makefile.depend | 15 | ||||
| -rw-r--r-- | usr.sbin/binmiscctl/binmiscctl.8 | 331 | ||||
| -rw-r--r-- | usr.sbin/binmiscctl/binmiscctl.c | 519 | 
4 files changed, 874 insertions, 0 deletions
| diff --git a/usr.sbin/binmiscctl/Makefile b/usr.sbin/binmiscctl/Makefile new file mode 100644 index 000000000000..157f21378c7a --- /dev/null +++ b/usr.sbin/binmiscctl/Makefile @@ -0,0 +1,9 @@ +# +# + +.include <bsd.own.mk> + +PROG=	binmiscctl +MAN=	binmiscctl.8 + +.include <bsd.prog.mk> diff --git a/usr.sbin/binmiscctl/Makefile.depend b/usr.sbin/binmiscctl/Makefile.depend new file mode 100644 index 000000000000..6ef78fac5cbf --- /dev/null +++ b/usr.sbin/binmiscctl/Makefile.depend @@ -0,0 +1,15 @@ +# Autogenerated - do NOT edit! + +DIRDEPS = \ +	include \ +	include/xlocale \ +	lib/${CSU_DIR} \ +	lib/libc \ +	lib/libcompiler_rt \ + + +.include <dirdeps.mk> + +.if ${DEP_RELDIR} == ${_DEP_RELDIR} +# local dependencies - needed for -jN in clean tree +.endif diff --git a/usr.sbin/binmiscctl/binmiscctl.8 b/usr.sbin/binmiscctl/binmiscctl.8 new file mode 100644 index 000000000000..17bce41a3212 --- /dev/null +++ b/usr.sbin/binmiscctl/binmiscctl.8 @@ -0,0 +1,331 @@ +.\"- +.\" Copyright (c) 2013 Stacey D. Son +.\" All rights reserved. +.\" +.\" Redistribution and use in source and binary forms, with or without +.\" modification, are permitted provided that the following conditions +.\" are met: +.\" 1. Redistributions of source code must retain the above copyright +.\"    notice, this list of conditions and the following disclaimer. +.\" 2. Redistributions in binary form must reproduce the above copyright +.\"    notice, this list of conditions and the following disclaimer in the +.\"    documentation and/or other materials provided with the distribution. +.\" +.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND +.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +.\" ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE +.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +.\" SUCH DAMAGE. +.\" +.\" Support for miscellaneous binary image activators +.\" +.Dd April 30, 2020 +.Dt BINMISCCTL 8 +.Os +.Sh NAME +.Nm binmiscctl +.Nd manage binary image activators +.Sh SYNOPSIS +.Nm +.Cm add +.Ar name +.Fl -interpreter +.Ar path +.Fl -magic +.Ar magic +.Fl -size +.Ar size +.Op Fl -mask Ar mask +.Op Fl -offset Ar offset +.Op Fl -set-enabled +.Op Fl -pre-open +.Nm +.Cm disable +.Ar name +.Nm +.Cm enable +.Ar name +.Nm +.Cm list +.Nm +.Cm lookup +.Ar name +.Nm +.Cm remove +.Ar name +.Sh DESCRIPTION +The +.Nm +utility +is the management utility for configuring miscellaneous binaries image +activators in the kernel. +It allows adding, deleting, disabling, +enabling, and looking up interpreters. +Also, all the interpreters can +be listed. +.Pp +The first argument on the command line indicates the operation to be +performed. +Operation must be one of the following: +.Bl -tag -width indent +.It Xo +.Cm add +.Ar name +.Fl -interpreter +.Ar path +.Fl -magic +.Ar magic +.Fl -size +.Ar size +.Op Fl -mask Ar mask +.Op Fl -offset Ar offset +.Op Fl -set-enabled +.Op Fl -pre-open +.Xc +Add a new activator entry in the kernel. +You must specify a +unique +.Ar name , +a +.Ar path +to the interpreter, +header +.Ar magic +bytes that uniquely identify a suitable binary for the activator, +and the +.Ar size +of the +.Ar magic +in bytes. +.Pp +Optionally, you may specify a +.Ar mask +to do a bitwise AND with the header bytes. +This effectively allows you to ignore fields in the binary header that +do not uniquely indentify the binary file's type. +.Pp +An +.Ar offset +may be specified for the magic bytes using the +.Fl -offset +option. +By default the +.Ar offset +is zero. +.Pp +To enable the activator entry the +.Fl -set-enabled +option is used. +The activator default state is disabled. +.Pp +To make the interpreter automatically available in jails and chroots, +use the +.Fl -pre-open +option to allow the kernel to open the binary at configuration time +rather then lazily when the interpreted program is started. +.Pp +The interpreter +.Ar path +may also contain arguments for the interpreter including +.Ar #a +which gets replaced by the old +.Dv argv0 +value in the interpreter string. +.It Cm disable Ar name +Disable the activator entry identified with +.Ar name . +.It Cm enable Ar name +Enable the activator entry identified with +.Ar name . +.It Cm list +Take a snapshot and print all the activator entries currently configured. +.It Cm lookup Ar name +Look up and print out the activator entry identified with +.Ar name . +.It Cm remove Ar name +Remove the activator entry identified with +.Ar name . +.El +.Sh EXAMPLES +Add an image activator to run the LLVM interpreter +.Po +.Xr lli 1 +.Pc +on bitcode +compiled files and set its state to enabled. +In this example +.Ar #a +is replaced with the old +.Dv argv0 +value so that +.Xr lli 1 +can fake its +.Dv argv0 : +.Bd -literal -offset indent +# binmiscctl add llvmbc --interpreter ''/usr/bin/lli \e +  --fake-argv0=#a'' --magic ''BC\\xc0\\xde'' --size 4 \e +  --set-enabled +.Ed +.Pp +Set the state of the +.Ar llvmbc +image activator to disabled: +.Bd -literal -offset indent +# binmiscctl disable llvmbc +.Ed +.Pp +Set the state of the +.Ar llvmbc +image activator to enabled: +.Bd -literal -offset indent +# binmiscctl enable llvmbc +.Ed +.Pp +Delete the +.Ar llvmbc +image activator: +.Bd -literal -offset indent +# binmiscctl remove llvmbc +.Ed +.Pp +Look up and list the record for the +.Ar llvmbc +image activator: +.Bd -literal -offset indent +# binmiscctl lookup llvmbc +.Ed +.Pp +Add QEMU bsd-user program as an image activator for ARM AARCH64 binaries: +.Bd -literal -offset indent +# binmiscctl add arm64 \e +  --interpreter "/usr/local/bin/qemu-aarch64-static" \e +  --magic "\ex7f\ex45\ex4c\ex46\ex02\ex01\ex01\ex00\ex00\ex00\e +           \ex00\ex00\ex00\ex00\ex00\ex00\ex02\ex00\exb7\ex00" \e +  --mask  "\exff\exff\exff\exff\exff\exff\exff\ex00\exff\exff\e +           \exff\exff\exff\exff\exff\exff\exfe\exff\exff\exff" \e +  --size 20 --set-enabled +.Ed +.Pp +Add QEMU bsd-user program as an image activator for ARM little-endian binaries: +.Bd -literal -offset indent +# binmiscctl add armelf \e +  --interpreter "/usr/local/bin/qemu-arm-static" \e +  --magic "\ex7f\ex45\ex4c\ex46\ex01\ex01\ex01\ex00\ex00\ex00\e +           \ex00\ex00\ex00\ex00\ex00\ex00\ex02\ex00\ex28\ex00" \e +  --mask  "\exff\exff\exff\exff\exff\exff\exff\ex00\exff\exff\e +           \exff\exff\exff\exff\exff\exff\exfe\exff\exff\exff" \e +  --size 20 --set-enabled +.Ed +.Pp +Add QEMU bsd-user program as an image activator for ARM big-endian binaries: +.Bd -literal -offset indent +# binmiscctl add armebelf \e +  --interpreter "/usr/local/bin/qemu-arm-static" \e +  --magic "\ex7f\ex45\ex4c\ex46\ex01\ex02\ex01\ex00\ex00\ex00\e +           \ex00\ex00\ex00\ex00\ex00\ex00\ex00\ex02\ex00\ex28" \e +  --mask  "\exff\exff\exff\exff\exff\exff\exff\ex00\exff\exff\e +           \exff\exff\exff\exff\exff\exff\exff\exfe\exff\exff" \e +  --size 20 --set-enabled +.Ed +.Pp +Add QEMU bsd-user program as an image activator for MIPS32 binaries: +.Bd -literal -offset indent +# binmiscctl add mips32 \e +  --interpreter "/usr/local/bin/qemu-mips-static" \e +  --magic "\ex7f\ex45\ex4c\ex46\ex01\ex02\ex01\ex00\ex00\ex00\e +           \ex00\ex00\ex00\ex00\ex00\ex00\ex00\ex02\ex00\ex08" \e +  --mask  "\exff\exff\exff\exff\exff\exff\exff\ex00\exff\exff\e +           \exff\exff\exff\exff\exff\exff\exff\exfe\exff\exff" \e +  --size 20 --set-enabled +.Ed +.Pp +Add QEMU bsd-user program as an image activator for MIPS64 binaries: +.Bd -literal -offset indent +# binmiscctl add mips64 \e +  --interpreter "/usr/local/bin/qemu-mips64-static" \e +  --magic "\ex7f\ex45\ex4c\ex46\ex02\ex02\ex01\ex00\ex00\ex00\e +           \ex00\ex00\ex00\ex00\ex00\ex00\ex00\ex02\ex00\ex08" \e +  --mask "\exff\exff\exff\exff\exff\exff\exff\ex00\exff\exff\e +          \exff\exff\exff\exff\exff\exff\exff\exfe\exff\exff" \e +  --size 20 --set-enabled +.Ed +.Pp +Add QEMU bsd-user program as an image activator for PowerPC binaries: +.Bd -literal -offset indent +# binmiscctl add powerpc \e +  --interpreter "/usr/local/bin/qemu-ppc-static" \e +  --magic "\ex7f\ex45\ex4c\ex46\ex01\ex02\ex01\ex00\ex00\ex00\e +           \ex00\ex00\ex00\ex00\ex00\ex00\ex00\ex02\ex00\ex14" \e +  --mask  "\exff\exff\exff\exff\exff\exff\exff\ex00\exff\exff\e +           \exff\exff\exff\exff\exff\exff\exff\exfe\exff\exff" \e +  --size 20 --set-enabled +.Ed +.Pp +Add QEMU bsd-user program as an image activator for PowerPC64 binaries: +.Bd -literal -offset indent +# binmiscctl add powerpc64 \e +  --interpreter "/usr/local/bin/qemu-ppc64-static" \e +  --magic "\ex7f\ex45\ex4c\ex46\ex02\ex02\ex01\ex00\ex00\ex00\e +           \ex00\ex00\ex00\ex00\ex00\ex00\ex00\ex02\ex00\ex15" \e +  --mask  "\exff\exff\exff\exff\exff\exff\exff\ex00\exff\exff\e +           \exff\exff\exff\exff\exff\exff\exff\exfe\exff\exff" \e +  --size 20 --set-enabled +.Ed +.Pp +Add QEMU bsd-user program as an image activator for 64-bit RISC-V binaries: +.Bd -literal -offset indent +# binmiscctl add riscv64 \e +  --interpreter "/usr/local/bin/qemu-riscv64-static" \e +  --magic "\ex7f\ex45\ex4c\ex46\ex02\ex01\ex01\ex00\ex00\ex00\e +           \ex00\ex00\ex00\ex00\ex00\ex00\ex02\ex00\exf3\ex00" \e +  --mask  "\exff\exff\exff\exff\exff\exff\exff\ex00\exff\exff\e +           \exff\exff\exff\exff\exff\exff\exfe\exff\exff\exff" \e +  --size 20 --set-enabled +.Ed +.Ss "Create and use an ARMv7 chroot on an AMD64 host" +Use an existing source tree to build a chroot host with architecture +overrides: +.Bd -literal -offset ident +D=/path/to/chroot +cd /usr/src +mkdir -p $D +make world TARGET=arm TARGET_ARCH=armv7 DESTDIR=$D +make distribution TARGET=arm TARGET_ARCH=armv7 DESTDIR=$D +.Ed +.Pp +With +.Pa emulators/qemu-user-static +from the +.Fx +Ports Collection, the emulator must be copied into the jail path +specified in the +.Nm +command. +Using the example above: +.Bd -literal -offset indent +mkdir $D/usr/local/bin +cp /usr/local/bin/qemu-arm-static $D/usr/local/bin +.Ed +.Pp +Now the user can chroot into the environment normally, as root: +.Bd -literal -offset indent +chroot $D +.Ed +.Sh SEE ALSO +.Xr lli 1 , +.Xr execve 2 , +.Xr jail 8 +.Sh HISTORY +The +.Nm +command was added in +.Fx 10.1 . +It was developed to support the imgact_binmisc kernel module. +.Sh AUTHORS +.An Stacey D Son Aq Mt sson@FreeBSD.org diff --git a/usr.sbin/binmiscctl/binmiscctl.c b/usr.sbin/binmiscctl/binmiscctl.c new file mode 100644 index 000000000000..6a4950c9bf3a --- /dev/null +++ b/usr.sbin/binmiscctl/binmiscctl.c @@ -0,0 +1,519 @@ +/*- + * Copyright (c) 2013 Stacey D. Son + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + *    notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + *    notice, this list of conditions and the following disclaimer in the + *    documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + */ + +#include <sys/types.h> +#include <sys/imgact_binmisc.h> +#include <sys/linker.h> +#include <sys/module.h> +#include <sys/sysctl.h> + +#include <ctype.h> +#include <errno.h> +#include <getopt.h> +#include <stdio.h> +#include <stdarg.h> +#include <stdint.h> +#include <stdlib.h> +#include <string.h> + +enum cmd { +	CMD_ADD = 0, +	CMD_REMOVE, +	CMD_DISABLE, +	CMD_ENABLE, +	CMD_LOOKUP, +	CMD_LIST, +}; + +extern char *__progname; + +typedef int (*cmd_func_t)(int argc, char *argv[], ximgact_binmisc_entry_t *xbe); + +int add_cmd(int argc, char *argv[], ximgact_binmisc_entry_t *xbe); +int name_cmd(int argc, char *argv[], ximgact_binmisc_entry_t *xbe); +int noname_cmd(int argc, char *argv[], ximgact_binmisc_entry_t *xbe); + +static const struct { +	const int token; +	const char *name; +	cmd_func_t func; +	const char *desc; +	const char *args; +} cmds[] = { +	{ +		CMD_ADD, +		"add", +		add_cmd, +		"Add a new binary image activator (requires 'root' privilege)", +		"<name> --interpreter <path_and_arguments> \\\n" +		"\t\t--magic <magic_bytes> [--mask <mask_bytes>] \\\n" +		"\t\t--size <magic_size> [--offset <magic_offset>] \\\n" +		"\t\t[--set-enabled] \\\n" +		"\t\t[--pre-open]" +	}, +	{ +		CMD_REMOVE, +		"remove", +		name_cmd, +		"Remove a binary image activator (requires 'root' privilege)", +		"<name>" +	}, +	{ +		CMD_DISABLE, +		"disable", +		name_cmd, +		"Disable a binary image activator (requires 'root' privilege)", +		"<name>" +	}, +	{ +		CMD_ENABLE, +		"enable", +		name_cmd, +		"Enable a binary image activator (requires 'root' privilege)", +		"<name>" +	}, +	{ +		CMD_LOOKUP, +		"lookup", +		name_cmd, +		"Lookup a binary image activator", +		"<name>" +	}, +	{ +		CMD_LIST, +		"list", +		noname_cmd, +		"List all the binary image activators", +		"" +	}, +}; + +static const struct option +add_opts[] = { +	{ "set-enabled",	no_argument,		NULL,	'e' }, +	{ "interpreter",	required_argument,	NULL,	'i' }, +	{ "mask",		required_argument,	NULL,	'M' }, +	{ "magic",		required_argument,	NULL,	'm' }, +	{ "offset",		required_argument,	NULL,	'o' }, +	{ "size",		required_argument,	NULL,	's' }, +	{ "pre-open",		no_argument,		NULL,	'p' }, +	{ NULL,			0,			NULL,	0   } +}; + +static char const *cmd_sysctl_name[] = { +	IBE_SYSCTL_NAME_ADD, +	IBE_SYSCTL_NAME_REMOVE, +	IBE_SYSCTL_NAME_DISABLE, +	IBE_SYSCTL_NAME_ENABLE, +	IBE_SYSCTL_NAME_LOOKUP, +	IBE_SYSCTL_NAME_LIST +}; + +static void __dead2 +usage(const char *format, ...) +{ +	va_list args; +	size_t i; +	int error = 0; + +	va_start(args, format); +	if (format) { +		vfprintf(stderr, format, args); +		error = -1; +	} +	va_end(args); +	fprintf(stderr, "\n"); +	fprintf(stderr, "usage: %s command [args...]\n\n", __progname); + +	for(i = 0; i < nitems(cmds); i++) { +		fprintf(stderr, "%s:\n", cmds[i].desc); +		fprintf(stderr, "\t%s %s %s\n\n", __progname, cmds[i].name, +		    cmds[i].args); +	} + +	exit (error); +} + +static void __dead2 +fatal(const char *format, ...) +{ +	va_list args; + +	va_start(args, format); +	if (format) +		vfprintf(stderr, format, args); +	fprintf(stderr, "\n"); + +	exit(-1); +} + +static void +getoptstr(char *str, size_t size, const char *argname) +{ +	if (strlen(optarg) > size) +		usage("'%s' too large", argname); +	strlcpy(str, optarg, size); +} + +static void +printxbe(ximgact_binmisc_entry_t *xbe) +{ +	uint32_t i, flags = xbe->xbe_flags; + +	if (xbe->xbe_version != IBE_VERSION) { +		fprintf(stderr, "Error: XBE version mismatch\n"); +		return; +	} + +	printf("name: %s\n", xbe->xbe_name); +	printf("interpreter: %s\n", xbe->xbe_interpreter); +	printf("flags: %s%s%s\n", (flags & IBF_ENABLED) ? "ENABLED " : "", +	    (flags & IBF_USE_MASK) ? "USE_MASK " : "", +	    (flags & IBF_PRE_OPEN) ? "PRE_OPEN " : ""); +	printf("magic size: %u\n", xbe->xbe_msize); +	printf("magic offset: %u\n", xbe->xbe_moffset); + +	printf("magic: "); +	for(i = 0; i < xbe->xbe_msize;  i++) { +		if (i && !(i % 12)) +			printf("\n       "); +		else +			if (i && !(i % 4)) +				printf(" "); +		printf("0x%02x ", xbe->xbe_magic[i]); +	} +	printf("\n"); + +	if (flags & IBF_USE_MASK) { +		printf("mask:  "); +		for(i = 0; i < xbe->xbe_msize;  i++) { +			if (i && !(i % 12)) +				printf("\n       "); +			else +				if (i && !(i % 4)) +					printf(" "); +			printf("0x%02x ", xbe->xbe_mask[i]); +		} +		printf("\n"); +	} + +	printf("\n"); +} + +static int +demux_cmd(__unused int argc, char *const argv[]) +{ +	size_t i; + +	optind = 1; +	optreset = 1; + +	for(i = 0; i < nitems(cmds); i++) { +		if (!strcasecmp(cmds[i].name, argv[0])) { +			return (i); +		} +	} + +	/* Unknown command */ +	return (-1); +} + +static int +strlit2bin_cpy(uint8_t *d, char *s, size_t size) +{ +	int c; +	size_t cnt = 0; + +	while((c = *s++) != '\0') { +		if (c == '\\') { +			/* Do '\' escapes. */ +			switch (*s) { +			case '\\': +				*d++ = '\\'; +				break; + +			case 'x': +				s++; +				c = toupper(*s++); +				*d = (c - (isdigit(c) ? '0' : ('A' - 10))) << 4; +				c = toupper(*s++); +				*d++ |= c - (isdigit(c) ? '0' : ('A' - 10)); +				break; + +			default: +				return (-1); +			} +		} else +			*d++ = c; + +		if (++cnt > size) +			return (-1); +	} + +	return (cnt); +} + +int +add_cmd(__unused int argc, char *argv[], ximgact_binmisc_entry_t *xbe) +{ +	int ch; +	char *magic = NULL, *mask = NULL; +	int sz; + +	if (argc == 0) +		usage("Required argument missing\n"); +	if (strlen(argv[0]) > IBE_NAME_MAX) +		usage("'%s' string length longer than IBE_NAME_MAX (%d)", +		    IBE_NAME_MAX); +	strlcpy(&xbe->xbe_name[0], argv[0], IBE_NAME_MAX); + +	while ((ch = getopt_long(argc, argv, "epi:m:M:o:s:", add_opts, NULL)) +	    != -1) { + +		switch(ch) { +		case 'i': +			getoptstr(xbe->xbe_interpreter, IBE_INTERP_LEN_MAX, +			    "interpreter"); +			break; + +		case 'm': +			free(magic); +			magic = strdup(optarg); +			break; + +		case 'M': +			free(mask); +			mask = strdup(optarg); +			xbe->xbe_flags |= IBF_USE_MASK; +			break; + +		case 'e': +			xbe->xbe_flags |= IBF_ENABLED; +			break; + +		case 'o': +			xbe->xbe_moffset = atol(optarg); +			break; + +		case 's': +			xbe->xbe_msize = atol(optarg); +			if (xbe->xbe_msize == 0 || +			    xbe->xbe_msize > IBE_MAGIC_MAX) +				usage("Error: Not valid '--size' value. " +				    "(Must be > 0 and < %u.)\n", +				    xbe->xbe_msize); +			break; + +		case 'p': +			xbe->xbe_flags |= IBF_PRE_OPEN; +			break; + +		default: +			usage("Unknown argument: '%c'", ch); +		} +	} + +	if (xbe->xbe_msize == 0) { +		if (NULL != magic) +			free(magic); +		if (NULL != mask) +			free(mask); +		usage("Error: Missing '--size' argument"); +	} + +	if (NULL != magic) { +		if (xbe->xbe_msize == 0) { +			if (magic) +				free(magic); +			if (mask) +				free(mask); +			usage("Error: Missing magic size argument"); +		} +		sz = strlit2bin_cpy(xbe->xbe_magic, magic, IBE_MAGIC_MAX); +		free(magic); +		if (sz == -1 || (uint32_t)sz != xbe->xbe_msize) { +			if (mask) +				free(mask); +			usage("Error: invalid magic argument"); +		} +		if (mask) { +			sz = strlit2bin_cpy(xbe->xbe_mask, mask, IBE_MAGIC_MAX); +			free(mask); +			if (sz == -1 || (uint32_t)sz != xbe->xbe_msize) +				usage("Error: invalid mask argument"); +		} +	} else { +		if (mask) +			free(mask); +		usage("Error: Missing magic argument"); +	} + +	if (!strnlen(xbe->xbe_interpreter, IBE_INTERP_LEN_MAX)) { +		usage("Error: Missing 'interpreter' argument"); +	} + +	return (0); +} + +int +name_cmd(int argc, char *argv[], ximgact_binmisc_entry_t *xbe) +{ +	if (argc == 0) +		usage("Required argument missing\n"); +	if (strlen(argv[0]) > IBE_NAME_MAX) +		usage("'%s' string length longer than IBE_NAME_MAX (%d)", +		    IBE_NAME_MAX); +	strlcpy(&xbe->xbe_name[0], argv[0], IBE_NAME_MAX); + +	return (0); +} + +int +noname_cmd(__unused int argc, __unused char *argv[], +    __unused ximgact_binmisc_entry_t *xbe) +{ + +	return (0); +} + +int +main(int argc, char **argv) +{ +	int error = 0, cmd = -1; +	ximgact_binmisc_entry_t xbe_in, *xbe_inp = NULL; +	ximgact_binmisc_entry_t xbe_out, *xbe_outp = NULL; +	size_t xbe_in_sz = 0; +	size_t xbe_out_sz = 0, *xbe_out_szp = NULL; +	uint32_t i; + +	if (modfind(KMOD_NAME) == -1) { +		if (kldload(KMOD_NAME) == -1) +			fatal("Can't load %s kernel module: %s", +			    KMOD_NAME, strerror(errno)); +	} + +	bzero(&xbe_in, sizeof(xbe_in)); +	bzero(&xbe_out, sizeof(xbe_out)); +	xbe_in.xbe_version = IBE_VERSION; + +	if (argc < 2) +		usage("Error: requires at least one argument"); + +	argc--, argv++; +	cmd = demux_cmd(argc, argv); +	if (cmd < 0) +		usage("Error: Unknown command \"%s\"", argv[0]); +	argc--, argv++; + +	error = (*cmds[cmd].func)(argc, argv, &xbe_in); +	if (error) +		usage("Can't parse command-line for '%s' command", +		    cmds[cmd].name); + +	if (cmd != CMD_LIST) { +		xbe_inp = &xbe_in; +		xbe_in_sz = sizeof(xbe_in); +	} else +		xbe_out_szp = &xbe_out_sz; +	if (cmd == CMD_LOOKUP) { +		xbe_out_sz = sizeof(xbe_out); +		xbe_outp = &xbe_out; +		xbe_out_szp = &xbe_out_sz; +	} + +	error = sysctlbyname(cmd_sysctl_name[cmd], xbe_outp, xbe_out_szp, +	    xbe_inp, xbe_in_sz); + +	if (error) +		switch(errno) { +		case EINVAL: +			usage("Invalid interpreter name or --interpreter, " +			    "--magic, --mask, or --size argument value"); +			break; + +		case EEXIST: +			usage("'%s' is not unique in activator list", +			    xbe_in.xbe_name); +			break; + +		case ENOENT: +			usage("'%s' is not found in activator list", +			    xbe_in.xbe_name); +			break; + +		case ENOSPC: +			fatal("Fatal: no more room in the activator list " +			    "(limited to %d enties)", IBE_MAX_ENTRIES); +			break; + +		case EPERM: +			usage("Insufficient privileges for '%s' command", +			    cmds[cmd].name); +			break; + +		default: +			fatal("Fatal: sysctlbyname() returned: %s", +			    strerror(errno)); +			break; +		} + + +	if (cmd == CMD_LOOKUP) +		printxbe(xbe_outp); + +	if (cmd == CMD_LIST && xbe_out_sz > 0) { +		xbe_outp = malloc(xbe_out_sz); +		if (!xbe_outp) +			fatal("Fatal: out of memory"); +		while(1) { +			size_t osize = xbe_out_sz; +			error = sysctlbyname(cmd_sysctl_name[cmd], xbe_outp, +			    &xbe_out_sz, NULL, 0); + +			if (error == -1 && errno == ENOMEM && +			    xbe_out_sz == osize) { +				/* +				 * Buffer too small. Increase it by one +				 * entry. +				 */ +				xbe_out_sz += sizeof(xbe_out); +				xbe_outp = realloc(xbe_outp, xbe_out_sz); +				if (!xbe_outp) +					fatal("Fatal: out of memory"); +			} else +				break; +		} +		if (error) { +			free(xbe_outp); +			fatal("Fatal: %s", strerror(errno)); +		} +		for(i = 0; i < howmany(xbe_out_sz, sizeof(xbe_out)); i++) +			printxbe(&xbe_outp[i]); +	} + +	return (error); +} | 
