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