33#include <sys/imgact.h>
34#include <sys/imgact_binmisc.h>
35#include <sys/kernel.h>
37#include <sys/malloc.h>
40#include <sys/sysctl.h>
43#include <machine/atomic.h>
65 uint8_t *ibe_interpreter;
66 ssize_t ibe_interp_offset;
67 uint32_t ibe_interp_argcnt;
68 uint32_t ibe_interp_length;
69 uint32_t ibe_argv0_cnt;
91#define ISM_OLD_ARGV0 'a'
97 SLIST_HEAD_INITIALIZER(interpreter_list);
99static int interp_list_entry_count;
101static struct sx interp_list_sx;
103#define INTERP_LIST_WLOCK() sx_xlock(&interp_list_sx)
104#define INTERP_LIST_RLOCK() sx_slock(&interp_list_sx)
105#define INTERP_LIST_WUNLOCK() sx_xunlock(&interp_list_sx)
106#define INTERP_LIST_RUNLOCK() sx_sunlock(&interp_list_sx)
108#define INTERP_LIST_LOCK_INIT() sx_init(&interp_list_sx, KMOD_NAME)
109#define INTERP_LIST_LOCK_DESTROY() sx_destroy(&interp_list_sx)
111#define INTERP_LIST_ASSERT_LOCKED() sx_assert(&interp_list_sx, SA_LOCKED)
119 uint32_t len = 0, argc = 1;
120 char t[IBE_INTERP_LEN_MAX];
123 memset(t, 0,
sizeof(t));
130 while (*sp !=
'\0') {
131 if (*sp ==
' ' || *sp ==
'\t') {
132 if (++len >= IBE_INTERP_LEN_MAX)
136 while (*sp ==
' ' || *sp ==
'\t')
147 ibe->ibe_interpreter =
malloc(len, M_BINMISC, M_WAITOK|M_ZERO);
150 memcpy(ibe->ibe_interpreter, t, len);
151 ibe->ibe_interp_argcnt = argc;
152 ibe->ibe_interp_length = len;
163 size_t namesz = min(strlen(xbe->xbe_name) + 1, IBE_NAME_MAX);
165 ibe =
malloc(
sizeof(*ibe), M_BINMISC, M_WAITOK|M_ZERO);
167 ibe->ibe_name =
malloc(namesz, M_BINMISC, M_WAITOK|M_ZERO);
168 strlcpy(ibe->ibe_name, xbe->xbe_name, namesz);
170 imgact_binmisc_populate_interp(xbe->xbe_interpreter, ibe);
172 ibe->ibe_magic =
malloc(xbe->xbe_msize, M_BINMISC, M_WAITOK|M_ZERO);
173 memcpy(ibe->ibe_magic, xbe->xbe_magic, xbe->xbe_msize);
175 ibe->ibe_mask =
malloc(xbe->xbe_msize, M_BINMISC, M_WAITOK|M_ZERO);
176 memcpy(ibe->ibe_mask, xbe->xbe_mask, xbe->xbe_msize);
178 ibe->ibe_moffset = xbe->xbe_moffset;
179 ibe->ibe_msize = xbe->xbe_msize;
180 ibe->ibe_flags = xbe->xbe_flags;
181 ibe->ibe_interp_offset = interp_offset;
182 ibe->ibe_argv0_cnt = argv0_cnt;
195 free(ibe->ibe_magic, M_BINMISC);
197 free(ibe->ibe_mask, M_BINMISC);
198 if (ibe->ibe_interpreter)
199 free(ibe->ibe_interpreter, M_BINMISC);
201 free(ibe->ibe_name, M_BINMISC);
203 free(ibe, M_BINMISC);
217 SLIST_FOREACH(ibe, &interpreter_list, link) {
218 if (strncmp(
name, ibe->ibe_name, IBE_NAME_MAX) == 0)
234 ssize_t interp_offset;
237 if (xbe->xbe_msize > IBE_MAGIC_MAX)
239 if (xbe->xbe_moffset + xbe->xbe_msize > IBE_MATCH_MAX)
242 for(cnt = 0, p = xbe->xbe_name; *p != 0; cnt++, p++)
243 if (cnt >= IBE_NAME_MAX || !isascii((
int)*p))
246 for(cnt = 0, p = xbe->xbe_interpreter; *p != 0; cnt++, p++)
247 if (cnt >= IBE_INTERP_LEN_MAX || !isascii((
int)*p))
251 p = xbe->xbe_interpreter;
254 while ((p = strchr(p,
'#')) != NULL) {
283 SLIST_INSERT_HEAD(&interpreter_list, ibe, link);
284 interp_list_entry_count++;
305 interp_list_entry_count--;
328 ibe->ibe_flags &= ~IBF_ENABLED;
349 ibe->ibe_flags |= IBF_ENABLED;
362 memset(xbe, 0,
sizeof(*xbe));
363 strlcpy(xbe->xbe_name, ibe->ibe_name, IBE_NAME_MAX);
366 memcpy(xbe->xbe_interpreter, ibe->ibe_interpreter,
367 ibe->ibe_interp_length);
368 for(i = 0; i < (ibe->ibe_interp_length - 1); i++)
369 if (xbe->xbe_interpreter[i] ==
'\0')
370 xbe->xbe_interpreter[i] =
' ';
372 memcpy(xbe->xbe_magic, ibe->ibe_magic, ibe->ibe_msize);
373 memcpy(xbe->xbe_mask, ibe->ibe_mask, ibe->ibe_msize);
374 xbe->xbe_version = IBE_VERSION;
375 xbe->xbe_flags = ibe->ibe_flags;
376 xbe->xbe_moffset = ibe->ibe_moffset;
377 xbe->xbe_msize = ibe->ibe_msize;
410 ximgact_binmisc_entry_t *xbe, *xbep;
412 int error = 0,
count;
415 count = interp_list_entry_count;
416 xbe =
malloc(
sizeof(*xbe) *
count, M_BINMISC, M_WAITOK|M_ZERO);
419 SLIST_FOREACH(ibe, &interpreter_list, link) {
427 error = SYSCTL_OUT(req, xbe,
sizeof(*xbe) *
count);
429 free(xbe, M_BINMISC);
440 ximgact_binmisc_entry_t xbe;
446 error = SYSCTL_IN(req, &xbe,
sizeof(xbe));
449 if (IBE_VERSION != xbe.xbe_version)
451 if ((xbe.xbe_flags & ~IBF_VALID_UFLAGS) != 0)
453 if (interp_list_entry_count == IBE_MAX_ENTRIES)
460 error = SYSCTL_IN(req, &xbe,
sizeof(xbe));
463 if (IBE_VERSION != xbe.xbe_version)
470 error = SYSCTL_IN(req, &xbe,
sizeof(xbe));
473 if (IBE_VERSION != xbe.xbe_version)
480 error = SYSCTL_IN(req, &xbe,
sizeof(xbe));
483 if (IBE_VERSION != xbe.xbe_version)
490 error = SYSCTL_IN(req, &xbe,
sizeof(xbe));
493 if (IBE_VERSION != xbe.xbe_version)
497 error = SYSCTL_OUT(req, &xbe,
sizeof(xbe));
505 error = SYSCTL_OUT(req, 0, interp_list_entry_count *
506 sizeof(ximgact_binmisc_entry_t));
522SYSCTL_NODE(_kern, OID_AUTO, binmisc, CTLFLAG_RW | CTLFLAG_MPSAFE, 0,
523 "Image activator for miscellaneous binaries");
526 CTLFLAG_MPSAFE|CTLTYPE_STRUCT|CTLFLAG_WR, NULL,
IBC_ADD,
528 "Add an activator entry");
531 CTLFLAG_MPSAFE|CTLTYPE_STRUCT|CTLFLAG_WR, NULL,
IBC_REMOVE,
533 "Remove an activator entry");
536 CTLFLAG_MPSAFE|CTLTYPE_STRUCT|CTLFLAG_WR, NULL,
IBC_DISABLE,
538 "Disable an activator entry");
541 CTLFLAG_MPSAFE|CTLTYPE_STRUCT|CTLFLAG_WR, NULL,
IBC_ENABLE,
543 "Enable an activator entry");
546 CTLFLAG_MPSAFE|CTLTYPE_STRUCT|CTLFLAG_RW|CTLFLAG_ANYBODY, NULL,
IBC_LOOKUP,
548 "Lookup an activator entry");
551 CTLFLAG_MPSAFE|CTLTYPE_STRUCT|CTLFLAG_RD|CTLFLAG_ANYBODY, NULL,
IBC_LIST,
553 "Get snapshot of all the activator entries");
565 SLIST_FOREACH(ibe, &interpreter_list, link) {
566 if (!(IBF_ENABLED & ibe->ibe_flags))
569 p = image_header + ibe->ibe_moffset;
571 if (IBF_USE_MASK & ibe->ibe_flags) {
573 for (i = 0; i < sz; i++)
574 if ((*p++ ^ ibe->ibe_magic[i]) &
578 for (i = 0; i < sz; i++)
579 if (*p++ ^ ibe->ibe_magic[i])
582 if (i == ibe->ibe_msize)
591 const char *image_header = imgp->image_header;
592 const char *fname = NULL;
597 size_t namelen, offset;
612 if (imgp->interpreted & IMGACT_BINMISC) {
617 imgp->interpreted |= IMGACT_BINMISC;
623 if (ibe->ibe_argv0_cnt != 0) {
624 if (imgp->args->fname != NULL) {
625 fname = imgp->args->fname;
628 sname = sbuf_new_auto();
634 namelen = strlen(fname);
645 offset = ibe->ibe_interp_length + ibe->ibe_interp_offset;
648 MPASS(ibe->ibe_argv0_cnt == 0 || namelen > 0);
649 offset += ibe->ibe_argv0_cnt * (namelen - 2);
658 imgp->args->argc += ibe->ibe_interp_argcnt;
664 s = ibe->ibe_interpreter;
665 d = imgp->args->begin_argv;
678 MPASS(ibe->ibe_argv0_cnt >= ++argv0_cnt);
679 memcpy(d, fname, namelen);
683 __assert_unreachable();
699 MPASS(ibe->ibe_argv0_cnt == argv0_cnt);
700 imgp->interpreter_name = imgp->args->begin_argv;
723 SLIST_FOREACH_SAFE(ibe, &interpreter_list, link, ibe_tmp) {
#define INTERP_LIST_WUNLOCK()
#define INTERP_LIST_RLOCK()
static int imgact_binmisc_add_entry(ximgact_binmisc_entry_t *xbe)
MALLOC_DEFINE(M_BINMISC, KMOD_NAME, "misc binary image activator")
static void imgact_binmisc_fini(void *arg)
static void imgact_binmisc_destroy_entry(imgact_binmisc_entry_t *ibe)
static int imgact_binmisc_lookup_entry(char *name, ximgact_binmisc_entry_t *xbe)
#define INTERP_LIST_WLOCK()
static imgact_binmisc_entry_t * imgact_binmisc_find_interpreter(const char *image_header)
static int imgact_binmisc_disable_entry(char *name)
SYSCTL_NODE(_kern, OID_AUTO, binmisc, CTLFLAG_RW|CTLFLAG_MPSAFE, 0, "Image activator for miscellaneous binaries")
static void imgact_binmisc_init(void *arg)
static imgact_binmisc_entry_t * imgact_binmisc_new_entry(ximgact_binmisc_entry_t *xbe, ssize_t interp_offset, int argv0_cnt)
struct imgact_binmisc_entry imgact_binmisc_entry_t
static int imgact_binmisc_exec(struct image_params *imgp)
static SLIST_HEAD(imgact_binmisc_entry)
SYSCTL_PROC(_kern_binmisc, OID_AUTO, add, CTLFLAG_MPSAFE|CTLTYPE_STRUCT|CTLFLAG_WR, NULL, IBC_ADD, sysctl_kern_binmisc, "S,ximgact_binmisc_entry", "Add an activator entry")
static struct execsw imgact_binmisc_execsw
#define INTERP_LIST_ASSERT_LOCKED()
static int imgact_binmisc_enable_entry(char *name)
SYSINIT(imgact_binmisc, SI_SUB_EXEC, SI_ORDER_MIDDLE, imgact_binmisc_init, NULL)
SYSUNINIT(imgact_binmisc, SI_SUB_EXEC, SI_ORDER_MIDDLE, imgact_binmisc_fini, NULL)
static int imgact_binmisc_populate_xbe(ximgact_binmisc_entry_t *xbe, imgact_binmisc_entry_t *ibe)
#define INTERP_LIST_LOCK_INIT()
EXEC_SET(imgact_binmisc, imgact_binmisc_execsw)
static imgact_binmisc_entry_t * imgact_binmisc_find_entry(char *name)
#define INTERP_LIST_RUNLOCK()
#define INTERP_LIST_LOCK_DESTROY()
static int imgact_binmisc_get_all_entries(struct sysctl_req *req)
static int imgact_binmisc_remove_entry(char *name)
static int sysctl_kern_binmisc(SYSCTL_HANDLER_ARGS)
static const struct execsw ** execsw
int exec_args_adjust_args(struct image_args *args, size_t consume, ssize_t extend)
void *() malloc(size_t size, struct malloc_type *mtp, int flags)
void free(void *addr, struct malloc_type *mtp)
int sbuf_finish(struct sbuf *s)
void sbuf_delete(struct sbuf *s)
int sbuf_printf(struct sbuf *s, const char *fmt,...)
char * sbuf_data(struct sbuf *s)