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