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