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 45 /** 46 * Miscellaneous binary interpreter image activator. 47 * 48 * If the given target executable's header matches 'xbe_magic' field in the 49 * 'interpreter_list' then it will use the user-level interpreter specified in 50 * the 'xbe_interpreter' field to execute the binary. The 'xbe_magic' field may 51 * be adjusted to a given offset using the value in the 'xbe_moffset' field 52 * and bits of the header may be masked using the 'xbe_mask' field. The 53 * 'interpreter_list' entries are managed using sysctl(3) as described in the 54 * <sys/imgact_binmisc.h> file. 55 */ 56 57 /* 58 * Node of the interpreter list. 59 */ 60 typedef 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; 73 } imgact_binmisc_entry_t; 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 93 MALLOC_DEFINE(M_BINMISC, KMOD_NAME, "misc binary image activator"); 94 95 /* The interpreter list. */ 96 static SLIST_HEAD(, imgact_binmisc_entry) interpreter_list = 97 SLIST_HEAD_INITIALIZER(interpreter_list); 98 99 static int interp_list_entry_count; 100 101 static 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 */ 116 static void 117 imgact_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 */ 158 static imgact_binmisc_entry_t * 159 imgact_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 */ 189 static void 190 imgact_binmisc_destroy_entry(imgact_binmisc_entry_t *ibe) 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 */ 210 static imgact_binmisc_entry_t * 211 imgact_binmisc_find_entry(char *name) 212 { 213 imgact_binmisc_entry_t *ibe; 214 215 INTERP_LIST_ASSERT_LOCKED(); 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 */ 229 static int 230 imgact_binmisc_add_entry(ximgact_binmisc_entry_t *xbe) 231 { 232 imgact_binmisc_entry_t *ibe; 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 274 INTERP_LIST_WLOCK(); 275 if (imgact_binmisc_find_entry(xbe->xbe_name) != NULL) { 276 INTERP_LIST_WUNLOCK(); 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++; 285 INTERP_LIST_WUNLOCK(); 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 */ 294 static int 295 imgact_binmisc_remove_entry(char *name) 296 { 297 imgact_binmisc_entry_t *ibe; 298 299 INTERP_LIST_WLOCK(); 300 if ((ibe = imgact_binmisc_find_entry(name)) == NULL) { 301 INTERP_LIST_WUNLOCK(); 302 return (ENOENT); 303 } 304 SLIST_REMOVE(&interpreter_list, ibe, imgact_binmisc_entry, link); 305 interp_list_entry_count--; 306 INTERP_LIST_WUNLOCK(); 307 308 imgact_binmisc_destroy_entry(ibe); 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 */ 317 static int 318 imgact_binmisc_disable_entry(char *name) 319 { 320 imgact_binmisc_entry_t *ibe; 321 322 INTERP_LIST_WLOCK(); 323 if ((ibe = imgact_binmisc_find_entry(name)) == NULL) { 324 INTERP_LIST_WUNLOCK(); 325 return (ENOENT); 326 } 327 328 ibe->ibe_flags &= ~IBF_ENABLED; 329 INTERP_LIST_WUNLOCK(); 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 */ 338 static int 339 imgact_binmisc_enable_entry(char *name) 340 { 341 imgact_binmisc_entry_t *ibe; 342 343 INTERP_LIST_WLOCK(); 344 if ((ibe = imgact_binmisc_find_entry(name)) == NULL) { 345 INTERP_LIST_WUNLOCK(); 346 return (ENOENT); 347 } 348 349 ibe->ibe_flags |= IBF_ENABLED; 350 INTERP_LIST_WUNLOCK(); 351 352 return (0); 353 } 354 355 static int 356 imgact_binmisc_populate_xbe(ximgact_binmisc_entry_t *xbe, 357 imgact_binmisc_entry_t *ibe) 358 { 359 uint32_t i; 360 361 INTERP_LIST_ASSERT_LOCKED(); 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 */ 386 static int 387 imgact_binmisc_lookup_entry(char *name, ximgact_binmisc_entry_t *xbe) 388 { 389 imgact_binmisc_entry_t *ibe; 390 int error = 0; 391 392 INTERP_LIST_RLOCK(); 393 if ((ibe = imgact_binmisc_find_entry(name)) == NULL) { 394 INTERP_LIST_RUNLOCK(); 395 return (ENOENT); 396 } 397 398 error = imgact_binmisc_populate_xbe(xbe, ibe); 399 INTERP_LIST_RUNLOCK(); 400 401 return (error); 402 } 403 404 /* 405 * Get a snapshot of all the interpreter entries in the list. 406 */ 407 static int 408 imgact_binmisc_get_all_entries(struct sysctl_req *req) 409 { 410 ximgact_binmisc_entry_t *xbe, *xbep; 411 imgact_binmisc_entry_t *ibe; 412 int error = 0, count; 413 414 INTERP_LIST_RLOCK(); 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 } 424 INTERP_LIST_RUNLOCK(); 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 */ 437 static int 438 sysctl_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 512 error = imgact_binmisc_get_all_entries(req); 513 break; 514 515 default: 516 return (EINVAL); 517 } 518 519 return (error); 520 } 521 522 SYSCTL_NODE(_kern, OID_AUTO, binmisc, CTLFLAG_RW | CTLFLAG_MPSAFE, 0, 523 "Image activator for miscellaneous binaries"); 524 525 SYSCTL_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 530 SYSCTL_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 535 SYSCTL_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 540 SYSCTL_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 545 SYSCTL_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 550 SYSCTL_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 555 static imgact_binmisc_entry_t * 556 imgact_binmisc_find_interpreter(const char *image_header) 557 { 558 imgact_binmisc_entry_t *ibe; 559 const char *p; 560 int i; 561 size_t sz; 562 563 INTERP_LIST_ASSERT_LOCKED(); 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 588 static int 589 imgact_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; 598 imgact_binmisc_entry_t *ibe; 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? */ 605 INTERP_LIST_RLOCK(); 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 702 done: 703 INTERP_LIST_RUNLOCK(); 704 if (sname) 705 sbuf_delete(sname); 706 return (error); 707 } 708 709 static void 710 imgact_binmisc_init(void *arg) 711 { 712 713 INTERP_LIST_LOCK_INIT(); 714 } 715 716 static void 717 imgact_binmisc_fini(void *arg) 718 { 719 imgact_binmisc_entry_t *ibe, *ibe_tmp; 720 721 /* Free all the interpreters. */ 722 INTERP_LIST_WLOCK(); 723 SLIST_FOREACH_SAFE(ibe, &interpreter_list, link, ibe_tmp) { 724 SLIST_REMOVE(&interpreter_list, ibe, imgact_binmisc_entry, 725 link); 726 imgact_binmisc_destroy_entry(ibe); 727 } 728 INTERP_LIST_WUNLOCK(); 729 730 INTERP_LIST_LOCK_DESTROY(); 731 } 732 733 SYSINIT(imgact_binmisc, SI_SUB_EXEC, SI_ORDER_MIDDLE, imgact_binmisc_init, 734 NULL); 735 SYSUNINIT(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 */ 741 static struct execsw imgact_binmisc_execsw = { 742 .ex_imgact = imgact_binmisc_exec, 743 .ex_name = KMOD_NAME 744 }; 745 EXEC_SET(imgact_binmisc, imgact_binmisc_execsw); 746