2 * Copyright (c) 2013 Stacey D. Son
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
14 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
28 #include <sys/cdefs.h>
29 __FBSDID("$FreeBSD$");
40 #include <sys/types.h>
41 #include <sys/imgact_binmisc.h>
42 #include <sys/linker.h>
43 #include <sys/sysctl.h>
54 extern char *__progname;
56 typedef int (*cmd_func_t)(int argc, char *argv[], ximgact_binmisc_entry_t *xbe);
58 int add_cmd(int argc, char *argv[], ximgact_binmisc_entry_t *xbe);
59 int name_cmd(int argc, char *argv[], ximgact_binmisc_entry_t *xbe);
60 int noname_cmd(int argc, char *argv[], ximgact_binmisc_entry_t *xbe);
73 "Add a new binary image activator (requires 'root' privilege)",
74 "<name> --interpreter <path_and_arguments> \\\n"
75 "\t\t--magic <magic_bytes> [--mask <mask_bytes>] \\\n"
76 "\t\t--size <magic_size> [--offset <magic_offset>] \\\n"
83 "Remove a binary image activator (requires 'root' privilege)",
90 "Disable a binary image activator (requires 'root' privilege)",
97 "Enable a binary image activator (requires 'root' privilege)",
104 "Lookup a binary image activator",
111 "List all the binary image activators",
116 static const struct option
118 { "set-enabled", no_argument, NULL, 'e' },
119 { "interpreter", required_argument, NULL, 'i' },
120 { "mask", required_argument, NULL, 'M' },
121 { "magic", required_argument, NULL, 'm' },
122 { "offset", required_argument, NULL, 'o' },
123 { "size", required_argument, NULL, 's' },
127 static char const *cmd_sysctl_name[] = {
129 IBE_SYSCTL_NAME_REMOVE,
130 IBE_SYSCTL_NAME_DISABLE,
131 IBE_SYSCTL_NAME_ENABLE,
132 IBE_SYSCTL_NAME_LOOKUP,
137 usage(const char *format, ...)
143 va_start(args, format);
145 vfprintf(stderr, format, args);
149 fprintf(stderr, "\n");
150 fprintf(stderr, "usage: %s command [args...]\n\n", __progname);
152 for(i = 0; i < ( sizeof (cmds) / sizeof (cmds[0])); i++) {
153 fprintf(stderr, "%s:\n", cmds[i].desc);
154 fprintf(stderr, "\t%s %s %s\n\n", __progname, cmds[i].name,
162 fatal(const char *format, ...)
166 va_start(args, format);
168 vfprintf(stderr, format, args);
169 fprintf(stderr, "\n");
175 getoptstr(char *str, size_t size, const char *argname)
177 if (strlen(optarg) > size)
178 usage("'%s' too large", argname);
179 strlcpy(str, optarg, size);
183 printxbe(ximgact_binmisc_entry_t *xbe)
185 uint32_t i, flags = xbe->xbe_flags;
187 if (xbe->xbe_version != IBE_VERSION) {
188 fprintf(stderr, "Error: XBE version mismatch\n");
192 printf("name: %s\n", xbe->xbe_name);
193 printf("interpreter: %s\n", xbe->xbe_interpreter);
194 printf("flags: %s%s\n", (flags & IBF_ENABLED) ? "ENABLED " : "",
195 (flags & IBF_USE_MASK) ? "USE_MASK " : "");
196 printf("magic size: %u\n", xbe->xbe_msize);
197 printf("magic offset: %u\n", xbe->xbe_moffset);
200 for(i = 0; i < xbe->xbe_msize; i++) {
206 printf("0x%02x ", xbe->xbe_magic[i]);
210 if (flags & IBF_USE_MASK) {
212 for(i = 0; i < xbe->xbe_msize; i++) {
218 printf("0x%02x ", xbe->xbe_mask[i]);
227 demux_cmd(__unused int argc, char *const argv[])
234 for(i = 0; i < ( sizeof (cmds) / sizeof (cmds[0])); i++) {
235 if (!strcasecmp(cmds[i].name, argv[0])) {
240 /* Unknown command */
245 strlit2bin_cpy(uint8_t *d, char *s, size_t size)
250 while((c = *s++) != '\0') {
252 /* Do '\' escapes. */
261 *d = (c - (isdigit(c) ? '0' : ('A' - 10))) << 4;
263 *d++ |= c - (isdigit(c) ? '0' : ('A' - 10));
280 add_cmd(__unused int argc, char *argv[], ximgact_binmisc_entry_t *xbe)
283 char *magic = NULL, *mask = NULL;
286 if (strlen(argv[0]) > IBE_NAME_MAX)
287 usage("'%s' string length longer than IBE_NAME_MAX (%d)",
289 strlcpy(&xbe->xbe_name[0], argv[0], IBE_NAME_MAX);
291 while ((ch = getopt_long(argc, argv, "ei:m:M:o:s:", add_opts, NULL))
296 getoptstr(xbe->xbe_interpreter, IBE_INTERP_LEN_MAX,
301 magic = strdup(optarg);
305 mask = strdup(optarg);
306 xbe->xbe_flags |= IBF_USE_MASK;
310 xbe->xbe_flags |= IBF_ENABLED;
314 xbe->xbe_moffset = atol(optarg);
318 xbe->xbe_msize = atol(optarg);
319 if (xbe->xbe_msize == 0 ||
320 xbe->xbe_msize > IBE_MAGIC_MAX)
321 usage("Error: Not valid '--size' value. "
322 "(Must be > 0 and < %u.)\n",
327 usage("Unknown argument: '%c'", ch);
331 if (xbe->xbe_msize == 0) {
336 usage("Error: Missing '--size' argument");
340 if (xbe->xbe_msize == 0) {
345 usage("Error: Missing magic size argument");
347 sz = strlit2bin_cpy(xbe->xbe_magic, magic, IBE_MAGIC_MAX);
349 if (sz == -1 || (uint32_t)sz != xbe->xbe_msize) {
352 usage("Error: invalid magic argument");
355 sz = strlit2bin_cpy(xbe->xbe_mask, mask, IBE_MAGIC_MAX);
357 if (sz == -1 || (uint32_t)sz != xbe->xbe_msize)
358 usage("Error: invalid mask argument");
363 usage("Error: Missing magic argument");
366 if (!xbe->xbe_interpreter) {
367 usage("Error: Missing 'interpreter' argument");
374 name_cmd(__unused int argc, char *argv[], ximgact_binmisc_entry_t *xbe)
376 if (strlen(argv[0]) > IBE_NAME_MAX)
377 usage("'%s' string length longer than IBE_NAME_MAX (%d)",
379 strlcpy(&xbe->xbe_name[0], argv[0], IBE_NAME_MAX);
385 noname_cmd(__unused int argc, __unused char *argv[],
386 __unused ximgact_binmisc_entry_t *xbe)
393 main(int argc, char **argv)
395 int error = 0, cmd = -1;
396 ximgact_binmisc_entry_t xbe_in, *xbe_inp = NULL;
397 ximgact_binmisc_entry_t xbe_out, *xbe_outp = NULL;
398 size_t xbe_in_sz = 0;
399 size_t xbe_out_sz = 0, *xbe_out_szp = NULL;
402 if (kldfind(KMOD_NAME) == -1) {
403 if (kldload(KMOD_NAME) == -1)
404 fatal("Can't load %s kernel module: %s",
405 KMOD_NAME, strerror(errno));
408 bzero(&xbe_in, sizeof(xbe_in));
409 bzero(&xbe_out, sizeof(xbe_out));
410 xbe_in.xbe_version = IBE_VERSION;
413 usage("Error: requires at least one argument");
416 cmd = demux_cmd(argc, argv);
418 usage("Error: Unknown command \"%s\"", argv[0]);
421 error = (*cmds[cmd].func)(argc, argv, &xbe_in);
423 usage("Can't parse command-line for '%s' command",
426 if (cmd != CMD_LIST) {
428 xbe_in_sz = sizeof(xbe_in);
430 xbe_out_szp = &xbe_out_sz;
431 if (cmd == CMD_LOOKUP) {
432 xbe_out_sz = sizeof(xbe_out);
434 xbe_out_szp = &xbe_out_sz;
437 error = sysctlbyname(cmd_sysctl_name[cmd], xbe_outp, xbe_out_szp,
443 usage("Invalid interpreter name or --interpreter, "
444 "--magic, --mask, or --size argument value");
448 usage("'%s' is not unique in activator list",
453 usage("'%s' is not found in activator list",
458 fatal("Fatal: no more room in the activator list "
459 "(limited to %d enties)", IBE_MAX_ENTRIES);
463 usage("Insufficient privileges for '%s' command",
468 fatal("Fatal: sysctlbyname() returned: %s",
474 if (cmd == CMD_LOOKUP)
477 if (cmd == CMD_LIST && xbe_out_sz > 0) {
478 xbe_outp = malloc(xbe_out_sz);
480 fatal("Fatal: out of memory");
482 size_t osize = xbe_out_sz;
483 error = sysctlbyname(cmd_sysctl_name[cmd], xbe_outp,
484 &xbe_out_sz, NULL, 0);
486 if (error == -1 && errno == ENOMEM &&
487 xbe_out_sz == osize) {
489 * Buffer too small. Increase it by one
492 xbe_out_sz += sizeof(xbe_out);
493 xbe_outp = realloc(xbe_outp, xbe_out_sz);
495 fatal("Fatal: out of memory");
501 fatal("Fatal: %s", strerror(errno));
503 for(i = 0; i < (xbe_out_sz / sizeof(xbe_out)); i++)
504 printxbe(&xbe_outp[i]);