diff options
Diffstat (limited to 'usr.sbin/binmiscctl')
-rw-r--r-- | usr.sbin/binmiscctl/Makefile | 10 | ||||
-rw-r--r-- | usr.sbin/binmiscctl/Makefile.depend | 18 | ||||
-rw-r--r-- | usr.sbin/binmiscctl/binmiscctl.8 | 309 | ||||
-rw-r--r-- | usr.sbin/binmiscctl/binmiscctl.c | 510 |
4 files changed, 847 insertions, 0 deletions
diff --git a/usr.sbin/binmiscctl/Makefile b/usr.sbin/binmiscctl/Makefile new file mode 100644 index 0000000..f2c2870 --- /dev/null +++ b/usr.sbin/binmiscctl/Makefile @@ -0,0 +1,10 @@ +# +# $FreeBSD$ +# + +.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 0000000..3646e2e --- /dev/null +++ b/usr.sbin/binmiscctl/Makefile.depend @@ -0,0 +1,18 @@ +# $FreeBSD$ +# Autogenerated - do NOT edit! + +DIRDEPS = \ + gnu/lib/csu \ + gnu/lib/libgcc \ + 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 0000000..4bc9986 --- /dev/null +++ b/usr.sbin/binmiscctl/binmiscctl.8 @@ -0,0 +1,309 @@ +.\"- +.\" 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. +.\" +.\" $FreeBSD$ +.\" +.\" Support for miscellaneous binary image activators +.\" +.Dd December 30, 2014 +.Dt BINMISCCTL 8 +.Os +.Sh NAME +.Nm binmiscctl +.Nd manage binary image activators +.Sh SYNOPSIS +.Nm +.Cm add +.Ar name +.Cm --interpreter +.Ar path +.Cm --magic +.Ar magic +.Cm --size +.Ar size +.Op Cm --mask Ar mask +.Op Cm --offset Ar offset +.Op Cm --set-enabled +.Nm +.Cm remove +.Ar name +.Nm +.Cm disable +.Ar name +.Nm +.Cm enable +.Ar name +.Nm +.Cm lookup +.Ar name +.Nm +.Cm list +.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 +.Cm --interpreter +.Ar path +.Cm --magic +.Ar magic +.Cm --size +.Ar size +.Op Cm --mask Ar mask +.Op Cm --offset Ar offset +.Op Cm --set-enabled +.Xc +Add a new activator entry in the kernel. +You must specify a +unique +.Ar name, +interpreter path and its arguments +.Ar path, +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 +.Cm --offset +option. +By default the +.Ar offset +is zero. +.Pp +To enable the activator entry the +.Cm --set-enabled +option is used. +The activator default state is disabled. +.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 remove Ar name +Remove the activator entry identified with +.Ar name . +.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 lookup Ar name +Look up and print out the activator entry identified with +.Ar name . +.It Cm list +Take a snapshot and print all the activator entries currently configured. +.El +.Sh EXAMPLES +Add an image activator to run the LLVM interpreter (lli) on bitcode +compiled files: +.Bd -ragged -offset indent +# binmiscctl add llvmbc --interpreter ''/usr/bin/lli --fake-argv0=#a'' +--magic ''BC\\xc0\\xde'' --size 4 --set-enabled +.Ed +.Pp +.Ar #a +is replaced with the old +.Dv argv0 +value so that 'lli' can fake its +.Dv argv0 . +Set its state to enabled. +.Pp +Set the state of the +.Ar llvmbc +image activator to disabled: +.Dl # binmiscctl disable llvmbc +.Pp +Set the state of the +.Ar llvmbc +image activator to enabled: +.Dl # binmiscctl enable llvmbc +.Pp +Delete the +.Ar llvmbc +image activator: +.Dl # binmiscctl remove llvmbc +.Pp +Look up and list the record for the +.Ar llvmbc +image activator: +.Dl # binmiscctl lookup llvmbc +.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\ex01\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 SPARC64 binaries: +.Bd -literal -offset indent +# binmiscctl add sparc64 \e + --interpreter "/usr/local/bin/qemu-sparc64-static" \e + --magic "\ex7f\ex45\ex4c\ex46\ex02\ex02\ex01\ex00\ex00\ex00\e + \ex00\ex00\ex00\ex00\ex00\ex00\ex00\ex02\ex00\ex2b" \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 +.Ss "Create and use an ARMv6 chroot on an AMD64 host" +Use an existing source tree to build a chroot host with architecture +overrides: +.Bd -literal +D=/path/to/chroot +cd /usr/src +mkdir -p $D +make world TARGET=arm TARGET_ARCH=armv6 DESTDIR=$D +make distribution TARGET=arm TARGET_ARCH=armv6 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 binmiscctl command. +Using the example above: +.Bd -literal +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 +chroot $D +.Ed +.Sh SEE ALSO +.Xr lli 1 , +.Xr execve 2 , +.Xr jail 8 +.Sh HISTORY +The +.Cm binmiscctl +command was added in +.Fx 10.1 . +It was developed to support the imgact_binmisc kernel module. +.Sh AUTHORS +Stacey D Son diff --git a/usr.sbin/binmiscctl/binmiscctl.c b/usr.sbin/binmiscctl/binmiscctl.c new file mode 100644 index 0000000..5ab82e4 --- /dev/null +++ b/usr.sbin/binmiscctl/binmiscctl.c @@ -0,0 +1,510 @@ +/*- + * 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/cdefs.h> +__FBSDID("$FreeBSD$"); + +#include <ctype.h> +#include <errno.h> +#include <getopt.h> +#include <stdio.h> +#include <stdarg.h> +#include <stdint.h> +#include <stdlib.h> +#include <string.h> + +#include <sys/types.h> +#include <sys/imgact_binmisc.h> +#include <sys/linker.h> +#include <sys/sysctl.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]" + }, + { + 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' }, + { 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 +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 < ( sizeof (cmds) / sizeof (cmds[0])); 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 +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\n", (flags & IBF_ENABLED) ? "ENABLED " : "", + (flags & IBF_USE_MASK) ? "USE_MASK " : ""); + 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 < ( sizeof (cmds) / sizeof (cmds[0])); 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 (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, "ei:m:M:o:s:", add_opts, NULL)) + != -1) { + + switch(ch) { + case 'i': + getoptstr(xbe->xbe_interpreter, IBE_INTERP_LEN_MAX, + "interpreter"); + break; + + case 'm': + magic = strdup(optarg); + break; + + case 'M': + 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; + + 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 (kldfind(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 == -1) + 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 < (xbe_out_sz / sizeof(xbe_out)); i++) + printxbe(&xbe_outp[i]); + } + + return (error); +} |