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$");
31 #include <sys/types.h>
32 #include <sys/imgact_binmisc.h>
33 #include <sys/linker.h>
34 #include <sys/module.h>
35 #include <sys/sysctl.h>
55 extern char *__progname;
57 typedef int (*cmd_func_t)(int argc, char *argv[], ximgact_binmisc_entry_t *xbe);
59 int add_cmd(int argc, char *argv[], ximgact_binmisc_entry_t *xbe);
60 int name_cmd(int argc, char *argv[], ximgact_binmisc_entry_t *xbe);
61 int noname_cmd(int argc, char *argv[], ximgact_binmisc_entry_t *xbe);
74 "Add a new binary image activator (requires 'root' privilege)",
75 "<name> --interpreter <path_and_arguments> \\\n"
76 "\t\t--magic <magic_bytes> [--mask <mask_bytes>] \\\n"
77 "\t\t--size <magic_size> [--offset <magic_offset>] \\\n"
84 "Remove a binary image activator (requires 'root' privilege)",
91 "Disable a binary image activator (requires 'root' privilege)",
98 "Enable a binary image activator (requires 'root' privilege)",
105 "Lookup a binary image activator",
112 "List all the binary image activators",
117 static const struct option
119 { "set-enabled", no_argument, NULL, 'e' },
120 { "interpreter", required_argument, NULL, 'i' },
121 { "mask", required_argument, NULL, 'M' },
122 { "magic", required_argument, NULL, 'm' },
123 { "offset", required_argument, NULL, 'o' },
124 { "size", required_argument, NULL, 's' },
128 static char const *cmd_sysctl_name[] = {
130 IBE_SYSCTL_NAME_REMOVE,
131 IBE_SYSCTL_NAME_DISABLE,
132 IBE_SYSCTL_NAME_ENABLE,
133 IBE_SYSCTL_NAME_LOOKUP,
138 usage(const char *format, ...)
144 va_start(args, format);
146 vfprintf(stderr, format, args);
150 fprintf(stderr, "\n");
151 fprintf(stderr, "usage: %s command [args...]\n\n", __progname);
153 for(i = 0; i < nitems(cmds); i++) {
154 fprintf(stderr, "%s:\n", cmds[i].desc);
155 fprintf(stderr, "\t%s %s %s\n\n", __progname, cmds[i].name,
163 fatal(const char *format, ...)
167 va_start(args, format);
169 vfprintf(stderr, format, args);
170 fprintf(stderr, "\n");
176 getoptstr(char *str, size_t size, const char *argname)
178 if (strlen(optarg) > size)
179 usage("'%s' too large", argname);
180 strlcpy(str, optarg, size);
184 printxbe(ximgact_binmisc_entry_t *xbe)
186 uint32_t i, flags = xbe->xbe_flags;
188 if (xbe->xbe_version != IBE_VERSION) {
189 fprintf(stderr, "Error: XBE version mismatch\n");
193 printf("name: %s\n", xbe->xbe_name);
194 printf("interpreter: %s\n", xbe->xbe_interpreter);
195 printf("flags: %s%s\n", (flags & IBF_ENABLED) ? "ENABLED " : "",
196 (flags & IBF_USE_MASK) ? "USE_MASK " : "");
197 printf("magic size: %u\n", xbe->xbe_msize);
198 printf("magic offset: %u\n", xbe->xbe_moffset);
201 for(i = 0; i < xbe->xbe_msize; i++) {
207 printf("0x%02x ", xbe->xbe_magic[i]);
211 if (flags & IBF_USE_MASK) {
213 for(i = 0; i < xbe->xbe_msize; i++) {
219 printf("0x%02x ", xbe->xbe_mask[i]);
228 demux_cmd(__unused int argc, char *const argv[])
235 for(i = 0; i < nitems(cmds); i++) {
236 if (!strcasecmp(cmds[i].name, argv[0])) {
241 /* Unknown command */
246 strlit2bin_cpy(uint8_t *d, char *s, size_t size)
251 while((c = *s++) != '\0') {
253 /* Do '\' escapes. */
262 *d = (c - (isdigit(c) ? '0' : ('A' - 10))) << 4;
264 *d++ |= c - (isdigit(c) ? '0' : ('A' - 10));
281 add_cmd(__unused int argc, char *argv[], ximgact_binmisc_entry_t *xbe)
284 char *magic = NULL, *mask = NULL;
287 if (strlen(argv[0]) > IBE_NAME_MAX)
288 usage("'%s' string length longer than IBE_NAME_MAX (%d)",
290 strlcpy(&xbe->xbe_name[0], argv[0], IBE_NAME_MAX);
292 while ((ch = getopt_long(argc, argv, "ei:m:M:o:s:", add_opts, NULL))
297 getoptstr(xbe->xbe_interpreter, IBE_INTERP_LEN_MAX,
303 magic = strdup(optarg);
308 mask = strdup(optarg);
309 xbe->xbe_flags |= IBF_USE_MASK;
313 xbe->xbe_flags |= IBF_ENABLED;
317 xbe->xbe_moffset = atol(optarg);
321 xbe->xbe_msize = atol(optarg);
322 if (xbe->xbe_msize == 0 ||
323 xbe->xbe_msize > IBE_MAGIC_MAX)
324 usage("Error: Not valid '--size' value. "
325 "(Must be > 0 and < %u.)\n",
330 usage("Unknown argument: '%c'", ch);
334 if (xbe->xbe_msize == 0) {
339 usage("Error: Missing '--size' argument");
343 if (xbe->xbe_msize == 0) {
348 usage("Error: Missing magic size argument");
350 sz = strlit2bin_cpy(xbe->xbe_magic, magic, IBE_MAGIC_MAX);
352 if (sz == -1 || (uint32_t)sz != xbe->xbe_msize) {
355 usage("Error: invalid magic argument");
358 sz = strlit2bin_cpy(xbe->xbe_mask, mask, IBE_MAGIC_MAX);
360 if (sz == -1 || (uint32_t)sz != xbe->xbe_msize)
361 usage("Error: invalid mask argument");
366 usage("Error: Missing magic argument");
369 if (!strnlen(xbe->xbe_interpreter, IBE_INTERP_LEN_MAX)) {
370 usage("Error: Missing 'interpreter' argument");
377 name_cmd(int argc, char *argv[], ximgact_binmisc_entry_t *xbe)
380 usage("Required argument missing\n");
381 if (strlen(argv[0]) > IBE_NAME_MAX)
382 usage("'%s' string length longer than IBE_NAME_MAX (%d)",
384 strlcpy(&xbe->xbe_name[0], argv[0], IBE_NAME_MAX);
390 noname_cmd(__unused int argc, __unused char *argv[],
391 __unused ximgact_binmisc_entry_t *xbe)
398 main(int argc, char **argv)
400 int error = 0, cmd = -1;
401 ximgact_binmisc_entry_t xbe_in, *xbe_inp = NULL;
402 ximgact_binmisc_entry_t xbe_out, *xbe_outp = NULL;
403 size_t xbe_in_sz = 0;
404 size_t xbe_out_sz = 0, *xbe_out_szp = NULL;
407 if (modfind(KMOD_NAME) == -1) {
408 if (kldload(KMOD_NAME) == -1)
409 fatal("Can't load %s kernel module: %s",
410 KMOD_NAME, strerror(errno));
413 bzero(&xbe_in, sizeof(xbe_in));
414 bzero(&xbe_out, sizeof(xbe_out));
415 xbe_in.xbe_version = IBE_VERSION;
418 usage("Error: requires at least one argument");
421 cmd = demux_cmd(argc, argv);
423 usage("Error: Unknown command \"%s\"", argv[0]);
426 error = (*cmds[cmd].func)(argc, argv, &xbe_in);
428 usage("Can't parse command-line for '%s' command",
431 if (cmd != CMD_LIST) {
433 xbe_in_sz = sizeof(xbe_in);
435 xbe_out_szp = &xbe_out_sz;
436 if (cmd == CMD_LOOKUP) {
437 xbe_out_sz = sizeof(xbe_out);
439 xbe_out_szp = &xbe_out_sz;
442 error = sysctlbyname(cmd_sysctl_name[cmd], xbe_outp, xbe_out_szp,
448 usage("Invalid interpreter name or --interpreter, "
449 "--magic, --mask, or --size argument value");
453 usage("'%s' is not unique in activator list",
458 usage("'%s' is not found in activator list",
463 fatal("Fatal: no more room in the activator list "
464 "(limited to %d enties)", IBE_MAX_ENTRIES);
468 usage("Insufficient privileges for '%s' command",
473 fatal("Fatal: sysctlbyname() returned: %s",
479 if (cmd == CMD_LOOKUP)
482 if (cmd == CMD_LIST && xbe_out_sz > 0) {
483 xbe_outp = malloc(xbe_out_sz);
485 fatal("Fatal: out of memory");
487 size_t osize = xbe_out_sz;
488 error = sysctlbyname(cmd_sysctl_name[cmd], xbe_outp,
489 &xbe_out_sz, NULL, 0);
491 if (error == -1 && errno == ENOMEM &&
492 xbe_out_sz == osize) {
494 * Buffer too small. Increase it by one
497 xbe_out_sz += sizeof(xbe_out);
498 xbe_outp = realloc(xbe_outp, xbe_out_sz);
500 fatal("Fatal: out of memory");
506 fatal("Fatal: %s", strerror(errno));
508 for(i = 0; i < howmany(xbe_out_sz, sizeof(xbe_out)); i++)
509 printxbe(&xbe_outp[i]);