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