1 /* 2 * CDDL HEADER START 3 * 4 * The contents of this file are subject to the terms of the 5 * Common Development and Distribution License, Version 1.0 only 6 * (the "License"). You may not use this file except in compliance 7 * with the License. 8 * 9 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 10 * or http://www.opensolaris.org/os/licensing. 11 * See the License for the specific language governing permissions 12 * and limitations under the License. 13 * 14 * When distributing Covered Code, include this CDDL HEADER in each 15 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 16 * If applicable, add the following below this CDDL HEADER, with the 17 * fields enclosed by brackets "[]" replaced with your own identifying 18 * information: Portions Copyright [yyyy] [name of copyright owner] 19 * 20 * CDDL HEADER END 21 */ 22 23 /* 24 * Copyright 2005 Sun Microsystems, Inc. All rights reserved. 25 * Use is subject to license terms. 26 */ 27 28 #pragma ident "%Z%%M% %I% %E% SMI" 29 30 /* 31 * zoneadm is a command interpreter for zone administration. It is all in 32 * C (i.e., no lex/yacc), and all the argument passing is argc/argv based. 33 * main() calls parse_and_run() which calls cmd_match(), then invokes the 34 * appropriate command's handler function. The rest of the program is the 35 * handler functions and their helper functions. 36 * 37 * Some of the helper functions are used largely to simplify I18N: reducing 38 * the need for translation notes. This is particularly true of many of 39 * the zerror() calls: doing e.g. zerror(gettext("%s failed"), "foo") rather 40 * than zerror(gettext("foo failed")) with a translation note indicating 41 * that "foo" need not be translated. 42 */ 43 44 #include <stdio.h> 45 #include <errno.h> 46 #include <unistd.h> 47 #include <signal.h> 48 #include <stdarg.h> 49 #include <ctype.h> 50 #include <stdlib.h> 51 #include <string.h> 52 #include <wait.h> 53 #include <zone.h> 54 #include <priv.h> 55 #include <locale.h> 56 #include <libintl.h> 57 #include <libzonecfg.h> 58 #include <bsm/adt.h> 59 #include <sys/utsname.h> 60 #include <sys/param.h> 61 #include <sys/types.h> 62 #include <sys/stat.h> 63 #include <sys/statvfs.h> 64 #include <assert.h> 65 #include <sys/sockio.h> 66 #include <sys/mntent.h> 67 #include <limits.h> 68 69 #include <fcntl.h> 70 #include <door.h> 71 #include <macros.h> 72 #include <libgen.h> 73 74 #include <pool.h> 75 #include <sys/pool.h> 76 77 #define MAXARGS 8 78 79 /* Reflects kernel zone entries */ 80 typedef struct zone_entry { 81 zoneid_t zid; 82 char zname[ZONENAME_MAX]; 83 char *zstate_str; 84 zone_state_t zstate_num; 85 char zroot[MAXPATHLEN]; 86 } zone_entry_t; 87 88 static zone_entry_t *zents; 89 static size_t nzents; 90 91 #if !defined(TEXT_DOMAIN) /* should be defined by cc -D */ 92 #define TEXT_DOMAIN "SYS_TEST" /* Use this only if it wasn't */ 93 #endif 94 95 #define Z_ERR 1 96 #define Z_USAGE 2 97 98 /* 0755 is the default directory mode. */ 99 #define DEFAULT_DIR_MODE \ 100 (S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH) 101 102 #define CMD_HELP 0 103 #define CMD_BOOT 1 104 #define CMD_HALT 2 105 #define CMD_READY 3 106 #define CMD_REBOOT 4 107 #define CMD_LIST 5 108 #define CMD_VERIFY 6 109 #define CMD_INSTALL 7 110 #define CMD_UNINSTALL 8 111 #define CMD_MOUNT 9 112 #define CMD_UNMOUNT 10 113 114 #define CMD_MIN CMD_HELP 115 #define CMD_MAX CMD_UNMOUNT 116 117 struct cmd { 118 uint_t cmd_num; /* command number */ 119 char *cmd_name; /* command name */ 120 char *short_usage; /* short form help */ 121 int (*handler)(int argc, char *argv[]); /* function to call */ 122 123 }; 124 125 #define SHELP_HELP "help" 126 #define SHELP_BOOT "boot [-s]" 127 #define SHELP_HALT "halt" 128 #define SHELP_READY "ready" 129 #define SHELP_REBOOT "reboot" 130 #define SHELP_LIST "list [-cipv]" 131 #define SHELP_VERIFY "verify" 132 #define SHELP_INSTALL "install" 133 #define SHELP_UNINSTALL "uninstall [-F]" 134 135 static int help_func(int argc, char *argv[]); 136 static int ready_func(int argc, char *argv[]); 137 static int boot_func(int argc, char *argv[]); 138 static int halt_func(int argc, char *argv[]); 139 static int reboot_func(int argc, char *argv[]); 140 static int list_func(int argc, char *argv[]); 141 static int verify_func(int argc, char *argv[]); 142 static int install_func(int argc, char *argv[]); 143 static int uninstall_func(int argc, char *argv[]); 144 static int mount_func(int argc, char *argv[]); 145 static int unmount_func(int argc, char *argv[]); 146 static int sanity_check(char *zone, int cmd_num, boolean_t running, 147 boolean_t unsafe_when_running); 148 static int cmd_match(char *cmd); 149 static int verify_details(int); 150 151 static struct cmd cmdtab[] = { 152 { CMD_HELP, "help", SHELP_HELP, help_func }, 153 { CMD_BOOT, "boot", SHELP_BOOT, boot_func }, 154 { CMD_HALT, "halt", SHELP_HALT, halt_func }, 155 { CMD_READY, "ready", SHELP_READY, ready_func }, 156 { CMD_REBOOT, "reboot", SHELP_REBOOT, reboot_func }, 157 { CMD_LIST, "list", SHELP_LIST, list_func }, 158 { CMD_VERIFY, "verify", SHELP_VERIFY, verify_func }, 159 { CMD_INSTALL, "install", SHELP_INSTALL, install_func }, 160 { CMD_UNINSTALL, "uninstall", SHELP_UNINSTALL, 161 uninstall_func }, 162 /* Private commands for admin/install */ 163 { CMD_MOUNT, "mount", NULL, mount_func }, 164 { CMD_UNMOUNT, "unmount", NULL, unmount_func } 165 }; 166 167 /* global variables */ 168 169 /* set early in main(), never modified thereafter, used all over the place */ 170 static char *execname; 171 static char *target_zone; 172 static char *locale; 173 174 /* used in do_subproc() and signal handler */ 175 static volatile boolean_t child_killed; 176 177 static char * 178 cmd_to_str(int cmd_num) 179 { 180 assert(cmd_num >= CMD_MIN && cmd_num <= CMD_MAX); 181 return (cmdtab[cmd_num].cmd_name); 182 } 183 184 /* This is a separate function because of gettext() wrapping. */ 185 static char * 186 long_help(int cmd_num) 187 { 188 assert(cmd_num >= CMD_MIN && cmd_num <= CMD_MAX); 189 switch (cmd_num) { 190 case CMD_HELP: 191 return (gettext("Print usage message.")); 192 case CMD_BOOT: 193 return (gettext("Activates (boots) specified zone. " 194 "The -s flag can be used\n\tto boot the zone in " 195 "the single-user state.")); 196 case CMD_HALT: 197 return (gettext("Halts specified zone, bypassing " 198 "shutdown scripts and removing runtime\n\t" 199 "resources of the zone.")); 200 case CMD_READY: 201 return (gettext("Prepares a zone for running " 202 "applications but does not start any user\n\t" 203 "processes in the zone.")); 204 case CMD_REBOOT: 205 return (gettext("Restarts the zone (equivalent to a " 206 "halt / boot sequence).\n\tFails if the zone is " 207 "not active.")); 208 case CMD_LIST: 209 return (gettext("Lists the current zones, or a " 210 "specific zone if indicated. By default,\n\tall " 211 "running zones are listed, though this can be " 212 "expanded to all\n\tinstalled zones with the -i " 213 "option or all configured zones with the\n\t-c " 214 "option. When used with the general -z <zone> " 215 "option, lists only the\n\tspecified zone, but " 216 "lists it regardless of its state, and the -i " 217 "and -c\n\toptions are disallowed. The -v option " 218 "can be used to display verbose\n\tinformation: " 219 "zone name, id, current state, root directory and " 220 "options.\n\tThe -p option can be used to request " 221 "machine-parsable output. The -v\n\tand -p " 222 "options are mutually exclusive. If neither -v " 223 "nor -p is used,\n\tjust the zone name is " 224 "listed.")); 225 case CMD_VERIFY: 226 return (gettext("Check to make sure the configuration " 227 "can safely be instantiated\n\ton the machine: " 228 "physical network interfaces exist, etc.")); 229 case CMD_INSTALL: 230 return (gettext("Install the configuration on to the " 231 "system.")); 232 case CMD_UNINSTALL: 233 return (gettext("Uninstall the configuration from the " 234 "system. The -F flag can be used\n\tto force the " 235 "action.")); 236 default: 237 return (""); 238 } 239 /* NOTREACHED */ 240 return (NULL); 241 } 242 243 /* 244 * Called with explicit B_TRUE when help is explicitly requested, B_FALSE for 245 * unexpected errors. 246 */ 247 248 static int 249 usage(boolean_t explicit) 250 { 251 int i; 252 FILE *fd = explicit ? stdout : stderr; 253 254 (void) fprintf(fd, "%s:\t%s help\n", gettext("usage"), execname); 255 (void) fprintf(fd, "\t%s [-z <zone>] list\n", execname); 256 (void) fprintf(fd, "\t%s -z <zone> <%s>\n", execname, 257 gettext("subcommand")); 258 (void) fprintf(fd, "\n%s:\n\n", gettext("Subcommands")); 259 for (i = CMD_MIN; i <= CMD_MAX; i++) { 260 if (cmdtab[i].short_usage == NULL) 261 continue; 262 (void) fprintf(fd, "%s\n", cmdtab[i].short_usage); 263 if (explicit) 264 (void) fprintf(fd, "\t%s\n\n", long_help(i)); 265 } 266 if (!explicit) 267 (void) fputs("\n", fd); 268 return (Z_USAGE); 269 } 270 271 static void 272 sub_usage(char *short_usage, int cmd_num) 273 { 274 (void) fprintf(stderr, "%s:\t%s\n", gettext("usage"), short_usage); 275 (void) fprintf(stderr, "\t%s\n", long_help(cmd_num)); 276 } 277 278 /* 279 * zperror() is like perror(3c) except that this also prints the executable 280 * name at the start of the message, and takes a boolean indicating whether 281 * to call libc'c strerror() or that from libzonecfg. 282 */ 283 284 static void 285 zperror(const char *str, boolean_t zonecfg_error) 286 { 287 (void) fprintf(stderr, "%s: %s: %s\n", execname, str, 288 zonecfg_error ? zonecfg_strerror(errno) : strerror(errno)); 289 } 290 291 /* 292 * zperror2() is very similar to zperror() above, except it also prints a 293 * supplied zone name after the executable. 294 * 295 * All current consumers of this function want libzonecfg's strerror() rather 296 * than libc's; if this ever changes, this function can be made more generic 297 * like zperror() above. 298 */ 299 300 static void 301 zperror2(const char *zone, const char *str) 302 { 303 (void) fprintf(stderr, "%s: %s: %s: %s\n", execname, zone, str, 304 zonecfg_strerror(errno)); 305 } 306 307 /* PRINTFLIKE1 */ 308 static void 309 zerror(const char *fmt, ...) 310 { 311 va_list alist; 312 313 va_start(alist, fmt); 314 (void) fprintf(stderr, "%s: ", execname); 315 if (target_zone != NULL) 316 (void) fprintf(stderr, "zone '%s': ", target_zone); 317 (void) vfprintf(stderr, fmt, alist); 318 (void) fprintf(stderr, "\n"); 319 va_end(alist); 320 } 321 322 static void * 323 safe_calloc(size_t nelem, size_t elsize) 324 { 325 void *r = calloc(nelem, elsize); 326 327 if (r == NULL) { 328 zerror(gettext("failed to allocate %lu bytes: %s"), 329 (ulong_t)nelem * elsize, strerror(errno)); 330 exit(Z_ERR); 331 } 332 return (r); 333 } 334 335 static void 336 zone_print(zone_entry_t *zent, boolean_t verbose, boolean_t parsable) 337 { 338 static boolean_t firsttime = B_TRUE; 339 340 assert(!(verbose && parsable)); 341 if (firsttime && verbose) { 342 firsttime = B_FALSE; 343 (void) printf("%*s %-16s %-14s %-30s\n", ZONEID_WIDTH, "ID", 344 "NAME", "STATUS", "PATH"); 345 } 346 if (!verbose) { 347 if (!parsable) { 348 (void) printf("%s\n", zent->zname); 349 return; 350 } 351 if (zent->zid == ZONE_ID_UNDEFINED) 352 (void) printf("-"); 353 else 354 (void) printf("%lu", zent->zid); 355 (void) printf(":%s:%s:%s\n", zent->zname, zent->zstate_str, 356 zent->zroot); 357 return; 358 } 359 if (zent->zstate_str != NULL) { 360 if (zent->zid == ZONE_ID_UNDEFINED) 361 (void) printf("%*s", ZONEID_WIDTH, "-"); 362 else 363 (void) printf("%*lu", ZONEID_WIDTH, zent->zid); 364 (void) printf(" %-16s %-14s %-30s\n", zent->zname, 365 zent->zstate_str, zent->zroot); 366 } 367 } 368 369 static int 370 lookup_zone_info(const char *zone_name, zoneid_t zid, zone_entry_t *zent) 371 { 372 char root[MAXPATHLEN]; 373 int err; 374 375 (void) strlcpy(zent->zname, zone_name, sizeof (zent->zname)); 376 (void) strlcpy(zent->zroot, "???", sizeof (zent->zroot)); 377 zent->zstate_str = "???"; 378 379 zent->zid = zid; 380 381 if ((err = zone_get_zonepath(zent->zname, root, sizeof (root))) != 382 Z_OK) { 383 errno = err; 384 zperror2(zent->zname, gettext("could not get zone path")); 385 return (Z_ERR); 386 } 387 (void) strlcpy(zent->zroot, root, sizeof (zent->zroot)); 388 389 if ((err = zone_get_state(zent->zname, &zent->zstate_num)) != Z_OK) { 390 errno = err; 391 zperror2(zent->zname, gettext("could not get state")); 392 return (Z_ERR); 393 } 394 zent->zstate_str = zone_state_str(zent->zstate_num); 395 396 return (Z_OK); 397 } 398 399 /* 400 * fetch_zents() calls zone_list(2) to find out how many zones are running 401 * (which is stored in the global nzents), then calls zone_list(2) again 402 * to fetch the list of running zones (stored in the global zents). This 403 * function may be called multiple times, so if zents is already set, we 404 * return immediately to save work. 405 */ 406 407 static int 408 fetch_zents(void) 409 { 410 zoneid_t *zids = NULL; 411 uint_t nzents_saved; 412 int i, retv; 413 FILE *fp; 414 boolean_t inaltroot; 415 zone_entry_t *zentp; 416 417 if (nzents > 0) 418 return (Z_OK); 419 420 if (zone_list(NULL, &nzents) != 0) { 421 zperror(gettext("failed to get zoneid list"), B_FALSE); 422 return (Z_ERR); 423 } 424 425 again: 426 if (nzents == 0) 427 return (Z_OK); 428 429 zids = safe_calloc(nzents, sizeof (zoneid_t)); 430 nzents_saved = nzents; 431 432 if (zone_list(zids, &nzents) != 0) { 433 zperror(gettext("failed to get zone list"), B_FALSE); 434 free(zids); 435 return (Z_ERR); 436 } 437 if (nzents != nzents_saved) { 438 /* list changed, try again */ 439 free(zids); 440 goto again; 441 } 442 443 zents = safe_calloc(nzents, sizeof (zone_entry_t)); 444 445 inaltroot = zonecfg_in_alt_root(); 446 if (inaltroot) 447 fp = zonecfg_open_scratch("", B_FALSE); 448 else 449 fp = NULL; 450 zentp = zents; 451 retv = Z_OK; 452 for (i = 0; i < nzents; i++) { 453 char name[ZONENAME_MAX]; 454 char altname[ZONENAME_MAX]; 455 456 if (getzonenamebyid(zids[i], name, sizeof (name)) < 0) { 457 zperror(gettext("failed to get zone name"), B_FALSE); 458 retv = Z_ERR; 459 continue; 460 } 461 if (zonecfg_is_scratch(name)) { 462 /* Ignore scratch zones by default */ 463 if (!inaltroot) 464 continue; 465 if (fp == NULL || 466 zonecfg_reverse_scratch(fp, name, altname, 467 sizeof (altname), NULL, 0) == -1) { 468 zerror(gettext("cannot resolve scratch " 469 "zone %s"), name); 470 retv = Z_ERR; 471 continue; 472 } 473 (void) strcpy(name, altname); 474 } else { 475 /* Ignore non-scratch when in an alternate root */ 476 if (inaltroot && strcmp(name, GLOBAL_ZONENAME) != 0) 477 continue; 478 } 479 if (lookup_zone_info(name, zids[i], zentp) != Z_OK) { 480 zerror(gettext("failed to get zone data")); 481 retv = Z_ERR; 482 continue; 483 } 484 zentp++; 485 } 486 nzents = zentp - zents; 487 if (fp != NULL) 488 zonecfg_close_scratch(fp); 489 490 free(zids); 491 return (retv); 492 } 493 494 static int 495 zone_print_list(zone_state_t min_state, boolean_t verbose, boolean_t parsable) 496 { 497 int i; 498 zone_entry_t zent; 499 FILE *cookie; 500 char *name; 501 502 /* 503 * First get the list of running zones from the kernel and print them. 504 * If that is all we need, then return. 505 */ 506 if ((i = fetch_zents()) != Z_OK) { 507 /* 508 * No need for error messages; fetch_zents() has already taken 509 * care of this. 510 */ 511 return (i); 512 } 513 for (i = 0; i < nzents; i++) 514 zone_print(&zents[i], verbose, parsable); 515 if (min_state >= ZONE_STATE_RUNNING) 516 return (Z_OK); 517 /* 518 * Next, get the full list of zones from the configuration, skipping 519 * any we have already printed. 520 */ 521 cookie = setzoneent(); 522 while ((name = getzoneent(cookie)) != NULL) { 523 for (i = 0; i < nzents; i++) { 524 if (strcmp(zents[i].zname, name) == 0) 525 break; 526 } 527 if (i < nzents) { 528 free(name); 529 continue; 530 } 531 if (lookup_zone_info(name, ZONE_ID_UNDEFINED, &zent) != Z_OK) { 532 free(name); 533 continue; 534 } 535 free(name); 536 if (zent.zstate_num >= min_state) 537 zone_print(&zent, verbose, parsable); 538 } 539 endzoneent(cookie); 540 return (Z_OK); 541 } 542 543 static zone_entry_t * 544 lookup_running_zone(char *str) 545 { 546 zoneid_t zoneid; 547 char *cp; 548 int i; 549 550 if (fetch_zents() != Z_OK) 551 return (NULL); 552 553 for (i = 0; i < nzents; i++) { 554 if (strcmp(str, zents[i].zname) == 0) 555 return (&zents[i]); 556 } 557 errno = 0; 558 zoneid = strtol(str, &cp, 0); 559 if (zoneid < MIN_ZONEID || zoneid > MAX_ZONEID || 560 errno != 0 || *cp != '\0') 561 return (NULL); 562 for (i = 0; i < nzents; i++) { 563 if (zoneid == zents[i].zid) 564 return (&zents[i]); 565 } 566 return (NULL); 567 } 568 569 /* 570 * Check a bit in a mode_t: if on is B_TRUE, that bit should be on; if 571 * B_FALSE, it should be off. Return B_TRUE if the mode is bad (incorrect). 572 */ 573 static boolean_t 574 bad_mode_bit(mode_t mode, mode_t bit, boolean_t on, char *file) 575 { 576 char *str; 577 578 assert(bit == S_IRUSR || bit == S_IWUSR || bit == S_IXUSR || 579 bit == S_IRGRP || bit == S_IWGRP || bit == S_IXGRP || 580 bit == S_IROTH || bit == S_IWOTH || bit == S_IXOTH); 581 /* 582 * TRANSLATION_NOTE 583 * The strings below will be used as part of a larger message, 584 * either: 585 * (file name) must be (owner|group|world) (read|writ|execut)able 586 * or 587 * (file name) must not be (owner|group|world) (read|writ|execut)able 588 */ 589 switch (bit) { 590 case S_IRUSR: 591 str = gettext("owner readable"); 592 break; 593 case S_IWUSR: 594 str = gettext("owner writable"); 595 break; 596 case S_IXUSR: 597 str = gettext("owner executable"); 598 break; 599 case S_IRGRP: 600 str = gettext("group readable"); 601 break; 602 case S_IWGRP: 603 str = gettext("group writable"); 604 break; 605 case S_IXGRP: 606 str = gettext("group executable"); 607 break; 608 case S_IROTH: 609 str = gettext("world readable"); 610 break; 611 case S_IWOTH: 612 str = gettext("world writable"); 613 break; 614 case S_IXOTH: 615 str = gettext("world executable"); 616 break; 617 } 618 if ((mode & bit) == (on ? 0 : bit)) { 619 /* 620 * TRANSLATION_NOTE 621 * The first parameter below is a file name; the second 622 * is one of the "(owner|group|world) (read|writ|execut)able" 623 * strings from above. 624 */ 625 /* 626 * The code below could be simplified but not in a way 627 * that would easily translate to non-English locales. 628 */ 629 if (on) { 630 (void) fprintf(stderr, gettext("%s must be %s.\n"), 631 file, str); 632 } else { 633 (void) fprintf(stderr, gettext("%s must not be %s.\n"), 634 file, str); 635 } 636 return (B_TRUE); 637 } 638 return (B_FALSE); 639 } 640 641 /* 642 * We want to make sure that no zone has its zone path as a child node 643 * (in the directory sense) of any other. We do that by comparing this 644 * zone's path to the path of all other (non-global) zones. The comparison 645 * in each case is simple: add '/' to the end of the path, then do a 646 * strncmp() of the two paths, using the length of the shorter one. 647 */ 648 649 static int 650 crosscheck_zonepaths(char *path) 651 { 652 char rpath[MAXPATHLEN]; /* resolved path */ 653 char path_copy[MAXPATHLEN]; /* copy of original path */ 654 char rpath_copy[MAXPATHLEN]; /* copy of original rpath */ 655 struct zoneent *ze; 656 int res, err; 657 FILE *cookie; 658 659 cookie = setzoneent(); 660 while ((ze = getzoneent_private(cookie)) != NULL) { 661 /* Skip zones which are not installed. */ 662 if (ze->zone_state < ZONE_STATE_INSTALLED) { 663 free(ze); 664 continue; 665 } 666 /* Skip the global zone and the current target zone. */ 667 if (strcmp(ze->zone_name, GLOBAL_ZONENAME) == 0 || 668 strcmp(ze->zone_name, target_zone) == 0) { 669 free(ze); 670 continue; 671 } 672 if (strlen(ze->zone_path) == 0) { 673 /* old index file without path, fall back */ 674 if ((err = zone_get_zonepath(ze->zone_name, 675 ze->zone_path, sizeof (ze->zone_path))) != Z_OK) { 676 errno = err; 677 zperror2(ze->zone_name, 678 gettext("could not get zone path")); 679 free(ze); 680 continue; 681 } 682 } 683 (void) snprintf(path_copy, sizeof (path_copy), "%s%s", 684 zonecfg_get_root(), ze->zone_path); 685 res = resolvepath(path_copy, rpath, sizeof (rpath)); 686 if (res == -1) { 687 if (errno != ENOENT) { 688 zperror(path_copy, B_FALSE); 689 free(ze); 690 return (Z_ERR); 691 } 692 (void) printf(gettext("WARNING: zone %s is installed, " 693 "but its %s %s does not exist.\n"), ze->zone_name, 694 "zonepath", path_copy); 695 free(ze); 696 continue; 697 } 698 rpath[res] = '\0'; 699 (void) snprintf(path_copy, sizeof (path_copy), "%s/", path); 700 (void) snprintf(rpath_copy, sizeof (rpath_copy), "%s/", rpath); 701 if (strncmp(path_copy, rpath_copy, 702 min(strlen(path_copy), strlen(rpath_copy))) == 0) { 703 (void) fprintf(stderr, gettext("%s zonepath (%s) and " 704 "%s zonepath (%s) overlap.\n"), 705 target_zone, path, ze->zone_name, rpath); 706 free(ze); 707 return (Z_ERR); 708 } 709 free(ze); 710 } 711 endzoneent(cookie); 712 return (Z_OK); 713 } 714 715 static int 716 validate_zonepath(char *path, int cmd_num) 717 { 718 int res; /* result of last library/system call */ 719 boolean_t err = B_FALSE; /* have we run into an error? */ 720 struct stat stbuf; 721 struct statvfs vfsbuf; 722 char rpath[MAXPATHLEN]; /* resolved path */ 723 char ppath[MAXPATHLEN]; /* parent path */ 724 char rppath[MAXPATHLEN]; /* resolved parent path */ 725 char rootpath[MAXPATHLEN]; /* root path */ 726 zone_state_t state; 727 728 if (path[0] != '/') { 729 (void) fprintf(stderr, 730 gettext("%s is not an absolute path.\n"), path); 731 return (Z_ERR); 732 } 733 if ((res = resolvepath(path, rpath, sizeof (rpath))) == -1) { 734 if ((errno != ENOENT) || 735 (cmd_num != CMD_VERIFY && cmd_num != CMD_INSTALL)) { 736 zperror(path, B_FALSE); 737 return (Z_ERR); 738 } 739 if (cmd_num == CMD_VERIFY) { 740 (void) fprintf(stderr, gettext("WARNING: %s does not " 741 "exist, so it cannot be verified.\nWhen 'zoneadm " 742 "%s' is run, '%s' will try to create\n%s, and '%s' " 743 "will be tried again,\nbut the '%s' may fail if:\n" 744 "the parent directory of %s is group- or other-" 745 "writable\nor\n%s overlaps with any other " 746 "installed zones.\n"), path, 747 cmd_to_str(CMD_INSTALL), cmd_to_str(CMD_INSTALL), 748 path, cmd_to_str(CMD_VERIFY), 749 cmd_to_str(CMD_VERIFY), path, path); 750 return (Z_OK); 751 } 752 /* 753 * The zonepath is supposed to be mode 700 but its 754 * parent(s) 755. So use 755 on the mkdirp() then 755 * chmod() the zonepath itself to 700. 756 */ 757 if (mkdirp(path, DEFAULT_DIR_MODE) < 0) { 758 zperror(path, B_FALSE); 759 return (Z_ERR); 760 } 761 /* 762 * If the chmod() fails, report the error, but might 763 * as well continue the verify procedure. 764 */ 765 if (chmod(path, S_IRWXU) != 0) 766 zperror(path, B_FALSE); 767 /* 768 * Since the mkdir() succeeded, we should not have to 769 * worry about a subsequent ENOENT, thus this should 770 * only recurse once. 771 */ 772 return (validate_zonepath(path, CMD_INSTALL)); 773 } 774 rpath[res] = '\0'; 775 if (strcmp(path, rpath) != 0) { 776 errno = Z_RESOLVED_PATH; 777 zperror(path, B_TRUE); 778 return (Z_ERR); 779 } 780 if ((res = stat(rpath, &stbuf)) != 0) { 781 zperror(rpath, B_FALSE); 782 return (Z_ERR); 783 } 784 if (!S_ISDIR(stbuf.st_mode)) { 785 (void) fprintf(stderr, gettext("%s is not a directory.\n"), 786 rpath); 787 return (Z_ERR); 788 } 789 if ((strcmp(stbuf.st_fstype, MNTTYPE_TMPFS) == 0) || 790 (strcmp(stbuf.st_fstype, MNTTYPE_XMEMFS) == 0)) { 791 (void) printf(gettext("WARNING: %s is on a temporary " 792 "file-system.\n"), rpath); 793 } 794 if (crosscheck_zonepaths(rpath) != Z_OK) 795 return (Z_ERR); 796 /* 797 * Try to collect and report as many minor errors as possible 798 * before returning, so the user can learn everything that needs 799 * to be fixed up front. 800 */ 801 if (stbuf.st_uid != 0) { 802 (void) fprintf(stderr, gettext("%s is not owned by root.\n"), 803 rpath); 804 err = B_TRUE; 805 } 806 err |= bad_mode_bit(stbuf.st_mode, S_IRUSR, B_TRUE, rpath); 807 err |= bad_mode_bit(stbuf.st_mode, S_IWUSR, B_TRUE, rpath); 808 err |= bad_mode_bit(stbuf.st_mode, S_IXUSR, B_TRUE, rpath); 809 err |= bad_mode_bit(stbuf.st_mode, S_IRGRP, B_FALSE, rpath); 810 err |= bad_mode_bit(stbuf.st_mode, S_IWGRP, B_FALSE, rpath); 811 err |= bad_mode_bit(stbuf.st_mode, S_IXGRP, B_FALSE, rpath); 812 err |= bad_mode_bit(stbuf.st_mode, S_IROTH, B_FALSE, rpath); 813 err |= bad_mode_bit(stbuf.st_mode, S_IWOTH, B_FALSE, rpath); 814 err |= bad_mode_bit(stbuf.st_mode, S_IXOTH, B_FALSE, rpath); 815 816 (void) snprintf(ppath, sizeof (ppath), "%s/..", path); 817 if ((res = resolvepath(ppath, rppath, sizeof (rppath))) == -1) { 818 zperror(ppath, B_FALSE); 819 return (Z_ERR); 820 } 821 rppath[res] = '\0'; 822 if ((res = stat(rppath, &stbuf)) != 0) { 823 zperror(rppath, B_FALSE); 824 return (Z_ERR); 825 } 826 /* theoretically impossible */ 827 if (!S_ISDIR(stbuf.st_mode)) { 828 (void) fprintf(stderr, gettext("%s is not a directory.\n"), 829 rppath); 830 return (Z_ERR); 831 } 832 if (stbuf.st_uid != 0) { 833 (void) fprintf(stderr, gettext("%s is not owned by root.\n"), 834 rppath); 835 err = B_TRUE; 836 } 837 err |= bad_mode_bit(stbuf.st_mode, S_IRUSR, B_TRUE, rppath); 838 err |= bad_mode_bit(stbuf.st_mode, S_IWUSR, B_TRUE, rppath); 839 err |= bad_mode_bit(stbuf.st_mode, S_IXUSR, B_TRUE, rppath); 840 err |= bad_mode_bit(stbuf.st_mode, S_IWGRP, B_FALSE, rppath); 841 err |= bad_mode_bit(stbuf.st_mode, S_IWOTH, B_FALSE, rppath); 842 if (strcmp(rpath, rppath) == 0) { 843 (void) fprintf(stderr, gettext("%s is its own parent.\n"), 844 rppath); 845 err = B_TRUE; 846 } 847 848 if (statvfs(rpath, &vfsbuf) != 0) { 849 zperror(rpath, B_FALSE); 850 return (Z_ERR); 851 } 852 if (strncmp(vfsbuf.f_basetype, "nfs", 3) == 0) { 853 (void) fprintf(stderr, gettext("Zonepath %s is over NFS, " 854 "which is not currently supported.\n"), rpath); 855 return (Z_ERR); 856 } 857 858 if ((res = zone_get_state(target_zone, &state)) != Z_OK) { 859 errno = res; 860 zperror2(target_zone, gettext("could not get state")); 861 return (Z_ERR); 862 } 863 /* 864 * The existence of the root path is only bad in the configured state, 865 * as it is *supposed* to be there at the installed and later states. 866 * State/command mismatches are caught earlier in verify_details(). 867 */ 868 if (state == ZONE_STATE_CONFIGURED) { 869 if (snprintf(rootpath, sizeof (rootpath), "%s/root", rpath) >= 870 sizeof (rootpath)) { 871 (void) fprintf(stderr, 872 gettext("Zonepath %s is too long.\n"), rpath); 873 return (Z_ERR); 874 } 875 if ((res = stat(rootpath, &stbuf)) == 0) { 876 (void) fprintf(stderr, gettext("Rootpath %s exists; " 877 "remove or move aside prior to %s.\n"), rootpath, 878 cmd_to_str(CMD_INSTALL)); 879 return (Z_ERR); 880 } 881 } 882 883 return (err ? Z_ERR : Z_OK); 884 } 885 886 static void 887 release_lock_file(int lockfd) 888 { 889 (void) close(lockfd); 890 } 891 892 static int 893 grab_lock_file(const char *zone_name, int *lockfd) 894 { 895 char pathbuf[PATH_MAX]; 896 struct flock flock; 897 898 if (snprintf(pathbuf, sizeof (pathbuf), "%s%s", zonecfg_get_root(), 899 ZONES_TMPDIR) >= sizeof (pathbuf)) { 900 zerror(gettext("alternate root path is too long")); 901 return (Z_ERR); 902 } 903 if (mkdir(pathbuf, S_IRWXU) < 0 && errno != EEXIST) { 904 zerror(gettext("could not mkdir %s: %s"), pathbuf, 905 strerror(errno)); 906 return (Z_ERR); 907 } 908 (void) chmod(pathbuf, S_IRWXU); 909 910 /* 911 * One of these lock files is created for each zone (when needed). 912 * The lock files are not cleaned up (except on system reboot), 913 * but since there is only one per zone, there is no resource 914 * starvation issue. 915 */ 916 if (snprintf(pathbuf, sizeof (pathbuf), "%s%s/%s.zoneadm.lock", 917 zonecfg_get_root(), ZONES_TMPDIR, zone_name) >= sizeof (pathbuf)) { 918 zerror(gettext("alternate root path is too long")); 919 return (Z_ERR); 920 } 921 if ((*lockfd = open(pathbuf, O_RDWR|O_CREAT, S_IRUSR|S_IWUSR)) < 0) { 922 zerror(gettext("could not open %s: %s"), pathbuf, 923 strerror(errno)); 924 return (Z_ERR); 925 } 926 /* 927 * Lock the file to synchronize with other zoneadmds 928 */ 929 flock.l_type = F_WRLCK; 930 flock.l_whence = SEEK_SET; 931 flock.l_start = (off_t)0; 932 flock.l_len = (off_t)0; 933 if (fcntl(*lockfd, F_SETLKW, &flock) < 0) { 934 zerror(gettext("unable to lock %s: %s"), pathbuf, 935 strerror(errno)); 936 release_lock_file(*lockfd); 937 return (Z_ERR); 938 } 939 return (Z_OK); 940 } 941 942 static boolean_t 943 get_doorname(const char *zone_name, char *buffer) 944 { 945 return (snprintf(buffer, PATH_MAX, "%s" ZONE_DOOR_PATH, 946 zonecfg_get_root(), zone_name) < PATH_MAX); 947 } 948 949 /* 950 * system daemons are not audited. For the global zone, this occurs 951 * "naturally" since init is started with the default audit 952 * characteristics. Since zoneadmd is a system daemon and it starts 953 * init for a zone, it is necessary to clear out the audit 954 * characteristics inherited from whomever started zoneadmd. This is 955 * indicated by the audit id, which is set from the ruid parameter of 956 * adt_set_user(), below. 957 */ 958 959 static void 960 prepare_audit_context() 961 { 962 adt_session_data_t *ah; 963 char *failure = gettext("audit failure: %s"); 964 965 if (adt_start_session(&ah, NULL, 0)) { 966 zerror(failure, strerror(errno)); 967 return; 968 } 969 if (adt_set_user(ah, ADT_NO_AUDIT, ADT_NO_AUDIT, 970 ADT_NO_AUDIT, ADT_NO_AUDIT, NULL, ADT_NEW)) { 971 zerror(failure, strerror(errno)); 972 (void) adt_end_session(ah); 973 return; 974 } 975 if (adt_set_proc(ah)) 976 zerror(failure, strerror(errno)); 977 978 (void) adt_end_session(ah); 979 } 980 981 static int 982 start_zoneadmd(const char *zone_name) 983 { 984 char doorpath[PATH_MAX]; 985 pid_t child_pid; 986 int error = Z_ERR; 987 int doorfd, lockfd; 988 struct door_info info; 989 990 if (!get_doorname(zone_name, doorpath)) 991 return (Z_ERR); 992 993 if (grab_lock_file(zone_name, &lockfd) != Z_OK) 994 return (Z_ERR); 995 996 /* 997 * Now that we have the lock, re-confirm that the daemon is 998 * *not* up and working fine. If it is still down, we have a green 999 * light to start it. 1000 */ 1001 if ((doorfd = open(doorpath, O_RDONLY)) < 0) { 1002 if (errno != ENOENT) { 1003 zperror(doorpath, B_FALSE); 1004 goto out; 1005 } 1006 } else { 1007 if (door_info(doorfd, &info) == 0 && 1008 ((info.di_attributes & DOOR_REVOKED) == 0)) { 1009 error = Z_OK; 1010 (void) close(doorfd); 1011 goto out; 1012 } 1013 (void) close(doorfd); 1014 } 1015 1016 if ((child_pid = fork()) == -1) { 1017 zperror(gettext("could not fork"), B_FALSE); 1018 goto out; 1019 } else if (child_pid == 0) { 1020 const char *argv[6], **ap; 1021 1022 /* child process */ 1023 prepare_audit_context(); 1024 1025 ap = argv; 1026 *ap++ = "zoneadmd"; 1027 *ap++ = "-z"; 1028 *ap++ = zone_name; 1029 if (zonecfg_in_alt_root()) { 1030 *ap++ = "-R"; 1031 *ap++ = zonecfg_get_root(); 1032 } 1033 *ap = NULL; 1034 1035 (void) execv("/usr/lib/zones/zoneadmd", (char * const *)argv); 1036 zperror(gettext("could not exec zoneadmd"), B_FALSE); 1037 _exit(Z_ERR); 1038 } else { 1039 /* parent process */ 1040 pid_t retval; 1041 int pstatus = 0; 1042 1043 do { 1044 retval = waitpid(child_pid, &pstatus, 0); 1045 } while (retval != child_pid); 1046 if (WIFSIGNALED(pstatus) || (WIFEXITED(pstatus) && 1047 WEXITSTATUS(pstatus) != 0)) { 1048 zerror(gettext("could not start %s"), "zoneadmd"); 1049 goto out; 1050 } 1051 } 1052 error = Z_OK; 1053 out: 1054 release_lock_file(lockfd); 1055 return (error); 1056 } 1057 1058 static int 1059 ping_zoneadmd(const char *zone_name) 1060 { 1061 char doorpath[PATH_MAX]; 1062 int doorfd; 1063 struct door_info info; 1064 1065 if (!get_doorname(zone_name, doorpath)) 1066 return (Z_ERR); 1067 1068 if ((doorfd = open(doorpath, O_RDONLY)) < 0) { 1069 return (Z_ERR); 1070 } 1071 if (door_info(doorfd, &info) == 0 && 1072 ((info.di_attributes & DOOR_REVOKED) == 0)) { 1073 (void) close(doorfd); 1074 return (Z_OK); 1075 } 1076 (void) close(doorfd); 1077 return (Z_ERR); 1078 } 1079 1080 static int 1081 call_zoneadmd(const char *zone_name, zone_cmd_arg_t *arg) 1082 { 1083 char doorpath[PATH_MAX]; 1084 int doorfd, result; 1085 door_arg_t darg; 1086 1087 zoneid_t zoneid; 1088 uint64_t uniqid = 0; 1089 1090 zone_cmd_rval_t *rvalp; 1091 size_t rlen; 1092 char *cp, *errbuf; 1093 1094 rlen = getpagesize(); 1095 if ((rvalp = malloc(rlen)) == NULL) { 1096 zerror(gettext("failed to allocate %lu bytes: %s"), rlen, 1097 strerror(errno)); 1098 return (-1); 1099 } 1100 1101 if ((zoneid = getzoneidbyname(zone_name)) != ZONE_ID_UNDEFINED) { 1102 (void) zone_getattr(zoneid, ZONE_ATTR_UNIQID, &uniqid, 1103 sizeof (uniqid)); 1104 } 1105 arg->uniqid = uniqid; 1106 (void) strlcpy(arg->locale, locale, sizeof (arg->locale)); 1107 if (!get_doorname(zone_name, doorpath)) { 1108 zerror(gettext("alternate root path is too long")); 1109 free(rvalp); 1110 return (-1); 1111 } 1112 1113 /* 1114 * Loop trying to start zoneadmd; if something goes seriously 1115 * wrong we break out and fail. 1116 */ 1117 for (;;) { 1118 if (start_zoneadmd(zone_name) != Z_OK) 1119 break; 1120 1121 if ((doorfd = open(doorpath, O_RDONLY)) < 0) { 1122 zperror(gettext("failed to open zone door"), B_FALSE); 1123 break; 1124 } 1125 1126 darg.data_ptr = (char *)arg; 1127 darg.data_size = sizeof (*arg); 1128 darg.desc_ptr = NULL; 1129 darg.desc_num = 0; 1130 darg.rbuf = (char *)rvalp; 1131 darg.rsize = rlen; 1132 if (door_call(doorfd, &darg) != 0) { 1133 (void) close(doorfd); 1134 /* 1135 * We'll get EBADF if the door has been revoked. 1136 */ 1137 if (errno != EBADF) { 1138 zperror(gettext("door_call failed"), B_FALSE); 1139 break; 1140 } 1141 continue; /* take another lap */ 1142 } 1143 (void) close(doorfd); 1144 1145 if (darg.data_size == 0) { 1146 /* Door server is going away; kick it again. */ 1147 continue; 1148 } 1149 1150 errbuf = rvalp->errbuf; 1151 while (*errbuf != '\0') { 1152 /* 1153 * Remove any newlines since zerror() 1154 * will append one automatically. 1155 */ 1156 cp = strchr(errbuf, '\n'); 1157 if (cp != NULL) 1158 *cp = '\0'; 1159 zerror("%s", errbuf); 1160 if (cp == NULL) 1161 break; 1162 errbuf = cp + 1; 1163 } 1164 result = rvalp->rval == 0 ? 0 : -1; 1165 free(rvalp); 1166 return (result); 1167 } 1168 1169 free(rvalp); 1170 return (-1); 1171 } 1172 1173 static int 1174 ready_func(int argc, char *argv[]) 1175 { 1176 zone_cmd_arg_t zarg; 1177 int arg; 1178 1179 if (zonecfg_in_alt_root()) { 1180 zerror(gettext("cannot ready zone in alternate root")); 1181 return (Z_ERR); 1182 } 1183 1184 optind = 0; 1185 if ((arg = getopt(argc, argv, "?")) != EOF) { 1186 switch (arg) { 1187 case '?': 1188 sub_usage(SHELP_READY, CMD_READY); 1189 return (optopt == '?' ? Z_OK : Z_USAGE); 1190 default: 1191 sub_usage(SHELP_READY, CMD_READY); 1192 return (Z_USAGE); 1193 } 1194 } 1195 if (argc > optind) { 1196 sub_usage(SHELP_READY, CMD_READY); 1197 return (Z_USAGE); 1198 } 1199 if (sanity_check(target_zone, CMD_READY, B_FALSE, B_FALSE) != Z_OK) 1200 return (Z_ERR); 1201 if (verify_details(CMD_READY) != Z_OK) 1202 return (Z_ERR); 1203 1204 zarg.cmd = Z_READY; 1205 if (call_zoneadmd(target_zone, &zarg) != 0) { 1206 zerror(gettext("call to %s failed"), "zoneadmd"); 1207 return (Z_ERR); 1208 } 1209 return (Z_OK); 1210 } 1211 1212 static int 1213 boot_func(int argc, char *argv[]) 1214 { 1215 zone_cmd_arg_t zarg; 1216 int arg; 1217 1218 if (zonecfg_in_alt_root()) { 1219 zerror(gettext("cannot boot zone in alternate root")); 1220 return (Z_ERR); 1221 } 1222 1223 zarg.bootbuf[0] = '\0'; 1224 1225 /* 1226 * At the current time, the only supported subargument to the 1227 * "boot" subcommand is "-s" which specifies a single-user boot. 1228 * In the future, other boot arguments should be supported 1229 * including "-m" for specifying alternate smf(5) milestones. 1230 */ 1231 optind = 0; 1232 if ((arg = getopt(argc, argv, "?s")) != EOF) { 1233 switch (arg) { 1234 case '?': 1235 sub_usage(SHELP_BOOT, CMD_BOOT); 1236 return (optopt == '?' ? Z_OK : Z_USAGE); 1237 case 's': 1238 (void) strlcpy(zarg.bootbuf, "-s", 1239 sizeof (zarg.bootbuf)); 1240 break; 1241 default: 1242 sub_usage(SHELP_BOOT, CMD_BOOT); 1243 return (Z_USAGE); 1244 } 1245 } 1246 if (argc > optind) { 1247 sub_usage(SHELP_BOOT, CMD_BOOT); 1248 return (Z_USAGE); 1249 } 1250 if (sanity_check(target_zone, CMD_BOOT, B_FALSE, B_FALSE) != Z_OK) 1251 return (Z_ERR); 1252 if (verify_details(CMD_BOOT) != Z_OK) 1253 return (Z_ERR); 1254 zarg.cmd = Z_BOOT; 1255 if (call_zoneadmd(target_zone, &zarg) != 0) { 1256 zerror(gettext("call to %s failed"), "zoneadmd"); 1257 return (Z_ERR); 1258 } 1259 return (Z_OK); 1260 } 1261 1262 static void 1263 fake_up_local_zone(zoneid_t zid, zone_entry_t *zeptr) 1264 { 1265 ssize_t result; 1266 1267 zeptr->zid = zid; 1268 /* 1269 * Since we're looking up our own (non-global) zone name, 1270 * we can be assured that it will succeed. 1271 */ 1272 result = getzonenamebyid(zid, zeptr->zname, sizeof (zeptr->zname)); 1273 assert(result >= 0); 1274 (void) strlcpy(zeptr->zroot, "/", sizeof (zeptr->zroot)); 1275 zeptr->zstate_str = "running"; 1276 } 1277 1278 static int 1279 list_func(int argc, char *argv[]) 1280 { 1281 zone_entry_t *zentp, zent; 1282 int arg, retv; 1283 boolean_t output = B_FALSE, verbose = B_FALSE, parsable = B_FALSE; 1284 zone_state_t min_state = ZONE_STATE_RUNNING; 1285 zoneid_t zone_id = getzoneid(); 1286 1287 if (target_zone == NULL) { 1288 /* all zones: default view to running but allow override */ 1289 optind = 0; 1290 while ((arg = getopt(argc, argv, "?cipv")) != EOF) { 1291 switch (arg) { 1292 case '?': 1293 sub_usage(SHELP_LIST, CMD_LIST); 1294 return (optopt == '?' ? Z_OK : Z_USAGE); 1295 case 'c': 1296 min_state = ZONE_STATE_CONFIGURED; 1297 break; 1298 case 'i': 1299 min_state = ZONE_STATE_INSTALLED; 1300 break; 1301 case 'p': 1302 parsable = B_TRUE; 1303 break; 1304 case 'v': 1305 verbose = B_TRUE; 1306 break; 1307 default: 1308 sub_usage(SHELP_LIST, CMD_LIST); 1309 return (Z_USAGE); 1310 } 1311 } 1312 if (parsable && verbose) { 1313 zerror(gettext("%s -p and -v are mutually exclusive."), 1314 cmd_to_str(CMD_LIST)); 1315 return (Z_ERR); 1316 } 1317 if (zone_id == GLOBAL_ZONEID) { 1318 retv = zone_print_list(min_state, verbose, parsable); 1319 } else { 1320 retv = Z_OK; 1321 fake_up_local_zone(zone_id, &zent); 1322 zone_print(&zent, verbose, parsable); 1323 } 1324 return (retv); 1325 } 1326 1327 /* 1328 * Specific target zone: disallow -i/-c suboptions. 1329 */ 1330 optind = 0; 1331 while ((arg = getopt(argc, argv, "?pv")) != EOF) { 1332 switch (arg) { 1333 case '?': 1334 sub_usage(SHELP_LIST, CMD_LIST); 1335 return (optopt == '?' ? Z_OK : Z_USAGE); 1336 case 'p': 1337 parsable = B_TRUE; 1338 break; 1339 case 'v': 1340 verbose = B_TRUE; 1341 break; 1342 default: 1343 sub_usage(SHELP_LIST, CMD_LIST); 1344 return (Z_USAGE); 1345 } 1346 } 1347 if (parsable && verbose) { 1348 zerror(gettext("%s -p and -v are mutually exclusive."), 1349 cmd_to_str(CMD_LIST)); 1350 return (Z_ERR); 1351 } 1352 if (argc > optind) { 1353 sub_usage(SHELP_LIST, CMD_LIST); 1354 return (Z_USAGE); 1355 } 1356 if (zone_id != GLOBAL_ZONEID) { 1357 fake_up_local_zone(zone_id, &zent); 1358 /* 1359 * main() will issue a Z_NO_ZONE error if it cannot get an 1360 * id for target_zone, which in a non-global zone should 1361 * happen for any zone name except `zonename`. Thus we 1362 * assert() that here but don't otherwise check. 1363 */ 1364 assert(strcmp(zent.zname, target_zone) == 0); 1365 zone_print(&zent, verbose, parsable); 1366 output = B_TRUE; 1367 } else if ((zentp = lookup_running_zone(target_zone)) != NULL) { 1368 zone_print(zentp, verbose, parsable); 1369 output = B_TRUE; 1370 } else if (lookup_zone_info(target_zone, ZONE_ID_UNDEFINED, 1371 &zent) == Z_OK) { 1372 zone_print(&zent, verbose, parsable); 1373 output = B_TRUE; 1374 } 1375 return (output ? Z_OK : Z_ERR); 1376 } 1377 1378 static void 1379 sigterm(int sig) 1380 { 1381 /* 1382 * Ignore SIG{INT,TERM}, so we don't end up in an infinite loop, 1383 * then propagate the signal to our process group. 1384 */ 1385 (void) sigset(SIGINT, SIG_IGN); 1386 (void) sigset(SIGTERM, SIG_IGN); 1387 (void) kill(0, sig); 1388 child_killed = B_TRUE; 1389 } 1390 1391 static int 1392 do_subproc(char *cmdbuf) 1393 { 1394 char inbuf[1024]; /* arbitrary large amount */ 1395 FILE *file; 1396 1397 child_killed = B_FALSE; 1398 /* 1399 * We use popen(3c) to launch child processes for [un]install; 1400 * this library call does not return a PID, so we have to kill 1401 * the whole process group. To avoid killing our parent, we 1402 * become a process group leader here. But doing so can wreak 1403 * havoc with reading from stdin when launched by a non-job-control 1404 * shell, so we close stdin and reopen it as /dev/null first. 1405 */ 1406 (void) close(STDIN_FILENO); 1407 (void) open("/dev/null", O_RDONLY); 1408 (void) setpgid(0, 0); 1409 (void) sigset(SIGINT, sigterm); 1410 (void) sigset(SIGTERM, sigterm); 1411 file = popen(cmdbuf, "r"); 1412 for (;;) { 1413 if (child_killed || fgets(inbuf, sizeof (inbuf), file) == NULL) 1414 break; 1415 (void) fputs(inbuf, stdout); 1416 } 1417 (void) sigset(SIGINT, SIG_DFL); 1418 (void) sigset(SIGTERM, SIG_DFL); 1419 return (pclose(file)); 1420 } 1421 1422 static int 1423 subproc_status(const char *cmd, int status) 1424 { 1425 if (WIFEXITED(status)) { 1426 int exit_code = WEXITSTATUS(status); 1427 1428 if (exit_code == 0) 1429 return (Z_OK); 1430 zerror(gettext("'%s' failed with exit code %d."), cmd, 1431 exit_code); 1432 } else if (WIFSIGNALED(status)) { 1433 int signal = WTERMSIG(status); 1434 char sigstr[SIG2STR_MAX]; 1435 1436 if (sig2str(signal, sigstr) == 0) { 1437 zerror(gettext("'%s' terminated by signal SIG%s."), cmd, 1438 sigstr); 1439 } else { 1440 zerror(gettext("'%s' terminated by an unknown signal."), 1441 cmd); 1442 } 1443 } else { 1444 zerror(gettext("'%s' failed for unknown reasons."), cmd); 1445 } 1446 return (Z_ERR); 1447 } 1448 1449 /* 1450 * Various sanity checks; make sure: 1451 * 1. We're in the global zone. 1452 * 2. The calling user has sufficient privilege. 1453 * 3. The target zone is neither the global zone nor anything starting with 1454 * "SUNW". 1455 * 4a. If we're looking for a 'not running' (i.e., configured or installed) 1456 * zone, the name service knows about it. 1457 * 4b. For some operations which expect a zone not to be running, that it is 1458 * not already running (or ready). 1459 */ 1460 static int 1461 sanity_check(char *zone, int cmd_num, boolean_t running, 1462 boolean_t unsafe_when_running) 1463 { 1464 zone_entry_t *zent; 1465 priv_set_t *privset; 1466 zone_state_t state; 1467 char kernzone[ZONENAME_MAX]; 1468 FILE *fp; 1469 1470 if (getzoneid() != GLOBAL_ZONEID) { 1471 zerror(gettext("must be in the global zone to %s a zone."), 1472 cmd_to_str(cmd_num)); 1473 return (Z_ERR); 1474 } 1475 1476 if ((privset = priv_allocset()) == NULL) { 1477 zerror(gettext("%s failed"), "priv_allocset"); 1478 return (Z_ERR); 1479 } 1480 1481 if (getppriv(PRIV_EFFECTIVE, privset) != 0) { 1482 zerror(gettext("%s failed"), "getppriv"); 1483 priv_freeset(privset); 1484 return (Z_ERR); 1485 } 1486 1487 if (priv_isfullset(privset) == B_FALSE) { 1488 zerror(gettext("only a privileged user may %s a zone."), 1489 cmd_to_str(cmd_num)); 1490 priv_freeset(privset); 1491 return (Z_ERR); 1492 } 1493 priv_freeset(privset); 1494 1495 if (zone == NULL) { 1496 zerror(gettext("no zone specified")); 1497 return (Z_ERR); 1498 } 1499 1500 if (strcmp(zone, GLOBAL_ZONENAME) == 0) { 1501 zerror(gettext("%s operation is invalid for the global zone."), 1502 cmd_to_str(cmd_num)); 1503 return (Z_ERR); 1504 } 1505 1506 if (strncmp(zone, "SUNW", 4) == 0) { 1507 zerror(gettext("%s operation is invalid for zones starting " 1508 "with SUNW."), cmd_to_str(cmd_num)); 1509 return (Z_ERR); 1510 } 1511 1512 if (!zonecfg_in_alt_root()) { 1513 zent = lookup_running_zone(zone); 1514 } else if ((fp = zonecfg_open_scratch("", B_FALSE)) == NULL) { 1515 zent = NULL; 1516 } else { 1517 if (zonecfg_find_scratch(fp, zone, zonecfg_get_root(), 1518 kernzone, sizeof (kernzone)) == 0) 1519 zent = lookup_running_zone(kernzone); 1520 else 1521 zent = NULL; 1522 zonecfg_close_scratch(fp); 1523 } 1524 1525 /* 1526 * Look up from the kernel for 'running' zones. 1527 */ 1528 if (running) { 1529 if (zent == NULL) { 1530 zerror(gettext("not running")); 1531 return (Z_ERR); 1532 } 1533 } else { 1534 int err; 1535 1536 if (unsafe_when_running && zent != NULL) { 1537 /* check whether the zone is ready or running */ 1538 if ((err = zone_get_state(zent->zname, 1539 &zent->zstate_num)) != Z_OK) { 1540 errno = err; 1541 zperror2(zent->zname, 1542 gettext("could not get state")); 1543 /* can't tell, so hedge */ 1544 zent->zstate_str = "ready/running"; 1545 } else { 1546 zent->zstate_str = 1547 zone_state_str(zent->zstate_num); 1548 } 1549 zerror(gettext("%s operation is invalid for %s zones."), 1550 cmd_to_str(cmd_num), zent->zstate_str); 1551 return (Z_ERR); 1552 } 1553 if ((err = zone_get_state(zone, &state)) != Z_OK) { 1554 errno = err; 1555 zperror2(zone, gettext("could not get state")); 1556 return (Z_ERR); 1557 } 1558 switch (cmd_num) { 1559 case CMD_UNINSTALL: 1560 if (state == ZONE_STATE_CONFIGURED) { 1561 zerror(gettext("is already in state '%s'."), 1562 zone_state_str(ZONE_STATE_CONFIGURED)); 1563 return (Z_ERR); 1564 } 1565 break; 1566 case CMD_INSTALL: 1567 if (state == ZONE_STATE_INSTALLED) { 1568 zerror(gettext("is already %s."), 1569 zone_state_str(ZONE_STATE_INSTALLED)); 1570 return (Z_ERR); 1571 } else if (state == ZONE_STATE_INCOMPLETE) { 1572 zerror(gettext("zone is %s; %s required."), 1573 zone_state_str(ZONE_STATE_INCOMPLETE), 1574 cmd_to_str(CMD_UNINSTALL)); 1575 return (Z_ERR); 1576 } 1577 break; 1578 case CMD_READY: 1579 case CMD_BOOT: 1580 case CMD_MOUNT: 1581 if (state < ZONE_STATE_INSTALLED) { 1582 zerror(gettext("must be %s before %s."), 1583 zone_state_str(ZONE_STATE_INSTALLED), 1584 cmd_to_str(cmd_num)); 1585 return (Z_ERR); 1586 } 1587 break; 1588 case CMD_VERIFY: 1589 if (state == ZONE_STATE_INCOMPLETE) { 1590 zerror(gettext("zone is %s; %s required."), 1591 zone_state_str(ZONE_STATE_INCOMPLETE), 1592 cmd_to_str(CMD_UNINSTALL)); 1593 return (Z_ERR); 1594 } 1595 break; 1596 case CMD_UNMOUNT: 1597 if (state != ZONE_STATE_MOUNTED) { 1598 zerror(gettext("must be %s before %s."), 1599 zone_state_str(ZONE_STATE_MOUNTED), 1600 cmd_to_str(cmd_num)); 1601 return (Z_ERR); 1602 } 1603 break; 1604 } 1605 } 1606 return (Z_OK); 1607 } 1608 1609 static int 1610 halt_func(int argc, char *argv[]) 1611 { 1612 zone_cmd_arg_t zarg; 1613 int arg; 1614 1615 if (zonecfg_in_alt_root()) { 1616 zerror(gettext("cannot halt zone in alternate root")); 1617 return (Z_ERR); 1618 } 1619 1620 optind = 0; 1621 if ((arg = getopt(argc, argv, "?")) != EOF) { 1622 switch (arg) { 1623 case '?': 1624 sub_usage(SHELP_HALT, CMD_HALT); 1625 return (optopt == '?' ? Z_OK : Z_USAGE); 1626 default: 1627 sub_usage(SHELP_HALT, CMD_HALT); 1628 return (Z_USAGE); 1629 } 1630 } 1631 if (argc > optind) { 1632 sub_usage(SHELP_HALT, CMD_HALT); 1633 return (Z_USAGE); 1634 } 1635 /* 1636 * zoneadmd should be the one to decide whether or not to proceed, 1637 * so even though it seems that the fourth parameter below should 1638 * perhaps be B_TRUE, it really shouldn't be. 1639 */ 1640 if (sanity_check(target_zone, CMD_HALT, B_FALSE, B_FALSE) != Z_OK) 1641 return (Z_ERR); 1642 1643 zarg.cmd = Z_HALT; 1644 return ((call_zoneadmd(target_zone, &zarg) == 0) ? Z_OK : Z_ERR); 1645 } 1646 1647 static int 1648 reboot_func(int argc, char *argv[]) 1649 { 1650 zone_cmd_arg_t zarg; 1651 int arg; 1652 1653 if (zonecfg_in_alt_root()) { 1654 zerror(gettext("cannot reboot zone in alternate root")); 1655 return (Z_ERR); 1656 } 1657 1658 optind = 0; 1659 if ((arg = getopt(argc, argv, "?")) != EOF) { 1660 switch (arg) { 1661 case '?': 1662 sub_usage(SHELP_REBOOT, CMD_REBOOT); 1663 return (optopt == '?' ? Z_OK : Z_USAGE); 1664 default: 1665 sub_usage(SHELP_REBOOT, CMD_REBOOT); 1666 return (Z_USAGE); 1667 } 1668 } 1669 if (argc > 0) { 1670 sub_usage(SHELP_REBOOT, CMD_REBOOT); 1671 return (Z_USAGE); 1672 } 1673 /* 1674 * zoneadmd should be the one to decide whether or not to proceed, 1675 * so even though it seems that the fourth parameter below should 1676 * perhaps be B_TRUE, it really shouldn't be. 1677 */ 1678 if (sanity_check(target_zone, CMD_REBOOT, B_TRUE, B_FALSE) != Z_OK) 1679 return (Z_ERR); 1680 1681 zarg.cmd = Z_REBOOT; 1682 return ((call_zoneadmd(target_zone, &zarg) == 0) ? Z_OK : Z_ERR); 1683 } 1684 1685 static int 1686 verify_rctls(zone_dochandle_t handle) 1687 { 1688 struct zone_rctltab rctltab; 1689 size_t rbs = rctlblk_size(); 1690 rctlblk_t *rctlblk; 1691 int error = Z_INVAL; 1692 1693 if ((rctlblk = malloc(rbs)) == NULL) { 1694 zerror(gettext("failed to allocate %lu bytes: %s"), rbs, 1695 strerror(errno)); 1696 return (Z_NOMEM); 1697 } 1698 1699 if (zonecfg_setrctlent(handle) != Z_OK) { 1700 zerror(gettext("zonecfg_setrctlent failed")); 1701 free(rctlblk); 1702 return (error); 1703 } 1704 1705 rctltab.zone_rctl_valptr = NULL; 1706 while (zonecfg_getrctlent(handle, &rctltab) == Z_OK) { 1707 struct zone_rctlvaltab *rctlval; 1708 const char *name = rctltab.zone_rctl_name; 1709 1710 if (!zonecfg_is_rctl(name)) { 1711 zerror(gettext("WARNING: Ignoring unrecognized rctl " 1712 "'%s'."), name); 1713 zonecfg_free_rctl_value_list(rctltab.zone_rctl_valptr); 1714 rctltab.zone_rctl_valptr = NULL; 1715 continue; 1716 } 1717 1718 for (rctlval = rctltab.zone_rctl_valptr; rctlval != NULL; 1719 rctlval = rctlval->zone_rctlval_next) { 1720 if (zonecfg_construct_rctlblk(rctlval, rctlblk) 1721 != Z_OK) { 1722 zerror(gettext("invalid rctl value: " 1723 "(priv=%s,limit=%s,action%s)"), 1724 rctlval->zone_rctlval_priv, 1725 rctlval->zone_rctlval_limit, 1726 rctlval->zone_rctlval_action); 1727 goto out; 1728 } 1729 if (!zonecfg_valid_rctl(name, rctlblk)) { 1730 zerror(gettext("(priv=%s,limit=%s,action=%s) " 1731 "is not a valid value for rctl '%s'"), 1732 rctlval->zone_rctlval_priv, 1733 rctlval->zone_rctlval_limit, 1734 rctlval->zone_rctlval_action, 1735 name); 1736 goto out; 1737 } 1738 } 1739 zonecfg_free_rctl_value_list(rctltab.zone_rctl_valptr); 1740 } 1741 rctltab.zone_rctl_valptr = NULL; 1742 error = Z_OK; 1743 out: 1744 zonecfg_free_rctl_value_list(rctltab.zone_rctl_valptr); 1745 (void) zonecfg_endrctlent(handle); 1746 free(rctlblk); 1747 return (error); 1748 } 1749 1750 static int 1751 verify_pool(zone_dochandle_t handle) 1752 { 1753 char poolname[MAXPATHLEN]; 1754 pool_conf_t *poolconf; 1755 pool_t *pool; 1756 int status; 1757 int error; 1758 1759 /* 1760 * This ends up being very similar to the check done in zoneadmd. 1761 */ 1762 error = zonecfg_get_pool(handle, poolname, sizeof (poolname)); 1763 if (error == Z_NO_ENTRY || (error == Z_OK && strlen(poolname) == 0)) { 1764 /* 1765 * No pool specified. 1766 */ 1767 return (0); 1768 } 1769 if (error != Z_OK) { 1770 zperror(gettext("Unable to retrieve pool name from " 1771 "configuration"), B_TRUE); 1772 return (error); 1773 } 1774 /* 1775 * Don't do anything if pools aren't enabled. 1776 */ 1777 if (pool_get_status(&status) != PO_SUCCESS || status != POOL_ENABLED) { 1778 zerror(gettext("WARNING: pools facility not active; " 1779 "zone will not be bound to pool '%s'."), poolname); 1780 return (Z_OK); 1781 } 1782 /* 1783 * Try to provide a sane error message if the requested pool doesn't 1784 * exist. It isn't clear that pools-related failures should 1785 * necessarily translate to a failure to verify the zone configuration, 1786 * hence they are not considered errors. 1787 */ 1788 if ((poolconf = pool_conf_alloc()) == NULL) { 1789 zerror(gettext("WARNING: pool_conf_alloc failed; " 1790 "using default pool")); 1791 return (Z_OK); 1792 } 1793 if (pool_conf_open(poolconf, pool_dynamic_location(), PO_RDONLY) != 1794 PO_SUCCESS) { 1795 zerror(gettext("WARNING: pool_conf_open failed; " 1796 "using default pool")); 1797 pool_conf_free(poolconf); 1798 return (Z_OK); 1799 } 1800 pool = pool_get_pool(poolconf, poolname); 1801 (void) pool_conf_close(poolconf); 1802 pool_conf_free(poolconf); 1803 if (pool == NULL) { 1804 zerror(gettext("WARNING: pool '%s' not found. " 1805 "using default pool"), poolname); 1806 } 1807 1808 return (Z_OK); 1809 } 1810 1811 static int 1812 verify_filesystems(zone_dochandle_t handle) 1813 { 1814 int return_code = Z_OK; 1815 struct zone_fstab fstab; 1816 char cmdbuf[MAXPATHLEN]; 1817 struct stat st; 1818 1819 /* 1820 * No need to verify inherit-pkg-dir fs types, as their type is 1821 * implicitly lofs, which is known. Therefore, the types are only 1822 * verified for regular filesystems below. 1823 * 1824 * Since the actual mount point is not known until the dependent mounts 1825 * are performed, we don't attempt any path validation here: that will 1826 * happen later when zoneadmd actually does the mounts. 1827 */ 1828 if (zonecfg_setfsent(handle) != Z_OK) { 1829 (void) fprintf(stderr, gettext("cannot verify file-systems: " 1830 "unable to enumerate mounts\n")); 1831 return (Z_ERR); 1832 } 1833 while (zonecfg_getfsent(handle, &fstab) == Z_OK) { 1834 if (!zonecfg_valid_fs_type(fstab.zone_fs_type)) { 1835 (void) fprintf(stderr, gettext("cannot verify fs %s: " 1836 "type %s is not allowed.\n"), fstab.zone_fs_dir, 1837 fstab.zone_fs_type); 1838 return_code = Z_ERR; 1839 goto next_fs; 1840 } 1841 /* 1842 * Verify /usr/lib/fs/<fstype>/mount exists. 1843 */ 1844 if (snprintf(cmdbuf, sizeof (cmdbuf), "/usr/lib/fs/%s/mount", 1845 fstab.zone_fs_type) > sizeof (cmdbuf)) { 1846 (void) fprintf(stderr, gettext("cannot verify fs %s: " 1847 "type %s is too long.\n"), fstab.zone_fs_dir, 1848 fstab.zone_fs_type); 1849 return_code = Z_ERR; 1850 goto next_fs; 1851 } 1852 if (stat(cmdbuf, &st) != 0) { 1853 (void) fprintf(stderr, gettext("cannot verify fs %s: " 1854 "can't access %s: %s\n"), fstab.zone_fs_dir, 1855 cmdbuf, strerror(errno)); 1856 return_code = Z_ERR; 1857 goto next_fs; 1858 } 1859 if (!S_ISREG(st.st_mode)) { 1860 (void) fprintf(stderr, gettext("cannot verify fs %s: " 1861 "%s is not a regular file\n"), fstab.zone_fs_dir, 1862 cmdbuf); 1863 return_code = Z_ERR; 1864 goto next_fs; 1865 } 1866 /* 1867 * Verify /usr/lib/fs/<fstype>/fsck exists iff zone_fs_raw is 1868 * set. 1869 */ 1870 if (snprintf(cmdbuf, sizeof (cmdbuf), "/usr/lib/fs/%s/fsck", 1871 fstab.zone_fs_type) > sizeof (cmdbuf)) { 1872 (void) fprintf(stderr, gettext("cannot verify fs %s: " 1873 "type %s is too long.\n"), fstab.zone_fs_dir, 1874 fstab.zone_fs_type); 1875 return_code = Z_ERR; 1876 goto next_fs; 1877 } 1878 if (fstab.zone_fs_raw[0] == '\0' && stat(cmdbuf, &st) == 0) { 1879 (void) fprintf(stderr, gettext("cannot verify fs %s: " 1880 "must specify 'raw' device for %s file-systems\n"), 1881 fstab.zone_fs_dir, fstab.zone_fs_type); 1882 return_code = Z_ERR; 1883 goto next_fs; 1884 } 1885 if (fstab.zone_fs_raw[0] != '\0' && 1886 (stat(cmdbuf, &st) != 0 || !S_ISREG(st.st_mode))) { 1887 (void) fprintf(stderr, gettext("cannot verify fs %s: " 1888 "'raw' device specified but " 1889 "no fsck executable exists for %s\n"), 1890 fstab.zone_fs_dir, fstab.zone_fs_type); 1891 return_code = Z_ERR; 1892 goto next_fs; 1893 } 1894 next_fs: 1895 zonecfg_free_fs_option_list(fstab.zone_fs_options); 1896 } 1897 (void) zonecfg_endfsent(handle); 1898 1899 return (return_code); 1900 } 1901 1902 static int 1903 verify_details(int cmd_num) 1904 { 1905 zone_dochandle_t handle; 1906 struct zone_nwiftab nwiftab; 1907 char zonepath[MAXPATHLEN], checkpath[MAXPATHLEN]; 1908 int return_code = Z_OK; 1909 int err; 1910 boolean_t in_alt_root; 1911 1912 if ((handle = zonecfg_init_handle()) == NULL) { 1913 zperror(cmd_to_str(cmd_num), B_TRUE); 1914 return (Z_ERR); 1915 } 1916 if ((err = zonecfg_get_handle(target_zone, handle)) != Z_OK) { 1917 errno = err; 1918 zperror(cmd_to_str(cmd_num), B_TRUE); 1919 zonecfg_fini_handle(handle); 1920 return (Z_ERR); 1921 } 1922 if ((err = zonecfg_get_zonepath(handle, zonepath, sizeof (zonepath))) != 1923 Z_OK) { 1924 errno = err; 1925 zperror(cmd_to_str(cmd_num), B_TRUE); 1926 zonecfg_fini_handle(handle); 1927 return (Z_ERR); 1928 } 1929 /* 1930 * zonecfg_get_zonepath() gets its data from the XML repository. 1931 * Verify this against the index file, which is checked first by 1932 * zone_get_zonepath(). If they don't match, bail out. 1933 */ 1934 if ((err = zone_get_zonepath(target_zone, checkpath, 1935 sizeof (checkpath))) != Z_OK) { 1936 errno = err; 1937 zperror2(target_zone, gettext("could not get zone path")); 1938 return (Z_ERR); 1939 } 1940 if (strcmp(zonepath, checkpath) != 0) { 1941 (void) fprintf(stderr, gettext("The XML repository has " 1942 "zonepath '%s',\nbut the index file has zonepath '%s'.\n" 1943 "These must match, so fix the incorrect entry.\n"), 1944 zonepath, checkpath); 1945 return (Z_ERR); 1946 } 1947 if (validate_zonepath(zonepath, cmd_num) != Z_OK) { 1948 (void) fprintf(stderr, gettext("could not verify zonepath %s " 1949 "because of the above errors.\n"), zonepath); 1950 return_code = Z_ERR; 1951 } 1952 1953 in_alt_root = zonecfg_in_alt_root(); 1954 if (in_alt_root) 1955 goto no_net; 1956 1957 if ((err = zonecfg_setnwifent(handle)) != Z_OK) { 1958 errno = err; 1959 zperror(cmd_to_str(cmd_num), B_TRUE); 1960 zonecfg_fini_handle(handle); 1961 return (Z_ERR); 1962 } 1963 while (zonecfg_getnwifent(handle, &nwiftab) == Z_OK) { 1964 struct lifreq lifr; 1965 sa_family_t af; 1966 int so, res; 1967 1968 /* skip any loopback interfaces */ 1969 if (strcmp(nwiftab.zone_nwif_physical, "lo0") == 0) 1970 continue; 1971 if ((res = zonecfg_valid_net_address(nwiftab.zone_nwif_address, 1972 &lifr)) != Z_OK) { 1973 (void) fprintf(stderr, gettext("could not verify %s " 1974 "%s=%s %s=%s: %s\n"), "net", "address", 1975 nwiftab.zone_nwif_address, "physical", 1976 nwiftab.zone_nwif_physical, zonecfg_strerror(res)); 1977 return_code = Z_ERR; 1978 continue; 1979 } 1980 af = lifr.lifr_addr.ss_family; 1981 (void) memset(&lifr, 0, sizeof (lifr)); 1982 (void) strlcpy(lifr.lifr_name, nwiftab.zone_nwif_physical, 1983 sizeof (lifr.lifr_name)); 1984 lifr.lifr_addr.ss_family = af; 1985 if ((so = socket(af, SOCK_DGRAM, 0)) < 0) { 1986 (void) fprintf(stderr, gettext("could not verify %s " 1987 "%s=%s %s=%s: could not get socket: %s\n"), "net", 1988 "address", nwiftab.zone_nwif_address, "physical", 1989 nwiftab.zone_nwif_physical, strerror(errno)); 1990 return_code = Z_ERR; 1991 continue; 1992 } 1993 if (ioctl(so, SIOCGLIFFLAGS, (caddr_t)&lifr) < 0) { 1994 (void) fprintf(stderr, 1995 gettext("could not verify %s %s=%s %s=%s: %s\n"), 1996 "net", "address", nwiftab.zone_nwif_address, 1997 "physical", nwiftab.zone_nwif_physical, 1998 strerror(errno)); 1999 return_code = Z_ERR; 2000 } 2001 (void) close(so); 2002 } 2003 (void) zonecfg_endnwifent(handle); 2004 no_net: 2005 2006 if (verify_filesystems(handle) != Z_OK) 2007 return_code = Z_ERR; 2008 if (!in_alt_root && verify_rctls(handle) != Z_OK) 2009 return_code = Z_ERR; 2010 if (!in_alt_root && verify_pool(handle) != Z_OK) 2011 return_code = Z_ERR; 2012 zonecfg_fini_handle(handle); 2013 if (return_code == Z_ERR) 2014 (void) fprintf(stderr, 2015 gettext("%s: zone %s failed to verify\n"), 2016 execname, target_zone); 2017 return (return_code); 2018 } 2019 2020 static int 2021 verify_func(int argc, char *argv[]) 2022 { 2023 int arg; 2024 2025 optind = 0; 2026 if ((arg = getopt(argc, argv, "?")) != EOF) { 2027 switch (arg) { 2028 case '?': 2029 sub_usage(SHELP_VERIFY, CMD_VERIFY); 2030 return (optopt == '?' ? Z_OK : Z_USAGE); 2031 default: 2032 sub_usage(SHELP_VERIFY, CMD_VERIFY); 2033 return (Z_USAGE); 2034 } 2035 } 2036 if (argc > optind) { 2037 sub_usage(SHELP_VERIFY, CMD_VERIFY); 2038 return (Z_USAGE); 2039 } 2040 if (sanity_check(target_zone, CMD_VERIFY, B_FALSE, B_FALSE) != Z_OK) 2041 return (Z_ERR); 2042 return (verify_details(CMD_VERIFY)); 2043 } 2044 2045 #define LUCREATEZONE "/usr/lib/lu/lucreatezone" 2046 2047 static int 2048 install_func(int argc, char *argv[]) 2049 { 2050 /* 9: "exec " and " -z " */ 2051 char cmdbuf[sizeof (LUCREATEZONE) + ZONENAME_MAX + 9]; 2052 int lockfd; 2053 int err, arg; 2054 char zonepath[MAXPATHLEN]; 2055 int status; 2056 2057 if (zonecfg_in_alt_root()) { 2058 zerror(gettext("cannot install zone in alternate root")); 2059 return (Z_ERR); 2060 } 2061 2062 optind = 0; 2063 if ((arg = getopt(argc, argv, "?")) != EOF) { 2064 switch (arg) { 2065 case '?': 2066 sub_usage(SHELP_INSTALL, CMD_INSTALL); 2067 return (optopt == '?' ? Z_OK : Z_USAGE); 2068 default: 2069 sub_usage(SHELP_INSTALL, CMD_INSTALL); 2070 return (Z_USAGE); 2071 } 2072 } 2073 if (argc > optind) { 2074 sub_usage(SHELP_INSTALL, CMD_INSTALL); 2075 return (Z_USAGE); 2076 } 2077 if (sanity_check(target_zone, CMD_INSTALL, B_FALSE, B_TRUE) != Z_OK) 2078 return (Z_ERR); 2079 if (verify_details(CMD_INSTALL) != Z_OK) 2080 return (Z_ERR); 2081 2082 if (grab_lock_file(target_zone, &lockfd) != Z_OK) { 2083 zerror(gettext("another %s may have an operation in progress."), 2084 "zoneadmd"); 2085 return (Z_ERR); 2086 } 2087 err = zone_set_state(target_zone, ZONE_STATE_INCOMPLETE); 2088 if (err != Z_OK) { 2089 errno = err; 2090 zperror2(target_zone, gettext("could not set state")); 2091 goto done; 2092 } 2093 2094 /* 2095 * According to the Application Packaging Developer's Guide, a 2096 * "checkinstall" script when included in a package is executed as 2097 * the user "install", if such a user exists, or by the user 2098 * "nobody". In order to support this dubious behavior, the path 2099 * to the zone being constructed is opened up during the life of 2100 * the command laying down the zone's root file system. Once this 2101 * has completed, regardless of whether it was successful, the 2102 * path to the zone is again restricted. 2103 */ 2104 if ((err = zone_get_zonepath(target_zone, zonepath, 2105 sizeof (zonepath))) != Z_OK) { 2106 errno = err; 2107 zperror2(target_zone, gettext("could not get zone path")); 2108 goto done; 2109 } 2110 if (chmod(zonepath, DEFAULT_DIR_MODE) != 0) { 2111 zperror(zonepath, B_FALSE); 2112 err = Z_ERR; 2113 goto done; 2114 } 2115 2116 /* 2117 * "exec" the command so that the returned status is that of 2118 * LUCREATEZONE and not the shell. 2119 */ 2120 (void) snprintf(cmdbuf, sizeof (cmdbuf), "exec " LUCREATEZONE " -z %s", 2121 target_zone); 2122 status = do_subproc(cmdbuf); 2123 if (chmod(zonepath, S_IRWXU) != 0) { 2124 zperror(zonepath, B_FALSE); 2125 err = Z_ERR; 2126 goto done; 2127 } 2128 if ((err = subproc_status(LUCREATEZONE, status)) != Z_OK) 2129 goto done; 2130 2131 if ((err = zone_set_state(target_zone, ZONE_STATE_INSTALLED)) != Z_OK) { 2132 errno = err; 2133 zperror2(target_zone, gettext("could not set state")); 2134 goto done; 2135 } 2136 2137 done: 2138 release_lock_file(lockfd); 2139 return ((err == Z_OK) ? Z_OK : Z_ERR); 2140 } 2141 2142 /* 2143 * On input, TRUE => yes, FALSE => no. 2144 * On return, TRUE => 1, FALSE => 0, could not ask => -1. 2145 */ 2146 2147 static int 2148 ask_yesno(boolean_t default_answer, const char *question) 2149 { 2150 char line[64]; /* should be large enough to answer yes or no */ 2151 2152 if (!isatty(STDIN_FILENO)) 2153 return (-1); 2154 for (;;) { 2155 (void) printf("%s (%s)? ", question, 2156 default_answer ? "[y]/n" : "y/[n]"); 2157 if (fgets(line, sizeof (line), stdin) == NULL || 2158 line[0] == '\n') 2159 return (default_answer ? 1 : 0); 2160 if (tolower(line[0]) == 'y') 2161 return (1); 2162 if (tolower(line[0]) == 'n') 2163 return (0); 2164 } 2165 } 2166 2167 #define RMCOMMAND "/usr/bin/rm -rf" 2168 2169 /* ARGSUSED */ 2170 int 2171 zfm_print(const char *p, void *r) { 2172 zerror(" %s\n", p); 2173 return (0); 2174 } 2175 2176 static int 2177 uninstall_func(int argc, char *argv[]) 2178 { 2179 /* 6: "exec " and " " */ 2180 char cmdbuf[sizeof (RMCOMMAND) + MAXPATHLEN + 6]; 2181 char line[ZONENAME_MAX + 128]; /* Enough for "Are you sure ..." */ 2182 char rootpath[MAXPATHLEN], devpath[MAXPATHLEN]; 2183 boolean_t force = B_FALSE; 2184 int lockfd, answer; 2185 int err, arg; 2186 int status; 2187 2188 if (zonecfg_in_alt_root()) { 2189 zerror(gettext("cannot uninstall zone in alternate root")); 2190 return (Z_ERR); 2191 } 2192 2193 optind = 0; 2194 while ((arg = getopt(argc, argv, "?F")) != EOF) { 2195 switch (arg) { 2196 case '?': 2197 sub_usage(SHELP_UNINSTALL, CMD_UNINSTALL); 2198 return (optopt == '?' ? Z_OK : Z_USAGE); 2199 case 'F': 2200 force = B_TRUE; 2201 break; 2202 default: 2203 sub_usage(SHELP_UNINSTALL, CMD_UNINSTALL); 2204 return (Z_USAGE); 2205 } 2206 } 2207 if (argc > optind) { 2208 sub_usage(SHELP_UNINSTALL, CMD_UNINSTALL); 2209 return (Z_USAGE); 2210 } 2211 2212 if (sanity_check(target_zone, CMD_UNINSTALL, B_FALSE, B_TRUE) != Z_OK) 2213 return (Z_ERR); 2214 2215 if (!force) { 2216 (void) snprintf(line, sizeof (line), 2217 gettext("Are you sure you want to %s zone %s"), 2218 cmd_to_str(CMD_UNINSTALL), target_zone); 2219 if ((answer = ask_yesno(B_FALSE, line)) == 0) { 2220 return (Z_OK); 2221 } else if (answer == -1) { 2222 zerror(gettext("Input not from terminal and -F " 2223 "not specified: %s not done."), 2224 cmd_to_str(CMD_UNINSTALL)); 2225 return (Z_ERR); 2226 } 2227 } 2228 2229 if ((err = zone_get_zonepath(target_zone, devpath, 2230 sizeof (devpath))) != Z_OK) { 2231 errno = err; 2232 zperror2(target_zone, gettext("could not get zone path")); 2233 return (Z_ERR); 2234 } 2235 (void) strlcat(devpath, "/dev", sizeof (devpath)); 2236 if ((err = zone_get_rootpath(target_zone, rootpath, 2237 sizeof (rootpath))) != Z_OK) { 2238 errno = err; 2239 zperror2(target_zone, gettext("could not get root path")); 2240 return (Z_ERR); 2241 } 2242 2243 /* 2244 * If there seems to be a zoneadmd running for this zone, call it 2245 * to tell it that an uninstall is happening; if all goes well it 2246 * will then shut itself down. 2247 */ 2248 if (ping_zoneadmd(target_zone) == Z_OK) { 2249 zone_cmd_arg_t zarg; 2250 zarg.cmd = Z_NOTE_UNINSTALLING; 2251 /* we don't care too much if this fails... just plow on */ 2252 (void) call_zoneadmd(target_zone, &zarg); 2253 } 2254 2255 if (grab_lock_file(target_zone, &lockfd) != Z_OK) { 2256 zerror(gettext("another %s may have an operation in progress."), 2257 "zoneadmd"); 2258 return (Z_ERR); 2259 } 2260 2261 /* Don't uninstall the zone if anything is mounted there */ 2262 err = zonecfg_find_mounts(rootpath, NULL, NULL); 2263 if (err) { 2264 zerror(gettext("These file-systems are mounted on " 2265 "subdirectories of %s.\n"), rootpath); 2266 (void) zonecfg_find_mounts(rootpath, zfm_print, NULL); 2267 return (Z_ERR); 2268 } 2269 2270 err = zone_set_state(target_zone, ZONE_STATE_INCOMPLETE); 2271 if (err != Z_OK) { 2272 errno = err; 2273 zperror2(target_zone, gettext("could not set state")); 2274 goto bad; 2275 } 2276 2277 /* 2278 * "exec" the command so that the returned status is that of 2279 * RMCOMMAND and not the shell. 2280 */ 2281 (void) snprintf(cmdbuf, sizeof (cmdbuf), "exec " RMCOMMAND " %s", 2282 devpath); 2283 status = do_subproc(cmdbuf); 2284 if ((err = subproc_status(RMCOMMAND, status)) != Z_OK) 2285 goto bad; 2286 (void) snprintf(cmdbuf, sizeof (cmdbuf), "exec " RMCOMMAND " %s", 2287 rootpath); 2288 status = do_subproc(cmdbuf); 2289 if ((err = subproc_status(RMCOMMAND, status)) != Z_OK) 2290 goto bad; 2291 err = zone_set_state(target_zone, ZONE_STATE_CONFIGURED); 2292 if (err != Z_OK) { 2293 errno = err; 2294 zperror2(target_zone, gettext("could not reset state")); 2295 } 2296 bad: 2297 release_lock_file(lockfd); 2298 return (err); 2299 } 2300 2301 /* ARGSUSED */ 2302 static int 2303 mount_func(int argc, char *argv[]) 2304 { 2305 zone_cmd_arg_t zarg; 2306 2307 if (argc > 0) 2308 return (Z_USAGE); 2309 if (sanity_check(target_zone, CMD_MOUNT, B_FALSE, B_FALSE) != Z_OK) 2310 return (Z_ERR); 2311 if (verify_details(CMD_MOUNT) != Z_OK) 2312 return (Z_ERR); 2313 2314 zarg.cmd = Z_MOUNT; 2315 if (call_zoneadmd(target_zone, &zarg) != 0) { 2316 zerror(gettext("call to %s failed"), "zoneadmd"); 2317 return (Z_ERR); 2318 } 2319 return (Z_OK); 2320 } 2321 2322 /* ARGSUSED */ 2323 static int 2324 unmount_func(int argc, char *argv[]) 2325 { 2326 zone_cmd_arg_t zarg; 2327 2328 if (argc > 0) 2329 return (Z_USAGE); 2330 if (sanity_check(target_zone, CMD_UNMOUNT, B_FALSE, B_FALSE) != Z_OK) 2331 return (Z_ERR); 2332 2333 zarg.cmd = Z_UNMOUNT; 2334 if (call_zoneadmd(target_zone, &zarg) != 0) { 2335 zerror(gettext("call to %s failed"), "zoneadmd"); 2336 return (Z_ERR); 2337 } 2338 return (Z_OK); 2339 } 2340 2341 static int 2342 help_func(int argc, char *argv[]) 2343 { 2344 int arg, cmd_num; 2345 2346 if (argc == 0) { 2347 (void) usage(B_TRUE); 2348 return (Z_OK); 2349 } 2350 optind = 0; 2351 if ((arg = getopt(argc, argv, "?")) != EOF) { 2352 switch (arg) { 2353 case '?': 2354 sub_usage(SHELP_HELP, CMD_HELP); 2355 return (optopt == '?' ? Z_OK : Z_USAGE); 2356 default: 2357 sub_usage(SHELP_HELP, CMD_HELP); 2358 return (Z_USAGE); 2359 } 2360 } 2361 while (optind < argc) { 2362 if ((cmd_num = cmd_match(argv[optind])) < 0) { 2363 sub_usage(SHELP_HELP, CMD_HELP); 2364 return (Z_USAGE); 2365 } 2366 sub_usage(cmdtab[cmd_num].short_usage, cmd_num); 2367 optind++; 2368 } 2369 return (Z_OK); 2370 } 2371 2372 /* 2373 * Returns: CMD_MIN thru CMD_MAX on success, -1 on error 2374 */ 2375 2376 static int 2377 cmd_match(char *cmd) 2378 { 2379 int i; 2380 2381 for (i = CMD_MIN; i <= CMD_MAX; i++) { 2382 /* return only if there is an exact match */ 2383 if (strcmp(cmd, cmdtab[i].cmd_name) == 0) 2384 return (cmdtab[i].cmd_num); 2385 } 2386 return (-1); 2387 } 2388 2389 static int 2390 parse_and_run(int argc, char *argv[]) 2391 { 2392 int i = cmd_match(argv[0]); 2393 2394 if (i < 0) 2395 return (usage(B_FALSE)); 2396 return (cmdtab[i].handler(argc - 1, &(argv[1]))); 2397 } 2398 2399 static char * 2400 get_execbasename(char *execfullname) 2401 { 2402 char *last_slash, *execbasename; 2403 2404 /* guard against '/' at end of command invocation */ 2405 for (;;) { 2406 last_slash = strrchr(execfullname, '/'); 2407 if (last_slash == NULL) { 2408 execbasename = execfullname; 2409 break; 2410 } else { 2411 execbasename = last_slash + 1; 2412 if (*execbasename == '\0') { 2413 *last_slash = '\0'; 2414 continue; 2415 } 2416 break; 2417 } 2418 } 2419 return (execbasename); 2420 } 2421 2422 int 2423 main(int argc, char **argv) 2424 { 2425 int arg; 2426 zoneid_t zid; 2427 struct stat st; 2428 2429 if ((locale = setlocale(LC_ALL, "")) == NULL) 2430 locale = "C"; 2431 (void) textdomain(TEXT_DOMAIN); 2432 setbuf(stdout, NULL); 2433 (void) sigset(SIGHUP, SIG_IGN); 2434 execname = get_execbasename(argv[0]); 2435 target_zone = NULL; 2436 if (chdir("/") != 0) { 2437 zerror(gettext("could not change directory to /.")); 2438 exit(Z_ERR); 2439 } 2440 2441 while ((arg = getopt(argc, argv, "?z:R:")) != EOF) { 2442 switch (arg) { 2443 case '?': 2444 return (usage(B_TRUE)); 2445 case 'z': 2446 target_zone = optarg; 2447 break; 2448 case 'R': /* private option for admin/install use */ 2449 if (*optarg != '/') { 2450 zerror(gettext("root path must be absolute.")); 2451 exit(Z_ERR); 2452 } 2453 if (stat(optarg, &st) == -1 || !S_ISDIR(st.st_mode)) { 2454 zerror( 2455 gettext("root path must be a directory.")); 2456 exit(Z_ERR); 2457 } 2458 zonecfg_set_root(optarg); 2459 break; 2460 default: 2461 return (usage(B_FALSE)); 2462 } 2463 } 2464 2465 if (optind >= argc) 2466 return (usage(B_FALSE)); 2467 if (target_zone != NULL && zone_get_id(target_zone, &zid) != 0) { 2468 errno = Z_NO_ZONE; 2469 zperror(target_zone, B_TRUE); 2470 exit(Z_ERR); 2471 } 2472 return (parse_and_run(argc - optind, &argv[optind])); 2473 } 2474