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/egrep -v '^\\./\\.zfs$|^\\./\\.zfs/' | " 2920 "/usr/bin/cpio -pdmuP@ %s > %s 2>&1", 2921 src, dst, outfile); 2922 2923 status = do_subproc(cmdbuf); 2924 2925 if ((err = subproc_status("copy", status)) != Z_OK) { 2926 if (!out_null) 2927 (void) fprintf(stderr, gettext("\nThe copy failed.\n" 2928 "More information can be found in %s\n"), outfile); 2929 return (err); 2930 } 2931 2932 if (!out_null) 2933 (void) unlink(outfile); 2934 2935 return (Z_OK); 2936 } 2937 2938 /* 2939 * Run sys-unconfig on a zone. This will leave the zone in the installed 2940 * state as long as there were no errors during the sys-unconfig. 2941 */ 2942 static int 2943 unconfigure_zone(char *zonepath) 2944 { 2945 int err; 2946 int status; 2947 struct stat unconfig_buf; 2948 zone_cmd_arg_t zarg; 2949 char cmdbuf[MAXPATHLEN + 51]; 2950 2951 /* The zone has to be installed in order to mount the scratch zone. */ 2952 if ((err = zone_set_state(target_zone, ZONE_STATE_INSTALLED)) != Z_OK) { 2953 errno = err; 2954 zperror2(target_zone, gettext("could not set state")); 2955 return (Z_ERR); 2956 } 2957 2958 /* 2959 * Check if the zone is already sys-unconfiged. This saves us 2960 * the work of bringing up the scratch zone so we can unconfigure it. 2961 */ 2962 (void) snprintf(cmdbuf, sizeof (cmdbuf), "%s/root/etc/.UNCONFIGURED", 2963 zonepath); 2964 if (stat(cmdbuf, &unconfig_buf) == 0) 2965 return (Z_OK); 2966 2967 zarg.cmd = Z_MOUNT; 2968 if (call_zoneadmd(target_zone, &zarg) != 0) { 2969 zerror(gettext("call to %s failed"), "zoneadmd"); 2970 (void) zone_set_state(target_zone, ZONE_STATE_INCOMPLETE); 2971 return (Z_ERR); 2972 } 2973 2974 (void) snprintf(cmdbuf, sizeof (cmdbuf), 2975 "/usr/sbin/zlogin -S %s /usr/sbin/sys-unconfig -R /a", target_zone); 2976 2977 status = do_subproc(cmdbuf); 2978 if ((err = subproc_status("sys-unconfig", status)) != Z_OK) { 2979 errno = err; 2980 zperror2(target_zone, gettext("sys-unconfig failed\n")); 2981 (void) zone_set_state(target_zone, ZONE_STATE_INCOMPLETE); 2982 } 2983 2984 zarg.cmd = Z_UNMOUNT; 2985 if (call_zoneadmd(target_zone, &zarg) != 0) { 2986 zerror(gettext("call to %s failed"), "zoneadmd"); 2987 (void) fprintf(stderr, gettext("could not unmount zone\n")); 2988 return (Z_ERR); 2989 } 2990 2991 return ((err == Z_OK) ? Z_OK : Z_ERR); 2992 } 2993 2994 /* ARGSUSED */ 2995 int 2996 zfm_print(const char *p, void *r) { 2997 zerror(" %s\n", p); 2998 return (0); 2999 } 3000 3001 static int 3002 clone_func(int argc, char *argv[]) 3003 { 3004 char *source_zone = NULL; 3005 int lockfd; 3006 int err, arg; 3007 char zonepath[MAXPATHLEN]; 3008 char source_zonepath[MAXPATHLEN]; 3009 zone_state_t state; 3010 zone_entry_t *zent; 3011 char *method = "copy"; 3012 3013 if (zonecfg_in_alt_root()) { 3014 zerror(gettext("cannot clone zone in alternate root")); 3015 return (Z_ERR); 3016 } 3017 3018 optind = 0; 3019 if ((arg = getopt(argc, argv, "?m:")) != EOF) { 3020 switch (arg) { 3021 case '?': 3022 sub_usage(SHELP_CLONE, CMD_CLONE); 3023 return (optopt == '?' ? Z_OK : Z_USAGE); 3024 case 'm': 3025 method = optarg; 3026 break; 3027 default: 3028 sub_usage(SHELP_CLONE, CMD_CLONE); 3029 return (Z_USAGE); 3030 } 3031 } 3032 if (argc != (optind + 1) || strcmp(method, "copy") != 0) { 3033 sub_usage(SHELP_CLONE, CMD_CLONE); 3034 return (Z_USAGE); 3035 } 3036 source_zone = argv[optind]; 3037 if (sanity_check(target_zone, CMD_CLONE, B_FALSE, B_TRUE) != Z_OK) 3038 return (Z_ERR); 3039 if (verify_details(CMD_CLONE) != Z_OK) 3040 return (Z_ERR); 3041 3042 /* 3043 * We also need to do some extra validation on the source zone. 3044 */ 3045 3046 if (strcmp(source_zone, GLOBAL_ZONENAME) == 0) { 3047 zerror(gettext("%s operation is invalid for the global zone."), 3048 cmd_to_str(CMD_CLONE)); 3049 return (Z_ERR); 3050 } 3051 3052 if (strncmp(source_zone, "SUNW", 4) == 0) { 3053 zerror(gettext("%s operation is invalid for zones starting " 3054 "with SUNW."), cmd_to_str(CMD_CLONE)); 3055 return (Z_ERR); 3056 } 3057 3058 zent = lookup_running_zone(source_zone); 3059 if (zent != NULL) { 3060 /* check whether the zone is ready or running */ 3061 if ((err = zone_get_state(zent->zname, &zent->zstate_num)) 3062 != Z_OK) { 3063 errno = err; 3064 zperror2(zent->zname, gettext("could not get state")); 3065 /* can't tell, so hedge */ 3066 zent->zstate_str = "ready/running"; 3067 } else { 3068 zent->zstate_str = zone_state_str(zent->zstate_num); 3069 } 3070 zerror(gettext("%s operation is invalid for %s zones."), 3071 cmd_to_str(CMD_CLONE), zent->zstate_str); 3072 return (Z_ERR); 3073 } 3074 3075 if ((err = zone_get_state(source_zone, &state)) != Z_OK) { 3076 errno = err; 3077 zperror2(source_zone, gettext("could not get state")); 3078 return (Z_ERR); 3079 } 3080 if (state != ZONE_STATE_INSTALLED) { 3081 (void) fprintf(stderr, 3082 gettext("%s: zone %s is %s; %s is required.\n"), 3083 execname, source_zone, zone_state_str(state), 3084 zone_state_str(ZONE_STATE_INSTALLED)); 3085 return (Z_ERR); 3086 } 3087 3088 /* 3089 * The source zone checks out ok, continue with the clone. 3090 */ 3091 3092 if (validate_clone(source_zone, target_zone) != Z_OK) 3093 return (Z_ERR); 3094 3095 if (grab_lock_file(target_zone, &lockfd) != Z_OK) { 3096 zerror(gettext("another %s may have an operation in progress."), 3097 "zoneadm"); 3098 return (Z_ERR); 3099 } 3100 3101 if ((err = zone_get_zonepath(source_zone, source_zonepath, 3102 sizeof (source_zonepath))) != Z_OK) { 3103 errno = err; 3104 zperror2(source_zone, gettext("could not get zone path")); 3105 goto done; 3106 } 3107 3108 if ((err = zone_get_zonepath(target_zone, zonepath, sizeof (zonepath))) 3109 != Z_OK) { 3110 errno = err; 3111 zperror2(target_zone, gettext("could not get zone path")); 3112 goto done; 3113 } 3114 3115 /* Don't clone the zone if anything is still mounted there */ 3116 if (zonecfg_find_mounts(source_zonepath, NULL, NULL)) { 3117 zerror(gettext("These file-systems are mounted on " 3118 "subdirectories of %s.\n"), source_zonepath); 3119 (void) zonecfg_find_mounts(source_zonepath, zfm_print, NULL); 3120 err = Z_ERR; 3121 goto done; 3122 } 3123 3124 if ((err = zone_set_state(target_zone, ZONE_STATE_INCOMPLETE)) 3125 != Z_OK) { 3126 errno = err; 3127 zperror2(target_zone, gettext("could not set state")); 3128 goto done; 3129 } 3130 3131 (void) printf(gettext("Cloning zonepath %s..."), source_zonepath); 3132 (void) fflush(stdout); 3133 3134 err = copy_zone(source_zonepath, zonepath); 3135 (void) printf("\n"); 3136 if (err != Z_OK) 3137 goto done; 3138 3139 err = unconfigure_zone(zonepath); 3140 3141 done: 3142 release_lock_file(lockfd); 3143 return ((err == Z_OK) ? Z_OK : Z_ERR); 3144 } 3145 3146 #define RMCOMMAND "/usr/bin/rm -rf" 3147 3148 /* 3149 * Used when moving a zonepath (via copying) to clean up the old path or 3150 * the new path if there was an error. 3151 * 3152 * This function handles the case of a zonepath being a zfs filesystem. 3153 * If it is a zfs filesystem, we cannot just remove the whole zonepath 3154 * since we can't remove the filesystem itself. Instead, we have to remove 3155 * the contents of the filesystem, but not the .zfs directory. 3156 */ 3157 static int 3158 remove_zonepath(char *zonepath) 3159 { 3160 int status; 3161 boolean_t is_zfs = B_FALSE; 3162 struct stat buf; 3163 char cmdbuf[sizeof (RMCOMMAND) + MAXPATHLEN + 128]; 3164 3165 (void) snprintf(cmdbuf, sizeof (cmdbuf), "%s/.zfs", zonepath); 3166 3167 if (stat(cmdbuf, &buf) == 0 && S_ISDIR(buf.st_mode)) 3168 is_zfs = B_TRUE; 3169 3170 if (is_zfs) { 3171 /* 3172 * This doesn't handle the (unlikely) case that there are 3173 * directories or files in the top-level zonepath with white 3174 * space in the names. 3175 */ 3176 (void) snprintf(cmdbuf, sizeof (cmdbuf), 3177 "cd %s && /usr/bin/ls -A | /usr/bin/egrep -v '^\\.zfs$' | " 3178 "/usr/bin/xargs " RMCOMMAND, zonepath); 3179 } else { 3180 /* 3181 * "exec" the command so that the returned status is 3182 * that of rm and not the shell. 3183 */ 3184 (void) snprintf(cmdbuf, sizeof (cmdbuf), 3185 "exec " RMCOMMAND " %s", zonepath); 3186 } 3187 3188 status = do_subproc(cmdbuf); 3189 3190 return (subproc_status("rm", status)); 3191 3192 } 3193 3194 static int 3195 move_func(int argc, char *argv[]) 3196 { 3197 char *new_zonepath = NULL; 3198 int lockfd; 3199 int err, arg; 3200 char zonepath[MAXPATHLEN]; 3201 zone_dochandle_t handle; 3202 boolean_t fast; 3203 boolean_t revert; 3204 struct stat zonepath_buf; 3205 struct stat new_zonepath_buf; 3206 3207 if (zonecfg_in_alt_root()) { 3208 zerror(gettext("cannot move zone in alternate root")); 3209 return (Z_ERR); 3210 } 3211 3212 optind = 0; 3213 if ((arg = getopt(argc, argv, "?")) != EOF) { 3214 switch (arg) { 3215 case '?': 3216 sub_usage(SHELP_MOVE, CMD_MOVE); 3217 return (optopt == '?' ? Z_OK : Z_USAGE); 3218 default: 3219 sub_usage(SHELP_MOVE, CMD_MOVE); 3220 return (Z_USAGE); 3221 } 3222 } 3223 if (argc != (optind + 1)) { 3224 sub_usage(SHELP_MOVE, CMD_MOVE); 3225 return (Z_USAGE); 3226 } 3227 new_zonepath = argv[optind]; 3228 if (sanity_check(target_zone, CMD_MOVE, B_FALSE, B_TRUE) != Z_OK) 3229 return (Z_ERR); 3230 if (verify_details(CMD_MOVE) != Z_OK) 3231 return (Z_ERR); 3232 3233 /* 3234 * Check out the new zonepath. This has the side effect of creating 3235 * a directory for the new zonepath. We depend on this later when we 3236 * stat to see if we are doing a cross file-system move or not. 3237 */ 3238 if (validate_zonepath(new_zonepath, CMD_MOVE) != Z_OK) 3239 return (Z_ERR); 3240 3241 if ((err = zone_get_zonepath(target_zone, zonepath, sizeof (zonepath))) 3242 != Z_OK) { 3243 errno = err; 3244 zperror2(target_zone, gettext("could not get zone path")); 3245 return (Z_ERR); 3246 } 3247 3248 if (stat(zonepath, &zonepath_buf) == -1) { 3249 zperror(gettext("could not stat zone path"), B_FALSE); 3250 return (Z_ERR); 3251 } 3252 3253 if (stat(new_zonepath, &new_zonepath_buf) == -1) { 3254 zperror(gettext("could not stat new zone path"), B_FALSE); 3255 return (Z_ERR); 3256 } 3257 3258 /* Don't move the zone if anything is still mounted there */ 3259 if (zonecfg_find_mounts(zonepath, NULL, NULL)) { 3260 zerror(gettext("These file-systems are mounted on " 3261 "subdirectories of %s.\n"), zonepath); 3262 (void) zonecfg_find_mounts(zonepath, zfm_print, NULL); 3263 return (Z_ERR); 3264 } 3265 3266 /* 3267 * Check if we are moving in the same filesystem and can do a fast 3268 * move or if we are crossing filesystems and have to copy the data. 3269 */ 3270 fast = (zonepath_buf.st_dev == new_zonepath_buf.st_dev); 3271 3272 if ((handle = zonecfg_init_handle()) == NULL) { 3273 zperror(cmd_to_str(CMD_MOVE), B_TRUE); 3274 return (Z_ERR); 3275 } 3276 3277 if ((err = zonecfg_get_handle(target_zone, handle)) != Z_OK) { 3278 errno = err; 3279 zperror(cmd_to_str(CMD_MOVE), B_TRUE); 3280 zonecfg_fini_handle(handle); 3281 return (Z_ERR); 3282 } 3283 3284 if (grab_lock_file(target_zone, &lockfd) != Z_OK) { 3285 zerror(gettext("another %s may have an operation in progress."), 3286 "zoneadm"); 3287 zonecfg_fini_handle(handle); 3288 return (Z_ERR); 3289 } 3290 3291 /* 3292 * We're making some file-system changes now so we have to clean up 3293 * the file-system before we are done. This will either clean up the 3294 * new zonepath if the zonecfg update failed or it will clean up the 3295 * old zonepath if everything is ok. 3296 */ 3297 revert = B_TRUE; 3298 3299 if (fast) { 3300 /* same filesystem, use rename for a quick move */ 3301 3302 /* 3303 * Remove the new_zonepath directory that got created above 3304 * during the validation. It gets in the way of the rename. 3305 */ 3306 if (rmdir(new_zonepath) != 0) { 3307 zperror(gettext("could not rmdir new zone path"), 3308 B_FALSE); 3309 zonecfg_fini_handle(handle); 3310 release_lock_file(lockfd); 3311 return (Z_ERR); 3312 } 3313 3314 if (rename(zonepath, new_zonepath) != 0) { 3315 /* 3316 * If this fails we don't need to do all of the 3317 * cleanup that happens for the rest of the code 3318 * so just return from this error. 3319 */ 3320 zperror(gettext("could not move zone"), B_FALSE); 3321 zonecfg_fini_handle(handle); 3322 release_lock_file(lockfd); 3323 return (Z_ERR); 3324 } 3325 3326 } else { 3327 (void) printf(gettext( 3328 "Moving across file-systems; copying zonepath %s..."), 3329 zonepath); 3330 (void) fflush(stdout); 3331 3332 err = copy_zone(zonepath, new_zonepath); 3333 3334 (void) printf("\n"); 3335 if (err != Z_OK) 3336 goto done; 3337 } 3338 3339 if ((err = zonecfg_set_zonepath(handle, new_zonepath)) != Z_OK) { 3340 errno = err; 3341 zperror(gettext("could not set new zonepath"), B_TRUE); 3342 goto done; 3343 } 3344 3345 if ((err = zonecfg_save(handle)) != Z_OK) { 3346 errno = err; 3347 zperror(gettext("zonecfg save failed"), B_TRUE); 3348 goto done; 3349 } 3350 3351 revert = B_FALSE; 3352 3353 done: 3354 zonecfg_fini_handle(handle); 3355 release_lock_file(lockfd); 3356 3357 /* 3358 * Clean up the file-system based on how things went. We either 3359 * clean up the new zonepath if the operation failed for some reason 3360 * or we clean up the old zonepath if everything is ok. 3361 */ 3362 if (revert) { 3363 /* The zonecfg update failed, cleanup the new zonepath. */ 3364 if (fast) { 3365 if (rename(new_zonepath, zonepath) != 0) { 3366 zperror(gettext("could not restore zonepath"), 3367 B_FALSE); 3368 /* 3369 * err is already != Z_OK since we're reverting 3370 */ 3371 } 3372 } else { 3373 (void) printf(gettext("Cleaning up zonepath %s..."), 3374 new_zonepath); 3375 (void) fflush(stdout); 3376 err = remove_zonepath(new_zonepath); 3377 (void) printf("\n"); 3378 3379 if (err != Z_OK) { 3380 errno = err; 3381 zperror(gettext("could not remove new " 3382 "zonepath"), B_TRUE); 3383 } else { 3384 /* 3385 * Because we're reverting we know the mainline 3386 * code failed but we just reused the err 3387 * variable so we reset it back to Z_ERR. 3388 */ 3389 err = Z_ERR; 3390 } 3391 } 3392 3393 } else { 3394 /* The move was successful, cleanup the old zonepath. */ 3395 if (!fast) { 3396 (void) printf( 3397 gettext("Cleaning up zonepath %s..."), zonepath); 3398 (void) fflush(stdout); 3399 err = remove_zonepath(zonepath); 3400 (void) printf("\n"); 3401 3402 if (err != Z_OK) { 3403 errno = err; 3404 zperror(gettext("could not remove zonepath"), 3405 B_TRUE); 3406 } 3407 } 3408 } 3409 3410 return ((err == Z_OK) ? Z_OK : Z_ERR); 3411 } 3412 3413 static int 3414 detach_func(int argc, char *argv[]) 3415 { 3416 int lockfd; 3417 int err, arg; 3418 char zonepath[MAXPATHLEN]; 3419 zone_dochandle_t handle; 3420 3421 if (zonecfg_in_alt_root()) { 3422 zerror(gettext("cannot detach zone in alternate root")); 3423 return (Z_ERR); 3424 } 3425 3426 optind = 0; 3427 if ((arg = getopt(argc, argv, "?")) != EOF) { 3428 switch (arg) { 3429 case '?': 3430 sub_usage(SHELP_DETACH, CMD_DETACH); 3431 return (optopt == '?' ? Z_OK : Z_USAGE); 3432 default: 3433 sub_usage(SHELP_DETACH, CMD_DETACH); 3434 return (Z_USAGE); 3435 } 3436 } 3437 if (sanity_check(target_zone, CMD_DETACH, B_FALSE, B_TRUE) != Z_OK) 3438 return (Z_ERR); 3439 if (verify_details(CMD_DETACH) != Z_OK) 3440 return (Z_ERR); 3441 3442 if ((err = zone_get_zonepath(target_zone, zonepath, sizeof (zonepath))) 3443 != Z_OK) { 3444 errno = err; 3445 zperror2(target_zone, gettext("could not get zone path")); 3446 return (Z_ERR); 3447 } 3448 3449 /* Don't detach the zone if anything is still mounted there */ 3450 if (zonecfg_find_mounts(zonepath, NULL, NULL)) { 3451 zerror(gettext("These file-systems are mounted on " 3452 "subdirectories of %s.\n"), zonepath); 3453 (void) zonecfg_find_mounts(zonepath, zfm_print, NULL); 3454 return (Z_ERR); 3455 } 3456 3457 if ((handle = zonecfg_init_handle()) == NULL) { 3458 zperror(cmd_to_str(CMD_DETACH), B_TRUE); 3459 return (Z_ERR); 3460 } 3461 3462 if ((err = zonecfg_get_handle(target_zone, handle)) != Z_OK) { 3463 errno = err; 3464 zperror(cmd_to_str(CMD_DETACH), B_TRUE); 3465 zonecfg_fini_handle(handle); 3466 return (Z_ERR); 3467 } 3468 3469 if (grab_lock_file(target_zone, &lockfd) != Z_OK) { 3470 zerror(gettext("another %s may have an operation in progress."), 3471 "zoneadm"); 3472 zonecfg_fini_handle(handle); 3473 return (Z_ERR); 3474 } 3475 3476 if ((err = zonecfg_get_detach_info(handle, B_TRUE)) != Z_OK) { 3477 errno = err; 3478 zperror(gettext("getting the detach information failed"), 3479 B_TRUE); 3480 goto done; 3481 } 3482 3483 if ((err = zonecfg_detach_save(handle)) != Z_OK) { 3484 errno = err; 3485 zperror(gettext("saving the detach manifest failed"), B_TRUE); 3486 goto done; 3487 } 3488 3489 if ((err = zone_set_state(target_zone, ZONE_STATE_CONFIGURED)) 3490 != Z_OK) { 3491 errno = err; 3492 zperror(gettext("could not reset state"), B_TRUE); 3493 } 3494 3495 done: 3496 zonecfg_fini_handle(handle); 3497 release_lock_file(lockfd); 3498 3499 return ((err == Z_OK) ? Z_OK : Z_ERR); 3500 } 3501 3502 /* 3503 * Find the specified package in the sw inventory on the handle and check 3504 * if the version matches what is passed in. 3505 * Return 0 if the packages match 3506 * 1 if the package is found but we have a version mismatch 3507 * -1 if the package is not found 3508 */ 3509 static int 3510 pkg_cmp(zone_dochandle_t handle, char *pkg_name, char *pkg_vers, 3511 char *return_vers, int vers_size) 3512 { 3513 int res = -1; 3514 struct zone_pkgtab pkgtab; 3515 3516 if (zonecfg_setpkgent(handle) != Z_OK) { 3517 (void) fprintf(stderr, 3518 gettext("unable to enumerate packages\n")); 3519 return (Z_ERR); 3520 } 3521 3522 while (zonecfg_getpkgent(handle, &pkgtab) == Z_OK) { 3523 if (strcmp(pkg_name, pkgtab.zone_pkg_name) != 0) 3524 continue; 3525 3526 if (strcmp(pkg_vers, pkgtab.zone_pkg_version) == 0) { 3527 res = 0; 3528 break; 3529 } 3530 3531 (void) strlcpy(return_vers, pkgtab.zone_pkg_version, vers_size); 3532 res = 1; 3533 break; 3534 } 3535 3536 (void) zonecfg_endpkgent(handle); 3537 return (res); 3538 } 3539 3540 /* 3541 * Used in software comparisons to check the packages between the two zone 3542 * handles. The packages have to match or we print a message telling the 3543 * user what is out of sync. The src_cmp flag tells us if the first handle 3544 * is the source machine global zone or not. This is used to enable the 3545 * right messages to be printed and also to enable extra version checking 3546 * that is not needed for the opposite comparison. 3547 */ 3548 static int 3549 pkg_check(char *header, zone_dochandle_t handle1, zone_dochandle_t handle2, 3550 boolean_t src_cmp) 3551 { 3552 int err; 3553 int res = Z_OK; 3554 boolean_t do_header = B_TRUE; 3555 char other_vers[ZONE_PKG_VERSMAX]; 3556 struct zone_pkgtab pkgtab; 3557 3558 if (zonecfg_setpkgent(handle1) != Z_OK) { 3559 (void) fprintf(stderr, 3560 gettext("unable to enumerate packages\n")); 3561 return (Z_ERR); 3562 } 3563 3564 while (zonecfg_getpkgent(handle1, &pkgtab) == Z_OK) { 3565 if ((err = pkg_cmp(handle2, pkgtab.zone_pkg_name, 3566 pkgtab.zone_pkg_version, other_vers, sizeof (other_vers))) 3567 != 0) { 3568 if (do_header && (err < 0 || src_cmp)) { 3569 /* LINTED E_SEC_PRINTF_VAR_FMT */ 3570 (void) fprintf(stderr, header); 3571 do_header = B_FALSE; 3572 } 3573 if (err < 0) { 3574 (void) fprintf(stderr, 3575 (src_cmp == B_TRUE) ? 3576 gettext("\t%s: not installed\n\t\t(%s)\n") : 3577 gettext("\t%s (%s)\n"), 3578 pkgtab.zone_pkg_name, 3579 pkgtab.zone_pkg_version); 3580 res = Z_ERR; 3581 } else if (src_cmp) { 3582 (void) fprintf(stderr, gettext( 3583 "\t%s: version mismatch\n\t\t(%s)" 3584 "\n\t\t(%s)\n"), 3585 pkgtab.zone_pkg_name, 3586 pkgtab.zone_pkg_version, other_vers); 3587 res = Z_ERR; 3588 } 3589 } 3590 } 3591 3592 (void) zonecfg_endpkgent(handle1); 3593 3594 return (res); 3595 } 3596 3597 /* 3598 * Find the specified patch in the sw inventory on the handle and check 3599 * if the version matches what is passed in. 3600 * Return 0 if the patches match 3601 * 1 if the patches is found but we have a version mismatch 3602 * -1 if the patches is not found 3603 */ 3604 static int 3605 patch_cmp(zone_dochandle_t handle, char *patch_id, char *patch_vers, 3606 char *return_vers, int vers_size) 3607 { 3608 int res = -1; 3609 struct zone_patchtab patchtab; 3610 3611 if (zonecfg_setpatchent(handle) != Z_OK) { 3612 (void) fprintf(stderr, 3613 gettext("unable to enumerate patches\n")); 3614 return (Z_ERR); 3615 } 3616 3617 while (zonecfg_getpatchent(handle, &patchtab) == Z_OK) { 3618 char *p; 3619 3620 if ((p = strchr(patchtab.zone_patch_id, '-')) != NULL) 3621 *p++ = '\0'; 3622 else 3623 p = ""; 3624 3625 if (strcmp(patch_id, patchtab.zone_patch_id) != 0) 3626 continue; 3627 3628 if (strcmp(patch_vers, p) == 0) { 3629 res = 0; 3630 break; 3631 } 3632 3633 (void) strlcpy(return_vers, p, vers_size); 3634 /* 3635 * Keep checking. This handles the case where multiple 3636 * versions of the same patch is installed. 3637 */ 3638 res = 1; 3639 } 3640 3641 (void) zonecfg_endpatchent(handle); 3642 return (res); 3643 } 3644 3645 /* 3646 * Used in software comparisons to check the patches between the two zone 3647 * handles. The patches have to match or we print a message telling the 3648 * user what is out of sync. The src_cmp flag tells us if the first handle 3649 * is the source machine global zone or not. This is used to enable the 3650 * right messages to be printed and also to enable extra version checking 3651 * that is not needed for the opposite comparison. 3652 */ 3653 static int 3654 patch_check(char *header, zone_dochandle_t handle1, zone_dochandle_t handle2, 3655 boolean_t src_cmp) 3656 { 3657 int err; 3658 int res = Z_OK; 3659 boolean_t do_header = B_TRUE; 3660 char other_vers[MAXNAMELEN]; 3661 struct zone_patchtab patchtab; 3662 3663 if (zonecfg_setpatchent(handle1) != Z_OK) { 3664 (void) fprintf(stderr, 3665 gettext("unable to enumerate patches\n")); 3666 return (Z_ERR); 3667 } 3668 3669 while (zonecfg_getpatchent(handle1, &patchtab) == Z_OK) { 3670 char *patch_vers; 3671 3672 if ((patch_vers = strchr(patchtab.zone_patch_id, '-')) != NULL) 3673 *patch_vers++ = '\0'; 3674 else 3675 patch_vers = ""; 3676 3677 if ((err = patch_cmp(handle2, patchtab.zone_patch_id, 3678 patch_vers, other_vers, sizeof (other_vers))) != 0) { 3679 if (do_header && (err < 0 || src_cmp)) { 3680 /* LINTED E_SEC_PRINTF_VAR_FMT */ 3681 (void) fprintf(stderr, header); 3682 do_header = B_FALSE; 3683 } 3684 if (err < 0) { 3685 (void) fprintf(stderr, 3686 (src_cmp == B_TRUE) ? 3687 gettext("\t%s: not installed\n") : 3688 gettext("\t%s\n"), 3689 patchtab.zone_patch_id); 3690 res = Z_ERR; 3691 } else if (src_cmp) { 3692 (void) fprintf(stderr, 3693 gettext("\t%s: version mismatch\n\t\t(%s) " 3694 "(%s)\n"), patchtab.zone_patch_id, 3695 patch_vers, other_vers); 3696 res = Z_ERR; 3697 } 3698 } 3699 } 3700 3701 (void) zonecfg_endpatchent(handle1); 3702 3703 return (res); 3704 } 3705 3706 /* 3707 * Compare the software on the local global zone and source system global 3708 * zone. Used when we are trying to attach a zone during migration. 3709 * l_handle is for the local system and s_handle is for the source system. 3710 * These have a snapshot of the appropriate packages and patches in the global 3711 * zone for the two machines. 3712 * The functions called here will print any messages that are needed to 3713 * inform the user about package or patch problems. 3714 */ 3715 static int 3716 sw_cmp(zone_dochandle_t l_handle, zone_dochandle_t s_handle) 3717 { 3718 char *hdr; 3719 int res = Z_OK; 3720 3721 /* 3722 * Check the source host for pkgs (and versions) that are not on the 3723 * local host. 3724 */ 3725 hdr = gettext("These packages installed on the source system are " 3726 "inconsistent with this system:\n"); 3727 if (pkg_check(hdr, s_handle, l_handle, B_TRUE) != Z_OK) 3728 res = Z_ERR; 3729 3730 /* 3731 * Now check the local host for pkgs that were not on the source host. 3732 * We already handled version mismatches in the loop above. 3733 */ 3734 hdr = gettext("These packages installed on this system were " 3735 "not installed on the source system:\n"); 3736 if (pkg_check(hdr, l_handle, s_handle, B_FALSE) != Z_OK) 3737 res = Z_ERR; 3738 3739 /* 3740 * Check the source host for patches that are not on the local host. 3741 */ 3742 hdr = gettext("These patches installed on the source system are " 3743 "inconsistent with this system:\n"); 3744 if (patch_check(hdr, s_handle, l_handle, B_TRUE) != Z_OK) 3745 res = Z_ERR; 3746 3747 /* 3748 * Check the local host for patches that were not on the source host. 3749 * We already handled version mismatches in the loop above. 3750 */ 3751 hdr = gettext("These patches installed on this system were " 3752 "not installed on the source system:\n"); 3753 if (patch_check(hdr, l_handle, s_handle, B_FALSE) != Z_OK) 3754 res = Z_ERR; 3755 3756 return (res); 3757 } 3758 3759 /* 3760 * During attach we go through and fix up the /dev entries for the zone 3761 * we are attaching. In order to regenerate /dev with the correct devices, 3762 * the old /dev will be removed, the zone readied (which generates a new 3763 * /dev) then halted, then we use the info from the manifest to update 3764 * the modes, owners, etc. on the new /dev. 3765 */ 3766 static int 3767 dev_fix(zone_dochandle_t handle) 3768 { 3769 int res; 3770 int err; 3771 int status; 3772 struct zone_devpermtab devtab; 3773 zone_cmd_arg_t zarg; 3774 char devpath[MAXPATHLEN]; 3775 /* 6: "exec " and " " */ 3776 char cmdbuf[sizeof (RMCOMMAND) + MAXPATHLEN + 6]; 3777 3778 if ((res = zonecfg_get_zonepath(handle, devpath, sizeof (devpath))) 3779 != Z_OK) 3780 return (res); 3781 3782 if (strlcat(devpath, "/dev", sizeof (devpath)) >= sizeof (devpath)) 3783 return (Z_TOO_BIG); 3784 3785 /* 3786 * "exec" the command so that the returned status is that of 3787 * RMCOMMAND and not the shell. 3788 */ 3789 (void) snprintf(cmdbuf, sizeof (cmdbuf), "exec " RMCOMMAND " %s", 3790 devpath); 3791 status = do_subproc(cmdbuf); 3792 if ((err = subproc_status(RMCOMMAND, status)) != Z_OK) { 3793 (void) fprintf(stderr, 3794 gettext("could not remove existing /dev\n")); 3795 return (Z_ERR); 3796 } 3797 3798 /* In order to ready the zone, it must be in the installed state */ 3799 if ((err = zone_set_state(target_zone, ZONE_STATE_INSTALLED)) != Z_OK) { 3800 errno = err; 3801 zperror(gettext("could not reset state"), B_TRUE); 3802 return (Z_ERR); 3803 } 3804 3805 /* We have to ready the zone to regen the dev tree */ 3806 zarg.cmd = Z_READY; 3807 if (call_zoneadmd(target_zone, &zarg) != 0) { 3808 zerror(gettext("call to %s failed"), "zoneadmd"); 3809 return (Z_ERR); 3810 } 3811 3812 zarg.cmd = Z_HALT; 3813 if (call_zoneadmd(target_zone, &zarg) != 0) { 3814 zerror(gettext("call to %s failed"), "zoneadmd"); 3815 return (Z_ERR); 3816 } 3817 3818 if (zonecfg_setdevperment(handle) != Z_OK) { 3819 (void) fprintf(stderr, 3820 gettext("unable to enumerate device entries\n")); 3821 return (Z_ERR); 3822 } 3823 3824 while (zonecfg_getdevperment(handle, &devtab) == Z_OK) { 3825 int err; 3826 3827 if ((err = zonecfg_devperms_apply(handle, 3828 devtab.zone_devperm_name, devtab.zone_devperm_uid, 3829 devtab.zone_devperm_gid, devtab.zone_devperm_mode, 3830 devtab.zone_devperm_acl)) != Z_OK && err != Z_INVAL) 3831 (void) fprintf(stderr, gettext("error updating device " 3832 "%s: %s\n"), devtab.zone_devperm_name, 3833 zonecfg_strerror(err)); 3834 3835 free(devtab.zone_devperm_acl); 3836 } 3837 3838 (void) zonecfg_enddevperment(handle); 3839 3840 return (Z_OK); 3841 } 3842 3843 static int 3844 attach_func(int argc, char *argv[]) 3845 { 3846 int lockfd; 3847 int err, arg; 3848 boolean_t force = B_FALSE; 3849 zone_dochandle_t handle; 3850 zone_dochandle_t athandle = NULL; 3851 char zonepath[MAXPATHLEN]; 3852 3853 if (zonecfg_in_alt_root()) { 3854 zerror(gettext("cannot attach zone in alternate root")); 3855 return (Z_ERR); 3856 } 3857 3858 optind = 0; 3859 if ((arg = getopt(argc, argv, "?F")) != EOF) { 3860 switch (arg) { 3861 case '?': 3862 sub_usage(SHELP_ATTACH, CMD_ATTACH); 3863 return (optopt == '?' ? Z_OK : Z_USAGE); 3864 case 'F': 3865 force = B_TRUE; 3866 break; 3867 default: 3868 sub_usage(SHELP_ATTACH, CMD_ATTACH); 3869 return (Z_USAGE); 3870 } 3871 } 3872 if (sanity_check(target_zone, CMD_ATTACH, B_FALSE, B_TRUE) != Z_OK) 3873 return (Z_ERR); 3874 if (verify_details(CMD_ATTACH) != Z_OK) 3875 return (Z_ERR); 3876 3877 if ((err = zone_get_zonepath(target_zone, zonepath, sizeof (zonepath))) 3878 != Z_OK) { 3879 errno = err; 3880 zperror2(target_zone, gettext("could not get zone path")); 3881 return (Z_ERR); 3882 } 3883 3884 if ((handle = zonecfg_init_handle()) == NULL) { 3885 zperror(cmd_to_str(CMD_ATTACH), B_TRUE); 3886 return (Z_ERR); 3887 } 3888 3889 if ((err = zonecfg_get_handle(target_zone, handle)) != Z_OK) { 3890 errno = err; 3891 zperror(cmd_to_str(CMD_ATTACH), B_TRUE); 3892 zonecfg_fini_handle(handle); 3893 return (Z_ERR); 3894 } 3895 3896 if (grab_lock_file(target_zone, &lockfd) != Z_OK) { 3897 zerror(gettext("another %s may have an operation in progress."), 3898 "zoneadm"); 3899 zonecfg_fini_handle(handle); 3900 return (Z_ERR); 3901 } 3902 3903 if (force) 3904 goto forced; 3905 3906 if ((athandle = zonecfg_init_handle()) == NULL) { 3907 zperror(cmd_to_str(CMD_ATTACH), B_TRUE); 3908 goto done; 3909 } 3910 3911 if ((err = zonecfg_get_attach_handle(zonepath, target_zone, B_TRUE, 3912 athandle)) != Z_OK) { 3913 if (err == Z_NO_ZONE) 3914 zerror(gettext("Not a detached zone")); 3915 else if (err == Z_INVALID_DOCUMENT) 3916 zerror(gettext("Cannot attach to an earlier release " 3917 "of the operating system")); 3918 else 3919 zperror(cmd_to_str(CMD_ATTACH), B_TRUE); 3920 goto done; 3921 } 3922 3923 /* Get the detach information for the locally defined zone. */ 3924 if ((err = zonecfg_get_detach_info(handle, B_FALSE)) != Z_OK) { 3925 errno = err; 3926 zperror(gettext("getting the attach information failed"), 3927 B_TRUE); 3928 goto done; 3929 } 3930 3931 /* sw_cmp prints error msgs as necessary */ 3932 if ((err = sw_cmp(handle, athandle)) != Z_OK) 3933 goto done; 3934 3935 if ((err = dev_fix(athandle)) != Z_OK) 3936 goto done; 3937 3938 forced: 3939 3940 zonecfg_rm_detached(handle, force); 3941 3942 if ((err = zone_set_state(target_zone, ZONE_STATE_INSTALLED)) != Z_OK) { 3943 errno = err; 3944 zperror(gettext("could not reset state"), B_TRUE); 3945 } 3946 3947 done: 3948 zonecfg_fini_handle(handle); 3949 release_lock_file(lockfd); 3950 if (athandle != NULL) 3951 zonecfg_fini_handle(athandle); 3952 3953 return ((err == Z_OK) ? Z_OK : Z_ERR); 3954 } 3955 3956 /* 3957 * On input, TRUE => yes, FALSE => no. 3958 * On return, TRUE => 1, FALSE => 0, could not ask => -1. 3959 */ 3960 3961 static int 3962 ask_yesno(boolean_t default_answer, const char *question) 3963 { 3964 char line[64]; /* should be large enough to answer yes or no */ 3965 3966 if (!isatty(STDIN_FILENO)) 3967 return (-1); 3968 for (;;) { 3969 (void) printf("%s (%s)? ", question, 3970 default_answer ? "[y]/n" : "y/[n]"); 3971 if (fgets(line, sizeof (line), stdin) == NULL || 3972 line[0] == '\n') 3973 return (default_answer ? 1 : 0); 3974 if (tolower(line[0]) == 'y') 3975 return (1); 3976 if (tolower(line[0]) == 'n') 3977 return (0); 3978 } 3979 } 3980 3981 static int 3982 uninstall_func(int argc, char *argv[]) 3983 { 3984 /* 6: "exec " and " " */ 3985 char cmdbuf[sizeof (RMCOMMAND) + MAXPATHLEN + 6]; 3986 char line[ZONENAME_MAX + 128]; /* Enough for "Are you sure ..." */ 3987 char rootpath[MAXPATHLEN], devpath[MAXPATHLEN]; 3988 boolean_t force = B_FALSE; 3989 int lockfd, answer; 3990 int err, arg; 3991 int status; 3992 3993 if (zonecfg_in_alt_root()) { 3994 zerror(gettext("cannot uninstall zone in alternate root")); 3995 return (Z_ERR); 3996 } 3997 3998 optind = 0; 3999 while ((arg = getopt(argc, argv, "?F")) != EOF) { 4000 switch (arg) { 4001 case '?': 4002 sub_usage(SHELP_UNINSTALL, CMD_UNINSTALL); 4003 return (optopt == '?' ? Z_OK : Z_USAGE); 4004 case 'F': 4005 force = B_TRUE; 4006 break; 4007 default: 4008 sub_usage(SHELP_UNINSTALL, CMD_UNINSTALL); 4009 return (Z_USAGE); 4010 } 4011 } 4012 if (argc > optind) { 4013 sub_usage(SHELP_UNINSTALL, CMD_UNINSTALL); 4014 return (Z_USAGE); 4015 } 4016 4017 if (sanity_check(target_zone, CMD_UNINSTALL, B_FALSE, B_TRUE) != Z_OK) 4018 return (Z_ERR); 4019 4020 if (!force) { 4021 (void) snprintf(line, sizeof (line), 4022 gettext("Are you sure you want to %s zone %s"), 4023 cmd_to_str(CMD_UNINSTALL), target_zone); 4024 if ((answer = ask_yesno(B_FALSE, line)) == 0) { 4025 return (Z_OK); 4026 } else if (answer == -1) { 4027 zerror(gettext("Input not from terminal and -F " 4028 "not specified: %s not done."), 4029 cmd_to_str(CMD_UNINSTALL)); 4030 return (Z_ERR); 4031 } 4032 } 4033 4034 if ((err = zone_get_zonepath(target_zone, devpath, 4035 sizeof (devpath))) != Z_OK) { 4036 errno = err; 4037 zperror2(target_zone, gettext("could not get zone path")); 4038 return (Z_ERR); 4039 } 4040 (void) strlcat(devpath, "/dev", sizeof (devpath)); 4041 if ((err = zone_get_rootpath(target_zone, rootpath, 4042 sizeof (rootpath))) != Z_OK) { 4043 errno = err; 4044 zperror2(target_zone, gettext("could not get root path")); 4045 return (Z_ERR); 4046 } 4047 4048 /* 4049 * If there seems to be a zoneadmd running for this zone, call it 4050 * to tell it that an uninstall is happening; if all goes well it 4051 * will then shut itself down. 4052 */ 4053 if (ping_zoneadmd(target_zone) == Z_OK) { 4054 zone_cmd_arg_t zarg; 4055 zarg.cmd = Z_NOTE_UNINSTALLING; 4056 /* we don't care too much if this fails... just plow on */ 4057 (void) call_zoneadmd(target_zone, &zarg); 4058 } 4059 4060 if (grab_lock_file(target_zone, &lockfd) != Z_OK) { 4061 zerror(gettext("another %s may have an operation in progress."), 4062 "zoneadm"); 4063 return (Z_ERR); 4064 } 4065 4066 /* Don't uninstall the zone if anything is mounted there */ 4067 err = zonecfg_find_mounts(rootpath, NULL, NULL); 4068 if (err) { 4069 zerror(gettext("These file-systems are mounted on " 4070 "subdirectories of %s.\n"), rootpath); 4071 (void) zonecfg_find_mounts(rootpath, zfm_print, NULL); 4072 return (Z_ERR); 4073 } 4074 4075 err = zone_set_state(target_zone, ZONE_STATE_INCOMPLETE); 4076 if (err != Z_OK) { 4077 errno = err; 4078 zperror2(target_zone, gettext("could not set state")); 4079 goto bad; 4080 } 4081 4082 /* 4083 * "exec" the command so that the returned status is that of 4084 * RMCOMMAND and not the shell. 4085 */ 4086 (void) snprintf(cmdbuf, sizeof (cmdbuf), "exec " RMCOMMAND " %s", 4087 devpath); 4088 status = do_subproc(cmdbuf); 4089 if ((err = subproc_status(RMCOMMAND, status)) != Z_OK) 4090 goto bad; 4091 (void) snprintf(cmdbuf, sizeof (cmdbuf), "exec " RMCOMMAND " %s", 4092 rootpath); 4093 status = do_subproc(cmdbuf); 4094 if ((err = subproc_status(RMCOMMAND, status)) != Z_OK) 4095 goto bad; 4096 err = zone_set_state(target_zone, ZONE_STATE_CONFIGURED); 4097 if (err != Z_OK) { 4098 errno = err; 4099 zperror2(target_zone, gettext("could not reset state")); 4100 } 4101 bad: 4102 release_lock_file(lockfd); 4103 return (err); 4104 } 4105 4106 /* ARGSUSED */ 4107 static int 4108 mount_func(int argc, char *argv[]) 4109 { 4110 zone_cmd_arg_t zarg; 4111 4112 if (argc > 0) 4113 return (Z_USAGE); 4114 if (sanity_check(target_zone, CMD_MOUNT, B_FALSE, B_FALSE) != Z_OK) 4115 return (Z_ERR); 4116 if (verify_details(CMD_MOUNT) != Z_OK) 4117 return (Z_ERR); 4118 4119 zarg.cmd = Z_MOUNT; 4120 if (call_zoneadmd(target_zone, &zarg) != 0) { 4121 zerror(gettext("call to %s failed"), "zoneadmd"); 4122 return (Z_ERR); 4123 } 4124 return (Z_OK); 4125 } 4126 4127 /* ARGSUSED */ 4128 static int 4129 unmount_func(int argc, char *argv[]) 4130 { 4131 zone_cmd_arg_t zarg; 4132 4133 if (argc > 0) 4134 return (Z_USAGE); 4135 if (sanity_check(target_zone, CMD_UNMOUNT, B_FALSE, B_FALSE) != Z_OK) 4136 return (Z_ERR); 4137 4138 zarg.cmd = Z_UNMOUNT; 4139 if (call_zoneadmd(target_zone, &zarg) != 0) { 4140 zerror(gettext("call to %s failed"), "zoneadmd"); 4141 return (Z_ERR); 4142 } 4143 return (Z_OK); 4144 } 4145 4146 static int 4147 help_func(int argc, char *argv[]) 4148 { 4149 int arg, cmd_num; 4150 4151 if (argc == 0) { 4152 (void) usage(B_TRUE); 4153 return (Z_OK); 4154 } 4155 optind = 0; 4156 if ((arg = getopt(argc, argv, "?")) != EOF) { 4157 switch (arg) { 4158 case '?': 4159 sub_usage(SHELP_HELP, CMD_HELP); 4160 return (optopt == '?' ? Z_OK : Z_USAGE); 4161 default: 4162 sub_usage(SHELP_HELP, CMD_HELP); 4163 return (Z_USAGE); 4164 } 4165 } 4166 while (optind < argc) { 4167 /* Private commands have NULL short_usage; omit them */ 4168 if ((cmd_num = cmd_match(argv[optind])) < 0 || 4169 cmdtab[cmd_num].short_usage == NULL) { 4170 sub_usage(SHELP_HELP, CMD_HELP); 4171 return (Z_USAGE); 4172 } 4173 sub_usage(cmdtab[cmd_num].short_usage, cmd_num); 4174 optind++; 4175 } 4176 return (Z_OK); 4177 } 4178 4179 /* 4180 * Returns: CMD_MIN thru CMD_MAX on success, -1 on error 4181 */ 4182 4183 static int 4184 cmd_match(char *cmd) 4185 { 4186 int i; 4187 4188 for (i = CMD_MIN; i <= CMD_MAX; i++) { 4189 /* return only if there is an exact match */ 4190 if (strcmp(cmd, cmdtab[i].cmd_name) == 0) 4191 return (cmdtab[i].cmd_num); 4192 } 4193 return (-1); 4194 } 4195 4196 static int 4197 parse_and_run(int argc, char *argv[]) 4198 { 4199 int i = cmd_match(argv[0]); 4200 4201 if (i < 0) 4202 return (usage(B_FALSE)); 4203 return (cmdtab[i].handler(argc - 1, &(argv[1]))); 4204 } 4205 4206 static char * 4207 get_execbasename(char *execfullname) 4208 { 4209 char *last_slash, *execbasename; 4210 4211 /* guard against '/' at end of command invocation */ 4212 for (;;) { 4213 last_slash = strrchr(execfullname, '/'); 4214 if (last_slash == NULL) { 4215 execbasename = execfullname; 4216 break; 4217 } else { 4218 execbasename = last_slash + 1; 4219 if (*execbasename == '\0') { 4220 *last_slash = '\0'; 4221 continue; 4222 } 4223 break; 4224 } 4225 } 4226 return (execbasename); 4227 } 4228 4229 int 4230 main(int argc, char **argv) 4231 { 4232 int arg; 4233 zoneid_t zid; 4234 struct stat st; 4235 4236 if ((locale = setlocale(LC_ALL, "")) == NULL) 4237 locale = "C"; 4238 (void) textdomain(TEXT_DOMAIN); 4239 setbuf(stdout, NULL); 4240 (void) sigset(SIGHUP, SIG_IGN); 4241 execname = get_execbasename(argv[0]); 4242 target_zone = NULL; 4243 if (chdir("/") != 0) { 4244 zerror(gettext("could not change directory to /.")); 4245 exit(Z_ERR); 4246 } 4247 4248 while ((arg = getopt(argc, argv, "?z:R:")) != EOF) { 4249 switch (arg) { 4250 case '?': 4251 return (usage(B_TRUE)); 4252 case 'z': 4253 target_zone = optarg; 4254 break; 4255 case 'R': /* private option for admin/install use */ 4256 if (*optarg != '/') { 4257 zerror(gettext("root path must be absolute.")); 4258 exit(Z_ERR); 4259 } 4260 if (stat(optarg, &st) == -1 || !S_ISDIR(st.st_mode)) { 4261 zerror( 4262 gettext("root path must be a directory.")); 4263 exit(Z_ERR); 4264 } 4265 zonecfg_set_root(optarg); 4266 break; 4267 default: 4268 return (usage(B_FALSE)); 4269 } 4270 } 4271 4272 if (optind >= argc) 4273 return (usage(B_FALSE)); 4274 if (target_zone != NULL && zone_get_id(target_zone, &zid) != 0) { 4275 errno = Z_NO_ZONE; 4276 zperror(target_zone, B_TRUE); 4277 exit(Z_ERR); 4278 } 4279 return (parse_and_run(argc - optind, &argv[optind])); 4280 } 4281