FreeBSD kernel kern code
imgact_binmisc.c
Go to the documentation of this file.
1/*-
2 * Copyright (c) 2013-16, Stacey D. Son
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
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.
13 *
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
24 * SUCH DAMAGE.
25 */
26
27#include <sys/cdefs.h>
28__FBSDID("$FreeBSD$");
29
30#include <sys/param.h>
31#include <sys/ctype.h>
32#include <sys/exec.h>
33#include <sys/imgact.h>
34#include <sys/imgact_binmisc.h>
35#include <sys/kernel.h>
36#include <sys/lock.h>
37#include <sys/malloc.h>
38#include <sys/mutex.h>
39#include <sys/sbuf.h>
40#include <sys/sysctl.h>
41#include <sys/sx.h>
42
43#include <machine/atomic.h>
44
57/*
58 * Node of the interpreter list.
59 */
60typedef struct imgact_binmisc_entry {
61 SLIST_ENTRY(imgact_binmisc_entry) link;
62 char *ibe_name;
63 uint8_t *ibe_magic;
64 uint8_t *ibe_mask;
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;
70 uint32_t ibe_flags;
71 uint32_t ibe_moffset;
72 uint32_t ibe_msize;
74
75/*
76 * sysctl() commands.
77 */
78#define IBC_ADD 1 /* Add given entry. */
79#define IBC_REMOVE 2 /* Remove entry for a given name. */
80#define IBC_DISABLE 3 /* Disable entry for a given name. */
81#define IBC_ENABLE 4 /* Enable entry for a given name. */
82#define IBC_LOOKUP 5 /* Lookup and return entry for given name. */
83#define IBC_LIST 6 /* Get a snapshot of the interpretor list. */
84
85/*
86 * Interpreter string macros.
87 *
88 * They all start with '#' followed by a single letter:
89 */
90#define ISM_POUND '#' /* "##" is the escape sequence for single #. */
91#define ISM_OLD_ARGV0 'a' /* "#a" is replaced with the old argv0. */
92
93MALLOC_DEFINE(M_BINMISC, KMOD_NAME, "misc binary image activator");
94
95/* The interpreter list. */
96static SLIST_HEAD(, imgact_binmisc_entry) interpreter_list =
97 SLIST_HEAD_INITIALIZER(interpreter_list);
98
99static int interp_list_entry_count;
100
101static struct sx interp_list_sx;
102
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)
107
108#define INTERP_LIST_LOCK_INIT() sx_init(&interp_list_sx, KMOD_NAME)
109#define INTERP_LIST_LOCK_DESTROY() sx_destroy(&interp_list_sx)
110
111#define INTERP_LIST_ASSERT_LOCKED() sx_assert(&interp_list_sx, SA_LOCKED)
112
113/*
114 * Populate the entry with the information about the interpreter.
115 */
116static void
117imgact_binmisc_populate_interp(char *str, imgact_binmisc_entry_t *ibe)
118{
119 uint32_t len = 0, argc = 1;
120 char t[IBE_INTERP_LEN_MAX];
121 char *sp, *tp;
122
123 memset(t, 0, sizeof(t));
124
125 /*
126 * Normalize interpreter string. Replace white space between args with
127 * single space.
128 */
129 sp = str; tp = t;
130 while (*sp != '\0') {
131 if (*sp == ' ' || *sp == '\t') {
132 if (++len >= IBE_INTERP_LEN_MAX)
133 break;
134 *tp++ = ' ';
135 argc++;
136 while (*sp == ' ' || *sp == '\t')
137 sp++;
138 continue;
139 } else {
140 *tp++ = *sp++;
141 len++;
142 }
143 }
144 *tp = '\0';
145 len++;
146
147 ibe->ibe_interpreter = malloc(len, M_BINMISC, M_WAITOK|M_ZERO);
148
149 /* Populate all the ibe fields for the interpreter. */
150 memcpy(ibe->ibe_interpreter, t, len);
151 ibe->ibe_interp_argcnt = argc;
152 ibe->ibe_interp_length = len;
153}
154
155/*
156 * Allocate memory and populate a new entry for the interpreter table.
157 */
159imgact_binmisc_new_entry(ximgact_binmisc_entry_t *xbe, ssize_t interp_offset,
160 int argv0_cnt)
161{
162 imgact_binmisc_entry_t *ibe = NULL;
163 size_t namesz = min(strlen(xbe->xbe_name) + 1, IBE_NAME_MAX);
164
165 ibe = malloc(sizeof(*ibe), M_BINMISC, M_WAITOK|M_ZERO);
166
167 ibe->ibe_name = malloc(namesz, M_BINMISC, M_WAITOK|M_ZERO);
168 strlcpy(ibe->ibe_name, xbe->xbe_name, namesz);
169
170 imgact_binmisc_populate_interp(xbe->xbe_interpreter, ibe);
171
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);
174
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);
177
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;
183 return (ibe);
184}
185
186/*
187 * Free the allocated memory for a given list item.
188 */
189static void
191{
192 if (!ibe)
193 return;
194 if (ibe->ibe_magic)
195 free(ibe->ibe_magic, M_BINMISC);
196 if (ibe->ibe_mask)
197 free(ibe->ibe_mask, M_BINMISC);
198 if (ibe->ibe_interpreter)
199 free(ibe->ibe_interpreter, M_BINMISC);
200 if (ibe->ibe_name)
201 free(ibe->ibe_name, M_BINMISC);
202 if (ibe)
203 free(ibe, M_BINMISC);
204}
205
206/*
207 * Find the interpreter in the list by the given name. Return NULL if not
208 * found.
209 */
212{
214
216
217 SLIST_FOREACH(ibe, &interpreter_list, link) {
218 if (strncmp(name, ibe->ibe_name, IBE_NAME_MAX) == 0)
219 return (ibe);
220 }
221
222 return (NULL);
223}
224
225/*
226 * Add the given interpreter if it doesn't already exist. Return EEXIST
227 * if the name already exist in the interpreter list.
228 */
229static int
230imgact_binmisc_add_entry(ximgact_binmisc_entry_t *xbe)
231{
233 char *p;
234 ssize_t interp_offset;
235 int argv0_cnt, cnt;
236
237 if (xbe->xbe_msize > IBE_MAGIC_MAX)
238 return (EINVAL);
239 if (xbe->xbe_moffset + xbe->xbe_msize > IBE_MATCH_MAX)
240 return (EINVAL);
241
242 for(cnt = 0, p = xbe->xbe_name; *p != 0; cnt++, p++)
243 if (cnt >= IBE_NAME_MAX || !isascii((int)*p))
244 return (EINVAL);
245
246 for(cnt = 0, p = xbe->xbe_interpreter; *p != 0; cnt++, p++)
247 if (cnt >= IBE_INTERP_LEN_MAX || !isascii((int)*p))
248 return (EINVAL);
249
250 /* Make sure we don't have any invalid #'s. */
251 p = xbe->xbe_interpreter;
252 interp_offset = 0;
253 argv0_cnt = 0;
254 while ((p = strchr(p, '#')) != NULL) {
255 p++;
256 switch(*p) {
257 case ISM_POUND:
258 /* "##" */
259 p++;
260 interp_offset--;
261 break;
262 case ISM_OLD_ARGV0:
263 /* "#a" */
264 p++;
265 argv0_cnt++;
266 break;
267 case 0:
268 default:
269 /* Anything besides the above is invalid. */
270 return (EINVAL);
271 }
272 }
273
275 if (imgact_binmisc_find_entry(xbe->xbe_name) != NULL) {
277 return (EEXIST);
278 }
279
280 /* Preallocate a new entry. */
281 ibe = imgact_binmisc_new_entry(xbe, interp_offset, argv0_cnt);
282
283 SLIST_INSERT_HEAD(&interpreter_list, ibe, link);
284 interp_list_entry_count++;
286
287 return (0);
288}
289
290/*
291 * Remove the interpreter in the list with the given name. Return ENOENT
292 * if not found.
293 */
294static int
296{
298
300 if ((ibe = imgact_binmisc_find_entry(name)) == NULL) {
302 return (ENOENT);
303 }
304 SLIST_REMOVE(&interpreter_list, ibe, imgact_binmisc_entry, link);
305 interp_list_entry_count--;
307
309
310 return (0);
311}
312
313/*
314 * Disable the interpreter in the list with the given name. Return ENOENT
315 * if not found.
316 */
317static int
319{
321
323 if ((ibe = imgact_binmisc_find_entry(name)) == NULL) {
325 return (ENOENT);
326 }
327
328 ibe->ibe_flags &= ~IBF_ENABLED;
330
331 return (0);
332}
333
334/*
335 * Enable the interpreter in the list with the given name. Return ENOENT
336 * if not found.
337 */
338static int
340{
342
344 if ((ibe = imgact_binmisc_find_entry(name)) == NULL) {
346 return (ENOENT);
347 }
348
349 ibe->ibe_flags |= IBF_ENABLED;
351
352 return (0);
353}
354
355static int
356imgact_binmisc_populate_xbe(ximgact_binmisc_entry_t *xbe,
358{
359 uint32_t i;
360
362 memset(xbe, 0, sizeof(*xbe));
363 strlcpy(xbe->xbe_name, ibe->ibe_name, IBE_NAME_MAX);
364
365 /* Copy interpreter string. Replace NULL breaks with space. */
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] = ' ';
371
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;
378
379 return (0);
380}
381
382/*
383 * Retrieve the interpreter with the give name and populate the
384 * ximgact_binmisc_entry structure. Return ENOENT if not found.
385 */
386static int
387imgact_binmisc_lookup_entry(char *name, ximgact_binmisc_entry_t *xbe)
388{
390 int error = 0;
391
393 if ((ibe = imgact_binmisc_find_entry(name)) == NULL) {
395 return (ENOENT);
396 }
397
398 error = imgact_binmisc_populate_xbe(xbe, ibe);
400
401 return (error);
402}
403
404/*
405 * Get a snapshot of all the interpreter entries in the list.
406 */
407static int
408imgact_binmisc_get_all_entries(struct sysctl_req *req)
409{
410 ximgact_binmisc_entry_t *xbe, *xbep;
412 int error = 0, count;
413
415 count = interp_list_entry_count;
416 xbe = malloc(sizeof(*xbe) * count, M_BINMISC, M_WAITOK|M_ZERO);
417
418 xbep = xbe;
419 SLIST_FOREACH(ibe, &interpreter_list, link) {
420 error = imgact_binmisc_populate_xbe(xbep++, ibe);
421 if (error)
422 break;
423 }
425
426 if (!error)
427 error = SYSCTL_OUT(req, xbe, sizeof(*xbe) * count);
428
429 free(xbe, M_BINMISC);
430 return (error);
431}
432
433/*
434 * sysctl() handler for munipulating interpretor table.
435 * Not MP safe (locked by sysctl).
436 */
437static int
438sysctl_kern_binmisc(SYSCTL_HANDLER_ARGS)
439{
440 ximgact_binmisc_entry_t xbe;
441 int error = 0;
442
443 switch(arg2) {
444 case IBC_ADD:
445 /* Add an entry. Limited to IBE_MAX_ENTRIES. */
446 error = SYSCTL_IN(req, &xbe, sizeof(xbe));
447 if (error)
448 return (error);
449 if (IBE_VERSION != xbe.xbe_version)
450 return (EINVAL);
451 if ((xbe.xbe_flags & ~IBF_VALID_UFLAGS) != 0)
452 return (EINVAL);
453 if (interp_list_entry_count == IBE_MAX_ENTRIES)
454 return (ENOSPC);
455 error = imgact_binmisc_add_entry(&xbe);
456 break;
457
458 case IBC_REMOVE:
459 /* Remove an entry. */
460 error = SYSCTL_IN(req, &xbe, sizeof(xbe));
461 if (error)
462 return (error);
463 if (IBE_VERSION != xbe.xbe_version)
464 return (EINVAL);
465 error = imgact_binmisc_remove_entry(xbe.xbe_name);
466 break;
467
468 case IBC_DISABLE:
469 /* Disable an entry. */
470 error = SYSCTL_IN(req, &xbe, sizeof(xbe));
471 if (error)
472 return (error);
473 if (IBE_VERSION != xbe.xbe_version)
474 return (EINVAL);
475 error = imgact_binmisc_disable_entry(xbe.xbe_name);
476 break;
477
478 case IBC_ENABLE:
479 /* Enable an entry. */
480 error = SYSCTL_IN(req, &xbe, sizeof(xbe));
481 if (error)
482 return (error);
483 if (IBE_VERSION != xbe.xbe_version)
484 return (EINVAL);
485 error = imgact_binmisc_enable_entry(xbe.xbe_name);
486 break;
487
488 case IBC_LOOKUP:
489 /* Lookup an entry. */
490 error = SYSCTL_IN(req, &xbe, sizeof(xbe));
491 if (error)
492 return (error);
493 if (IBE_VERSION != xbe.xbe_version)
494 return (EINVAL);
495 error = imgact_binmisc_lookup_entry(xbe.xbe_name, &xbe);
496 if (!error)
497 error = SYSCTL_OUT(req, &xbe, sizeof(xbe));
498 break;
499
500 case IBC_LIST:
501 /* Return a snapshot of the interpretor list. */
502
503 if (!req->oldptr) {
504 /* No pointer then just return the list size. */
505 error = SYSCTL_OUT(req, 0, interp_list_entry_count *
506 sizeof(ximgact_binmisc_entry_t));
507 return (error);
508 } else
509 if (!req->oldlen)
510 return (EINVAL);
511
513 break;
514
515 default:
516 return (EINVAL);
517 }
518
519 return (error);
520}
521
522SYSCTL_NODE(_kern, OID_AUTO, binmisc, CTLFLAG_RW | CTLFLAG_MPSAFE, 0,
523 "Image activator for miscellaneous binaries");
524
525SYSCTL_PROC(_kern_binmisc, OID_AUTO, add,
526 CTLFLAG_MPSAFE|CTLTYPE_STRUCT|CTLFLAG_WR, NULL, IBC_ADD,
527 sysctl_kern_binmisc, "S,ximgact_binmisc_entry",
528 "Add an activator entry");
529
530SYSCTL_PROC(_kern_binmisc, OID_AUTO, remove,
531 CTLFLAG_MPSAFE|CTLTYPE_STRUCT|CTLFLAG_WR, NULL, IBC_REMOVE,
532 sysctl_kern_binmisc, "S,ximgact_binmisc_entry",
533 "Remove an activator entry");
534
535SYSCTL_PROC(_kern_binmisc, OID_AUTO, disable,
536 CTLFLAG_MPSAFE|CTLTYPE_STRUCT|CTLFLAG_WR, NULL, IBC_DISABLE,
537 sysctl_kern_binmisc, "S,ximgact_binmisc_entry",
538 "Disable an activator entry");
539
540SYSCTL_PROC(_kern_binmisc, OID_AUTO, enable,
541 CTLFLAG_MPSAFE|CTLTYPE_STRUCT|CTLFLAG_WR, NULL, IBC_ENABLE,
542 sysctl_kern_binmisc, "S,ximgact_binmisc_entry",
543 "Enable an activator entry");
544
545SYSCTL_PROC(_kern_binmisc, OID_AUTO, lookup,
546 CTLFLAG_MPSAFE|CTLTYPE_STRUCT|CTLFLAG_RW|CTLFLAG_ANYBODY, NULL, IBC_LOOKUP,
547 sysctl_kern_binmisc, "S,ximgact_binmisc_entry",
548 "Lookup an activator entry");
549
550SYSCTL_PROC(_kern_binmisc, OID_AUTO, list,
551 CTLFLAG_MPSAFE|CTLTYPE_STRUCT|CTLFLAG_RD|CTLFLAG_ANYBODY, NULL, IBC_LIST,
552 sysctl_kern_binmisc, "S,ximgact_binmisc_entry",
553 "Get snapshot of all the activator entries");
554
556imgact_binmisc_find_interpreter(const char *image_header)
557{
559 const char *p;
560 int i;
561 size_t sz;
562
564
565 SLIST_FOREACH(ibe, &interpreter_list, link) {
566 if (!(IBF_ENABLED & ibe->ibe_flags))
567 continue;
568
569 p = image_header + ibe->ibe_moffset;
570 sz = ibe->ibe_msize;
571 if (IBF_USE_MASK & ibe->ibe_flags) {
572 /* Compare using mask. */
573 for (i = 0; i < sz; i++)
574 if ((*p++ ^ ibe->ibe_magic[i]) &
575 ibe->ibe_mask[i])
576 break;
577 } else {
578 for (i = 0; i < sz; i++)
579 if (*p++ ^ ibe->ibe_magic[i])
580 break;
581 }
582 if (i == ibe->ibe_msize)
583 return (ibe);
584 }
585 return (NULL);
586}
587
588static int
589imgact_binmisc_exec(struct image_params *imgp)
590{
591 const char *image_header = imgp->image_header;
592 const char *fname = NULL;
593 int error = 0;
594#ifdef INVARIANTS
595 int argv0_cnt = 0;
596#endif
597 size_t namelen, offset;
599 struct sbuf *sname;
600 char *s, *d;
601
602 sname = NULL;
603 namelen = 0;
604 /* Do we have an interpreter for the given image header? */
606 if ((ibe = imgact_binmisc_find_interpreter(image_header)) == NULL) {
607 error = -1;
608 goto done;
609 }
610
611 /* No interpreter nesting allowed. */
612 if (imgp->interpreted & IMGACT_BINMISC) {
613 error = ENOEXEC;
614 goto done;
615 }
616
617 imgp->interpreted |= IMGACT_BINMISC;
618
619 /*
620 * Don't bother with the overhead of putting fname together if we're not
621 * using #a.
622 */
623 if (ibe->ibe_argv0_cnt != 0) {
624 if (imgp->args->fname != NULL) {
625 fname = imgp->args->fname;
626 } else {
627 /* Use the fdescfs(5) path for fexecve(2). */
628 sname = sbuf_new_auto();
629 sbuf_printf(sname, "/dev/fd/%d", imgp->args->fd);
630 sbuf_finish(sname);
631 fname = sbuf_data(sname);
632 }
633
634 namelen = strlen(fname);
635 }
636
637 /*
638 * We need to "push" the interpreter in the arg[] list. To do this,
639 * we first shift all the other values in the `begin_argv' area to
640 * provide the exact amount of room for the values added. Set up
641 * `offset' as the number of bytes to be added to the `begin_argv'
642 * area. ibe_interp_offset is the fixed offset from macros present in
643 * the interpreter string.
644 */
645 offset = ibe->ibe_interp_length + ibe->ibe_interp_offset;
646
647 /* Variable offset to be added from macros to the interpreter string. */
648 MPASS(ibe->ibe_argv0_cnt == 0 || namelen > 0);
649 offset += ibe->ibe_argv0_cnt * (namelen - 2);
650
651 /* Make room for the interpreter */
652 error = exec_args_adjust_args(imgp->args, 0, offset);
653 if (error != 0) {
654 goto done;
655 }
656
657 /* Add the new argument(s) in the count. */
658 imgp->args->argc += ibe->ibe_interp_argcnt;
659
660 /*
661 * The original arg[] list has been shifted appropriately. Copy in
662 * the interpreter path.
663 */
664 s = ibe->ibe_interpreter;
665 d = imgp->args->begin_argv;
666 while(*s != '\0') {
667 switch (*s) {
668 case '#':
669 /* Handle "#" in interpreter string. */
670 s++;
671 switch(*s) {
672 case ISM_POUND:
673 /* "##": Replace with a single '#' */
674 *d++ = '#';
675 break;
676 case ISM_OLD_ARGV0:
677 /* "#a": Replace with old arg0 (fname). */
678 MPASS(ibe->ibe_argv0_cnt >= ++argv0_cnt);
679 memcpy(d, fname, namelen);
680 d += namelen;
681 break;
682 default:
683 __assert_unreachable();
684 }
685 break;
686 case ' ':
687 /* Replace space with NUL to separate arguments. */
688 *d++ = '\0';
689 break;
690 default:
691 *d++ = *s;
692 break;
693 }
694 s++;
695 }
696 *d = '\0';
697
698 /* Catch ibe->ibe_argv0_cnt counting more #a than we did. */
699 MPASS(ibe->ibe_argv0_cnt == argv0_cnt);
700 imgp->interpreter_name = imgp->args->begin_argv;
701
702done:
704 if (sname)
705 sbuf_delete(sname);
706 return (error);
707}
708
709static void
711{
712
714}
715
716static void
718{
719 imgact_binmisc_entry_t *ibe, *ibe_tmp;
720
721 /* Free all the interpreters. */
723 SLIST_FOREACH_SAFE(ibe, &interpreter_list, link, ibe_tmp) {
724 SLIST_REMOVE(&interpreter_list, ibe, imgact_binmisc_entry,
725 link);
727 }
729
731}
732
733SYSINIT(imgact_binmisc, SI_SUB_EXEC, SI_ORDER_MIDDLE, imgact_binmisc_init,
734 NULL);
735SYSUNINIT(imgact_binmisc, SI_SUB_EXEC, SI_ORDER_MIDDLE, imgact_binmisc_fini,
736 NULL);
737
738/*
739 * Tell kern_execve.c about it, with a little help from the linker.
740 */
742 .ex_imgact = imgact_binmisc_exec,
743 .ex_name = KMOD_NAME
744};
int * count
Definition: cpufreq_if.m:63
const char * name
Definition: kern_fail.c:145
#define IBC_ENABLE
#define INTERP_LIST_WUNLOCK()
#define IBC_REMOVE
#define INTERP_LIST_RLOCK()
static int imgact_binmisc_add_entry(ximgact_binmisc_entry_t *xbe)
#define IBC_LIST
#define IBC_DISABLE
#define ISM_POUND
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
__FBSDID("$FreeBSD$")
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()
#define IBC_ADD
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)
#define IBC_LOOKUP
static int imgact_binmisc_populate_xbe(ximgact_binmisc_entry_t *xbe, imgact_binmisc_entry_t *ibe)
#define ISM_OLD_ARGV0
#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
Definition: kern_exec.c:210
int exec_args_adjust_args(struct image_args *args, size_t consume, ssize_t extend)
Definition: kern_exec.c:1569
void *() malloc(size_t size, struct malloc_type *mtp, int flags)
Definition: kern_malloc.c:632
void free(void *addr, struct malloc_type *mtp)
Definition: kern_malloc.c:907
int sbuf_finish(struct sbuf *s)
Definition: subr_sbuf.c:833
void sbuf_delete(struct sbuf *s)
Definition: subr_sbuf.c:898
int sbuf_printf(struct sbuf *s, const char *fmt,...)
Definition: subr_sbuf.c:739
char * sbuf_data(struct sbuf *s)
Definition: subr_sbuf.c:862