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