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 (the "License"). 6 * You may not use this file except in compliance with the License. 7 * 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9 * or http://www.opensolaris.org/os/licensing. 10 * See the License for the specific language governing permissions 11 * and limitations under the License. 12 * 13 * When distributing Covered Code, include this CDDL HEADER in each 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15 * If applicable, add the following below this CDDL HEADER, with the 16 * fields enclosed by brackets "[]" replaced with your own identifying 17 * information: Portions Copyright [yyyy] [name of copyright owner] 18 * 19 * CDDL HEADER END 20 */ 21 22 /* 23 * Copyright 2006 Sun Microsystems, Inc. All rights reserved. 24 * Use is subject to license terms. 25 */ 26 27 #pragma ident "%Z%%M% %I% %E% SMI" 28 29 /* 30 * zoneadm is a command interpreter for zone administration. It is all in 31 * C (i.e., no lex/yacc), and all the argument passing is argc/argv based. 32 * main() calls parse_and_run() which calls cmd_match(), then invokes the 33 * appropriate command's handler function. The rest of the program is the 34 * handler functions and their helper functions. 35 * 36 * Some of the helper functions are used largely to simplify I18N: reducing 37 * the need for translation notes. This is particularly true of many of 38 * the zerror() calls: doing e.g. zerror(gettext("%s failed"), "foo") rather 39 * than zerror(gettext("foo failed")) with a translation note indicating 40 * that "foo" need not be translated. 41 */ 42 43 #include <stdio.h> 44 #include <errno.h> 45 #include <unistd.h> 46 #include <signal.h> 47 #include <stdarg.h> 48 #include <ctype.h> 49 #include <stdlib.h> 50 #include <string.h> 51 #include <wait.h> 52 #include <zone.h> 53 #include <priv.h> 54 #include <locale.h> 55 #include <libintl.h> 56 #include <libzonecfg.h> 57 #include <bsm/adt.h> 58 #include <sys/utsname.h> 59 #include <sys/param.h> 60 #include <sys/types.h> 61 #include <sys/stat.h> 62 #include <sys/statvfs.h> 63 #include <assert.h> 64 #include <sys/sockio.h> 65 #include <sys/mntent.h> 66 #include <limits.h> 67 #include <libzfs.h> 68 69 #include <fcntl.h> 70 #include <door.h> 71 #include <macros.h> 72 #include <libgen.h> 73 #include <fnmatch.h> 74 75 #include <pool.h> 76 #include <sys/pool.h> 77 78 #define MAXARGS 8 79 80 /* Reflects kernel zone entries */ 81 typedef struct zone_entry { 82 zoneid_t zid; 83 char zname[ZONENAME_MAX]; 84 char *zstate_str; 85 zone_state_t zstate_num; 86 char zroot[MAXPATHLEN]; 87 } zone_entry_t; 88 89 static zone_entry_t *zents; 90 static size_t nzents; 91 92 #if !defined(TEXT_DOMAIN) /* should be defined by cc -D */ 93 #define TEXT_DOMAIN "SYS_TEST" /* Use this only if it wasn't */ 94 #endif 95 96 #define Z_ERR 1 97 #define Z_USAGE 2 98 99 /* 0755 is the default directory mode. */ 100 #define DEFAULT_DIR_MODE \ 101 (S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH) 102 103 #define CMD_HELP 0 104 #define CMD_BOOT 1 105 #define CMD_HALT 2 106 #define CMD_READY 3 107 #define CMD_REBOOT 4 108 #define CMD_LIST 5 109 #define CMD_VERIFY 6 110 #define CMD_INSTALL 7 111 #define CMD_UNINSTALL 8 112 #define CMD_MOUNT 9 113 #define CMD_UNMOUNT 10 114 #define CMD_CLONE 11 115 #define CMD_MOVE 12 116 #define CMD_DETACH 13 117 #define CMD_ATTACH 14 118 119 #define CMD_MIN CMD_HELP 120 #define CMD_MAX CMD_ATTACH 121 122 struct cmd { 123 uint_t cmd_num; /* command number */ 124 char *cmd_name; /* command name */ 125 char *short_usage; /* short form help */ 126 int (*handler)(int argc, char *argv[]); /* function to call */ 127 128 }; 129 130 #define SHELP_HELP "help" 131 #define SHELP_BOOT "boot [-s]" 132 #define SHELP_HALT "halt" 133 #define SHELP_READY "ready" 134 #define SHELP_REBOOT "reboot" 135 #define SHELP_LIST "list [-cipv]" 136 #define SHELP_VERIFY "verify" 137 #define SHELP_INSTALL "install" 138 #define SHELP_UNINSTALL "uninstall [-F]" 139 #define SHELP_CLONE "clone [-m method] zonename" 140 #define SHELP_MOVE "move zonepath" 141 #define SHELP_DETACH "detach" 142 #define SHELP_ATTACH "attach [-F]" 143 144 static int help_func(int argc, char *argv[]); 145 static int ready_func(int argc, char *argv[]); 146 static int boot_func(int argc, char *argv[]); 147 static int halt_func(int argc, char *argv[]); 148 static int reboot_func(int argc, char *argv[]); 149 static int list_func(int argc, char *argv[]); 150 static int verify_func(int argc, char *argv[]); 151 static int install_func(int argc, char *argv[]); 152 static int uninstall_func(int argc, char *argv[]); 153 static int mount_func(int argc, char *argv[]); 154 static int unmount_func(int argc, char *argv[]); 155 static int clone_func(int argc, char *argv[]); 156 static int move_func(int argc, char *argv[]); 157 static int detach_func(int argc, char *argv[]); 158 static int attach_func(int argc, char *argv[]); 159 static int sanity_check(char *zone, int cmd_num, boolean_t running, 160 boolean_t unsafe_when_running); 161 static int cmd_match(char *cmd); 162 static int verify_details(int); 163 164 static struct cmd cmdtab[] = { 165 { CMD_HELP, "help", SHELP_HELP, help_func }, 166 { CMD_BOOT, "boot", SHELP_BOOT, boot_func }, 167 { CMD_HALT, "halt", SHELP_HALT, halt_func }, 168 { CMD_READY, "ready", SHELP_READY, ready_func }, 169 { CMD_REBOOT, "reboot", SHELP_REBOOT, reboot_func }, 170 { CMD_LIST, "list", SHELP_LIST, list_func }, 171 { CMD_VERIFY, "verify", SHELP_VERIFY, verify_func }, 172 { CMD_INSTALL, "install", SHELP_INSTALL, install_func }, 173 { CMD_UNINSTALL, "uninstall", SHELP_UNINSTALL, 174 uninstall_func }, 175 /* mount and unmount are private commands for admin/install */ 176 { CMD_MOUNT, "mount", NULL, mount_func }, 177 { CMD_UNMOUNT, "unmount", NULL, unmount_func }, 178 { CMD_CLONE, "clone", SHELP_CLONE, clone_func }, 179 { CMD_MOVE, "move", SHELP_MOVE, move_func }, 180 { CMD_DETACH, "detach", SHELP_DETACH, detach_func }, 181 { CMD_ATTACH, "attach", SHELP_ATTACH, attach_func } 182 }; 183 184 /* global variables */ 185 186 /* set early in main(), never modified thereafter, used all over the place */ 187 static char *execname; 188 static char *target_zone; 189 static char *locale; 190 191 /* used in do_subproc() and signal handler */ 192 static volatile boolean_t child_killed; 193 194 static char * 195 cmd_to_str(int cmd_num) 196 { 197 assert(cmd_num >= CMD_MIN && cmd_num <= CMD_MAX); 198 return (cmdtab[cmd_num].cmd_name); 199 } 200 201 /* This is a separate function because of gettext() wrapping. */ 202 static char * 203 long_help(int cmd_num) 204 { 205 assert(cmd_num >= CMD_MIN && cmd_num <= CMD_MAX); 206 switch (cmd_num) { 207 case CMD_HELP: 208 return (gettext("Print usage message.")); 209 case CMD_BOOT: 210 return (gettext("Activates (boots) specified zone. " 211 "The -s flag can be used\n\tto boot the zone in " 212 "the single-user state.")); 213 case CMD_HALT: 214 return (gettext("Halts specified zone, bypassing " 215 "shutdown scripts and removing runtime\n\t" 216 "resources of the zone.")); 217 case CMD_READY: 218 return (gettext("Prepares a zone for running " 219 "applications but does not start any user\n\t" 220 "processes in the zone.")); 221 case CMD_REBOOT: 222 return (gettext("Restarts the zone (equivalent to a " 223 "halt / boot sequence).\n\tFails if the zone is " 224 "not active.")); 225 case CMD_LIST: 226 return (gettext("Lists the current zones, or a " 227 "specific zone if indicated. By default,\n\tall " 228 "running zones are listed, though this can be " 229 "expanded to all\n\tinstalled zones with the -i " 230 "option or all configured zones with the\n\t-c " 231 "option. When used with the general -z <zone> " 232 "option, lists only the\n\tspecified zone, but " 233 "lists it regardless of its state, and the -i " 234 "and -c\n\toptions are disallowed. The -v option " 235 "can be used to display verbose\n\tinformation: " 236 "zone name, id, current state, root directory and " 237 "options.\n\tThe -p option can be used to request " 238 "machine-parsable output. The -v\n\tand -p " 239 "options are mutually exclusive. If neither -v " 240 "nor -p is used,\n\tjust the zone name is " 241 "listed.")); 242 case CMD_VERIFY: 243 return (gettext("Check to make sure the configuration " 244 "can safely be instantiated\n\ton the machine: " 245 "physical network interfaces exist, etc.")); 246 case CMD_INSTALL: 247 return (gettext("Install the configuration on to the " 248 "system.")); 249 case CMD_UNINSTALL: 250 return (gettext("Uninstall the configuration from the " 251 "system. The -F flag can be used\n\tto force the " 252 "action.")); 253 case CMD_CLONE: 254 return (gettext("Clone the installation of another " 255 "zone.")); 256 case CMD_MOVE: 257 return (gettext("Move the zone to a new zonepath.")); 258 default: 259 return (""); 260 } 261 /* NOTREACHED */ 262 return (NULL); 263 } 264 265 /* 266 * Called with explicit B_TRUE when help is explicitly requested, B_FALSE for 267 * unexpected errors. 268 */ 269 270 static int 271 usage(boolean_t explicit) 272 { 273 int i; 274 FILE *fd = explicit ? stdout : stderr; 275 276 (void) fprintf(fd, "%s:\t%s help\n", gettext("usage"), execname); 277 (void) fprintf(fd, "\t%s [-z <zone>] list\n", execname); 278 (void) fprintf(fd, "\t%s -z <zone> <%s>\n", execname, 279 gettext("subcommand")); 280 (void) fprintf(fd, "\n%s:\n\n", gettext("Subcommands")); 281 for (i = CMD_MIN; i <= CMD_MAX; i++) { 282 if (cmdtab[i].short_usage == NULL) 283 continue; 284 (void) fprintf(fd, "%s\n", cmdtab[i].short_usage); 285 if (explicit) 286 (void) fprintf(fd, "\t%s\n\n", long_help(i)); 287 } 288 if (!explicit) 289 (void) fputs("\n", fd); 290 return (Z_USAGE); 291 } 292 293 static void 294 sub_usage(char *short_usage, int cmd_num) 295 { 296 (void) fprintf(stderr, "%s:\t%s\n", gettext("usage"), short_usage); 297 (void) fprintf(stderr, "\t%s\n", long_help(cmd_num)); 298 } 299 300 /* 301 * zperror() is like perror(3c) except that this also prints the executable 302 * name at the start of the message, and takes a boolean indicating whether 303 * to call libc'c strerror() or that from libzonecfg. 304 */ 305 306 static void 307 zperror(const char *str, boolean_t zonecfg_error) 308 { 309 (void) fprintf(stderr, "%s: %s: %s\n", execname, str, 310 zonecfg_error ? zonecfg_strerror(errno) : strerror(errno)); 311 } 312 313 /* 314 * zperror2() is very similar to zperror() above, except it also prints a 315 * supplied zone name after the executable. 316 * 317 * All current consumers of this function want libzonecfg's strerror() rather 318 * than libc's; if this ever changes, this function can be made more generic 319 * like zperror() above. 320 */ 321 322 static void 323 zperror2(const char *zone, const char *str) 324 { 325 (void) fprintf(stderr, "%s: %s: %s: %s\n", execname, zone, str, 326 zonecfg_strerror(errno)); 327 } 328 329 /* PRINTFLIKE1 */ 330 static void 331 zerror(const char *fmt, ...) 332 { 333 va_list alist; 334 335 va_start(alist, fmt); 336 (void) fprintf(stderr, "%s: ", execname); 337 if (target_zone != NULL) 338 (void) fprintf(stderr, "zone '%s': ", target_zone); 339 (void) vfprintf(stderr, fmt, alist); 340 (void) fprintf(stderr, "\n"); 341 va_end(alist); 342 } 343 344 static void * 345 safe_calloc(size_t nelem, size_t elsize) 346 { 347 void *r = calloc(nelem, elsize); 348 349 if (r == NULL) { 350 zerror(gettext("failed to allocate %lu bytes: %s"), 351 (ulong_t)nelem * elsize, strerror(errno)); 352 exit(Z_ERR); 353 } 354 return (r); 355 } 356 357 static void 358 zone_print(zone_entry_t *zent, boolean_t verbose, boolean_t parsable) 359 { 360 static boolean_t firsttime = B_TRUE; 361 362 assert(!(verbose && parsable)); 363 if (firsttime && verbose) { 364 firsttime = B_FALSE; 365 (void) printf("%*s %-16s %-14s %-30s\n", ZONEID_WIDTH, "ID", 366 "NAME", "STATUS", "PATH"); 367 } 368 if (!verbose) { 369 if (!parsable) { 370 (void) printf("%s\n", zent->zname); 371 return; 372 } 373 if (zent->zid == ZONE_ID_UNDEFINED) 374 (void) printf("-"); 375 else 376 (void) printf("%lu", zent->zid); 377 (void) printf(":%s:%s:%s\n", zent->zname, zent->zstate_str, 378 zent->zroot); 379 return; 380 } 381 if (zent->zstate_str != NULL) { 382 if (zent->zid == ZONE_ID_UNDEFINED) 383 (void) printf("%*s", ZONEID_WIDTH, "-"); 384 else 385 (void) printf("%*lu", ZONEID_WIDTH, zent->zid); 386 (void) printf(" %-16s %-14s %-30s\n", zent->zname, 387 zent->zstate_str, zent->zroot); 388 } 389 } 390 391 static int 392 lookup_zone_info(const char *zone_name, zoneid_t zid, zone_entry_t *zent) 393 { 394 char root[MAXPATHLEN]; 395 int err; 396 397 (void) strlcpy(zent->zname, zone_name, sizeof (zent->zname)); 398 (void) strlcpy(zent->zroot, "???", sizeof (zent->zroot)); 399 zent->zstate_str = "???"; 400 401 zent->zid = zid; 402 403 if ((err = zone_get_zonepath(zent->zname, root, sizeof (root))) != 404 Z_OK) { 405 errno = err; 406 zperror2(zent->zname, gettext("could not get zone path")); 407 return (Z_ERR); 408 } 409 (void) strlcpy(zent->zroot, root, sizeof (zent->zroot)); 410 411 if ((err = zone_get_state(zent->zname, &zent->zstate_num)) != Z_OK) { 412 errno = err; 413 zperror2(zent->zname, gettext("could not get state")); 414 return (Z_ERR); 415 } 416 zent->zstate_str = zone_state_str(zent->zstate_num); 417 418 return (Z_OK); 419 } 420 421 /* 422 * fetch_zents() calls zone_list(2) to find out how many zones are running 423 * (which is stored in the global nzents), then calls zone_list(2) again 424 * to fetch the list of running zones (stored in the global zents). This 425 * function may be called multiple times, so if zents is already set, we 426 * return immediately to save work. 427 */ 428 429 static int 430 fetch_zents(void) 431 { 432 zoneid_t *zids = NULL; 433 uint_t nzents_saved; 434 int i, retv; 435 FILE *fp; 436 boolean_t inaltroot; 437 zone_entry_t *zentp; 438 439 if (nzents > 0) 440 return (Z_OK); 441 442 if (zone_list(NULL, &nzents) != 0) { 443 zperror(gettext("failed to get zoneid list"), B_FALSE); 444 return (Z_ERR); 445 } 446 447 again: 448 if (nzents == 0) 449 return (Z_OK); 450 451 zids = safe_calloc(nzents, sizeof (zoneid_t)); 452 nzents_saved = nzents; 453 454 if (zone_list(zids, &nzents) != 0) { 455 zperror(gettext("failed to get zone list"), B_FALSE); 456 free(zids); 457 return (Z_ERR); 458 } 459 if (nzents != nzents_saved) { 460 /* list changed, try again */ 461 free(zids); 462 goto again; 463 } 464 465 zents = safe_calloc(nzents, sizeof (zone_entry_t)); 466 467 inaltroot = zonecfg_in_alt_root(); 468 if (inaltroot) 469 fp = zonecfg_open_scratch("", B_FALSE); 470 else 471 fp = NULL; 472 zentp = zents; 473 retv = Z_OK; 474 for (i = 0; i < nzents; i++) { 475 char name[ZONENAME_MAX]; 476 char altname[ZONENAME_MAX]; 477 478 if (getzonenamebyid(zids[i], name, sizeof (name)) < 0) { 479 zperror(gettext("failed to get zone name"), B_FALSE); 480 retv = Z_ERR; 481 continue; 482 } 483 if (zonecfg_is_scratch(name)) { 484 /* Ignore scratch zones by default */ 485 if (!inaltroot) 486 continue; 487 if (fp == NULL || 488 zonecfg_reverse_scratch(fp, name, altname, 489 sizeof (altname), NULL, 0) == -1) { 490 zerror(gettext("could not resolve scratch " 491 "zone %s"), name); 492 retv = Z_ERR; 493 continue; 494 } 495 (void) strcpy(name, altname); 496 } else { 497 /* Ignore non-scratch when in an alternate root */ 498 if (inaltroot && strcmp(name, GLOBAL_ZONENAME) != 0) 499 continue; 500 } 501 if (lookup_zone_info(name, zids[i], zentp) != Z_OK) { 502 zerror(gettext("failed to get zone data")); 503 retv = Z_ERR; 504 continue; 505 } 506 zentp++; 507 } 508 nzents = zentp - zents; 509 if (fp != NULL) 510 zonecfg_close_scratch(fp); 511 512 free(zids); 513 return (retv); 514 } 515 516 static int 517 zone_print_list(zone_state_t min_state, boolean_t verbose, boolean_t parsable) 518 { 519 int i; 520 zone_entry_t zent; 521 FILE *cookie; 522 char *name; 523 524 /* 525 * First get the list of running zones from the kernel and print them. 526 * If that is all we need, then return. 527 */ 528 if ((i = fetch_zents()) != Z_OK) { 529 /* 530 * No need for error messages; fetch_zents() has already taken 531 * care of this. 532 */ 533 return (i); 534 } 535 for (i = 0; i < nzents; i++) 536 zone_print(&zents[i], verbose, parsable); 537 if (min_state >= ZONE_STATE_RUNNING) 538 return (Z_OK); 539 /* 540 * Next, get the full list of zones from the configuration, skipping 541 * any we have already printed. 542 */ 543 cookie = setzoneent(); 544 while ((name = getzoneent(cookie)) != NULL) { 545 for (i = 0; i < nzents; i++) { 546 if (strcmp(zents[i].zname, name) == 0) 547 break; 548 } 549 if (i < nzents) { 550 free(name); 551 continue; 552 } 553 if (lookup_zone_info(name, ZONE_ID_UNDEFINED, &zent) != Z_OK) { 554 free(name); 555 continue; 556 } 557 free(name); 558 if (zent.zstate_num >= min_state) 559 zone_print(&zent, verbose, parsable); 560 } 561 endzoneent(cookie); 562 return (Z_OK); 563 } 564 565 static zone_entry_t * 566 lookup_running_zone(char *str) 567 { 568 zoneid_t zoneid; 569 char *cp; 570 int i; 571 572 if (fetch_zents() != Z_OK) 573 return (NULL); 574 575 for (i = 0; i < nzents; i++) { 576 if (strcmp(str, zents[i].zname) == 0) 577 return (&zents[i]); 578 } 579 errno = 0; 580 zoneid = strtol(str, &cp, 0); 581 if (zoneid < MIN_ZONEID || zoneid > MAX_ZONEID || 582 errno != 0 || *cp != '\0') 583 return (NULL); 584 for (i = 0; i < nzents; i++) { 585 if (zoneid == zents[i].zid) 586 return (&zents[i]); 587 } 588 return (NULL); 589 } 590 591 /* 592 * Check a bit in a mode_t: if on is B_TRUE, that bit should be on; if 593 * B_FALSE, it should be off. Return B_TRUE if the mode is bad (incorrect). 594 */ 595 static boolean_t 596 bad_mode_bit(mode_t mode, mode_t bit, boolean_t on, char *file) 597 { 598 char *str; 599 600 assert(bit == S_IRUSR || bit == S_IWUSR || bit == S_IXUSR || 601 bit == S_IRGRP || bit == S_IWGRP || bit == S_IXGRP || 602 bit == S_IROTH || bit == S_IWOTH || bit == S_IXOTH); 603 /* 604 * TRANSLATION_NOTE 605 * The strings below will be used as part of a larger message, 606 * either: 607 * (file name) must be (owner|group|world) (read|writ|execut)able 608 * or 609 * (file name) must not be (owner|group|world) (read|writ|execut)able 610 */ 611 switch (bit) { 612 case S_IRUSR: 613 str = gettext("owner readable"); 614 break; 615 case S_IWUSR: 616 str = gettext("owner writable"); 617 break; 618 case S_IXUSR: 619 str = gettext("owner executable"); 620 break; 621 case S_IRGRP: 622 str = gettext("group readable"); 623 break; 624 case S_IWGRP: 625 str = gettext("group writable"); 626 break; 627 case S_IXGRP: 628 str = gettext("group executable"); 629 break; 630 case S_IROTH: 631 str = gettext("world readable"); 632 break; 633 case S_IWOTH: 634 str = gettext("world writable"); 635 break; 636 case S_IXOTH: 637 str = gettext("world executable"); 638 break; 639 } 640 if ((mode & bit) == (on ? 0 : bit)) { 641 /* 642 * TRANSLATION_NOTE 643 * The first parameter below is a file name; the second 644 * is one of the "(owner|group|world) (read|writ|execut)able" 645 * strings from above. 646 */ 647 /* 648 * The code below could be simplified but not in a way 649 * that would easily translate to non-English locales. 650 */ 651 if (on) { 652 (void) fprintf(stderr, gettext("%s must be %s.\n"), 653 file, str); 654 } else { 655 (void) fprintf(stderr, gettext("%s must not be %s.\n"), 656 file, str); 657 } 658 return (B_TRUE); 659 } 660 return (B_FALSE); 661 } 662 663 /* 664 * We want to make sure that no zone has its zone path as a child node 665 * (in the directory sense) of any other. We do that by comparing this 666 * zone's path to the path of all other (non-global) zones. The comparison 667 * in each case is simple: add '/' to the end of the path, then do a 668 * strncmp() of the two paths, using the length of the shorter one. 669 */ 670 671 static int 672 crosscheck_zonepaths(char *path) 673 { 674 char rpath[MAXPATHLEN]; /* resolved path */ 675 char path_copy[MAXPATHLEN]; /* copy of original path */ 676 char rpath_copy[MAXPATHLEN]; /* copy of original rpath */ 677 struct zoneent *ze; 678 int res, err; 679 FILE *cookie; 680 681 cookie = setzoneent(); 682 while ((ze = getzoneent_private(cookie)) != NULL) { 683 /* Skip zones which are not installed. */ 684 if (ze->zone_state < ZONE_STATE_INSTALLED) { 685 free(ze); 686 continue; 687 } 688 /* Skip the global zone and the current target zone. */ 689 if (strcmp(ze->zone_name, GLOBAL_ZONENAME) == 0 || 690 strcmp(ze->zone_name, target_zone) == 0) { 691 free(ze); 692 continue; 693 } 694 if (strlen(ze->zone_path) == 0) { 695 /* old index file without path, fall back */ 696 if ((err = zone_get_zonepath(ze->zone_name, 697 ze->zone_path, sizeof (ze->zone_path))) != Z_OK) { 698 errno = err; 699 zperror2(ze->zone_name, 700 gettext("could not get zone path")); 701 free(ze); 702 continue; 703 } 704 } 705 (void) snprintf(path_copy, sizeof (path_copy), "%s%s", 706 zonecfg_get_root(), ze->zone_path); 707 res = resolvepath(path_copy, rpath, sizeof (rpath)); 708 if (res == -1) { 709 if (errno != ENOENT) { 710 zperror(path_copy, B_FALSE); 711 free(ze); 712 return (Z_ERR); 713 } 714 (void) printf(gettext("WARNING: zone %s is installed, " 715 "but its %s %s does not exist.\n"), ze->zone_name, 716 "zonepath", path_copy); 717 free(ze); 718 continue; 719 } 720 rpath[res] = '\0'; 721 (void) snprintf(path_copy, sizeof (path_copy), "%s/", path); 722 (void) snprintf(rpath_copy, sizeof (rpath_copy), "%s/", rpath); 723 if (strncmp(path_copy, rpath_copy, 724 min(strlen(path_copy), strlen(rpath_copy))) == 0) { 725 /* 726 * TRANSLATION_NOTE 727 * zonepath is a literal that should not be translated. 728 */ 729 (void) fprintf(stderr, gettext("%s zonepath (%s) and " 730 "%s zonepath (%s) overlap.\n"), 731 target_zone, path, ze->zone_name, rpath); 732 free(ze); 733 return (Z_ERR); 734 } 735 free(ze); 736 } 737 endzoneent(cookie); 738 return (Z_OK); 739 } 740 741 static int 742 validate_zonepath(char *path, int cmd_num) 743 { 744 int res; /* result of last library/system call */ 745 boolean_t err = B_FALSE; /* have we run into an error? */ 746 struct stat stbuf; 747 struct statvfs vfsbuf; 748 char rpath[MAXPATHLEN]; /* resolved path */ 749 char ppath[MAXPATHLEN]; /* parent path */ 750 char rppath[MAXPATHLEN]; /* resolved parent path */ 751 char rootpath[MAXPATHLEN]; /* root path */ 752 zone_state_t state; 753 754 if (path[0] != '/') { 755 (void) fprintf(stderr, 756 gettext("%s is not an absolute path.\n"), path); 757 return (Z_ERR); 758 } 759 if ((res = resolvepath(path, rpath, sizeof (rpath))) == -1) { 760 if ((errno != ENOENT) || 761 (cmd_num != CMD_VERIFY && cmd_num != CMD_INSTALL && 762 cmd_num != CMD_CLONE && cmd_num != CMD_MOVE)) { 763 zperror(path, B_FALSE); 764 return (Z_ERR); 765 } 766 if (cmd_num == CMD_VERIFY) { 767 /* 768 * TRANSLATION_NOTE 769 * zoneadm is a literal that should not be translated. 770 */ 771 (void) fprintf(stderr, gettext("WARNING: %s does not " 772 "exist, so it could not be verified.\nWhen " 773 "'zoneadm %s' is run, '%s' will try to create\n%s, " 774 "and '%s' will be tried again,\nbut the '%s' may " 775 "fail if:\nthe parent directory of %s is group- or " 776 "other-writable\nor\n%s overlaps with any other " 777 "installed zones.\n"), path, 778 cmd_to_str(CMD_INSTALL), cmd_to_str(CMD_INSTALL), 779 path, cmd_to_str(CMD_VERIFY), 780 cmd_to_str(CMD_VERIFY), path, path); 781 return (Z_OK); 782 } 783 /* 784 * The zonepath is supposed to be mode 700 but its 785 * parent(s) 755. So use 755 on the mkdirp() then 786 * chmod() the zonepath itself to 700. 787 */ 788 if (mkdirp(path, DEFAULT_DIR_MODE) < 0) { 789 zperror(path, B_FALSE); 790 return (Z_ERR); 791 } 792 /* 793 * If the chmod() fails, report the error, but might 794 * as well continue the verify procedure. 795 */ 796 if (chmod(path, S_IRWXU) != 0) 797 zperror(path, B_FALSE); 798 /* 799 * Since the mkdir() succeeded, we should not have to 800 * worry about a subsequent ENOENT, thus this should 801 * only recurse once. 802 */ 803 return (validate_zonepath(path, cmd_num)); 804 } 805 rpath[res] = '\0'; 806 if (strcmp(path, rpath) != 0) { 807 errno = Z_RESOLVED_PATH; 808 zperror(path, B_TRUE); 809 return (Z_ERR); 810 } 811 if ((res = stat(rpath, &stbuf)) != 0) { 812 zperror(rpath, B_FALSE); 813 return (Z_ERR); 814 } 815 if (!S_ISDIR(stbuf.st_mode)) { 816 (void) fprintf(stderr, gettext("%s is not a directory.\n"), 817 rpath); 818 return (Z_ERR); 819 } 820 if ((strcmp(stbuf.st_fstype, MNTTYPE_TMPFS) == 0) || 821 (strcmp(stbuf.st_fstype, MNTTYPE_XMEMFS) == 0)) { 822 (void) printf(gettext("WARNING: %s is on a temporary " 823 "file-system.\n"), rpath); 824 } 825 if (crosscheck_zonepaths(rpath) != Z_OK) 826 return (Z_ERR); 827 /* 828 * Try to collect and report as many minor errors as possible 829 * before returning, so the user can learn everything that needs 830 * to be fixed up front. 831 */ 832 if (stbuf.st_uid != 0) { 833 (void) fprintf(stderr, gettext("%s is not owned by root.\n"), 834 rpath); 835 err = B_TRUE; 836 } 837 err |= bad_mode_bit(stbuf.st_mode, S_IRUSR, B_TRUE, rpath); 838 err |= bad_mode_bit(stbuf.st_mode, S_IWUSR, B_TRUE, rpath); 839 err |= bad_mode_bit(stbuf.st_mode, S_IXUSR, B_TRUE, rpath); 840 err |= bad_mode_bit(stbuf.st_mode, S_IRGRP, B_FALSE, rpath); 841 err |= bad_mode_bit(stbuf.st_mode, S_IWGRP, B_FALSE, rpath); 842 err |= bad_mode_bit(stbuf.st_mode, S_IXGRP, B_FALSE, rpath); 843 err |= bad_mode_bit(stbuf.st_mode, S_IROTH, B_FALSE, rpath); 844 err |= bad_mode_bit(stbuf.st_mode, S_IWOTH, B_FALSE, rpath); 845 err |= bad_mode_bit(stbuf.st_mode, S_IXOTH, B_FALSE, rpath); 846 847 (void) snprintf(ppath, sizeof (ppath), "%s/..", path); 848 if ((res = resolvepath(ppath, rppath, sizeof (rppath))) == -1) { 849 zperror(ppath, B_FALSE); 850 return (Z_ERR); 851 } 852 rppath[res] = '\0'; 853 if ((res = stat(rppath, &stbuf)) != 0) { 854 zperror(rppath, B_FALSE); 855 return (Z_ERR); 856 } 857 /* theoretically impossible */ 858 if (!S_ISDIR(stbuf.st_mode)) { 859 (void) fprintf(stderr, gettext("%s is not a directory.\n"), 860 rppath); 861 return (Z_ERR); 862 } 863 if (stbuf.st_uid != 0) { 864 (void) fprintf(stderr, gettext("%s is not owned by root.\n"), 865 rppath); 866 err = B_TRUE; 867 } 868 err |= bad_mode_bit(stbuf.st_mode, S_IRUSR, B_TRUE, rppath); 869 err |= bad_mode_bit(stbuf.st_mode, S_IWUSR, B_TRUE, rppath); 870 err |= bad_mode_bit(stbuf.st_mode, S_IXUSR, B_TRUE, rppath); 871 err |= bad_mode_bit(stbuf.st_mode, S_IWGRP, B_FALSE, rppath); 872 err |= bad_mode_bit(stbuf.st_mode, S_IWOTH, B_FALSE, rppath); 873 if (strcmp(rpath, rppath) == 0) { 874 (void) fprintf(stderr, gettext("%s is its own parent.\n"), 875 rppath); 876 err = B_TRUE; 877 } 878 879 if (statvfs(rpath, &vfsbuf) != 0) { 880 zperror(rpath, B_FALSE); 881 return (Z_ERR); 882 } 883 if (strcmp(vfsbuf.f_basetype, MNTTYPE_NFS) == 0) { 884 /* 885 * TRANSLATION_NOTE 886 * Zonepath and NFS are literals that should not be translated. 887 */ 888 (void) fprintf(stderr, gettext("Zonepath %s is on an NFS " 889 "mounted file-system.\n" 890 "\tA local file-system must be used.\n"), rpath); 891 return (Z_ERR); 892 } 893 if (vfsbuf.f_flag & ST_NOSUID) { 894 /* 895 * TRANSLATION_NOTE 896 * Zonepath and nosuid are literals that should not be 897 * translated. 898 */ 899 (void) fprintf(stderr, gettext("Zonepath %s is on a nosuid " 900 "file-system.\n"), rpath); 901 return (Z_ERR); 902 } 903 904 if ((res = zone_get_state(target_zone, &state)) != Z_OK) { 905 errno = res; 906 zperror2(target_zone, gettext("could not get state")); 907 return (Z_ERR); 908 } 909 /* 910 * The existence of the root path is only bad in the configured state, 911 * as it is *supposed* to be there at the installed and later states. 912 * However, the root path is expected to be there if the zone is 913 * detached. 914 * State/command mismatches are caught earlier in verify_details(). 915 */ 916 if (state == ZONE_STATE_CONFIGURED && cmd_num != CMD_ATTACH) { 917 if (snprintf(rootpath, sizeof (rootpath), "%s/root", rpath) >= 918 sizeof (rootpath)) { 919 /* 920 * TRANSLATION_NOTE 921 * Zonepath is a literal that should not be translated. 922 */ 923 (void) fprintf(stderr, 924 gettext("Zonepath %s is too long.\n"), rpath); 925 return (Z_ERR); 926 } 927 if ((res = stat(rootpath, &stbuf)) == 0) { 928 if (zonecfg_detached(rpath)) 929 (void) fprintf(stderr, 930 gettext("Cannot %s detached " 931 "zone.\nUse attach or remove %s " 932 "directory.\n"), cmd_to_str(cmd_num), 933 rpath); 934 else 935 (void) fprintf(stderr, 936 gettext("Rootpath %s exists; " 937 "remove or move aside prior to %s.\n"), 938 rootpath, cmd_to_str(cmd_num)); 939 return (Z_ERR); 940 } 941 } 942 943 return (err ? Z_ERR : Z_OK); 944 } 945 946 static void 947 release_lock_file(int lockfd) 948 { 949 (void) close(lockfd); 950 } 951 952 static int 953 grab_lock_file(const char *zone_name, int *lockfd) 954 { 955 char pathbuf[PATH_MAX]; 956 struct flock flock; 957 958 if (snprintf(pathbuf, sizeof (pathbuf), "%s%s", zonecfg_get_root(), 959 ZONES_TMPDIR) >= sizeof (pathbuf)) { 960 zerror(gettext("alternate root path is too long")); 961 return (Z_ERR); 962 } 963 if (mkdir(pathbuf, S_IRWXU) < 0 && errno != EEXIST) { 964 zerror(gettext("could not mkdir %s: %s"), pathbuf, 965 strerror(errno)); 966 return (Z_ERR); 967 } 968 (void) chmod(pathbuf, S_IRWXU); 969 970 /* 971 * One of these lock files is created for each zone (when needed). 972 * The lock files are not cleaned up (except on system reboot), 973 * but since there is only one per zone, there is no resource 974 * starvation issue. 975 */ 976 if (snprintf(pathbuf, sizeof (pathbuf), "%s%s/%s.zoneadm.lock", 977 zonecfg_get_root(), ZONES_TMPDIR, zone_name) >= sizeof (pathbuf)) { 978 zerror(gettext("alternate root path is too long")); 979 return (Z_ERR); 980 } 981 if ((*lockfd = open(pathbuf, O_RDWR|O_CREAT, S_IRUSR|S_IWUSR)) < 0) { 982 zerror(gettext("could not open %s: %s"), pathbuf, 983 strerror(errno)); 984 return (Z_ERR); 985 } 986 /* 987 * Lock the file to synchronize with other zoneadmds 988 */ 989 flock.l_type = F_WRLCK; 990 flock.l_whence = SEEK_SET; 991 flock.l_start = (off_t)0; 992 flock.l_len = (off_t)0; 993 if (fcntl(*lockfd, F_SETLKW, &flock) < 0) { 994 zerror(gettext("unable to lock %s: %s"), pathbuf, 995 strerror(errno)); 996 release_lock_file(*lockfd); 997 return (Z_ERR); 998 } 999 return (Z_OK); 1000 } 1001 1002 static boolean_t 1003 get_doorname(const char *zone_name, char *buffer) 1004 { 1005 return (snprintf(buffer, PATH_MAX, "%s" ZONE_DOOR_PATH, 1006 zonecfg_get_root(), zone_name) < PATH_MAX); 1007 } 1008 1009 /* 1010 * system daemons are not audited. For the global zone, this occurs 1011 * "naturally" since init is started with the default audit 1012 * characteristics. Since zoneadmd is a system daemon and it starts 1013 * init for a zone, it is necessary to clear out the audit 1014 * characteristics inherited from whomever started zoneadmd. This is 1015 * indicated by the audit id, which is set from the ruid parameter of 1016 * adt_set_user(), below. 1017 */ 1018 1019 static void 1020 prepare_audit_context() 1021 { 1022 adt_session_data_t *ah; 1023 char *failure = gettext("audit failure: %s"); 1024 1025 if (adt_start_session(&ah, NULL, 0)) { 1026 zerror(failure, strerror(errno)); 1027 return; 1028 } 1029 if (adt_set_user(ah, ADT_NO_AUDIT, ADT_NO_AUDIT, 1030 ADT_NO_AUDIT, ADT_NO_AUDIT, NULL, ADT_NEW)) { 1031 zerror(failure, strerror(errno)); 1032 (void) adt_end_session(ah); 1033 return; 1034 } 1035 if (adt_set_proc(ah)) 1036 zerror(failure, strerror(errno)); 1037 1038 (void) adt_end_session(ah); 1039 } 1040 1041 static int 1042 start_zoneadmd(const char *zone_name) 1043 { 1044 char doorpath[PATH_MAX]; 1045 pid_t child_pid; 1046 int error = Z_ERR; 1047 int doorfd, lockfd; 1048 struct door_info info; 1049 1050 if (!get_doorname(zone_name, doorpath)) 1051 return (Z_ERR); 1052 1053 if (grab_lock_file(zone_name, &lockfd) != Z_OK) 1054 return (Z_ERR); 1055 1056 /* 1057 * Now that we have the lock, re-confirm that the daemon is 1058 * *not* up and working fine. If it is still down, we have a green 1059 * light to start it. 1060 */ 1061 if ((doorfd = open(doorpath, O_RDONLY)) < 0) { 1062 if (errno != ENOENT) { 1063 zperror(doorpath, B_FALSE); 1064 goto out; 1065 } 1066 } else { 1067 if (door_info(doorfd, &info) == 0 && 1068 ((info.di_attributes & DOOR_REVOKED) == 0)) { 1069 error = Z_OK; 1070 (void) close(doorfd); 1071 goto out; 1072 } 1073 (void) close(doorfd); 1074 } 1075 1076 if ((child_pid = fork()) == -1) { 1077 zperror(gettext("could not fork"), B_FALSE); 1078 goto out; 1079 } else if (child_pid == 0) { 1080 const char *argv[6], **ap; 1081 1082 /* child process */ 1083 prepare_audit_context(); 1084 1085 ap = argv; 1086 *ap++ = "zoneadmd"; 1087 *ap++ = "-z"; 1088 *ap++ = zone_name; 1089 if (zonecfg_in_alt_root()) { 1090 *ap++ = "-R"; 1091 *ap++ = zonecfg_get_root(); 1092 } 1093 *ap = NULL; 1094 1095 (void) execv("/usr/lib/zones/zoneadmd", (char * const *)argv); 1096 /* 1097 * TRANSLATION_NOTE 1098 * zoneadmd is a literal that should not be translated. 1099 */ 1100 zperror(gettext("could not exec zoneadmd"), B_FALSE); 1101 _exit(Z_ERR); 1102 } else { 1103 /* parent process */ 1104 pid_t retval; 1105 int pstatus = 0; 1106 1107 do { 1108 retval = waitpid(child_pid, &pstatus, 0); 1109 } while (retval != child_pid); 1110 if (WIFSIGNALED(pstatus) || (WIFEXITED(pstatus) && 1111 WEXITSTATUS(pstatus) != 0)) { 1112 zerror(gettext("could not start %s"), "zoneadmd"); 1113 goto out; 1114 } 1115 } 1116 error = Z_OK; 1117 out: 1118 release_lock_file(lockfd); 1119 return (error); 1120 } 1121 1122 static int 1123 ping_zoneadmd(const char *zone_name) 1124 { 1125 char doorpath[PATH_MAX]; 1126 int doorfd; 1127 struct door_info info; 1128 1129 if (!get_doorname(zone_name, doorpath)) 1130 return (Z_ERR); 1131 1132 if ((doorfd = open(doorpath, O_RDONLY)) < 0) { 1133 return (Z_ERR); 1134 } 1135 if (door_info(doorfd, &info) == 0 && 1136 ((info.di_attributes & DOOR_REVOKED) == 0)) { 1137 (void) close(doorfd); 1138 return (Z_OK); 1139 } 1140 (void) close(doorfd); 1141 return (Z_ERR); 1142 } 1143 1144 static int 1145 call_zoneadmd(const char *zone_name, zone_cmd_arg_t *arg) 1146 { 1147 char doorpath[PATH_MAX]; 1148 int doorfd, result; 1149 door_arg_t darg; 1150 1151 zoneid_t zoneid; 1152 uint64_t uniqid = 0; 1153 1154 zone_cmd_rval_t *rvalp; 1155 size_t rlen; 1156 char *cp, *errbuf; 1157 1158 rlen = getpagesize(); 1159 if ((rvalp = malloc(rlen)) == NULL) { 1160 zerror(gettext("failed to allocate %lu bytes: %s"), rlen, 1161 strerror(errno)); 1162 return (-1); 1163 } 1164 1165 if ((zoneid = getzoneidbyname(zone_name)) != ZONE_ID_UNDEFINED) { 1166 (void) zone_getattr(zoneid, ZONE_ATTR_UNIQID, &uniqid, 1167 sizeof (uniqid)); 1168 } 1169 arg->uniqid = uniqid; 1170 (void) strlcpy(arg->locale, locale, sizeof (arg->locale)); 1171 if (!get_doorname(zone_name, doorpath)) { 1172 zerror(gettext("alternate root path is too long")); 1173 free(rvalp); 1174 return (-1); 1175 } 1176 1177 /* 1178 * Loop trying to start zoneadmd; if something goes seriously 1179 * wrong we break out and fail. 1180 */ 1181 for (;;) { 1182 if (start_zoneadmd(zone_name) != Z_OK) 1183 break; 1184 1185 if ((doorfd = open(doorpath, O_RDONLY)) < 0) { 1186 zperror(gettext("failed to open zone door"), B_FALSE); 1187 break; 1188 } 1189 1190 darg.data_ptr = (char *)arg; 1191 darg.data_size = sizeof (*arg); 1192 darg.desc_ptr = NULL; 1193 darg.desc_num = 0; 1194 darg.rbuf = (char *)rvalp; 1195 darg.rsize = rlen; 1196 if (door_call(doorfd, &darg) != 0) { 1197 (void) close(doorfd); 1198 /* 1199 * We'll get EBADF if the door has been revoked. 1200 */ 1201 if (errno != EBADF) { 1202 zperror(gettext("door_call failed"), B_FALSE); 1203 break; 1204 } 1205 continue; /* take another lap */ 1206 } 1207 (void) close(doorfd); 1208 1209 if (darg.data_size == 0) { 1210 /* Door server is going away; kick it again. */ 1211 continue; 1212 } 1213 1214 errbuf = rvalp->errbuf; 1215 while (*errbuf != '\0') { 1216 /* 1217 * Remove any newlines since zerror() 1218 * will append one automatically. 1219 */ 1220 cp = strchr(errbuf, '\n'); 1221 if (cp != NULL) 1222 *cp = '\0'; 1223 zerror("%s", errbuf); 1224 if (cp == NULL) 1225 break; 1226 errbuf = cp + 1; 1227 } 1228 result = rvalp->rval == 0 ? 0 : -1; 1229 free(rvalp); 1230 return (result); 1231 } 1232 1233 free(rvalp); 1234 return (-1); 1235 } 1236 1237 static int 1238 ready_func(int argc, char *argv[]) 1239 { 1240 zone_cmd_arg_t zarg; 1241 int arg; 1242 1243 if (zonecfg_in_alt_root()) { 1244 zerror(gettext("cannot ready zone in alternate root")); 1245 return (Z_ERR); 1246 } 1247 1248 optind = 0; 1249 if ((arg = getopt(argc, argv, "?")) != EOF) { 1250 switch (arg) { 1251 case '?': 1252 sub_usage(SHELP_READY, CMD_READY); 1253 return (optopt == '?' ? Z_OK : Z_USAGE); 1254 default: 1255 sub_usage(SHELP_READY, CMD_READY); 1256 return (Z_USAGE); 1257 } 1258 } 1259 if (argc > optind) { 1260 sub_usage(SHELP_READY, CMD_READY); 1261 return (Z_USAGE); 1262 } 1263 if (sanity_check(target_zone, CMD_READY, B_FALSE, B_FALSE) != Z_OK) 1264 return (Z_ERR); 1265 if (verify_details(CMD_READY) != Z_OK) 1266 return (Z_ERR); 1267 1268 zarg.cmd = Z_READY; 1269 if (call_zoneadmd(target_zone, &zarg) != 0) { 1270 zerror(gettext("call to %s failed"), "zoneadmd"); 1271 return (Z_ERR); 1272 } 1273 return (Z_OK); 1274 } 1275 1276 static int 1277 boot_func(int argc, char *argv[]) 1278 { 1279 zone_cmd_arg_t zarg; 1280 int arg; 1281 1282 if (zonecfg_in_alt_root()) { 1283 zerror(gettext("cannot boot zone in alternate root")); 1284 return (Z_ERR); 1285 } 1286 1287 zarg.bootbuf[0] = '\0'; 1288 1289 /* 1290 * At the current time, the only supported subargument to the 1291 * "boot" subcommand is "-s" which specifies a single-user boot. 1292 * In the future, other boot arguments should be supported 1293 * including "-m" for specifying alternate smf(5) milestones. 1294 */ 1295 optind = 0; 1296 if ((arg = getopt(argc, argv, "?s")) != EOF) { 1297 switch (arg) { 1298 case '?': 1299 sub_usage(SHELP_BOOT, CMD_BOOT); 1300 return (optopt == '?' ? Z_OK : Z_USAGE); 1301 case 's': 1302 (void) strlcpy(zarg.bootbuf, "-s", 1303 sizeof (zarg.bootbuf)); 1304 break; 1305 default: 1306 sub_usage(SHELP_BOOT, CMD_BOOT); 1307 return (Z_USAGE); 1308 } 1309 } 1310 if (argc > optind) { 1311 sub_usage(SHELP_BOOT, CMD_BOOT); 1312 return (Z_USAGE); 1313 } 1314 if (sanity_check(target_zone, CMD_BOOT, B_FALSE, B_FALSE) != Z_OK) 1315 return (Z_ERR); 1316 if (verify_details(CMD_BOOT) != Z_OK) 1317 return (Z_ERR); 1318 zarg.cmd = Z_BOOT; 1319 if (call_zoneadmd(target_zone, &zarg) != 0) { 1320 zerror(gettext("call to %s failed"), "zoneadmd"); 1321 return (Z_ERR); 1322 } 1323 return (Z_OK); 1324 } 1325 1326 static void 1327 fake_up_local_zone(zoneid_t zid, zone_entry_t *zeptr) 1328 { 1329 ssize_t result; 1330 1331 zeptr->zid = zid; 1332 /* 1333 * Since we're looking up our own (non-global) zone name, 1334 * we can be assured that it will succeed. 1335 */ 1336 result = getzonenamebyid(zid, zeptr->zname, sizeof (zeptr->zname)); 1337 assert(result >= 0); 1338 (void) strlcpy(zeptr->zroot, "/", sizeof (zeptr->zroot)); 1339 zeptr->zstate_str = "running"; 1340 } 1341 1342 static int 1343 list_func(int argc, char *argv[]) 1344 { 1345 zone_entry_t *zentp, zent; 1346 int arg, retv; 1347 boolean_t output = B_FALSE, verbose = B_FALSE, parsable = B_FALSE; 1348 zone_state_t min_state = ZONE_STATE_RUNNING; 1349 zoneid_t zone_id = getzoneid(); 1350 1351 if (target_zone == NULL) { 1352 /* all zones: default view to running but allow override */ 1353 optind = 0; 1354 while ((arg = getopt(argc, argv, "?cipv")) != EOF) { 1355 switch (arg) { 1356 case '?': 1357 sub_usage(SHELP_LIST, CMD_LIST); 1358 return (optopt == '?' ? Z_OK : Z_USAGE); 1359 /* 1360 * The 'i' and 'c' options are not mutually 1361 * exclusive so if 'c' is given, then min_state 1362 * is set to 0 (ZONE_STATE_CONFIGURED) which is 1363 * the lowest possible state. If 'i' is given, 1364 * then min_state is set to be the lowest state 1365 * so far. 1366 */ 1367 case 'c': 1368 min_state = ZONE_STATE_CONFIGURED; 1369 break; 1370 case 'i': 1371 min_state = min(ZONE_STATE_INSTALLED, 1372 min_state); 1373 1374 break; 1375 case 'p': 1376 parsable = B_TRUE; 1377 break; 1378 case 'v': 1379 verbose = B_TRUE; 1380 break; 1381 default: 1382 sub_usage(SHELP_LIST, CMD_LIST); 1383 return (Z_USAGE); 1384 } 1385 } 1386 if (parsable && verbose) { 1387 zerror(gettext("%s -p and -v are mutually exclusive."), 1388 cmd_to_str(CMD_LIST)); 1389 return (Z_ERR); 1390 } 1391 if (zone_id == GLOBAL_ZONEID) { 1392 retv = zone_print_list(min_state, verbose, parsable); 1393 } else { 1394 retv = Z_OK; 1395 fake_up_local_zone(zone_id, &zent); 1396 zone_print(&zent, verbose, parsable); 1397 } 1398 return (retv); 1399 } 1400 1401 /* 1402 * Specific target zone: disallow -i/-c suboptions. 1403 */ 1404 optind = 0; 1405 while ((arg = getopt(argc, argv, "?pv")) != EOF) { 1406 switch (arg) { 1407 case '?': 1408 sub_usage(SHELP_LIST, CMD_LIST); 1409 return (optopt == '?' ? Z_OK : Z_USAGE); 1410 case 'p': 1411 parsable = B_TRUE; 1412 break; 1413 case 'v': 1414 verbose = B_TRUE; 1415 break; 1416 default: 1417 sub_usage(SHELP_LIST, CMD_LIST); 1418 return (Z_USAGE); 1419 } 1420 } 1421 if (parsable && verbose) { 1422 zerror(gettext("%s -p and -v are mutually exclusive."), 1423 cmd_to_str(CMD_LIST)); 1424 return (Z_ERR); 1425 } 1426 if (argc > optind) { 1427 sub_usage(SHELP_LIST, CMD_LIST); 1428 return (Z_USAGE); 1429 } 1430 if (zone_id != GLOBAL_ZONEID) { 1431 fake_up_local_zone(zone_id, &zent); 1432 /* 1433 * main() will issue a Z_NO_ZONE error if it cannot get an 1434 * id for target_zone, which in a non-global zone should 1435 * happen for any zone name except `zonename`. Thus we 1436 * assert() that here but don't otherwise check. 1437 */ 1438 assert(strcmp(zent.zname, target_zone) == 0); 1439 zone_print(&zent, verbose, parsable); 1440 output = B_TRUE; 1441 } else if ((zentp = lookup_running_zone(target_zone)) != NULL) { 1442 zone_print(zentp, verbose, parsable); 1443 output = B_TRUE; 1444 } else if (lookup_zone_info(target_zone, ZONE_ID_UNDEFINED, 1445 &zent) == Z_OK) { 1446 zone_print(&zent, verbose, parsable); 1447 output = B_TRUE; 1448 } 1449 return (output ? Z_OK : Z_ERR); 1450 } 1451 1452 static void 1453 sigterm(int sig) 1454 { 1455 /* 1456 * Ignore SIG{INT,TERM}, so we don't end up in an infinite loop, 1457 * then propagate the signal to our process group. 1458 */ 1459 (void) sigset(SIGINT, SIG_IGN); 1460 (void) sigset(SIGTERM, SIG_IGN); 1461 (void) kill(0, sig); 1462 child_killed = B_TRUE; 1463 } 1464 1465 static int 1466 do_subproc(char *cmdbuf) 1467 { 1468 char inbuf[1024]; /* arbitrary large amount */ 1469 FILE *file; 1470 1471 child_killed = B_FALSE; 1472 /* 1473 * We use popen(3c) to launch child processes for [un]install; 1474 * this library call does not return a PID, so we have to kill 1475 * the whole process group. To avoid killing our parent, we 1476 * become a process group leader here. But doing so can wreak 1477 * havoc with reading from stdin when launched by a non-job-control 1478 * shell, so we close stdin and reopen it as /dev/null first. 1479 */ 1480 (void) close(STDIN_FILENO); 1481 (void) open("/dev/null", O_RDONLY); 1482 (void) setpgid(0, 0); 1483 (void) sigset(SIGINT, sigterm); 1484 (void) sigset(SIGTERM, sigterm); 1485 file = popen(cmdbuf, "r"); 1486 for (;;) { 1487 if (child_killed || fgets(inbuf, sizeof (inbuf), file) == NULL) 1488 break; 1489 (void) fputs(inbuf, stdout); 1490 } 1491 (void) sigset(SIGINT, SIG_DFL); 1492 (void) sigset(SIGTERM, SIG_DFL); 1493 return (pclose(file)); 1494 } 1495 1496 static int 1497 subproc_status(const char *cmd, int status) 1498 { 1499 if (WIFEXITED(status)) { 1500 int exit_code = WEXITSTATUS(status); 1501 1502 if (exit_code == 0) 1503 return (Z_OK); 1504 zerror(gettext("'%s' failed with exit code %d."), cmd, 1505 exit_code); 1506 } else if (WIFSIGNALED(status)) { 1507 int signal = WTERMSIG(status); 1508 char sigstr[SIG2STR_MAX]; 1509 1510 if (sig2str(signal, sigstr) == 0) { 1511 zerror(gettext("'%s' terminated by signal SIG%s."), cmd, 1512 sigstr); 1513 } else { 1514 zerror(gettext("'%s' terminated by an unknown signal."), 1515 cmd); 1516 } 1517 } else { 1518 zerror(gettext("'%s' failed for unknown reasons."), cmd); 1519 } 1520 return (Z_ERR); 1521 } 1522 1523 /* 1524 * Various sanity checks; make sure: 1525 * 1. We're in the global zone. 1526 * 2. The calling user has sufficient privilege. 1527 * 3. The target zone is neither the global zone nor anything starting with 1528 * "SUNW". 1529 * 4a. If we're looking for a 'not running' (i.e., configured or installed) 1530 * zone, the name service knows about it. 1531 * 4b. For some operations which expect a zone not to be running, that it is 1532 * not already running (or ready). 1533 */ 1534 static int 1535 sanity_check(char *zone, int cmd_num, boolean_t running, 1536 boolean_t unsafe_when_running) 1537 { 1538 zone_entry_t *zent; 1539 priv_set_t *privset; 1540 zone_state_t state; 1541 char kernzone[ZONENAME_MAX]; 1542 FILE *fp; 1543 1544 if (getzoneid() != GLOBAL_ZONEID) { 1545 zerror(gettext("must be in the global zone to %s a zone."), 1546 cmd_to_str(cmd_num)); 1547 return (Z_ERR); 1548 } 1549 1550 if ((privset = priv_allocset()) == NULL) { 1551 zerror(gettext("%s failed"), "priv_allocset"); 1552 return (Z_ERR); 1553 } 1554 1555 if (getppriv(PRIV_EFFECTIVE, privset) != 0) { 1556 zerror(gettext("%s failed"), "getppriv"); 1557 priv_freeset(privset); 1558 return (Z_ERR); 1559 } 1560 1561 if (priv_isfullset(privset) == B_FALSE) { 1562 zerror(gettext("only a privileged user may %s a zone."), 1563 cmd_to_str(cmd_num)); 1564 priv_freeset(privset); 1565 return (Z_ERR); 1566 } 1567 priv_freeset(privset); 1568 1569 if (zone == NULL) { 1570 zerror(gettext("no zone specified")); 1571 return (Z_ERR); 1572 } 1573 1574 if (strcmp(zone, GLOBAL_ZONENAME) == 0) { 1575 zerror(gettext("%s operation is invalid for the global zone."), 1576 cmd_to_str(cmd_num)); 1577 return (Z_ERR); 1578 } 1579 1580 if (strncmp(zone, "SUNW", 4) == 0) { 1581 zerror(gettext("%s operation is invalid for zones starting " 1582 "with SUNW."), cmd_to_str(cmd_num)); 1583 return (Z_ERR); 1584 } 1585 1586 if (!zonecfg_in_alt_root()) { 1587 zent = lookup_running_zone(zone); 1588 } else if ((fp = zonecfg_open_scratch("", B_FALSE)) == NULL) { 1589 zent = NULL; 1590 } else { 1591 if (zonecfg_find_scratch(fp, zone, zonecfg_get_root(), 1592 kernzone, sizeof (kernzone)) == 0) 1593 zent = lookup_running_zone(kernzone); 1594 else 1595 zent = NULL; 1596 zonecfg_close_scratch(fp); 1597 } 1598 1599 /* 1600 * Look up from the kernel for 'running' zones. 1601 */ 1602 if (running) { 1603 if (zent == NULL) { 1604 zerror(gettext("not running")); 1605 return (Z_ERR); 1606 } 1607 } else { 1608 int err; 1609 1610 if (unsafe_when_running && zent != NULL) { 1611 /* check whether the zone is ready or running */ 1612 if ((err = zone_get_state(zent->zname, 1613 &zent->zstate_num)) != Z_OK) { 1614 errno = err; 1615 zperror2(zent->zname, 1616 gettext("could not get state")); 1617 /* can't tell, so hedge */ 1618 zent->zstate_str = "ready/running"; 1619 } else { 1620 zent->zstate_str = 1621 zone_state_str(zent->zstate_num); 1622 } 1623 zerror(gettext("%s operation is invalid for %s zones."), 1624 cmd_to_str(cmd_num), zent->zstate_str); 1625 return (Z_ERR); 1626 } 1627 if ((err = zone_get_state(zone, &state)) != Z_OK) { 1628 errno = err; 1629 zperror2(zone, gettext("could not get state")); 1630 return (Z_ERR); 1631 } 1632 switch (cmd_num) { 1633 case CMD_UNINSTALL: 1634 if (state == ZONE_STATE_CONFIGURED) { 1635 zerror(gettext("is already in state '%s'."), 1636 zone_state_str(ZONE_STATE_CONFIGURED)); 1637 return (Z_ERR); 1638 } 1639 break; 1640 case CMD_ATTACH: 1641 case CMD_CLONE: 1642 case CMD_INSTALL: 1643 if (state == ZONE_STATE_INSTALLED) { 1644 zerror(gettext("is already %s."), 1645 zone_state_str(ZONE_STATE_INSTALLED)); 1646 return (Z_ERR); 1647 } else if (state == ZONE_STATE_INCOMPLETE) { 1648 zerror(gettext("zone is %s; %s required."), 1649 zone_state_str(ZONE_STATE_INCOMPLETE), 1650 cmd_to_str(CMD_UNINSTALL)); 1651 return (Z_ERR); 1652 } 1653 break; 1654 case CMD_DETACH: 1655 case CMD_MOVE: 1656 case CMD_READY: 1657 case CMD_BOOT: 1658 case CMD_MOUNT: 1659 if (state < ZONE_STATE_INSTALLED) { 1660 zerror(gettext("must be %s before %s."), 1661 zone_state_str(ZONE_STATE_INSTALLED), 1662 cmd_to_str(cmd_num)); 1663 return (Z_ERR); 1664 } 1665 break; 1666 case CMD_VERIFY: 1667 if (state == ZONE_STATE_INCOMPLETE) { 1668 zerror(gettext("zone is %s; %s required."), 1669 zone_state_str(ZONE_STATE_INCOMPLETE), 1670 cmd_to_str(CMD_UNINSTALL)); 1671 return (Z_ERR); 1672 } 1673 break; 1674 case CMD_UNMOUNT: 1675 if (state != ZONE_STATE_MOUNTED) { 1676 zerror(gettext("must be %s before %s."), 1677 zone_state_str(ZONE_STATE_MOUNTED), 1678 cmd_to_str(cmd_num)); 1679 return (Z_ERR); 1680 } 1681 break; 1682 } 1683 } 1684 return (Z_OK); 1685 } 1686 1687 static int 1688 halt_func(int argc, char *argv[]) 1689 { 1690 zone_cmd_arg_t zarg; 1691 int arg; 1692 1693 if (zonecfg_in_alt_root()) { 1694 zerror(gettext("cannot halt zone in alternate root")); 1695 return (Z_ERR); 1696 } 1697 1698 optind = 0; 1699 if ((arg = getopt(argc, argv, "?")) != EOF) { 1700 switch (arg) { 1701 case '?': 1702 sub_usage(SHELP_HALT, CMD_HALT); 1703 return (optopt == '?' ? Z_OK : Z_USAGE); 1704 default: 1705 sub_usage(SHELP_HALT, CMD_HALT); 1706 return (Z_USAGE); 1707 } 1708 } 1709 if (argc > optind) { 1710 sub_usage(SHELP_HALT, CMD_HALT); 1711 return (Z_USAGE); 1712 } 1713 /* 1714 * zoneadmd should be the one to decide whether or not to proceed, 1715 * so even though it seems that the fourth parameter below should 1716 * perhaps be B_TRUE, it really shouldn't be. 1717 */ 1718 if (sanity_check(target_zone, CMD_HALT, B_FALSE, B_FALSE) != Z_OK) 1719 return (Z_ERR); 1720 1721 zarg.cmd = Z_HALT; 1722 return ((call_zoneadmd(target_zone, &zarg) == 0) ? Z_OK : Z_ERR); 1723 } 1724 1725 static int 1726 reboot_func(int argc, char *argv[]) 1727 { 1728 zone_cmd_arg_t zarg; 1729 int arg; 1730 1731 if (zonecfg_in_alt_root()) { 1732 zerror(gettext("cannot reboot zone in alternate root")); 1733 return (Z_ERR); 1734 } 1735 1736 optind = 0; 1737 if ((arg = getopt(argc, argv, "?")) != EOF) { 1738 switch (arg) { 1739 case '?': 1740 sub_usage(SHELP_REBOOT, CMD_REBOOT); 1741 return (optopt == '?' ? Z_OK : Z_USAGE); 1742 default: 1743 sub_usage(SHELP_REBOOT, CMD_REBOOT); 1744 return (Z_USAGE); 1745 } 1746 } 1747 if (argc > 0) { 1748 sub_usage(SHELP_REBOOT, CMD_REBOOT); 1749 return (Z_USAGE); 1750 } 1751 /* 1752 * zoneadmd should be the one to decide whether or not to proceed, 1753 * so even though it seems that the fourth parameter below should 1754 * perhaps be B_TRUE, it really shouldn't be. 1755 */ 1756 if (sanity_check(target_zone, CMD_REBOOT, B_TRUE, B_FALSE) != Z_OK) 1757 return (Z_ERR); 1758 if (verify_details(CMD_REBOOT) != Z_OK) 1759 return (Z_ERR); 1760 1761 zarg.cmd = Z_REBOOT; 1762 return ((call_zoneadmd(target_zone, &zarg) == 0) ? Z_OK : Z_ERR); 1763 } 1764 1765 static int 1766 verify_rctls(zone_dochandle_t handle) 1767 { 1768 struct zone_rctltab rctltab; 1769 size_t rbs = rctlblk_size(); 1770 rctlblk_t *rctlblk; 1771 int error = Z_INVAL; 1772 1773 if ((rctlblk = malloc(rbs)) == NULL) { 1774 zerror(gettext("failed to allocate %lu bytes: %s"), rbs, 1775 strerror(errno)); 1776 return (Z_NOMEM); 1777 } 1778 1779 if (zonecfg_setrctlent(handle) != Z_OK) { 1780 zerror(gettext("zonecfg_setrctlent failed")); 1781 free(rctlblk); 1782 return (error); 1783 } 1784 1785 rctltab.zone_rctl_valptr = NULL; 1786 while (zonecfg_getrctlent(handle, &rctltab) == Z_OK) { 1787 struct zone_rctlvaltab *rctlval; 1788 const char *name = rctltab.zone_rctl_name; 1789 1790 if (!zonecfg_is_rctl(name)) { 1791 zerror(gettext("WARNING: Ignoring unrecognized rctl " 1792 "'%s'."), name); 1793 zonecfg_free_rctl_value_list(rctltab.zone_rctl_valptr); 1794 rctltab.zone_rctl_valptr = NULL; 1795 continue; 1796 } 1797 1798 for (rctlval = rctltab.zone_rctl_valptr; rctlval != NULL; 1799 rctlval = rctlval->zone_rctlval_next) { 1800 if (zonecfg_construct_rctlblk(rctlval, rctlblk) 1801 != Z_OK) { 1802 zerror(gettext("invalid rctl value: " 1803 "(priv=%s,limit=%s,action%s)"), 1804 rctlval->zone_rctlval_priv, 1805 rctlval->zone_rctlval_limit, 1806 rctlval->zone_rctlval_action); 1807 goto out; 1808 } 1809 if (!zonecfg_valid_rctl(name, rctlblk)) { 1810 zerror(gettext("(priv=%s,limit=%s,action=%s) " 1811 "is not a valid value for rctl '%s'"), 1812 rctlval->zone_rctlval_priv, 1813 rctlval->zone_rctlval_limit, 1814 rctlval->zone_rctlval_action, 1815 name); 1816 goto out; 1817 } 1818 } 1819 zonecfg_free_rctl_value_list(rctltab.zone_rctl_valptr); 1820 } 1821 rctltab.zone_rctl_valptr = NULL; 1822 error = Z_OK; 1823 out: 1824 zonecfg_free_rctl_value_list(rctltab.zone_rctl_valptr); 1825 (void) zonecfg_endrctlent(handle); 1826 free(rctlblk); 1827 return (error); 1828 } 1829 1830 static int 1831 verify_pool(zone_dochandle_t handle) 1832 { 1833 char poolname[MAXPATHLEN]; 1834 pool_conf_t *poolconf; 1835 pool_t *pool; 1836 int status; 1837 int error; 1838 1839 /* 1840 * This ends up being very similar to the check done in zoneadmd. 1841 */ 1842 error = zonecfg_get_pool(handle, poolname, sizeof (poolname)); 1843 if (error == Z_NO_ENTRY || (error == Z_OK && strlen(poolname) == 0)) { 1844 /* 1845 * No pool specified. 1846 */ 1847 return (0); 1848 } 1849 if (error != Z_OK) { 1850 zperror(gettext("Unable to retrieve pool name from " 1851 "configuration"), B_TRUE); 1852 return (error); 1853 } 1854 /* 1855 * Don't do anything if pools aren't enabled. 1856 */ 1857 if (pool_get_status(&status) != PO_SUCCESS || status != POOL_ENABLED) { 1858 zerror(gettext("WARNING: pools facility not active; " 1859 "zone will not be bound to pool '%s'."), poolname); 1860 return (Z_OK); 1861 } 1862 /* 1863 * Try to provide a sane error message if the requested pool doesn't 1864 * exist. It isn't clear that pools-related failures should 1865 * necessarily translate to a failure to verify the zone configuration, 1866 * hence they are not considered errors. 1867 */ 1868 if ((poolconf = pool_conf_alloc()) == NULL) { 1869 zerror(gettext("WARNING: pool_conf_alloc failed; " 1870 "using default pool")); 1871 return (Z_OK); 1872 } 1873 if (pool_conf_open(poolconf, pool_dynamic_location(), PO_RDONLY) != 1874 PO_SUCCESS) { 1875 zerror(gettext("WARNING: pool_conf_open failed; " 1876 "using default pool")); 1877 pool_conf_free(poolconf); 1878 return (Z_OK); 1879 } 1880 pool = pool_get_pool(poolconf, poolname); 1881 (void) pool_conf_close(poolconf); 1882 pool_conf_free(poolconf); 1883 if (pool == NULL) { 1884 zerror(gettext("WARNING: pool '%s' not found. " 1885 "using default pool"), poolname); 1886 } 1887 1888 return (Z_OK); 1889 } 1890 1891 static int 1892 verify_ipd(zone_dochandle_t handle) 1893 { 1894 int return_code = Z_OK; 1895 struct zone_fstab fstab; 1896 struct stat st; 1897 char specdir[MAXPATHLEN]; 1898 1899 if (zonecfg_setipdent(handle) != Z_OK) { 1900 /* 1901 * TRANSLATION_NOTE 1902 * inherit-pkg-dirs is a literal that should not be translated. 1903 */ 1904 (void) fprintf(stderr, gettext("could not verify " 1905 "inherit-pkg-dirs: unable to enumerate mounts\n")); 1906 return (Z_ERR); 1907 } 1908 while (zonecfg_getipdent(handle, &fstab) == Z_OK) { 1909 /* 1910 * Verify fs_dir exists. 1911 */ 1912 (void) snprintf(specdir, sizeof (specdir), "%s%s", 1913 zonecfg_get_root(), fstab.zone_fs_dir); 1914 if (stat(specdir, &st) != 0) { 1915 /* 1916 * TRANSLATION_NOTE 1917 * inherit-pkg-dir is a literal that should not be 1918 * translated. 1919 */ 1920 (void) fprintf(stderr, gettext("could not verify " 1921 "inherit-pkg-dir %s: %s\n"), 1922 fstab.zone_fs_dir, strerror(errno)); 1923 return_code = Z_ERR; 1924 } 1925 if (strcmp(st.st_fstype, MNTTYPE_NFS) == 0) { 1926 /* 1927 * TRANSLATION_NOTE 1928 * inherit-pkg-dir and NFS are literals that should 1929 * not be translated. 1930 */ 1931 (void) fprintf(stderr, gettext("cannot verify " 1932 "inherit-pkg-dir %s: NFS mounted file-system.\n" 1933 "\tA local file-system must be used.\n"), 1934 fstab.zone_fs_dir); 1935 return_code = Z_ERR; 1936 } 1937 } 1938 (void) zonecfg_endipdent(handle); 1939 1940 return (return_code); 1941 } 1942 1943 /* ARGSUSED */ 1944 static void 1945 zfs_fs_err_handler(const char *fmt, va_list ap) 1946 { 1947 /* 1948 * Do nothing - do not print the libzfs error messages. 1949 */ 1950 } 1951 1952 /* 1953 * Verify that the ZFS dataset exists, and its mountpoint 1954 * property is set to "legacy". 1955 */ 1956 static int 1957 verify_fs_zfs(struct zone_fstab *fstab) 1958 { 1959 zfs_handle_t *zhp; 1960 char propbuf[ZFS_MAXPROPLEN]; 1961 1962 zfs_set_error_handler(zfs_fs_err_handler); 1963 1964 if ((zhp = zfs_open(fstab->zone_fs_special, ZFS_TYPE_ANY)) == NULL) { 1965 (void) fprintf(stderr, gettext("could not verify fs %s: " 1966 "could not access zfs dataset '%s'\n"), 1967 fstab->zone_fs_dir, fstab->zone_fs_special); 1968 return (Z_ERR); 1969 } 1970 1971 if (zfs_get_type(zhp) != ZFS_TYPE_FILESYSTEM) { 1972 (void) fprintf(stderr, gettext("cannot verify fs %s: " 1973 "'%s' is not a filesystem\n"), 1974 fstab->zone_fs_dir, fstab->zone_fs_special); 1975 zfs_close(zhp); 1976 return (Z_ERR); 1977 } 1978 1979 if (zfs_prop_get(zhp, ZFS_PROP_MOUNTPOINT, propbuf, sizeof (propbuf), 1980 NULL, NULL, 0, 0) != 0 || strcmp(propbuf, "legacy") != 0) { 1981 (void) fprintf(stderr, gettext("could not verify fs %s: " 1982 "zfs '%s' mountpoint is not \"legacy\"\n"), 1983 fstab->zone_fs_dir, fstab->zone_fs_special); 1984 zfs_close(zhp); 1985 return (Z_ERR); 1986 } 1987 1988 zfs_close(zhp); 1989 return (Z_OK); 1990 } 1991 1992 /* 1993 * Verify that the special device/filesystem exists and is valid. 1994 */ 1995 static int 1996 verify_fs_special(struct zone_fstab *fstab) 1997 { 1998 struct stat st; 1999 2000 if (strcmp(fstab->zone_fs_type, MNTTYPE_ZFS) == 0) 2001 return (verify_fs_zfs(fstab)); 2002 2003 if (stat(fstab->zone_fs_special, &st) != 0) { 2004 (void) fprintf(stderr, gettext("could not verify fs " 2005 "%s: could not access %s: %s\n"), fstab->zone_fs_dir, 2006 fstab->zone_fs_special, strerror(errno)); 2007 return (Z_ERR); 2008 } 2009 2010 if (strcmp(st.st_fstype, MNTTYPE_NFS) == 0) { 2011 /* 2012 * TRANSLATION_NOTE 2013 * fs and NFS are literals that should 2014 * not be translated. 2015 */ 2016 (void) fprintf(stderr, gettext("cannot verify " 2017 "fs %s: NFS mounted file-system.\n" 2018 "\tA local file-system must be used.\n"), 2019 fstab->zone_fs_special); 2020 return (Z_ERR); 2021 } 2022 2023 return (Z_OK); 2024 } 2025 2026 static int 2027 verify_filesystems(zone_dochandle_t handle) 2028 { 2029 int return_code = Z_OK; 2030 struct zone_fstab fstab; 2031 char cmdbuf[MAXPATHLEN]; 2032 struct stat st; 2033 2034 /* 2035 * No need to verify inherit-pkg-dir fs types, as their type is 2036 * implicitly lofs, which is known. Therefore, the types are only 2037 * verified for regular filesystems below. 2038 * 2039 * Since the actual mount point is not known until the dependent mounts 2040 * are performed, we don't attempt any path validation here: that will 2041 * happen later when zoneadmd actually does the mounts. 2042 */ 2043 if (zonecfg_setfsent(handle) != Z_OK) { 2044 (void) fprintf(stderr, gettext("could not verify file-systems: " 2045 "unable to enumerate mounts\n")); 2046 return (Z_ERR); 2047 } 2048 while (zonecfg_getfsent(handle, &fstab) == Z_OK) { 2049 if (!zonecfg_valid_fs_type(fstab.zone_fs_type)) { 2050 (void) fprintf(stderr, gettext("cannot verify fs %s: " 2051 "type %s is not allowed.\n"), fstab.zone_fs_dir, 2052 fstab.zone_fs_type); 2053 return_code = Z_ERR; 2054 goto next_fs; 2055 } 2056 /* 2057 * Verify /usr/lib/fs/<fstype>/mount exists. 2058 */ 2059 if (snprintf(cmdbuf, sizeof (cmdbuf), "/usr/lib/fs/%s/mount", 2060 fstab.zone_fs_type) > sizeof (cmdbuf)) { 2061 (void) fprintf(stderr, gettext("cannot verify fs %s: " 2062 "type %s is too long.\n"), fstab.zone_fs_dir, 2063 fstab.zone_fs_type); 2064 return_code = Z_ERR; 2065 goto next_fs; 2066 } 2067 if (stat(cmdbuf, &st) != 0) { 2068 (void) fprintf(stderr, gettext("could not verify fs " 2069 "%s: could not access %s: %s\n"), fstab.zone_fs_dir, 2070 cmdbuf, strerror(errno)); 2071 return_code = Z_ERR; 2072 goto next_fs; 2073 } 2074 if (!S_ISREG(st.st_mode)) { 2075 (void) fprintf(stderr, gettext("could not verify fs " 2076 "%s: %s is not a regular file\n"), 2077 fstab.zone_fs_dir, cmdbuf); 2078 return_code = Z_ERR; 2079 goto next_fs; 2080 } 2081 /* 2082 * Verify /usr/lib/fs/<fstype>/fsck exists iff zone_fs_raw is 2083 * set. 2084 */ 2085 if (snprintf(cmdbuf, sizeof (cmdbuf), "/usr/lib/fs/%s/fsck", 2086 fstab.zone_fs_type) > sizeof (cmdbuf)) { 2087 (void) fprintf(stderr, gettext("cannot verify fs %s: " 2088 "type %s is too long.\n"), fstab.zone_fs_dir, 2089 fstab.zone_fs_type); 2090 return_code = Z_ERR; 2091 goto next_fs; 2092 } 2093 if (fstab.zone_fs_raw[0] == '\0' && stat(cmdbuf, &st) == 0) { 2094 (void) fprintf(stderr, gettext("could not verify fs " 2095 "%s: must specify 'raw' device for %s " 2096 "file-systems\n"), 2097 fstab.zone_fs_dir, fstab.zone_fs_type); 2098 return_code = Z_ERR; 2099 goto next_fs; 2100 } 2101 if (fstab.zone_fs_raw[0] != '\0' && 2102 (stat(cmdbuf, &st) != 0 || !S_ISREG(st.st_mode))) { 2103 (void) fprintf(stderr, gettext("cannot verify fs %s: " 2104 "'raw' device specified but " 2105 "no fsck executable exists for %s\n"), 2106 fstab.zone_fs_dir, fstab.zone_fs_type); 2107 return_code = Z_ERR; 2108 goto next_fs; 2109 } 2110 2111 /* Verify fs_special. */ 2112 if ((return_code = verify_fs_special(&fstab)) != Z_OK) 2113 goto next_fs; 2114 2115 /* Verify fs_raw. */ 2116 if (fstab.zone_fs_raw[0] != '\0' && 2117 stat(fstab.zone_fs_raw, &st) != 0) { 2118 /* 2119 * TRANSLATION_NOTE 2120 * fs is a literal that should not be translated. 2121 */ 2122 (void) fprintf(stderr, gettext("could not verify fs " 2123 "%s: could not access %s: %s\n"), fstab.zone_fs_dir, 2124 fstab.zone_fs_raw, strerror(errno)); 2125 return_code = Z_ERR; 2126 goto next_fs; 2127 } 2128 next_fs: 2129 zonecfg_free_fs_option_list(fstab.zone_fs_options); 2130 } 2131 (void) zonecfg_endfsent(handle); 2132 2133 return (return_code); 2134 } 2135 2136 const char *current_dataset; 2137 2138 /* 2139 * Custom error handler for errors incurred as part of the checks below. We 2140 * want to trim off the leading 'cannot open ...' to create a better error 2141 * message. The only other way this can fail is if we fail to set the 'zoned' 2142 * property. In this case we just pass the error on verbatim. 2143 */ 2144 static void 2145 zfs_error_handler(const char *fmt, va_list ap) 2146 { 2147 char buf[1024]; 2148 2149 (void) vsnprintf(buf, sizeof (buf), fmt, ap); 2150 2151 if (strncmp(gettext("cannot open "), buf, 2152 strlen(gettext("cannot open "))) == 0) 2153 /* 2154 * TRANSLATION_NOTE 2155 * zfs and dataset are literals that should not be translated. 2156 */ 2157 (void) fprintf(stderr, gettext("could not verify zfs " 2158 "dataset %s%s\n"), current_dataset, strchr(buf, ':')); 2159 else 2160 (void) fprintf(stderr, gettext("could not verify zfs dataset " 2161 "%s: %s\n"), current_dataset, buf); 2162 } 2163 2164 /* ARGSUSED */ 2165 static int 2166 check_zvol(zfs_handle_t *zhp, void *unused) 2167 { 2168 int ret; 2169 2170 if (zfs_get_type(zhp) == ZFS_TYPE_VOLUME) { 2171 /* 2172 * TRANSLATION_NOTE 2173 * zfs and dataset are literals that should not be translated. 2174 */ 2175 (void) fprintf(stderr, gettext("cannot verify zfs dataset %s: " 2176 "volumes cannot be specified as a zone dataset resource\n"), 2177 zfs_get_name(zhp)); 2178 ret = -1; 2179 } else { 2180 ret = zfs_iter_children(zhp, check_zvol, NULL); 2181 } 2182 2183 zfs_close(zhp); 2184 2185 return (ret); 2186 } 2187 2188 /* 2189 * Validate that the given dataset exists on the system, and that neither it nor 2190 * its children are zvols. 2191 * 2192 * Note that we don't do anything with the 'zoned' property here. All 2193 * management is done in zoneadmd when the zone is actually rebooted. This 2194 * allows us to automatically set the zoned property even when a zone is 2195 * rebooted by the administrator. 2196 */ 2197 static int 2198 verify_datasets(zone_dochandle_t handle) 2199 { 2200 int return_code = Z_OK; 2201 struct zone_dstab dstab; 2202 zfs_handle_t *zhp; 2203 char propbuf[ZFS_MAXPROPLEN]; 2204 char source[ZFS_MAXNAMELEN]; 2205 zfs_source_t srctype; 2206 2207 if (zonecfg_setdsent(handle) != Z_OK) { 2208 /* 2209 * TRANSLATION_NOTE 2210 * zfs and dataset are literals that should not be translated. 2211 */ 2212 (void) fprintf(stderr, gettext("could not verify zfs datasets: " 2213 "unable to enumerate datasets\n")); 2214 return (Z_ERR); 2215 } 2216 2217 zfs_set_error_handler(zfs_error_handler); 2218 2219 while (zonecfg_getdsent(handle, &dstab) == Z_OK) { 2220 2221 current_dataset = dstab.zone_dataset_name; 2222 2223 if ((zhp = zfs_open(dstab.zone_dataset_name, 2224 ZFS_TYPE_FILESYSTEM | ZFS_TYPE_VOLUME)) == NULL) { 2225 return_code = Z_ERR; 2226 continue; 2227 } 2228 2229 if (zfs_prop_get(zhp, ZFS_PROP_MOUNTPOINT, propbuf, 2230 sizeof (propbuf), &srctype, source, 2231 sizeof (source), 0) == 0 && 2232 (srctype == ZFS_SRC_INHERITED)) { 2233 (void) fprintf(stderr, gettext("could not verify zfs " 2234 "dataset %s: mountpoint cannot be inherited\n"), 2235 dstab.zone_dataset_name); 2236 return_code = Z_ERR; 2237 zfs_close(zhp); 2238 continue; 2239 } 2240 2241 if (zfs_get_type(zhp) == ZFS_TYPE_VOLUME) { 2242 (void) fprintf(stderr, gettext("cannot verify zfs " 2243 "dataset %s: volumes cannot be specified as a " 2244 "zone dataset resource\n"), 2245 dstab.zone_dataset_name); 2246 return_code = Z_ERR; 2247 } 2248 2249 if (zfs_iter_children(zhp, check_zvol, NULL) != 0) 2250 return_code = Z_ERR; 2251 2252 zfs_close(zhp); 2253 } 2254 (void) zonecfg_enddsent(handle); 2255 2256 return (return_code); 2257 } 2258 2259 static int 2260 verify_details(int cmd_num) 2261 { 2262 zone_dochandle_t handle; 2263 struct zone_nwiftab nwiftab; 2264 char zonepath[MAXPATHLEN], checkpath[MAXPATHLEN]; 2265 int return_code = Z_OK; 2266 int err; 2267 boolean_t in_alt_root; 2268 2269 if ((handle = zonecfg_init_handle()) == NULL) { 2270 zperror(cmd_to_str(cmd_num), B_TRUE); 2271 return (Z_ERR); 2272 } 2273 if ((err = zonecfg_get_handle(target_zone, handle)) != Z_OK) { 2274 errno = err; 2275 zperror(cmd_to_str(cmd_num), B_TRUE); 2276 zonecfg_fini_handle(handle); 2277 return (Z_ERR); 2278 } 2279 if ((err = zonecfg_get_zonepath(handle, zonepath, sizeof (zonepath))) != 2280 Z_OK) { 2281 errno = err; 2282 zperror(cmd_to_str(cmd_num), B_TRUE); 2283 zonecfg_fini_handle(handle); 2284 return (Z_ERR); 2285 } 2286 /* 2287 * zonecfg_get_zonepath() gets its data from the XML repository. 2288 * Verify this against the index file, which is checked first by 2289 * zone_get_zonepath(). If they don't match, bail out. 2290 */ 2291 if ((err = zone_get_zonepath(target_zone, checkpath, 2292 sizeof (checkpath))) != Z_OK) { 2293 errno = err; 2294 zperror2(target_zone, gettext("could not get zone path")); 2295 return (Z_ERR); 2296 } 2297 if (strcmp(zonepath, checkpath) != 0) { 2298 /* 2299 * TRANSLATION_NOTE 2300 * XML and zonepath are literals that should not be translated. 2301 */ 2302 (void) fprintf(stderr, gettext("The XML repository has " 2303 "zonepath '%s',\nbut the index file has zonepath '%s'.\n" 2304 "These must match, so fix the incorrect entry.\n"), 2305 zonepath, checkpath); 2306 return (Z_ERR); 2307 } 2308 if (validate_zonepath(zonepath, cmd_num) != Z_OK) { 2309 (void) fprintf(stderr, gettext("could not verify zonepath %s " 2310 "because of the above errors.\n"), zonepath); 2311 return_code = Z_ERR; 2312 } 2313 2314 in_alt_root = zonecfg_in_alt_root(); 2315 if (in_alt_root) 2316 goto no_net; 2317 2318 if ((err = zonecfg_setnwifent(handle)) != Z_OK) { 2319 errno = err; 2320 zperror(cmd_to_str(cmd_num), B_TRUE); 2321 zonecfg_fini_handle(handle); 2322 return (Z_ERR); 2323 } 2324 while (zonecfg_getnwifent(handle, &nwiftab) == Z_OK) { 2325 struct lifreq lifr; 2326 sa_family_t af; 2327 int so, res; 2328 2329 /* skip any loopback interfaces */ 2330 if (strcmp(nwiftab.zone_nwif_physical, "lo0") == 0) 2331 continue; 2332 if ((res = zonecfg_valid_net_address(nwiftab.zone_nwif_address, 2333 &lifr)) != Z_OK) { 2334 (void) fprintf(stderr, gettext("could not verify %s " 2335 "%s=%s %s=%s: %s\n"), "net", "address", 2336 nwiftab.zone_nwif_address, "physical", 2337 nwiftab.zone_nwif_physical, zonecfg_strerror(res)); 2338 return_code = Z_ERR; 2339 continue; 2340 } 2341 af = lifr.lifr_addr.ss_family; 2342 (void) memset(&lifr, 0, sizeof (lifr)); 2343 (void) strlcpy(lifr.lifr_name, nwiftab.zone_nwif_physical, 2344 sizeof (lifr.lifr_name)); 2345 lifr.lifr_addr.ss_family = af; 2346 if ((so = socket(af, SOCK_DGRAM, 0)) < 0) { 2347 (void) fprintf(stderr, gettext("could not verify %s " 2348 "%s=%s %s=%s: could not get socket: %s\n"), "net", 2349 "address", nwiftab.zone_nwif_address, "physical", 2350 nwiftab.zone_nwif_physical, strerror(errno)); 2351 return_code = Z_ERR; 2352 continue; 2353 } 2354 if (ioctl(so, SIOCGLIFFLAGS, (caddr_t)&lifr) < 0) { 2355 (void) fprintf(stderr, 2356 gettext("could not verify %s %s=%s %s=%s: %s\n"), 2357 "net", "address", nwiftab.zone_nwif_address, 2358 "physical", nwiftab.zone_nwif_physical, 2359 strerror(errno)); 2360 return_code = Z_ERR; 2361 } 2362 (void) close(so); 2363 } 2364 (void) zonecfg_endnwifent(handle); 2365 no_net: 2366 2367 if (verify_filesystems(handle) != Z_OK) 2368 return_code = Z_ERR; 2369 if (verify_ipd(handle) != Z_OK) 2370 return_code = Z_ERR; 2371 if (!in_alt_root && verify_rctls(handle) != Z_OK) 2372 return_code = Z_ERR; 2373 if (!in_alt_root && verify_pool(handle) != Z_OK) 2374 return_code = Z_ERR; 2375 if (!in_alt_root && verify_datasets(handle) != Z_OK) 2376 return_code = Z_ERR; 2377 zonecfg_fini_handle(handle); 2378 if (return_code == Z_ERR) 2379 (void) fprintf(stderr, 2380 gettext("%s: zone %s failed to verify\n"), 2381 execname, target_zone); 2382 return (return_code); 2383 } 2384 2385 static int 2386 verify_func(int argc, char *argv[]) 2387 { 2388 int arg; 2389 2390 optind = 0; 2391 if ((arg = getopt(argc, argv, "?")) != EOF) { 2392 switch (arg) { 2393 case '?': 2394 sub_usage(SHELP_VERIFY, CMD_VERIFY); 2395 return (optopt == '?' ? Z_OK : Z_USAGE); 2396 default: 2397 sub_usage(SHELP_VERIFY, CMD_VERIFY); 2398 return (Z_USAGE); 2399 } 2400 } 2401 if (argc > optind) { 2402 sub_usage(SHELP_VERIFY, CMD_VERIFY); 2403 return (Z_USAGE); 2404 } 2405 if (sanity_check(target_zone, CMD_VERIFY, B_FALSE, B_FALSE) != Z_OK) 2406 return (Z_ERR); 2407 return (verify_details(CMD_VERIFY)); 2408 } 2409 2410 #define LUCREATEZONE "/usr/lib/lu/lucreatezone" 2411 2412 static int 2413 install_func(int argc, char *argv[]) 2414 { 2415 /* 9: "exec " and " -z " */ 2416 char cmdbuf[sizeof (LUCREATEZONE) + ZONENAME_MAX + 9]; 2417 int lockfd; 2418 int err, arg; 2419 char zonepath[MAXPATHLEN]; 2420 int status; 2421 2422 if (zonecfg_in_alt_root()) { 2423 zerror(gettext("cannot install zone in alternate root")); 2424 return (Z_ERR); 2425 } 2426 2427 optind = 0; 2428 if ((arg = getopt(argc, argv, "?")) != EOF) { 2429 switch (arg) { 2430 case '?': 2431 sub_usage(SHELP_INSTALL, CMD_INSTALL); 2432 return (optopt == '?' ? Z_OK : Z_USAGE); 2433 default: 2434 sub_usage(SHELP_INSTALL, CMD_INSTALL); 2435 return (Z_USAGE); 2436 } 2437 } 2438 if (argc > optind) { 2439 sub_usage(SHELP_INSTALL, CMD_INSTALL); 2440 return (Z_USAGE); 2441 } 2442 if (sanity_check(target_zone, CMD_INSTALL, B_FALSE, B_TRUE) != Z_OK) 2443 return (Z_ERR); 2444 if (verify_details(CMD_INSTALL) != Z_OK) 2445 return (Z_ERR); 2446 2447 if (grab_lock_file(target_zone, &lockfd) != Z_OK) { 2448 zerror(gettext("another %s may have an operation in progress."), 2449 "zoneadm"); 2450 return (Z_ERR); 2451 } 2452 err = zone_set_state(target_zone, ZONE_STATE_INCOMPLETE); 2453 if (err != Z_OK) { 2454 errno = err; 2455 zperror2(target_zone, gettext("could not set state")); 2456 goto done; 2457 } 2458 2459 /* 2460 * According to the Application Packaging Developer's Guide, a 2461 * "checkinstall" script when included in a package is executed as 2462 * the user "install", if such a user exists, or by the user 2463 * "nobody". In order to support this dubious behavior, the path 2464 * to the zone being constructed is opened up during the life of 2465 * the command laying down the zone's root file system. Once this 2466 * has completed, regardless of whether it was successful, the 2467 * path to the zone is again restricted. 2468 */ 2469 if ((err = zone_get_zonepath(target_zone, zonepath, 2470 sizeof (zonepath))) != Z_OK) { 2471 errno = err; 2472 zperror2(target_zone, gettext("could not get zone path")); 2473 goto done; 2474 } 2475 if (chmod(zonepath, DEFAULT_DIR_MODE) != 0) { 2476 zperror(zonepath, B_FALSE); 2477 err = Z_ERR; 2478 goto done; 2479 } 2480 2481 /* 2482 * "exec" the command so that the returned status is that of 2483 * LUCREATEZONE and not the shell. 2484 */ 2485 (void) snprintf(cmdbuf, sizeof (cmdbuf), "exec " LUCREATEZONE " -z %s", 2486 target_zone); 2487 status = do_subproc(cmdbuf); 2488 if (chmod(zonepath, S_IRWXU) != 0) { 2489 zperror(zonepath, B_FALSE); 2490 err = Z_ERR; 2491 goto done; 2492 } 2493 if ((err = subproc_status(LUCREATEZONE, status)) != Z_OK) 2494 goto done; 2495 2496 if ((err = zone_set_state(target_zone, ZONE_STATE_INSTALLED)) != Z_OK) { 2497 errno = err; 2498 zperror2(target_zone, gettext("could not set state")); 2499 goto done; 2500 } 2501 2502 done: 2503 release_lock_file(lockfd); 2504 return ((err == Z_OK) ? Z_OK : Z_ERR); 2505 } 2506 2507 /* 2508 * Check that the inherited pkg dirs are the same for the clone and its source. 2509 * The easiest way to do that is check that the list of ipds is the same 2510 * by matching each one against the other. This algorithm should be fine since 2511 * the list of ipds should not be that long. 2512 */ 2513 static int 2514 valid_ipd_clone(zone_dochandle_t s_handle, char *source_zone, 2515 zone_dochandle_t t_handle, char *target_zone) 2516 { 2517 int err; 2518 int res = Z_OK; 2519 int s_cnt = 0; 2520 int t_cnt = 0; 2521 struct zone_fstab s_fstab; 2522 struct zone_fstab t_fstab; 2523 2524 /* 2525 * First check the source of the clone against the target. 2526 */ 2527 if ((err = zonecfg_setipdent(s_handle)) != Z_OK) { 2528 errno = err; 2529 zperror2(source_zone, gettext("could not enumerate " 2530 "inherit-pkg-dirs")); 2531 return (Z_ERR); 2532 } 2533 2534 while (zonecfg_getipdent(s_handle, &s_fstab) == Z_OK) { 2535 boolean_t match = B_FALSE; 2536 2537 s_cnt++; 2538 2539 if ((err = zonecfg_setipdent(t_handle)) != Z_OK) { 2540 errno = err; 2541 zperror2(target_zone, gettext("could not enumerate " 2542 "inherit-pkg-dirs")); 2543 (void) zonecfg_endipdent(s_handle); 2544 return (Z_ERR); 2545 } 2546 2547 while (zonecfg_getipdent(t_handle, &t_fstab) == Z_OK) { 2548 if (strcmp(s_fstab.zone_fs_dir, t_fstab.zone_fs_dir) 2549 == 0) { 2550 match = B_TRUE; 2551 break; 2552 } 2553 } 2554 (void) zonecfg_endipdent(t_handle); 2555 2556 if (!match) { 2557 (void) fprintf(stderr, gettext("inherit-pkg-dir " 2558 "'%s' is not configured in zone %s.\n"), 2559 s_fstab.zone_fs_dir, target_zone); 2560 res = Z_ERR; 2561 } 2562 } 2563 2564 (void) zonecfg_endipdent(s_handle); 2565 2566 /* skip the next check if we already have errors */ 2567 if (res == Z_ERR) 2568 return (res); 2569 2570 /* 2571 * Now check the number of ipds in the target so we can verify 2572 * that the source is not a subset of the target. 2573 */ 2574 if ((err = zonecfg_setipdent(t_handle)) != Z_OK) { 2575 errno = err; 2576 zperror2(target_zone, gettext("could not enumerate " 2577 "inherit-pkg-dirs")); 2578 return (Z_ERR); 2579 } 2580 2581 while (zonecfg_getipdent(t_handle, &t_fstab) == Z_OK) 2582 t_cnt++; 2583 2584 (void) zonecfg_endipdent(t_handle); 2585 2586 if (t_cnt != s_cnt) { 2587 (void) fprintf(stderr, gettext("Zone %s is configured " 2588 "with inherit-pkg-dirs that are not configured in zone " 2589 "%s.\n"), target_zone, source_zone); 2590 res = Z_ERR; 2591 } 2592 2593 return (res); 2594 } 2595 2596 static void 2597 warn_dev_match(zone_dochandle_t s_handle, char *source_zone, 2598 zone_dochandle_t t_handle, char *target_zone) 2599 { 2600 int err; 2601 struct zone_devtab s_devtab; 2602 struct zone_devtab t_devtab; 2603 2604 if ((err = zonecfg_setdevent(t_handle)) != Z_OK) { 2605 errno = err; 2606 zperror2(target_zone, gettext("could not enumerate devices")); 2607 return; 2608 } 2609 2610 while (zonecfg_getdevent(t_handle, &t_devtab) == Z_OK) { 2611 if ((err = zonecfg_setdevent(s_handle)) != Z_OK) { 2612 errno = err; 2613 zperror2(source_zone, 2614 gettext("could not enumerate devices")); 2615 (void) zonecfg_enddevent(t_handle); 2616 return; 2617 } 2618 2619 while (zonecfg_getdevent(s_handle, &s_devtab) == Z_OK) { 2620 /* 2621 * Use fnmatch to catch the case where wildcards 2622 * were used in one zone and the other has an 2623 * explicit entry (e.g. /dev/dsk/c0t0d0s6 vs. 2624 * /dev/\*dsk/c0t0d0s6). 2625 */ 2626 if (fnmatch(t_devtab.zone_dev_match, 2627 s_devtab.zone_dev_match, FNM_PATHNAME) == 0 || 2628 fnmatch(s_devtab.zone_dev_match, 2629 t_devtab.zone_dev_match, FNM_PATHNAME) == 0) { 2630 (void) fprintf(stderr, 2631 gettext("WARNING: device '%s' " 2632 "is configured in both zones.\n"), 2633 t_devtab.zone_dev_match); 2634 break; 2635 } 2636 } 2637 (void) zonecfg_enddevent(s_handle); 2638 } 2639 2640 (void) zonecfg_enddevent(t_handle); 2641 } 2642 2643 /* 2644 * Check if the specified mount option (opt) is contained within the 2645 * options string. 2646 */ 2647 static boolean_t 2648 opt_match(char *opt, char *options) 2649 { 2650 char *p; 2651 char *lastp; 2652 2653 if ((p = strtok_r(options, ",", &lastp)) != NULL) { 2654 if (strcmp(p, opt) == 0) 2655 return (B_TRUE); 2656 while ((p = strtok_r(NULL, ",", &lastp)) != NULL) { 2657 if (strcmp(p, opt) == 0) 2658 return (B_TRUE); 2659 } 2660 } 2661 2662 return (B_FALSE); 2663 } 2664 2665 #define RW_LOFS "WARNING: read-write lofs file-system on '%s' is configured " \ 2666 "in both zones.\n" 2667 2668 static void 2669 print_fs_warnings(struct zone_fstab *s_fstab, struct zone_fstab *t_fstab) 2670 { 2671 /* 2672 * It is ok to have shared lofs mounted fs but we want to warn if 2673 * either is rw since this will effect the other zone. 2674 */ 2675 if (strcmp(t_fstab->zone_fs_type, "lofs") == 0) { 2676 zone_fsopt_t *optp; 2677 2678 /* The default is rw so no options means rw */ 2679 if (t_fstab->zone_fs_options == NULL || 2680 s_fstab->zone_fs_options == NULL) { 2681 (void) fprintf(stderr, gettext(RW_LOFS), 2682 t_fstab->zone_fs_special); 2683 return; 2684 } 2685 2686 for (optp = s_fstab->zone_fs_options; optp != NULL; 2687 optp = optp->zone_fsopt_next) { 2688 if (opt_match("rw", optp->zone_fsopt_opt)) { 2689 (void) fprintf(stderr, gettext(RW_LOFS), 2690 s_fstab->zone_fs_special); 2691 return; 2692 } 2693 } 2694 2695 for (optp = t_fstab->zone_fs_options; optp != NULL; 2696 optp = optp->zone_fsopt_next) { 2697 if (opt_match("rw", optp->zone_fsopt_opt)) { 2698 (void) fprintf(stderr, gettext(RW_LOFS), 2699 t_fstab->zone_fs_special); 2700 return; 2701 } 2702 } 2703 2704 return; 2705 } 2706 2707 /* 2708 * TRANSLATION_NOTE 2709 * The first variable is the file-system type and the second is 2710 * the file-system special device. For example, 2711 * WARNING: ufs file-system on '/dev/dsk/c0t0d0s0' ... 2712 */ 2713 (void) fprintf(stderr, gettext("WARNING: %s file-system on '%s' " 2714 "is configured in both zones.\n"), t_fstab->zone_fs_type, 2715 t_fstab->zone_fs_special); 2716 } 2717 2718 static void 2719 warn_fs_match(zone_dochandle_t s_handle, char *source_zone, 2720 zone_dochandle_t t_handle, char *target_zone) 2721 { 2722 int err; 2723 struct zone_fstab s_fstab; 2724 struct zone_fstab t_fstab; 2725 2726 if ((err = zonecfg_setfsent(t_handle)) != Z_OK) { 2727 errno = err; 2728 zperror2(target_zone, 2729 gettext("could not enumerate file-systems")); 2730 return; 2731 } 2732 2733 while (zonecfg_getfsent(t_handle, &t_fstab) == Z_OK) { 2734 if ((err = zonecfg_setfsent(s_handle)) != Z_OK) { 2735 errno = err; 2736 zperror2(source_zone, 2737 gettext("could not enumerate file-systems")); 2738 (void) zonecfg_endfsent(t_handle); 2739 return; 2740 } 2741 2742 while (zonecfg_getfsent(s_handle, &s_fstab) == Z_OK) { 2743 if (strcmp(t_fstab.zone_fs_special, 2744 s_fstab.zone_fs_special) == 0) { 2745 print_fs_warnings(&s_fstab, &t_fstab); 2746 break; 2747 } 2748 } 2749 (void) zonecfg_endfsent(s_handle); 2750 } 2751 2752 (void) zonecfg_endfsent(t_handle); 2753 } 2754 2755 /* 2756 * We don't catch the case where you used the same IP address but 2757 * it is not an exact string match. For example, 192.9.0.128 vs. 192.09.0.128. 2758 * However, we're not going to worry about that but we will check for 2759 * a possible netmask on one of the addresses (e.g. 10.0.0.1 and 10.0.0.1/24) 2760 * and handle that case as a match. 2761 */ 2762 static void 2763 warn_ip_match(zone_dochandle_t s_handle, char *source_zone, 2764 zone_dochandle_t t_handle, char *target_zone) 2765 { 2766 int err; 2767 struct zone_nwiftab s_nwiftab; 2768 struct zone_nwiftab t_nwiftab; 2769 2770 if ((err = zonecfg_setnwifent(t_handle)) != Z_OK) { 2771 errno = err; 2772 zperror2(target_zone, 2773 gettext("could not enumerate network interfaces")); 2774 return; 2775 } 2776 2777 while (zonecfg_getnwifent(t_handle, &t_nwiftab) == Z_OK) { 2778 char *p; 2779 2780 /* remove an (optional) netmask from the address */ 2781 if ((p = strchr(t_nwiftab.zone_nwif_address, '/')) != NULL) 2782 *p = '\0'; 2783 2784 if ((err = zonecfg_setnwifent(s_handle)) != Z_OK) { 2785 errno = err; 2786 zperror2(source_zone, 2787 gettext("could not enumerate network interfaces")); 2788 (void) zonecfg_endnwifent(t_handle); 2789 return; 2790 } 2791 2792 while (zonecfg_getnwifent(s_handle, &s_nwiftab) == Z_OK) { 2793 /* remove an (optional) netmask from the address */ 2794 if ((p = strchr(s_nwiftab.zone_nwif_address, '/')) 2795 != NULL) 2796 *p = '\0'; 2797 2798 if (strcmp(t_nwiftab.zone_nwif_address, 2799 s_nwiftab.zone_nwif_address) == 0) { 2800 (void) fprintf(stderr, 2801 gettext("WARNING: network address '%s' " 2802 "is configured in both zones.\n"), 2803 t_nwiftab.zone_nwif_address); 2804 break; 2805 } 2806 } 2807 (void) zonecfg_endnwifent(s_handle); 2808 } 2809 2810 (void) zonecfg_endnwifent(t_handle); 2811 } 2812 2813 static void 2814 warn_dataset_match(zone_dochandle_t s_handle, char *source_zone, 2815 zone_dochandle_t t_handle, char *target_zone) 2816 { 2817 int err; 2818 struct zone_dstab s_dstab; 2819 struct zone_dstab t_dstab; 2820 2821 if ((err = zonecfg_setdsent(t_handle)) != Z_OK) { 2822 errno = err; 2823 zperror2(target_zone, gettext("could not enumerate datasets")); 2824 return; 2825 } 2826 2827 while (zonecfg_getdsent(t_handle, &t_dstab) == Z_OK) { 2828 if ((err = zonecfg_setdsent(s_handle)) != Z_OK) { 2829 errno = err; 2830 zperror2(source_zone, 2831 gettext("could not enumerate datasets")); 2832 (void) zonecfg_enddsent(t_handle); 2833 return; 2834 } 2835 2836 while (zonecfg_getdsent(s_handle, &s_dstab) == Z_OK) { 2837 if (strcmp(t_dstab.zone_dataset_name, 2838 s_dstab.zone_dataset_name) == 0) { 2839 (void) fprintf(stderr, 2840 gettext("WARNING: dataset '%s' " 2841 "is configured in both zones.\n"), 2842 t_dstab.zone_dataset_name); 2843 break; 2844 } 2845 } 2846 (void) zonecfg_enddsent(s_handle); 2847 } 2848 2849 (void) zonecfg_enddsent(t_handle); 2850 } 2851 2852 static int 2853 validate_clone(char *source_zone, char *target_zone) 2854 { 2855 int err = Z_OK; 2856 zone_dochandle_t s_handle; 2857 zone_dochandle_t t_handle; 2858 2859 if ((t_handle = zonecfg_init_handle()) == NULL) { 2860 zperror(cmd_to_str(CMD_CLONE), B_TRUE); 2861 return (Z_ERR); 2862 } 2863 if ((err = zonecfg_get_handle(target_zone, t_handle)) != Z_OK) { 2864 errno = err; 2865 zperror(cmd_to_str(CMD_CLONE), B_TRUE); 2866 zonecfg_fini_handle(t_handle); 2867 return (Z_ERR); 2868 } 2869 2870 if ((s_handle = zonecfg_init_handle()) == NULL) { 2871 zperror(cmd_to_str(CMD_CLONE), B_TRUE); 2872 zonecfg_fini_handle(t_handle); 2873 return (Z_ERR); 2874 } 2875 if ((err = zonecfg_get_handle(source_zone, s_handle)) != Z_OK) { 2876 errno = err; 2877 zperror(cmd_to_str(CMD_CLONE), B_TRUE); 2878 goto done; 2879 } 2880 2881 /* verify new zone has same inherit-pkg-dirs */ 2882 err = valid_ipd_clone(s_handle, source_zone, t_handle, target_zone); 2883 2884 /* warn about imported fs's which are the same */ 2885 warn_fs_match(s_handle, source_zone, t_handle, target_zone); 2886 2887 /* warn about imported IP addresses which are the same */ 2888 warn_ip_match(s_handle, source_zone, t_handle, target_zone); 2889 2890 /* warn about imported devices which are the same */ 2891 warn_dev_match(s_handle, source_zone, t_handle, target_zone); 2892 2893 /* warn about imported datasets which are the same */ 2894 warn_dataset_match(s_handle, source_zone, t_handle, target_zone); 2895 2896 done: 2897 zonecfg_fini_handle(t_handle); 2898 zonecfg_fini_handle(s_handle); 2899 2900 return ((err == Z_OK) ? Z_OK : Z_ERR); 2901 } 2902 2903 static int 2904 copy_zone(char *src, char *dst) 2905 { 2906 boolean_t out_null = B_FALSE; 2907 int status; 2908 int err; 2909 char *outfile; 2910 char cmdbuf[MAXPATHLEN * 2 + 128]; 2911 2912 if ((outfile = tempnam("/var/log", "zone")) == NULL) { 2913 outfile = "/dev/null"; 2914 out_null = B_TRUE; 2915 } 2916 2917 (void) snprintf(cmdbuf, sizeof (cmdbuf), 2918 "cd %s && /usr/bin/find . -depth -print | " 2919 "/usr/bin/cpio -pdmuP@ %s > %s 2>&1", 2920 src, dst, outfile); 2921 2922 status = do_subproc(cmdbuf); 2923 2924 if ((err = subproc_status("copy", status)) != Z_OK) { 2925 if (!out_null) 2926 (void) fprintf(stderr, gettext("\nThe copy failed.\n" 2927 "More information can be found in %s\n"), outfile); 2928 return (err); 2929 } 2930 2931 if (!out_null) 2932 (void) unlink(outfile); 2933 2934 return (Z_OK); 2935 } 2936 2937 /* 2938 * Run sys-unconfig on a zone. This will leave the zone in the installed 2939 * state as long as there were no errors during the sys-unconfig. 2940 */ 2941 static int 2942 unconfigure_zone(char *zonepath) 2943 { 2944 int err; 2945 int status; 2946 struct stat unconfig_buf; 2947 zone_cmd_arg_t zarg; 2948 char cmdbuf[MAXPATHLEN + 51]; 2949 2950 /* The zone has to be installed in order to mount the scratch zone. */ 2951 if ((err = zone_set_state(target_zone, ZONE_STATE_INSTALLED)) != Z_OK) { 2952 errno = err; 2953 zperror2(target_zone, gettext("could not set state")); 2954 return (Z_ERR); 2955 } 2956 2957 /* 2958 * Check if the zone is already sys-unconfiged. This saves us 2959 * the work of bringing up the scratch zone so we can unconfigure it. 2960 */ 2961 (void) snprintf(cmdbuf, sizeof (cmdbuf), "%s/root/etc/.UNCONFIGURED", 2962 zonepath); 2963 if (stat(cmdbuf, &unconfig_buf) == 0) 2964 return (Z_OK); 2965 2966 zarg.cmd = Z_MOUNT; 2967 if (call_zoneadmd(target_zone, &zarg) != 0) { 2968 zerror(gettext("call to %s failed"), "zoneadmd"); 2969 (void) zone_set_state(target_zone, ZONE_STATE_INCOMPLETE); 2970 return (Z_ERR); 2971 } 2972 2973 (void) snprintf(cmdbuf, sizeof (cmdbuf), 2974 "/usr/sbin/zlogin -S %s /usr/sbin/sys-unconfig -R /a", target_zone); 2975 2976 status = do_subproc(cmdbuf); 2977 if ((err = subproc_status("sys-unconfig", status)) != Z_OK) { 2978 errno = err; 2979 zperror2(target_zone, gettext("sys-unconfig failed\n")); 2980 (void) zone_set_state(target_zone, ZONE_STATE_INCOMPLETE); 2981 } 2982 2983 zarg.cmd = Z_UNMOUNT; 2984 if (call_zoneadmd(target_zone, &zarg) != 0) { 2985 zerror(gettext("call to %s failed"), "zoneadmd"); 2986 (void) fprintf(stderr, gettext("could not unmount zone\n")); 2987 return (Z_ERR); 2988 } 2989 2990 return ((err == Z_OK) ? Z_OK : Z_ERR); 2991 } 2992 2993 /* ARGSUSED */ 2994 int 2995 zfm_print(const char *p, void *r) { 2996 zerror(" %s\n", p); 2997 return (0); 2998 } 2999 3000 static int 3001 clone_func(int argc, char *argv[]) 3002 { 3003 char *source_zone = NULL; 3004 int lockfd; 3005 int err, arg; 3006 char zonepath[MAXPATHLEN]; 3007 char source_zonepath[MAXPATHLEN]; 3008 zone_state_t state; 3009 zone_entry_t *zent; 3010 char *method = "copy"; 3011 3012 if (zonecfg_in_alt_root()) { 3013 zerror(gettext("cannot clone zone in alternate root")); 3014 return (Z_ERR); 3015 } 3016 3017 optind = 0; 3018 if ((arg = getopt(argc, argv, "?m:")) != EOF) { 3019 switch (arg) { 3020 case '?': 3021 sub_usage(SHELP_CLONE, CMD_CLONE); 3022 return (optopt == '?' ? Z_OK : Z_USAGE); 3023 case 'm': 3024 method = optarg; 3025 break; 3026 default: 3027 sub_usage(SHELP_CLONE, CMD_CLONE); 3028 return (Z_USAGE); 3029 } 3030 } 3031 if (argc != (optind + 1) || strcmp(method, "copy") != 0) { 3032 sub_usage(SHELP_CLONE, CMD_CLONE); 3033 return (Z_USAGE); 3034 } 3035 source_zone = argv[optind]; 3036 if (sanity_check(target_zone, CMD_CLONE, B_FALSE, B_TRUE) != Z_OK) 3037 return (Z_ERR); 3038 if (verify_details(CMD_CLONE) != Z_OK) 3039 return (Z_ERR); 3040 3041 /* 3042 * We also need to do some extra validation on the source zone. 3043 */ 3044 3045 if (strcmp(source_zone, GLOBAL_ZONENAME) == 0) { 3046 zerror(gettext("%s operation is invalid for the global zone."), 3047 cmd_to_str(CMD_CLONE)); 3048 return (Z_ERR); 3049 } 3050 3051 if (strncmp(source_zone, "SUNW", 4) == 0) { 3052 zerror(gettext("%s operation is invalid for zones starting " 3053 "with SUNW."), cmd_to_str(CMD_CLONE)); 3054 return (Z_ERR); 3055 } 3056 3057 zent = lookup_running_zone(source_zone); 3058 if (zent != NULL) { 3059 /* check whether the zone is ready or running */ 3060 if ((err = zone_get_state(zent->zname, &zent->zstate_num)) 3061 != Z_OK) { 3062 errno = err; 3063 zperror2(zent->zname, gettext("could not get state")); 3064 /* can't tell, so hedge */ 3065 zent->zstate_str = "ready/running"; 3066 } else { 3067 zent->zstate_str = zone_state_str(zent->zstate_num); 3068 } 3069 zerror(gettext("%s operation is invalid for %s zones."), 3070 cmd_to_str(CMD_CLONE), zent->zstate_str); 3071 return (Z_ERR); 3072 } 3073 3074 if ((err = zone_get_state(source_zone, &state)) != Z_OK) { 3075 errno = err; 3076 zperror2(source_zone, gettext("could not get state")); 3077 return (Z_ERR); 3078 } 3079 if (state != ZONE_STATE_INSTALLED) { 3080 (void) fprintf(stderr, 3081 gettext("%s: zone %s is %s; %s is required.\n"), 3082 execname, source_zone, zone_state_str(state), 3083 zone_state_str(ZONE_STATE_INSTALLED)); 3084 return (Z_ERR); 3085 } 3086 3087 /* 3088 * The source zone checks out ok, continue with the clone. 3089 */ 3090 3091 if (validate_clone(source_zone, target_zone) != Z_OK) 3092 return (Z_ERR); 3093 3094 if (grab_lock_file(target_zone, &lockfd) != Z_OK) { 3095 zerror(gettext("another %s may have an operation in progress."), 3096 "zoneadm"); 3097 return (Z_ERR); 3098 } 3099 3100 if ((err = zone_get_zonepath(source_zone, source_zonepath, 3101 sizeof (source_zonepath))) != Z_OK) { 3102 errno = err; 3103 zperror2(source_zone, gettext("could not get zone path")); 3104 goto done; 3105 } 3106 3107 if ((err = zone_get_zonepath(target_zone, zonepath, sizeof (zonepath))) 3108 != Z_OK) { 3109 errno = err; 3110 zperror2(target_zone, gettext("could not get zone path")); 3111 goto done; 3112 } 3113 3114 /* Don't clone the zone if anything is still mounted there */ 3115 if (zonecfg_find_mounts(source_zonepath, NULL, NULL)) { 3116 zerror(gettext("These file-systems are mounted on " 3117 "subdirectories of %s.\n"), source_zonepath); 3118 (void) zonecfg_find_mounts(source_zonepath, zfm_print, NULL); 3119 err = Z_ERR; 3120 goto done; 3121 } 3122 3123 if ((err = zone_set_state(target_zone, ZONE_STATE_INCOMPLETE)) 3124 != Z_OK) { 3125 errno = err; 3126 zperror2(target_zone, gettext("could not set state")); 3127 goto done; 3128 } 3129 3130 (void) printf(gettext("Cloning zonepath %s..."), source_zonepath); 3131 (void) fflush(stdout); 3132 3133 err = copy_zone(source_zonepath, zonepath); 3134 (void) printf("\n"); 3135 if (err != Z_OK) 3136 goto done; 3137 3138 err = unconfigure_zone(zonepath); 3139 3140 done: 3141 release_lock_file(lockfd); 3142 return ((err == Z_OK) ? Z_OK : Z_ERR); 3143 } 3144 3145 #define RMCOMMAND "/usr/bin/rm -rf" 3146 3147 static int 3148 move_func(int argc, char *argv[]) 3149 { 3150 /* 6: "exec " and " " */ 3151 char cmdbuf[sizeof (RMCOMMAND) + MAXPATHLEN + 6]; 3152 char *new_zonepath = NULL; 3153 int lockfd; 3154 int err, arg; 3155 char zonepath[MAXPATHLEN]; 3156 zone_dochandle_t handle; 3157 boolean_t fast; 3158 boolean_t revert; 3159 struct stat zonepath_buf; 3160 struct stat new_zonepath_buf; 3161 3162 if (zonecfg_in_alt_root()) { 3163 zerror(gettext("cannot move zone in alternate root")); 3164 return (Z_ERR); 3165 } 3166 3167 optind = 0; 3168 if ((arg = getopt(argc, argv, "?")) != EOF) { 3169 switch (arg) { 3170 case '?': 3171 sub_usage(SHELP_MOVE, CMD_MOVE); 3172 return (optopt == '?' ? Z_OK : Z_USAGE); 3173 default: 3174 sub_usage(SHELP_MOVE, CMD_MOVE); 3175 return (Z_USAGE); 3176 } 3177 } 3178 if (argc != (optind + 1)) { 3179 sub_usage(SHELP_MOVE, CMD_MOVE); 3180 return (Z_USAGE); 3181 } 3182 new_zonepath = argv[optind]; 3183 if (sanity_check(target_zone, CMD_MOVE, B_FALSE, B_TRUE) != Z_OK) 3184 return (Z_ERR); 3185 if (verify_details(CMD_MOVE) != Z_OK) 3186 return (Z_ERR); 3187 3188 /* 3189 * Check out the new zonepath. This has the side effect of creating 3190 * a directory for the new zonepath. We depend on this later when we 3191 * stat to see if we are doing a cross file-system move or not. 3192 */ 3193 if (validate_zonepath(new_zonepath, CMD_MOVE) != Z_OK) 3194 return (Z_ERR); 3195 3196 if ((err = zone_get_zonepath(target_zone, zonepath, sizeof (zonepath))) 3197 != Z_OK) { 3198 errno = err; 3199 zperror2(target_zone, gettext("could not get zone path")); 3200 return (Z_ERR); 3201 } 3202 3203 if (stat(zonepath, &zonepath_buf) == -1) { 3204 zperror(gettext("could not stat zone path"), B_FALSE); 3205 return (Z_ERR); 3206 } 3207 3208 if (stat(new_zonepath, &new_zonepath_buf) == -1) { 3209 zperror(gettext("could not stat new zone path"), B_FALSE); 3210 return (Z_ERR); 3211 } 3212 3213 /* Don't move the zone if anything is still mounted there */ 3214 if (zonecfg_find_mounts(zonepath, NULL, NULL)) { 3215 zerror(gettext("These file-systems are mounted on " 3216 "subdirectories of %s.\n"), zonepath); 3217 (void) zonecfg_find_mounts(zonepath, zfm_print, NULL); 3218 return (Z_ERR); 3219 } 3220 3221 /* 3222 * Check if we are moving in the same filesystem and can do a fast 3223 * move or if we are crossing filesystems and have to copy the data. 3224 */ 3225 fast = (zonepath_buf.st_dev == new_zonepath_buf.st_dev); 3226 3227 if ((handle = zonecfg_init_handle()) == NULL) { 3228 zperror(cmd_to_str(CMD_MOVE), B_TRUE); 3229 return (Z_ERR); 3230 } 3231 3232 if ((err = zonecfg_get_handle(target_zone, handle)) != Z_OK) { 3233 errno = err; 3234 zperror(cmd_to_str(CMD_MOVE), B_TRUE); 3235 zonecfg_fini_handle(handle); 3236 return (Z_ERR); 3237 } 3238 3239 if (grab_lock_file(target_zone, &lockfd) != Z_OK) { 3240 zerror(gettext("another %s may have an operation in progress."), 3241 "zoneadm"); 3242 zonecfg_fini_handle(handle); 3243 return (Z_ERR); 3244 } 3245 3246 /* 3247 * We're making some file-system changes now so we have to clean up 3248 * the file-system before we are done. This will either clean up the 3249 * new zonepath if the zonecfg update failed or it will clean up the 3250 * old zonepath if everything is ok. 3251 */ 3252 revert = B_TRUE; 3253 3254 if (fast) { 3255 /* same filesystem, use rename for a quick move */ 3256 3257 /* 3258 * Remove the new_zonepath directory that got created above 3259 * during the validation. It gets in the way of the rename. 3260 */ 3261 if (rmdir(new_zonepath) != 0) { 3262 zperror(gettext("could not rmdir new zone path"), 3263 B_FALSE); 3264 zonecfg_fini_handle(handle); 3265 release_lock_file(lockfd); 3266 return (Z_ERR); 3267 } 3268 3269 if (rename(zonepath, new_zonepath) != 0) { 3270 /* 3271 * If this fails we don't need to do all of the 3272 * cleanup that happens for the rest of the code 3273 * so just return from this error. 3274 */ 3275 zperror(gettext("could not move zone"), B_FALSE); 3276 zonecfg_fini_handle(handle); 3277 release_lock_file(lockfd); 3278 return (Z_ERR); 3279 } 3280 3281 } else { 3282 (void) printf(gettext( 3283 "Moving across file-systems; copying zonepath %s..."), 3284 zonepath); 3285 (void) fflush(stdout); 3286 3287 err = copy_zone(zonepath, new_zonepath); 3288 3289 (void) printf("\n"); 3290 if (err != Z_OK) 3291 goto done; 3292 } 3293 3294 if ((err = zonecfg_set_zonepath(handle, new_zonepath)) != Z_OK) { 3295 errno = err; 3296 zperror(gettext("could not set new zonepath"), B_TRUE); 3297 goto done; 3298 } 3299 3300 if ((err = zonecfg_save(handle)) != Z_OK) { 3301 errno = err; 3302 zperror(gettext("zonecfg save failed"), B_TRUE); 3303 goto done; 3304 } 3305 3306 revert = B_FALSE; 3307 3308 done: 3309 zonecfg_fini_handle(handle); 3310 release_lock_file(lockfd); 3311 3312 /* 3313 * Clean up the file-system based on how things went. We either 3314 * clean up the new zonepath if the operation failed for some reason 3315 * or we clean up the old zonepath if everything is ok. 3316 */ 3317 if (revert) { 3318 /* The zonecfg update failed, cleanup the new zonepath. */ 3319 if (fast) { 3320 if (rename(new_zonepath, zonepath) != 0) { 3321 zperror(gettext("could not restore zonepath"), 3322 B_FALSE); 3323 /* 3324 * err is already != Z_OK since we're reverting 3325 */ 3326 } 3327 } else { 3328 int status; 3329 3330 (void) printf(gettext("Cleaning up zonepath %s..."), 3331 new_zonepath); 3332 (void) fflush(stdout); 3333 3334 /* 3335 * "exec" the command so that the returned status is 3336 * that of rm and not the shell. 3337 */ 3338 (void) snprintf(cmdbuf, sizeof (cmdbuf), 3339 "exec " RMCOMMAND " %s", new_zonepath); 3340 3341 status = do_subproc(cmdbuf); 3342 3343 (void) printf("\n"); 3344 3345 if ((err = subproc_status("rm", status)) != Z_OK) { 3346 errno = err; 3347 zperror(gettext("could not remove new " 3348 "zonepath"), B_TRUE); 3349 } else { 3350 /* 3351 * Because we're reverting we know the mainline 3352 * code failed but we just reused the err 3353 * variable so we reset it back to Z_ERR. 3354 */ 3355 err = Z_ERR; 3356 } 3357 } 3358 3359 } else { 3360 /* The move was successful, cleanup the old zonepath. */ 3361 if (!fast) { 3362 int status; 3363 3364 (void) printf( 3365 gettext("Cleaning up zonepath %s..."), zonepath); 3366 (void) fflush(stdout); 3367 3368 /* 3369 * "exec" the command so that the returned status is 3370 * that of rm and not the shell. 3371 */ 3372 (void) snprintf(cmdbuf, sizeof (cmdbuf), 3373 "exec " RMCOMMAND " %s", zonepath); 3374 3375 status = do_subproc(cmdbuf); 3376 3377 (void) printf("\n"); 3378 3379 if ((err = subproc_status("rm", status)) != Z_OK) { 3380 errno = err; 3381 zperror(gettext("could not remove zonepath"), 3382 B_TRUE); 3383 } 3384 } 3385 } 3386 3387 return ((err == Z_OK) ? Z_OK : Z_ERR); 3388 } 3389 3390 static int 3391 detach_func(int argc, char *argv[]) 3392 { 3393 int lockfd; 3394 int err, arg; 3395 char zonepath[MAXPATHLEN]; 3396 zone_dochandle_t handle; 3397 3398 if (zonecfg_in_alt_root()) { 3399 zerror(gettext("cannot detach zone in alternate root")); 3400 return (Z_ERR); 3401 } 3402 3403 optind = 0; 3404 if ((arg = getopt(argc, argv, "?")) != EOF) { 3405 switch (arg) { 3406 case '?': 3407 sub_usage(SHELP_DETACH, CMD_DETACH); 3408 return (optopt == '?' ? Z_OK : Z_USAGE); 3409 default: 3410 sub_usage(SHELP_DETACH, CMD_DETACH); 3411 return (Z_USAGE); 3412 } 3413 } 3414 if (sanity_check(target_zone, CMD_DETACH, B_FALSE, B_TRUE) != Z_OK) 3415 return (Z_ERR); 3416 if (verify_details(CMD_DETACH) != Z_OK) 3417 return (Z_ERR); 3418 3419 if ((err = zone_get_zonepath(target_zone, zonepath, sizeof (zonepath))) 3420 != Z_OK) { 3421 errno = err; 3422 zperror2(target_zone, gettext("could not get zone path")); 3423 return (Z_ERR); 3424 } 3425 3426 /* Don't detach the zone if anything is still mounted there */ 3427 if (zonecfg_find_mounts(zonepath, NULL, NULL)) { 3428 zerror(gettext("These file-systems are mounted on " 3429 "subdirectories of %s.\n"), zonepath); 3430 (void) zonecfg_find_mounts(zonepath, zfm_print, NULL); 3431 return (Z_ERR); 3432 } 3433 3434 if ((handle = zonecfg_init_handle()) == NULL) { 3435 zperror(cmd_to_str(CMD_DETACH), B_TRUE); 3436 return (Z_ERR); 3437 } 3438 3439 if ((err = zonecfg_get_handle(target_zone, handle)) != Z_OK) { 3440 errno = err; 3441 zperror(cmd_to_str(CMD_DETACH), B_TRUE); 3442 zonecfg_fini_handle(handle); 3443 return (Z_ERR); 3444 } 3445 3446 if (grab_lock_file(target_zone, &lockfd) != Z_OK) { 3447 zerror(gettext("another %s may have an operation in progress."), 3448 "zoneadm"); 3449 zonecfg_fini_handle(handle); 3450 return (Z_ERR); 3451 } 3452 3453 if ((err = zonecfg_get_detach_info(handle, B_TRUE)) != Z_OK) { 3454 errno = err; 3455 zperror(gettext("getting the detach information failed"), 3456 B_TRUE); 3457 goto done; 3458 } 3459 3460 if ((err = zonecfg_detach_save(handle)) != Z_OK) { 3461 errno = err; 3462 zperror(gettext("saving the detach manifest failed"), B_TRUE); 3463 goto done; 3464 } 3465 3466 if ((err = zone_set_state(target_zone, ZONE_STATE_CONFIGURED)) 3467 != Z_OK) { 3468 errno = err; 3469 zperror(gettext("could not reset state"), B_TRUE); 3470 } 3471 3472 done: 3473 zonecfg_fini_handle(handle); 3474 release_lock_file(lockfd); 3475 3476 return ((err == Z_OK) ? Z_OK : Z_ERR); 3477 } 3478 3479 /* 3480 * Find the specified package in the sw inventory on the handle and check 3481 * if the version matches what is passed in. 3482 * Return 0 if the packages match 3483 * 1 if the package is found but we have a version mismatch 3484 * -1 if the package is not found 3485 */ 3486 static int 3487 pkg_cmp(zone_dochandle_t handle, char *pkg_name, char *pkg_vers, 3488 char *return_vers, int vers_size) 3489 { 3490 int res = -1; 3491 struct zone_pkgtab pkgtab; 3492 3493 if (zonecfg_setpkgent(handle) != Z_OK) { 3494 (void) fprintf(stderr, 3495 gettext("unable to enumerate packages\n")); 3496 return (Z_ERR); 3497 } 3498 3499 while (zonecfg_getpkgent(handle, &pkgtab) == Z_OK) { 3500 if (strcmp(pkg_name, pkgtab.zone_pkg_name) != 0) 3501 continue; 3502 3503 if (strcmp(pkg_vers, pkgtab.zone_pkg_version) == 0) { 3504 res = 0; 3505 break; 3506 } 3507 3508 (void) strlcpy(return_vers, pkgtab.zone_pkg_version, vers_size); 3509 res = 1; 3510 break; 3511 } 3512 3513 (void) zonecfg_endpkgent(handle); 3514 return (res); 3515 } 3516 3517 /* 3518 * Used in software comparisons to check the packages between the two zone 3519 * handles. The packages have to match or we print a message telling the 3520 * user what is out of sync. The src_cmp flag tells us if the first handle 3521 * is the source machine global zone or not. This is used to enable the 3522 * right messages to be printed and also to enable extra version checking 3523 * that is not needed for the opposite comparison. 3524 */ 3525 static int 3526 pkg_check(char *header, zone_dochandle_t handle1, zone_dochandle_t handle2, 3527 boolean_t src_cmp) 3528 { 3529 int err; 3530 int res = Z_OK; 3531 boolean_t do_header = B_TRUE; 3532 char other_vers[ZONE_PKG_VERSMAX]; 3533 struct zone_pkgtab pkgtab; 3534 3535 if (zonecfg_setpkgent(handle1) != Z_OK) { 3536 (void) fprintf(stderr, 3537 gettext("unable to enumerate packages\n")); 3538 return (Z_ERR); 3539 } 3540 3541 while (zonecfg_getpkgent(handle1, &pkgtab) == Z_OK) { 3542 if ((err = pkg_cmp(handle2, pkgtab.zone_pkg_name, 3543 pkgtab.zone_pkg_version, other_vers, sizeof (other_vers))) 3544 != 0) { 3545 if (do_header && (err < 0 || src_cmp)) { 3546 /* LINTED E_SEC_PRINTF_VAR_FMT */ 3547 (void) fprintf(stderr, header); 3548 do_header = B_FALSE; 3549 } 3550 if (err < 0) { 3551 (void) fprintf(stderr, 3552 (src_cmp == B_TRUE) ? 3553 gettext("\t%s: not installed\n\t\t(%s)\n") : 3554 gettext("\t%s (%s)\n"), 3555 pkgtab.zone_pkg_name, 3556 pkgtab.zone_pkg_version); 3557 res = Z_ERR; 3558 } else if (src_cmp) { 3559 (void) fprintf(stderr, gettext( 3560 "\t%s: version mismatch\n\t\t(%s)" 3561 "\n\t\t(%s)\n"), 3562 pkgtab.zone_pkg_name, 3563 pkgtab.zone_pkg_version, other_vers); 3564 res = Z_ERR; 3565 } 3566 } 3567 } 3568 3569 (void) zonecfg_endpkgent(handle1); 3570 3571 return (res); 3572 } 3573 3574 /* 3575 * Find the specified patch in the sw inventory on the handle and check 3576 * if the version matches what is passed in. 3577 * Return 0 if the patches match 3578 * 1 if the patches is found but we have a version mismatch 3579 * -1 if the patches is not found 3580 */ 3581 static int 3582 patch_cmp(zone_dochandle_t handle, char *patch_id, char *patch_vers, 3583 char *return_vers, int vers_size) 3584 { 3585 int res = -1; 3586 struct zone_patchtab patchtab; 3587 3588 if (zonecfg_setpatchent(handle) != Z_OK) { 3589 (void) fprintf(stderr, 3590 gettext("unable to enumerate patches\n")); 3591 return (Z_ERR); 3592 } 3593 3594 while (zonecfg_getpatchent(handle, &patchtab) == Z_OK) { 3595 char *p; 3596 3597 if ((p = strchr(patchtab.zone_patch_id, '-')) != NULL) 3598 *p++ = '\0'; 3599 else 3600 p = ""; 3601 3602 if (strcmp(patch_id, patchtab.zone_patch_id) != 0) 3603 continue; 3604 3605 if (strcmp(patch_vers, p) == 0) { 3606 res = 0; 3607 break; 3608 } 3609 3610 (void) strlcpy(return_vers, p, vers_size); 3611 /* 3612 * Keep checking. This handles the case where multiple 3613 * versions of the same patch is installed. 3614 */ 3615 res = 1; 3616 } 3617 3618 (void) zonecfg_endpatchent(handle); 3619 return (res); 3620 } 3621 3622 /* 3623 * Used in software comparisons to check the patches between the two zone 3624 * handles. The patches have to match or we print a message telling the 3625 * user what is out of sync. The src_cmp flag tells us if the first handle 3626 * is the source machine global zone or not. This is used to enable the 3627 * right messages to be printed and also to enable extra version checking 3628 * that is not needed for the opposite comparison. 3629 */ 3630 static int 3631 patch_check(char *header, zone_dochandle_t handle1, zone_dochandle_t handle2, 3632 boolean_t src_cmp) 3633 { 3634 int err; 3635 int res = Z_OK; 3636 boolean_t do_header = B_TRUE; 3637 char other_vers[MAXNAMELEN]; 3638 struct zone_patchtab patchtab; 3639 3640 if (zonecfg_setpatchent(handle1) != Z_OK) { 3641 (void) fprintf(stderr, 3642 gettext("unable to enumerate patches\n")); 3643 return (Z_ERR); 3644 } 3645 3646 while (zonecfg_getpatchent(handle1, &patchtab) == Z_OK) { 3647 char *patch_vers; 3648 3649 if ((patch_vers = strchr(patchtab.zone_patch_id, '-')) != NULL) 3650 *patch_vers++ = '\0'; 3651 else 3652 patch_vers = ""; 3653 3654 if ((err = patch_cmp(handle2, patchtab.zone_patch_id, 3655 patch_vers, other_vers, sizeof (other_vers))) != 0) { 3656 if (do_header && (err < 0 || src_cmp)) { 3657 /* LINTED E_SEC_PRINTF_VAR_FMT */ 3658 (void) fprintf(stderr, header); 3659 do_header = B_FALSE; 3660 } 3661 if (err < 0) { 3662 (void) fprintf(stderr, 3663 (src_cmp == B_TRUE) ? 3664 gettext("\t%s: not installed\n") : 3665 gettext("\t%s\n"), 3666 patchtab.zone_patch_id); 3667 res = Z_ERR; 3668 } else if (src_cmp) { 3669 (void) fprintf(stderr, 3670 gettext("\t%s: version mismatch\n\t\t(%s) " 3671 "(%s)\n"), patchtab.zone_patch_id, 3672 patch_vers, other_vers); 3673 res = Z_ERR; 3674 } 3675 } 3676 } 3677 3678 (void) zonecfg_endpatchent(handle1); 3679 3680 return (res); 3681 } 3682 3683 /* 3684 * Compare the software on the local global zone and source system global 3685 * zone. Used when we are trying to attach a zone during migration. 3686 * l_handle is for the local system and s_handle is for the source system. 3687 * These have a snapshot of the appropriate packages and patches in the global 3688 * zone for the two machines. 3689 * The functions called here will print any messages that are needed to 3690 * inform the user about package or patch problems. 3691 */ 3692 static int 3693 sw_cmp(zone_dochandle_t l_handle, zone_dochandle_t s_handle) 3694 { 3695 char *hdr; 3696 int res = Z_OK; 3697 3698 /* 3699 * Check the source host for pkgs (and versions) that are not on the 3700 * local host. 3701 */ 3702 hdr = gettext("These packages installed on the source system are " 3703 "inconsistent with this system:\n"); 3704 if (pkg_check(hdr, s_handle, l_handle, B_TRUE) != Z_OK) 3705 res = Z_ERR; 3706 3707 /* 3708 * Now check the local host for pkgs that were not on the source host. 3709 * We already handled version mismatches in the loop above. 3710 */ 3711 hdr = gettext("These packages installed on this system were " 3712 "not installed on the source system:\n"); 3713 if (pkg_check(hdr, l_handle, s_handle, B_FALSE) != Z_OK) 3714 res = Z_ERR; 3715 3716 /* 3717 * Check the source host for patches that are not on the local host. 3718 */ 3719 hdr = gettext("These patches installed on the source system are " 3720 "inconsistent with this system:\n"); 3721 if (patch_check(hdr, s_handle, l_handle, B_TRUE) != Z_OK) 3722 res = Z_ERR; 3723 3724 /* 3725 * Check the local host for patches that were not on the source host. 3726 * We already handled version mismatches in the loop above. 3727 */ 3728 hdr = gettext("These patches installed on this system were " 3729 "not installed on the source system:\n"); 3730 if (patch_check(hdr, l_handle, s_handle, B_FALSE) != Z_OK) 3731 res = Z_ERR; 3732 3733 return (res); 3734 } 3735 3736 /* 3737 * During attach we go through and fix up the /dev entries for the zone 3738 * we are attaching. In order to regenerate /dev with the correct devices, 3739 * the old /dev will be removed, the zone readied (which generates a new 3740 * /dev) then halted, then we use the info from the manifest to update 3741 * the modes, owners, etc. on the new /dev. 3742 */ 3743 static int 3744 dev_fix(zone_dochandle_t handle) 3745 { 3746 int res; 3747 int err; 3748 int status; 3749 struct zone_devpermtab devtab; 3750 zone_cmd_arg_t zarg; 3751 char devpath[MAXPATHLEN]; 3752 /* 6: "exec " and " " */ 3753 char cmdbuf[sizeof (RMCOMMAND) + MAXPATHLEN + 6]; 3754 3755 if ((res = zonecfg_get_zonepath(handle, devpath, sizeof (devpath))) 3756 != Z_OK) 3757 return (res); 3758 3759 if (strlcat(devpath, "/dev", sizeof (devpath)) >= sizeof (devpath)) 3760 return (Z_TOO_BIG); 3761 3762 /* 3763 * "exec" the command so that the returned status is that of 3764 * RMCOMMAND and not the shell. 3765 */ 3766 (void) snprintf(cmdbuf, sizeof (cmdbuf), "exec " RMCOMMAND " %s", 3767 devpath); 3768 status = do_subproc(cmdbuf); 3769 if ((err = subproc_status(RMCOMMAND, status)) != Z_OK) { 3770 (void) fprintf(stderr, 3771 gettext("could not remove existing /dev\n")); 3772 return (Z_ERR); 3773 } 3774 3775 /* In order to ready the zone, it must be in the installed state */ 3776 if ((err = zone_set_state(target_zone, ZONE_STATE_INSTALLED)) != Z_OK) { 3777 errno = err; 3778 zperror(gettext("could not reset state"), B_TRUE); 3779 return (Z_ERR); 3780 } 3781 3782 /* We have to ready the zone to regen the dev tree */ 3783 zarg.cmd = Z_READY; 3784 if (call_zoneadmd(target_zone, &zarg) != 0) { 3785 zerror(gettext("call to %s failed"), "zoneadmd"); 3786 return (Z_ERR); 3787 } 3788 3789 zarg.cmd = Z_HALT; 3790 if (call_zoneadmd(target_zone, &zarg) != 0) { 3791 zerror(gettext("call to %s failed"), "zoneadmd"); 3792 return (Z_ERR); 3793 } 3794 3795 if (zonecfg_setdevperment(handle) != Z_OK) { 3796 (void) fprintf(stderr, 3797 gettext("unable to enumerate device entries\n")); 3798 return (Z_ERR); 3799 } 3800 3801 while (zonecfg_getdevperment(handle, &devtab) == Z_OK) { 3802 int err; 3803 3804 if ((err = zonecfg_devperms_apply(handle, 3805 devtab.zone_devperm_name, devtab.zone_devperm_uid, 3806 devtab.zone_devperm_gid, devtab.zone_devperm_mode, 3807 devtab.zone_devperm_acl)) != Z_OK && err != Z_INVAL) 3808 (void) fprintf(stderr, gettext("error updating device " 3809 "%s: %s\n"), devtab.zone_devperm_name, 3810 zonecfg_strerror(err)); 3811 3812 free(devtab.zone_devperm_acl); 3813 } 3814 3815 (void) zonecfg_enddevperment(handle); 3816 3817 return (Z_OK); 3818 } 3819 3820 static int 3821 attach_func(int argc, char *argv[]) 3822 { 3823 int lockfd; 3824 int err, arg; 3825 boolean_t force = B_FALSE; 3826 zone_dochandle_t handle; 3827 zone_dochandle_t athandle = NULL; 3828 char zonepath[MAXPATHLEN]; 3829 3830 if (zonecfg_in_alt_root()) { 3831 zerror(gettext("cannot attach zone in alternate root")); 3832 return (Z_ERR); 3833 } 3834 3835 optind = 0; 3836 if ((arg = getopt(argc, argv, "?F")) != EOF) { 3837 switch (arg) { 3838 case '?': 3839 sub_usage(SHELP_ATTACH, CMD_ATTACH); 3840 return (optopt == '?' ? Z_OK : Z_USAGE); 3841 case 'F': 3842 force = B_TRUE; 3843 break; 3844 default: 3845 sub_usage(SHELP_ATTACH, CMD_ATTACH); 3846 return (Z_USAGE); 3847 } 3848 } 3849 if (sanity_check(target_zone, CMD_ATTACH, B_FALSE, B_TRUE) != Z_OK) 3850 return (Z_ERR); 3851 if (verify_details(CMD_ATTACH) != Z_OK) 3852 return (Z_ERR); 3853 3854 if ((err = zone_get_zonepath(target_zone, zonepath, sizeof (zonepath))) 3855 != Z_OK) { 3856 errno = err; 3857 zperror2(target_zone, gettext("could not get zone path")); 3858 return (Z_ERR); 3859 } 3860 3861 if ((handle = zonecfg_init_handle()) == NULL) { 3862 zperror(cmd_to_str(CMD_ATTACH), B_TRUE); 3863 return (Z_ERR); 3864 } 3865 3866 if ((err = zonecfg_get_handle(target_zone, handle)) != Z_OK) { 3867 errno = err; 3868 zperror(cmd_to_str(CMD_ATTACH), B_TRUE); 3869 zonecfg_fini_handle(handle); 3870 return (Z_ERR); 3871 } 3872 3873 if (grab_lock_file(target_zone, &lockfd) != Z_OK) { 3874 zerror(gettext("another %s may have an operation in progress."), 3875 "zoneadm"); 3876 zonecfg_fini_handle(handle); 3877 return (Z_ERR); 3878 } 3879 3880 if (force) 3881 goto forced; 3882 3883 if ((athandle = zonecfg_init_handle()) == NULL) { 3884 zperror(cmd_to_str(CMD_ATTACH), B_TRUE); 3885 goto done; 3886 } 3887 3888 if ((err = zonecfg_get_attach_handle(zonepath, target_zone, B_TRUE, 3889 athandle)) != Z_OK) { 3890 if (err == Z_NO_ZONE) 3891 zerror(gettext("Not a detached zone")); 3892 else if (err == Z_INVALID_DOCUMENT) 3893 zerror(gettext("Cannot attach to an earlier release " 3894 "of the operating system")); 3895 else 3896 zperror(cmd_to_str(CMD_ATTACH), B_TRUE); 3897 goto done; 3898 } 3899 3900 /* Get the detach information for the locally defined zone. */ 3901 if ((err = zonecfg_get_detach_info(handle, B_FALSE)) != Z_OK) { 3902 errno = err; 3903 zperror(gettext("getting the attach information failed"), 3904 B_TRUE); 3905 goto done; 3906 } 3907 3908 /* sw_cmp prints error msgs as necessary */ 3909 if ((err = sw_cmp(handle, athandle)) != Z_OK) 3910 goto done; 3911 3912 if ((err = dev_fix(athandle)) != Z_OK) 3913 goto done; 3914 3915 forced: 3916 3917 zonecfg_rm_detached(handle, force); 3918 3919 if ((err = zone_set_state(target_zone, ZONE_STATE_INSTALLED)) != Z_OK) { 3920 errno = err; 3921 zperror(gettext("could not reset state"), B_TRUE); 3922 } 3923 3924 done: 3925 zonecfg_fini_handle(handle); 3926 release_lock_file(lockfd); 3927 if (athandle != NULL) 3928 zonecfg_fini_handle(athandle); 3929 3930 return ((err == Z_OK) ? Z_OK : Z_ERR); 3931 } 3932 3933 /* 3934 * On input, TRUE => yes, FALSE => no. 3935 * On return, TRUE => 1, FALSE => 0, could not ask => -1. 3936 */ 3937 3938 static int 3939 ask_yesno(boolean_t default_answer, const char *question) 3940 { 3941 char line[64]; /* should be large enough to answer yes or no */ 3942 3943 if (!isatty(STDIN_FILENO)) 3944 return (-1); 3945 for (;;) { 3946 (void) printf("%s (%s)? ", question, 3947 default_answer ? "[y]/n" : "y/[n]"); 3948 if (fgets(line, sizeof (line), stdin) == NULL || 3949 line[0] == '\n') 3950 return (default_answer ? 1 : 0); 3951 if (tolower(line[0]) == 'y') 3952 return (1); 3953 if (tolower(line[0]) == 'n') 3954 return (0); 3955 } 3956 } 3957 3958 static int 3959 uninstall_func(int argc, char *argv[]) 3960 { 3961 /* 6: "exec " and " " */ 3962 char cmdbuf[sizeof (RMCOMMAND) + MAXPATHLEN + 6]; 3963 char line[ZONENAME_MAX + 128]; /* Enough for "Are you sure ..." */ 3964 char rootpath[MAXPATHLEN], devpath[MAXPATHLEN]; 3965 boolean_t force = B_FALSE; 3966 int lockfd, answer; 3967 int err, arg; 3968 int status; 3969 3970 if (zonecfg_in_alt_root()) { 3971 zerror(gettext("cannot uninstall zone in alternate root")); 3972 return (Z_ERR); 3973 } 3974 3975 optind = 0; 3976 while ((arg = getopt(argc, argv, "?F")) != EOF) { 3977 switch (arg) { 3978 case '?': 3979 sub_usage(SHELP_UNINSTALL, CMD_UNINSTALL); 3980 return (optopt == '?' ? Z_OK : Z_USAGE); 3981 case 'F': 3982 force = B_TRUE; 3983 break; 3984 default: 3985 sub_usage(SHELP_UNINSTALL, CMD_UNINSTALL); 3986 return (Z_USAGE); 3987 } 3988 } 3989 if (argc > optind) { 3990 sub_usage(SHELP_UNINSTALL, CMD_UNINSTALL); 3991 return (Z_USAGE); 3992 } 3993 3994 if (sanity_check(target_zone, CMD_UNINSTALL, B_FALSE, B_TRUE) != Z_OK) 3995 return (Z_ERR); 3996 3997 if (!force) { 3998 (void) snprintf(line, sizeof (line), 3999 gettext("Are you sure you want to %s zone %s"), 4000 cmd_to_str(CMD_UNINSTALL), target_zone); 4001 if ((answer = ask_yesno(B_FALSE, line)) == 0) { 4002 return (Z_OK); 4003 } else if (answer == -1) { 4004 zerror(gettext("Input not from terminal and -F " 4005 "not specified: %s not done."), 4006 cmd_to_str(CMD_UNINSTALL)); 4007 return (Z_ERR); 4008 } 4009 } 4010 4011 if ((err = zone_get_zonepath(target_zone, devpath, 4012 sizeof (devpath))) != Z_OK) { 4013 errno = err; 4014 zperror2(target_zone, gettext("could not get zone path")); 4015 return (Z_ERR); 4016 } 4017 (void) strlcat(devpath, "/dev", sizeof (devpath)); 4018 if ((err = zone_get_rootpath(target_zone, rootpath, 4019 sizeof (rootpath))) != Z_OK) { 4020 errno = err; 4021 zperror2(target_zone, gettext("could not get root path")); 4022 return (Z_ERR); 4023 } 4024 4025 /* 4026 * If there seems to be a zoneadmd running for this zone, call it 4027 * to tell it that an uninstall is happening; if all goes well it 4028 * will then shut itself down. 4029 */ 4030 if (ping_zoneadmd(target_zone) == Z_OK) { 4031 zone_cmd_arg_t zarg; 4032 zarg.cmd = Z_NOTE_UNINSTALLING; 4033 /* we don't care too much if this fails... just plow on */ 4034 (void) call_zoneadmd(target_zone, &zarg); 4035 } 4036 4037 if (grab_lock_file(target_zone, &lockfd) != Z_OK) { 4038 zerror(gettext("another %s may have an operation in progress."), 4039 "zoneadm"); 4040 return (Z_ERR); 4041 } 4042 4043 /* Don't uninstall the zone if anything is mounted there */ 4044 err = zonecfg_find_mounts(rootpath, NULL, NULL); 4045 if (err) { 4046 zerror(gettext("These file-systems are mounted on " 4047 "subdirectories of %s.\n"), rootpath); 4048 (void) zonecfg_find_mounts(rootpath, zfm_print, NULL); 4049 return (Z_ERR); 4050 } 4051 4052 err = zone_set_state(target_zone, ZONE_STATE_INCOMPLETE); 4053 if (err != Z_OK) { 4054 errno = err; 4055 zperror2(target_zone, gettext("could not set state")); 4056 goto bad; 4057 } 4058 4059 /* 4060 * "exec" the command so that the returned status is that of 4061 * RMCOMMAND and not the shell. 4062 */ 4063 (void) snprintf(cmdbuf, sizeof (cmdbuf), "exec " RMCOMMAND " %s", 4064 devpath); 4065 status = do_subproc(cmdbuf); 4066 if ((err = subproc_status(RMCOMMAND, status)) != Z_OK) 4067 goto bad; 4068 (void) snprintf(cmdbuf, sizeof (cmdbuf), "exec " RMCOMMAND " %s", 4069 rootpath); 4070 status = do_subproc(cmdbuf); 4071 if ((err = subproc_status(RMCOMMAND, status)) != Z_OK) 4072 goto bad; 4073 err = zone_set_state(target_zone, ZONE_STATE_CONFIGURED); 4074 if (err != Z_OK) { 4075 errno = err; 4076 zperror2(target_zone, gettext("could not reset state")); 4077 } 4078 bad: 4079 release_lock_file(lockfd); 4080 return (err); 4081 } 4082 4083 /* ARGSUSED */ 4084 static int 4085 mount_func(int argc, char *argv[]) 4086 { 4087 zone_cmd_arg_t zarg; 4088 4089 if (argc > 0) 4090 return (Z_USAGE); 4091 if (sanity_check(target_zone, CMD_MOUNT, B_FALSE, B_FALSE) != Z_OK) 4092 return (Z_ERR); 4093 if (verify_details(CMD_MOUNT) != Z_OK) 4094 return (Z_ERR); 4095 4096 zarg.cmd = Z_MOUNT; 4097 if (call_zoneadmd(target_zone, &zarg) != 0) { 4098 zerror(gettext("call to %s failed"), "zoneadmd"); 4099 return (Z_ERR); 4100 } 4101 return (Z_OK); 4102 } 4103 4104 /* ARGSUSED */ 4105 static int 4106 unmount_func(int argc, char *argv[]) 4107 { 4108 zone_cmd_arg_t zarg; 4109 4110 if (argc > 0) 4111 return (Z_USAGE); 4112 if (sanity_check(target_zone, CMD_UNMOUNT, B_FALSE, B_FALSE) != Z_OK) 4113 return (Z_ERR); 4114 4115 zarg.cmd = Z_UNMOUNT; 4116 if (call_zoneadmd(target_zone, &zarg) != 0) { 4117 zerror(gettext("call to %s failed"), "zoneadmd"); 4118 return (Z_ERR); 4119 } 4120 return (Z_OK); 4121 } 4122 4123 static int 4124 help_func(int argc, char *argv[]) 4125 { 4126 int arg, cmd_num; 4127 4128 if (argc == 0) { 4129 (void) usage(B_TRUE); 4130 return (Z_OK); 4131 } 4132 optind = 0; 4133 if ((arg = getopt(argc, argv, "?")) != EOF) { 4134 switch (arg) { 4135 case '?': 4136 sub_usage(SHELP_HELP, CMD_HELP); 4137 return (optopt == '?' ? Z_OK : Z_USAGE); 4138 default: 4139 sub_usage(SHELP_HELP, CMD_HELP); 4140 return (Z_USAGE); 4141 } 4142 } 4143 while (optind < argc) { 4144 /* Private commands have NULL short_usage; omit them */ 4145 if ((cmd_num = cmd_match(argv[optind])) < 0 || 4146 cmdtab[cmd_num].short_usage == NULL) { 4147 sub_usage(SHELP_HELP, CMD_HELP); 4148 return (Z_USAGE); 4149 } 4150 sub_usage(cmdtab[cmd_num].short_usage, cmd_num); 4151 optind++; 4152 } 4153 return (Z_OK); 4154 } 4155 4156 /* 4157 * Returns: CMD_MIN thru CMD_MAX on success, -1 on error 4158 */ 4159 4160 static int 4161 cmd_match(char *cmd) 4162 { 4163 int i; 4164 4165 for (i = CMD_MIN; i <= CMD_MAX; i++) { 4166 /* return only if there is an exact match */ 4167 if (strcmp(cmd, cmdtab[i].cmd_name) == 0) 4168 return (cmdtab[i].cmd_num); 4169 } 4170 return (-1); 4171 } 4172 4173 static int 4174 parse_and_run(int argc, char *argv[]) 4175 { 4176 int i = cmd_match(argv[0]); 4177 4178 if (i < 0) 4179 return (usage(B_FALSE)); 4180 return (cmdtab[i].handler(argc - 1, &(argv[1]))); 4181 } 4182 4183 static char * 4184 get_execbasename(char *execfullname) 4185 { 4186 char *last_slash, *execbasename; 4187 4188 /* guard against '/' at end of command invocation */ 4189 for (;;) { 4190 last_slash = strrchr(execfullname, '/'); 4191 if (last_slash == NULL) { 4192 execbasename = execfullname; 4193 break; 4194 } else { 4195 execbasename = last_slash + 1; 4196 if (*execbasename == '\0') { 4197 *last_slash = '\0'; 4198 continue; 4199 } 4200 break; 4201 } 4202 } 4203 return (execbasename); 4204 } 4205 4206 int 4207 main(int argc, char **argv) 4208 { 4209 int arg; 4210 zoneid_t zid; 4211 struct stat st; 4212 4213 if ((locale = setlocale(LC_ALL, "")) == NULL) 4214 locale = "C"; 4215 (void) textdomain(TEXT_DOMAIN); 4216 setbuf(stdout, NULL); 4217 (void) sigset(SIGHUP, SIG_IGN); 4218 execname = get_execbasename(argv[0]); 4219 target_zone = NULL; 4220 if (chdir("/") != 0) { 4221 zerror(gettext("could not change directory to /.")); 4222 exit(Z_ERR); 4223 } 4224 4225 while ((arg = getopt(argc, argv, "?z:R:")) != EOF) { 4226 switch (arg) { 4227 case '?': 4228 return (usage(B_TRUE)); 4229 case 'z': 4230 target_zone = optarg; 4231 break; 4232 case 'R': /* private option for admin/install use */ 4233 if (*optarg != '/') { 4234 zerror(gettext("root path must be absolute.")); 4235 exit(Z_ERR); 4236 } 4237 if (stat(optarg, &st) == -1 || !S_ISDIR(st.st_mode)) { 4238 zerror( 4239 gettext("root path must be a directory.")); 4240 exit(Z_ERR); 4241 } 4242 zonecfg_set_root(optarg); 4243 break; 4244 default: 4245 return (usage(B_FALSE)); 4246 } 4247 } 4248 4249 if (optind >= argc) 4250 return (usage(B_FALSE)); 4251 if (target_zone != NULL && zone_get_id(target_zone, &zid) != 0) { 4252 errno = Z_NO_ZONE; 4253 zperror(target_zone, B_TRUE); 4254 exit(Z_ERR); 4255 } 4256 return (parse_and_run(argc - optind, &argv[optind])); 4257 } 4258