1 /*- 2 * Copyright (c) 1999 Poul-Henning Kamp. 3 * Copyright (c) 2009-2012 James Gritton 4 * All rights reserved. 5 * 6 * Redistribution and use in source and binary forms, with or without 7 * modification, are permitted provided that the following conditions 8 * are met: 9 * 1. Redistributions of source code must retain the above copyright 10 * notice, this list of conditions and the following disclaimer. 11 * 2. Redistributions in binary form must reproduce the above copyright 12 * notice, this list of conditions and the following disclaimer in the 13 * documentation and/or other materials provided with the distribution. 14 * 15 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 16 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 17 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 18 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 19 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 20 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 21 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 22 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 23 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 24 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 25 * SUCH DAMAGE. 26 */ 27 28 #include <sys/cdefs.h> 29 __FBSDID("$FreeBSD$"); 30 31 #include <sys/types.h> 32 #include <sys/stat.h> 33 #include <sys/socket.h> 34 #include <sys/sysctl.h> 35 36 #include <arpa/inet.h> 37 #include <netinet/in.h> 38 39 #include <err.h> 40 #include <errno.h> 41 #include <stdarg.h> 42 #include <stdio.h> 43 #include <stdlib.h> 44 #include <string.h> 45 #include <unistd.h> 46 47 #include "jailp.h" 48 49 #define JP_RDTUN(jp) (((jp)->jp_ctltype & CTLFLAG_RDTUN) == CTLFLAG_RDTUN) 50 51 struct permspec { 52 const char *name; 53 enum intparam ipnum; 54 int rev; 55 }; 56 57 const char *cfname; 58 int iflag; 59 int note_remove; 60 int verbose; 61 62 static void clear_persist(struct cfjail *j); 63 static int update_jail(struct cfjail *j); 64 static int rdtun_params(struct cfjail *j, int dofail); 65 static void running_jid(struct cfjail *j, int dflag); 66 static void jail_quoted_warnx(const struct cfjail *j, const char *name_msg, 67 const char *noname_msg); 68 static int jailparam_set_note(const struct cfjail *j, struct jailparam *jp, 69 unsigned njp, int flags); 70 static void print_jail(FILE *fp, struct cfjail *j, int oldcl); 71 static void print_param(FILE *fp, const struct cfparam *p, int sep, int doname); 72 static void quoted_print(FILE *fp, char *str); 73 static void usage(void); 74 75 static struct permspec perm_sysctl[] = { 76 { "security.jail.set_hostname_allowed", KP_ALLOW_SET_HOSTNAME, 0 }, 77 { "security.jail.sysvipc_allowed", KP_ALLOW_SYSVIPC, 0 }, 78 { "security.jail.allow_raw_sockets", KP_ALLOW_RAW_SOCKETS, 0 }, 79 { "security.jail.chflags_allowed", KP_ALLOW_CHFLAGS, 0 }, 80 { "security.jail.mount_allowed", KP_ALLOW_MOUNT, 0 }, 81 { "security.jail.socket_unixiproute_only", KP_ALLOW_SOCKET_AF, 1 }, 82 }; 83 84 static const enum intparam startcommands[] = { 85 IP__NULL, 86 #ifdef INET 87 IP__IP4_IFADDR, 88 #endif 89 #ifdef INET6 90 IP__IP6_IFADDR, 91 #endif 92 IP_MOUNT, 93 IP__MOUNT_FROM_FSTAB, 94 IP_MOUNT_DEVFS, 95 IP_MOUNT_FDESCFS, 96 IP_MOUNT_PROCFS, 97 IP_EXEC_PRESTART, 98 IP__OP, 99 IP_VNET_INTERFACE, 100 IP_EXEC_START, 101 IP_COMMAND, 102 IP_EXEC_POSTSTART, 103 IP__NULL 104 }; 105 106 static const enum intparam stopcommands[] = { 107 IP__NULL, 108 IP_EXEC_PRESTOP, 109 IP_EXEC_STOP, 110 IP_STOP_TIMEOUT, 111 IP__OP, 112 IP_EXEC_POSTSTOP, 113 IP_MOUNT_PROCFS, 114 IP_MOUNT_FDESCFS, 115 IP_MOUNT_DEVFS, 116 IP__MOUNT_FROM_FSTAB, 117 IP_MOUNT, 118 #ifdef INET6 119 IP__IP6_IFADDR, 120 #endif 121 #ifdef INET 122 IP__IP4_IFADDR, 123 #endif 124 IP__NULL 125 }; 126 127 int 128 main(int argc, char **argv) 129 { 130 struct stat st; 131 FILE *jfp; 132 struct cfjail *j; 133 char *JidFile; 134 size_t sysvallen; 135 unsigned op, pi; 136 int ch, docf, error, i, oldcl, sysval; 137 int dflag, Rflag; 138 char enforce_statfs[4]; 139 #if defined(INET) || defined(INET6) 140 char *cs, *ncs; 141 #endif 142 #if defined(INET) && defined(INET6) 143 struct in6_addr addr6; 144 #endif 145 146 op = 0; 147 dflag = Rflag = 0; 148 docf = 1; 149 cfname = CONF_FILE; 150 JidFile = NULL; 151 152 while ((ch = getopt(argc, argv, "cdf:hiJ:lmn:p:qrRs:u:U:v")) != -1) { 153 switch (ch) { 154 case 'c': 155 op |= JF_START; 156 break; 157 case 'd': 158 dflag = 1; 159 break; 160 case 'f': 161 cfname = optarg; 162 break; 163 case 'h': 164 #if defined(INET) || defined(INET6) 165 add_param(NULL, NULL, IP_IP_HOSTNAME, NULL); 166 #endif 167 docf = 0; 168 break; 169 case 'i': 170 iflag = 1; 171 verbose = -1; 172 break; 173 case 'J': 174 JidFile = optarg; 175 break; 176 case 'l': 177 add_param(NULL, NULL, IP_EXEC_CLEAN, NULL); 178 docf = 0; 179 break; 180 case 'm': 181 op |= JF_SET; 182 break; 183 case 'n': 184 add_param(NULL, NULL, KP_NAME, optarg); 185 docf = 0; 186 break; 187 case 'p': 188 paralimit = strtol(optarg, NULL, 10); 189 if (paralimit == 0) 190 paralimit = -1; 191 break; 192 case 'q': 193 verbose = -1; 194 break; 195 case 'r': 196 op |= JF_STOP; 197 break; 198 case 'R': 199 op |= JF_STOP; 200 Rflag = 1; 201 break; 202 case 's': 203 add_param(NULL, NULL, KP_SECURELEVEL, optarg); 204 docf = 0; 205 break; 206 case 'u': 207 add_param(NULL, NULL, IP_EXEC_JAIL_USER, optarg); 208 add_param(NULL, NULL, IP_EXEC_SYSTEM_JAIL_USER, NULL); 209 docf = 0; 210 break; 211 case 'U': 212 add_param(NULL, NULL, IP_EXEC_JAIL_USER, optarg); 213 add_param(NULL, NULL, IP_EXEC_SYSTEM_JAIL_USER, 214 "false"); 215 docf = 0; 216 break; 217 case 'v': 218 verbose = 1; 219 break; 220 default: 221 usage(); 222 } 223 } 224 argc -= optind; 225 argv += optind; 226 227 /* Find out which of the four command line styles this is. */ 228 oldcl = 0; 229 if (!op) { 230 /* Old-style command line with four fixed parameters */ 231 if (argc < 4 || argv[0][0] != '/') 232 usage(); 233 op = JF_START; 234 docf = 0; 235 oldcl = 1; 236 add_param(NULL, NULL, KP_PATH, argv[0]); 237 add_param(NULL, NULL, KP_HOST_HOSTNAME, argv[1]); 238 #if defined(INET) || defined(INET6) 239 if (argv[2][0] != '\0') { 240 for (cs = argv[2];; cs = ncs + 1) { 241 ncs = strchr(cs, ','); 242 if (ncs) 243 *ncs = '\0'; 244 add_param(NULL, NULL, 245 #if defined(INET) && defined(INET6) 246 inet_pton(AF_INET6, cs, &addr6) == 1 247 ? KP_IP6_ADDR : KP_IP4_ADDR, 248 #elif defined(INET) 249 KP_IP4_ADDR, 250 #elif defined(INET6) 251 KP_IP6_ADDR, 252 #endif 253 cs); 254 if (!ncs) 255 break; 256 } 257 } 258 #endif 259 for (i = 3; i < argc; i++) 260 add_param(NULL, NULL, IP_COMMAND, argv[i]); 261 /* Emulate the defaults from security.jail.* sysctls. */ 262 sysvallen = sizeof(sysval); 263 if (sysctlbyname("security.jail.jailed", &sysval, &sysvallen, 264 NULL, 0) == 0 && sysval == 0) { 265 for (pi = 0; pi < sizeof(perm_sysctl) / 266 sizeof(perm_sysctl[0]); pi++) { 267 sysvallen = sizeof(sysval); 268 if (sysctlbyname(perm_sysctl[pi].name, 269 &sysval, &sysvallen, NULL, 0) == 0) 270 add_param(NULL, NULL, 271 perm_sysctl[pi].ipnum, 272 (sysval ? 1 : 0) ^ 273 perm_sysctl[pi].rev 274 ? NULL : "false"); 275 } 276 sysvallen = sizeof(sysval); 277 if (sysctlbyname("security.jail.enforce_statfs", 278 &sysval, &sysvallen, NULL, 0) == 0) { 279 snprintf(enforce_statfs, 280 sizeof(enforce_statfs), "%d", sysval); 281 add_param(NULL, NULL, KP_ENFORCE_STATFS, 282 enforce_statfs); 283 } 284 } 285 } else if (op == JF_STOP) { 286 /* Jail remove, perhaps using the config file */ 287 if (!docf || argc == 0) 288 usage(); 289 if (!Rflag) 290 for (i = 0; i < argc; i++) 291 if (strchr(argv[i], '=')) 292 usage(); 293 if ((docf = !Rflag && 294 (!strcmp(cfname, "-") || stat(cfname, &st) == 0))) 295 load_config(); 296 note_remove = docf || argc > 1 || wild_jail_name(argv[0]); 297 } else if (argc > 1 || (argc == 1 && strchr(argv[0], '='))) { 298 /* Single jail specified on the command line */ 299 if (Rflag) 300 usage(); 301 docf = 0; 302 for (i = 0; i < argc; i++) { 303 if (!strncmp(argv[i], "command", 7) && 304 (argv[i][7] == '\0' || argv[i][7] == '=')) { 305 if (argv[i][7] == '=') 306 add_param(NULL, NULL, IP_COMMAND, 307 argv[i] + 8); 308 for (i++; i < argc; i++) 309 add_param(NULL, NULL, IP_COMMAND, 310 argv[i]); 311 } 312 #ifdef INET 313 else if (!strncmp(argv[i], "ip4.addr=", 9)) { 314 for (cs = argv[i] + 9;; cs = ncs + 1) { 315 ncs = strchr(cs, ','); 316 if (ncs) 317 *ncs = '\0'; 318 add_param(NULL, NULL, KP_IP4_ADDR, cs); 319 if (!ncs) 320 break; 321 } 322 } 323 #endif 324 #ifdef INET6 325 else if (!strncmp(argv[i], "ip6.addr=", 9)) { 326 for (cs = argv[i] + 9;; cs = ncs + 1) { 327 ncs = strchr(cs, ','); 328 if (ncs) 329 *ncs = '\0'; 330 add_param(NULL, NULL, KP_IP6_ADDR, cs); 331 if (!ncs) 332 break; 333 } 334 } 335 #endif 336 else 337 add_param(NULL, NULL, 0, argv[i]); 338 } 339 } else { 340 /* From the config file, perhaps with a specified jail */ 341 if (Rflag || !docf) 342 usage(); 343 load_config(); 344 } 345 346 /* Find out which jails will be run. */ 347 dep_setup(docf); 348 error = 0; 349 if (op == JF_STOP) { 350 for (i = 0; i < argc; i++) 351 if (start_state(argv[i], docf, op, Rflag) < 0) 352 error = 1; 353 } else { 354 if (start_state(argv[0], docf, op, 0) < 0) 355 exit(1); 356 } 357 358 jfp = NULL; 359 if (JidFile != NULL) { 360 jfp = fopen(JidFile, "w"); 361 if (jfp == NULL) 362 err(1, "open %s", JidFile); 363 setlinebuf(jfp); 364 } 365 setlinebuf(stdout); 366 367 /* 368 * The main loop: Get an available jail and perform the required 369 * operation on it. When that is done, the jail may be finished, 370 * or it may go back for the next step. 371 */ 372 while ((j = next_jail())) 373 { 374 if (j->flags & JF_FAILED) { 375 error = 1; 376 if (j->comparam == NULL) { 377 dep_done(j, 0); 378 continue; 379 } 380 } 381 if (!(j->flags & JF_PARAMS)) 382 { 383 j->flags |= JF_PARAMS; 384 if (dflag) 385 add_param(j, NULL, IP_ALLOW_DYING, NULL); 386 if (check_intparams(j) < 0) 387 continue; 388 if ((j->flags & (JF_START | JF_SET)) && 389 import_params(j) < 0) 390 continue; 391 } 392 if (!j->jid) 393 running_jid(j, 394 (j->flags & (JF_SET | JF_DEPEND)) == JF_SET 395 ? dflag || bool_param(j->intparams[IP_ALLOW_DYING]) 396 : 0); 397 if (finish_command(j)) 398 continue; 399 400 switch (j->flags & JF_OP_MASK) { 401 /* 402 * These operations just turn into a different op 403 * depending on the jail's current status. 404 */ 405 case JF_START_SET: 406 j->flags = j->jid < 0 ? JF_START : JF_SET; 407 break; 408 case JF_SET_RESTART: 409 if (j->jid < 0) { 410 jail_quoted_warnx(j, "not found", 411 "no jail specified"); 412 failed(j); 413 continue; 414 } 415 j->flags = rdtun_params(j, 0) ? JF_RESTART : JF_SET; 416 if (j->flags == JF_RESTART) 417 dep_reset(j); 418 break; 419 case JF_START_SET_RESTART: 420 j->flags = j->jid < 0 ? JF_START 421 : rdtun_params(j, 0) ? JF_RESTART : JF_SET; 422 if (j->flags == JF_RESTART) 423 dep_reset(j); 424 } 425 426 switch (j->flags & JF_OP_MASK) { 427 case JF_START: 428 if (j->comparam == NULL) { 429 if (j->jid > 0 && 430 !(j->flags & (JF_DEPEND | JF_WILD))) { 431 jail_quoted_warnx(j, "already exists", 432 NULL); 433 failed(j); 434 continue; 435 } 436 if (dep_check(j)) 437 continue; 438 if (j->jid > 0) 439 goto jail_create_done; 440 j->comparam = startcommands; 441 j->comstring = NULL; 442 } 443 if (next_command(j)) 444 continue; 445 jail_create_done: 446 clear_persist(j); 447 if (jfp != NULL) 448 print_jail(jfp, j, oldcl); 449 dep_done(j, 0); 450 break; 451 452 case JF_SET: 453 if (j->jid < 0 && !(j->flags & JF_DEPEND)) { 454 jail_quoted_warnx(j, "not found", 455 "no jail specified"); 456 failed(j); 457 continue; 458 } 459 if (dep_check(j)) 460 continue; 461 if (!(j->flags & JF_DEPEND)) { 462 if (rdtun_params(j, 1) < 0 || 463 update_jail(j) < 0) 464 continue; 465 if (verbose >= 0 && (j->name || verbose > 0)) 466 jail_note(j, "updated\n"); 467 } 468 dep_done(j, 0); 469 break; 470 471 case JF_STOP: 472 case JF_RESTART: 473 if (j->comparam == NULL) { 474 if (dep_check(j)) 475 continue; 476 if (j->jid < 0) { 477 if (!(j->flags & (JF_DEPEND|JF_WILD))) { 478 if (verbose >= 0) 479 jail_quoted_warnx(j, 480 "not found", NULL); 481 failed(j); 482 } 483 goto jail_remove_done; 484 } 485 j->comparam = stopcommands; 486 j->comstring = NULL; 487 } else if ((j->flags & JF_FAILED) && j->jid > 0) 488 goto jail_remove_done; 489 if (next_command(j)) 490 continue; 491 jail_remove_done: 492 dep_done(j, 0); 493 if ((j->flags & (JF_START | JF_FAILED)) == JF_START) { 494 j->comparam = NULL; 495 j->flags &= ~JF_STOP; 496 dep_reset(j); 497 requeue(j, j->ndeps ? &depend : &ready); 498 } 499 break; 500 } 501 } 502 503 if (jfp != NULL) 504 fclose(jfp); 505 exit(error); 506 } 507 508 /* 509 * Mark a jail's failure for future handling. 510 */ 511 void 512 failed(struct cfjail *j) 513 { 514 j->flags |= JF_FAILED; 515 TAILQ_REMOVE(j->queue, j, tq); 516 TAILQ_INSERT_HEAD(&ready, j, tq); 517 j->queue = &ready; 518 } 519 520 /* 521 * Exit slightly more gracefully when out of memory. 522 */ 523 void * 524 emalloc(size_t size) 525 { 526 void *p; 527 528 p = malloc(size); 529 if (!p) 530 err(1, "malloc"); 531 return p; 532 } 533 534 void * 535 erealloc(void *ptr, size_t size) 536 { 537 void *p; 538 539 p = realloc(ptr, size); 540 if (!p) 541 err(1, "malloc"); 542 return p; 543 } 544 545 char * 546 estrdup(const char *str) 547 { 548 char *ns; 549 550 ns = strdup(str); 551 if (!ns) 552 err(1, "malloc"); 553 return ns; 554 } 555 556 /* 557 * Print a message including an optional jail name. 558 */ 559 void 560 jail_note(const struct cfjail *j, const char *fmt, ...) 561 { 562 va_list ap, tap; 563 char *cs; 564 size_t len; 565 566 va_start(ap, fmt); 567 va_copy(tap, ap); 568 len = vsnprintf(NULL, 0, fmt, tap); 569 va_end(tap); 570 cs = alloca(len + 1); 571 (void)vsnprintf(cs, len + 1, fmt, ap); 572 va_end(ap); 573 if (j->name) 574 printf("%s: %s", j->name, cs); 575 else 576 printf("%s", cs); 577 } 578 579 /* 580 * Print a warning message including an optional jail name. 581 */ 582 void 583 jail_warnx(const struct cfjail *j, const char *fmt, ...) 584 { 585 va_list ap, tap; 586 char *cs; 587 size_t len; 588 589 va_start(ap, fmt); 590 va_copy(tap, ap); 591 len = vsnprintf(NULL, 0, fmt, tap); 592 va_end(tap); 593 cs = alloca(len + 1); 594 (void)vsnprintf(cs, len + 1, fmt, ap); 595 va_end(ap); 596 if (j->name) 597 warnx("%s: %s", j->name, cs); 598 else 599 warnx("%s", cs); 600 } 601 602 /* 603 * Create a new jail. 604 */ 605 int 606 create_jail(struct cfjail *j) 607 { 608 struct iovec jiov[4]; 609 struct stat st; 610 struct jailparam *jp, *setparams, *setparams2, *sjp; 611 const char *path; 612 int dopersist, ns, jid, dying, didfail; 613 614 /* 615 * Check the jail's path, with a better error message than jail_set 616 * gives. 617 */ 618 if ((path = string_param(j->intparams[KP_PATH]))) { 619 if (j->name != NULL && path[0] != '/') { 620 jail_warnx(j, "path %s: not an absolute pathname", 621 path); 622 return -1; 623 } 624 if (stat(path, &st) < 0) { 625 jail_warnx(j, "path %s: %s", path, strerror(errno)); 626 return -1; 627 } 628 if (!S_ISDIR(st.st_mode)) { 629 jail_warnx(j, "path %s: %s", path, strerror(ENOTDIR)); 630 return -1; 631 } 632 } 633 634 /* 635 * Copy all the parameters, except that "persist" is always set when 636 * there are commands to run later. 637 */ 638 dopersist = !bool_param(j->intparams[KP_PERSIST]) && 639 (j->intparams[IP_EXEC_START] || j->intparams[IP_COMMAND] || 640 j->intparams[IP_EXEC_POSTSTART]); 641 sjp = setparams = 642 alloca((j->njp + dopersist) * sizeof(struct jailparam)); 643 if (dopersist && jailparam_init(sjp++, "persist") < 0) { 644 jail_warnx(j, "%s", jail_errmsg); 645 return -1; 646 } 647 for (jp = j->jp; jp < j->jp + j->njp; jp++) 648 if (!dopersist || !equalopts(jp->jp_name, "persist")) 649 *sjp++ = *jp; 650 ns = sjp - setparams; 651 652 didfail = 0; 653 j->jid = jailparam_set_note(j, setparams, ns, JAIL_CREATE); 654 if (j->jid < 0 && errno == EEXIST && 655 bool_param(j->intparams[IP_ALLOW_DYING]) && 656 int_param(j->intparams[KP_JID], &jid) && jid != 0) { 657 /* 658 * The jail already exists, but may be dying. 659 * Make sure it is, in which case an update is appropriate. 660 */ 661 jiov[0].iov_base = __DECONST(char *, "jid"); 662 jiov[0].iov_len = sizeof("jid"); 663 jiov[1].iov_base = &jid; 664 jiov[1].iov_len = sizeof(jid); 665 jiov[2].iov_base = __DECONST(char *, "dying"); 666 jiov[2].iov_len = sizeof("dying"); 667 jiov[3].iov_base = &dying; 668 jiov[3].iov_len = sizeof(dying); 669 if (jail_get(jiov, 4, JAIL_DYING) < 0) { 670 /* 671 * It could be that the jail just barely finished 672 * dying, or it could be that the jid never existed 673 * but the name does. In either case, another try 674 * at creating the jail should do the right thing. 675 */ 676 if (errno == ENOENT) 677 j->jid = jailparam_set_note(j, setparams, ns, 678 JAIL_CREATE); 679 } else if (dying) { 680 j->jid = jid; 681 if (rdtun_params(j, 1) < 0) { 682 j->jid = -1; 683 didfail = 1; 684 } else { 685 sjp = setparams2 = alloca((j->njp + dopersist) * 686 sizeof(struct jailparam)); 687 for (jp = setparams; jp < setparams + ns; jp++) 688 if (!JP_RDTUN(jp) || 689 !strcmp(jp->jp_name, "jid")) 690 *sjp++ = *jp; 691 j->jid = jailparam_set_note(j, setparams2, 692 sjp - setparams2, JAIL_UPDATE | JAIL_DYING); 693 /* 694 * Again, perhaps the jail just finished dying. 695 */ 696 if (j->jid < 0 && errno == ENOENT) 697 j->jid = jailparam_set_note(j, 698 setparams, ns, JAIL_CREATE); 699 } 700 } 701 } 702 if (j->jid < 0 && !didfail) { 703 jail_warnx(j, "%s", jail_errmsg); 704 failed(j); 705 } 706 if (dopersist) { 707 jailparam_free(setparams, 1); 708 if (j->jid > 0) 709 j->flags |= JF_PERSIST; 710 } 711 return j->jid; 712 } 713 714 /* 715 * Remove a temporarily set "persist" parameter. 716 */ 717 static void 718 clear_persist(struct cfjail *j) 719 { 720 struct iovec jiov[4]; 721 int jid; 722 723 if (!(j->flags & JF_PERSIST)) 724 return; 725 j->flags &= ~JF_PERSIST; 726 jiov[0].iov_base = __DECONST(char *, "jid"); 727 jiov[0].iov_len = sizeof("jid"); 728 jiov[1].iov_base = &j->jid; 729 jiov[1].iov_len = sizeof(j->jid); 730 jiov[2].iov_base = __DECONST(char *, "nopersist"); 731 jiov[2].iov_len = sizeof("nopersist"); 732 jiov[3].iov_base = NULL; 733 jiov[3].iov_len = 0; 734 jid = jail_set(jiov, 4, JAIL_UPDATE); 735 if (verbose > 0) 736 jail_note(j, "jail_set(JAIL_UPDATE) jid=%d nopersist%s%s\n", 737 j->jid, jid < 0 ? ": " : "", 738 jid < 0 ? strerror(errno) : ""); 739 } 740 741 /* 742 * Set a jail's parameters. 743 */ 744 static int 745 update_jail(struct cfjail *j) 746 { 747 struct jailparam *jp, *setparams, *sjp; 748 int ns, jid; 749 750 ns = 0; 751 for (jp = j->jp; jp < j->jp + j->njp; jp++) 752 if (!JP_RDTUN(jp)) 753 ns++; 754 if (ns == 0) 755 return 0; 756 sjp = setparams = alloca(++ns * sizeof(struct jailparam)); 757 if (jailparam_init(sjp, "jid") < 0 || 758 jailparam_import_raw(sjp, &j->jid, sizeof j->jid) < 0) { 759 jail_warnx(j, "%s", jail_errmsg); 760 failed(j); 761 return -1; 762 } 763 for (jp = j->jp; jp < j->jp + j->njp; jp++) 764 if (!JP_RDTUN(jp)) 765 *++sjp = *jp; 766 767 jid = jailparam_set_note(j, setparams, ns, 768 bool_param(j->intparams[IP_ALLOW_DYING]) 769 ? JAIL_UPDATE | JAIL_DYING : JAIL_UPDATE); 770 if (jid < 0) { 771 jail_warnx(j, "%s", jail_errmsg); 772 failed(j); 773 } 774 jailparam_free(setparams, 1); 775 return jid; 776 } 777 778 /* 779 * Return if a jail set would change any create-only parameters. 780 */ 781 static int 782 rdtun_params(struct cfjail *j, int dofail) 783 { 784 struct jailparam *jp, *rtparams, *rtjp; 785 int nrt, rval; 786 787 if (j->flags & JF_RDTUN) 788 return 0; 789 j->flags |= JF_RDTUN; 790 nrt = 0; 791 for (jp = j->jp; jp < j->jp + j->njp; jp++) 792 if (JP_RDTUN(jp) && strcmp(jp->jp_name, "jid")) 793 nrt++; 794 if (nrt == 0) 795 return 0; 796 rtjp = rtparams = alloca(++nrt * sizeof(struct jailparam)); 797 if (jailparam_init(rtjp, "jid") < 0 || 798 jailparam_import_raw(rtjp, &j->jid, sizeof j->jid) < 0) { 799 jail_warnx(j, "%s", jail_errmsg); 800 exit(1); 801 } 802 for (jp = j->jp; jp < j->jp + j->njp; jp++) 803 if (JP_RDTUN(jp) && strcmp(jp->jp_name, "jid")) 804 *++rtjp = *jp; 805 rval = 0; 806 if (jailparam_get(rtparams, nrt, 807 bool_param(j->intparams[IP_ALLOW_DYING]) ? JAIL_DYING : 0) > 0) { 808 rtjp = rtparams + 1; 809 for (jp = j->jp; rtjp < rtparams + nrt; jp++) { 810 if (JP_RDTUN(jp) && strcmp(jp->jp_name, "jid")) { 811 if (!((jp->jp_flags & (JP_BOOL | JP_NOBOOL)) && 812 jp->jp_valuelen == 0 && 813 *(int *)jp->jp_value) && 814 !(rtjp->jp_valuelen == jp->jp_valuelen && 815 !memcmp(rtjp->jp_value, jp->jp_value, 816 jp->jp_valuelen))) { 817 if (dofail) { 818 jail_warnx(j, "%s cannot be " 819 "changed after creation", 820 jp->jp_name); 821 failed(j); 822 rval = -1; 823 } else 824 rval = 1; 825 break; 826 } 827 rtjp++; 828 } 829 } 830 } 831 for (rtjp = rtparams + 1; rtjp < rtparams + nrt; rtjp++) 832 rtjp->jp_name = NULL; 833 jailparam_free(rtparams, nrt); 834 return rval; 835 } 836 837 /* 838 * Get the jail's jid if it is running. 839 */ 840 static void 841 running_jid(struct cfjail *j, int dflag) 842 { 843 struct iovec jiov[2]; 844 const char *pval; 845 char *ep; 846 int jid; 847 848 if ((pval = string_param(j->intparams[KP_JID]))) { 849 if (!(jid = strtol(pval, &ep, 10)) || *ep) { 850 j->jid = -1; 851 return; 852 } 853 jiov[0].iov_base = __DECONST(char *, "jid"); 854 jiov[0].iov_len = sizeof("jid"); 855 jiov[1].iov_base = &jid; 856 jiov[1].iov_len = sizeof(jid); 857 } else if ((pval = string_param(j->intparams[KP_NAME]))) { 858 jiov[0].iov_base = __DECONST(char *, "name"); 859 jiov[0].iov_len = sizeof("name"); 860 jiov[1].iov_len = strlen(pval) + 1; 861 jiov[1].iov_base = alloca(jiov[1].iov_len); 862 strcpy(jiov[1].iov_base, pval); 863 } else { 864 j->jid = -1; 865 return; 866 } 867 j->jid = jail_get(jiov, 2, dflag ? JAIL_DYING : 0); 868 } 869 870 static void 871 jail_quoted_warnx(const struct cfjail *j, const char *name_msg, 872 const char *noname_msg) 873 { 874 const char *pval; 875 876 if ((pval = j->name) || (pval = string_param(j->intparams[KP_JID])) || 877 (pval = string_param(j->intparams[KP_NAME]))) 878 warnx("\"%s\" %s", pval, name_msg); 879 else 880 warnx("%s", noname_msg); 881 } 882 883 /* 884 * Set jail parameters and possibly print them out. 885 */ 886 static int 887 jailparam_set_note(const struct cfjail *j, struct jailparam *jp, unsigned njp, 888 int flags) 889 { 890 char *value; 891 int jid; 892 unsigned i; 893 894 jid = jailparam_set(jp, njp, flags); 895 if (verbose > 0) { 896 jail_note(j, "jail_set(%s%s)", 897 (flags & (JAIL_CREATE | JAIL_UPDATE)) == JAIL_CREATE 898 ? "JAIL_CREATE" : "JAIL_UPDATE", 899 (flags & JAIL_DYING) ? " | JAIL_DYING" : ""); 900 for (i = 0; i < njp; i++) { 901 printf(" %s", jp[i].jp_name); 902 if (jp[i].jp_value == NULL) 903 continue; 904 putchar('='); 905 value = jailparam_export(jp + i); 906 if (value == NULL) 907 err(1, "jailparam_export"); 908 quoted_print(stdout, value); 909 free(value); 910 } 911 if (jid < 0) 912 printf(": %s", strerror(errno)); 913 printf("\n"); 914 } 915 return jid; 916 } 917 918 /* 919 * Print a jail record. 920 */ 921 static void 922 print_jail(FILE *fp, struct cfjail *j, int oldcl) 923 { 924 struct cfparam *p; 925 926 if (oldcl) { 927 fprintf(fp, "%d\t", j->jid); 928 print_param(fp, j->intparams[KP_PATH], ',', 0); 929 putc('\t', fp); 930 print_param(fp, j->intparams[KP_HOST_HOSTNAME], ',', 0); 931 putc('\t', fp); 932 #ifdef INET 933 print_param(fp, j->intparams[KP_IP4_ADDR], ',', 0); 934 #ifdef INET6 935 if (j->intparams[KP_IP4_ADDR] && 936 !TAILQ_EMPTY(&j->intparams[KP_IP4_ADDR]->val) && 937 j->intparams[KP_IP6_ADDR] && 938 !TAILQ_EMPTY(&j->intparams[KP_IP6_ADDR]->val)) 939 putc(',', fp); 940 #endif 941 #endif 942 #ifdef INET6 943 print_param(fp, j->intparams[KP_IP6_ADDR], ',', 0); 944 #endif 945 putc('\t', fp); 946 print_param(fp, j->intparams[IP_COMMAND], ' ', 0); 947 } else { 948 fprintf(fp, "jid=%d", j->jid); 949 TAILQ_FOREACH(p, &j->params, tq) 950 if (strcmp(p->name, "jid")) { 951 putc(' ', fp); 952 print_param(fp, p, ',', 1); 953 } 954 } 955 putc('\n', fp); 956 } 957 958 /* 959 * Print a parameter value, or a name=value pair. 960 */ 961 static void 962 print_param(FILE *fp, const struct cfparam *p, int sep, int doname) 963 { 964 const struct cfstring *s, *ts; 965 966 if (doname) 967 fputs(p->name, fp); 968 if (p == NULL || TAILQ_EMPTY(&p->val)) 969 return; 970 if (doname) 971 putc('=', fp); 972 TAILQ_FOREACH_SAFE(s, &p->val, tq, ts) { 973 quoted_print(fp, s->s); 974 if (ts != NULL) 975 putc(sep, fp); 976 } 977 } 978 979 /* 980 * Print a string with quotes around spaces. 981 */ 982 static void 983 quoted_print(FILE *fp, char *str) 984 { 985 int c, qc; 986 char *p = str; 987 988 qc = !*p ? '"' 989 : strchr(p, '\'') ? '"' 990 : strchr(p, '"') ? '\'' 991 : strchr(p, ' ') || strchr(p, '\t') ? '"' 992 : 0; 993 if (qc) 994 putc(qc, fp); 995 while ((c = *p++)) { 996 if (c == '\\' || c == qc) 997 putc('\\', fp); 998 putc(c, fp); 999 } 1000 if (qc) 1001 putc(qc, fp); 1002 } 1003 1004 static void 1005 usage(void) 1006 { 1007 1008 (void)fprintf(stderr, 1009 "usage: jail [-dhilqv] [-J jid_file] [-u username] [-U username]\n" 1010 " -[cmr] param=value ... [command=command ...]\n" 1011 " jail [-dqv] [-f file] -[cmr] [jail]\n" 1012 " jail [-qv] [-f file] -[rR] ['*' | jail ...]\n" 1013 " jail [-dhilqv] [-J jid_file] [-u username] [-U username]\n" 1014 " [-n jailname] [-s securelevel]\n" 1015 " path hostname [ip[,...]] command ...\n"); 1016 exit(1); 1017 } 1018