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 zerror(gettext("must be in the global zone to %s a zone."), 1553 cmd_to_str(cmd_num)); 1554 return (Z_ERR); 1555 } 1556 1557 if ((privset = priv_allocset()) == NULL) { 1558 zerror(gettext("%s failed"), "priv_allocset"); 1559 return (Z_ERR); 1560 } 1561 1562 if (getppriv(PRIV_EFFECTIVE, privset) != 0) { 1563 zerror(gettext("%s failed"), "getppriv"); 1564 priv_freeset(privset); 1565 return (Z_ERR); 1566 } 1567 1568 if (priv_isfullset(privset) == B_FALSE) { 1569 zerror(gettext("only a privileged user may %s a zone."), 1570 cmd_to_str(cmd_num)); 1571 priv_freeset(privset); 1572 return (Z_ERR); 1573 } 1574 priv_freeset(privset); 1575 1576 if (zone == NULL) { 1577 zerror(gettext("no zone specified")); 1578 return (Z_ERR); 1579 } 1580 1581 if (strcmp(zone, GLOBAL_ZONENAME) == 0) { 1582 zerror(gettext("%s operation is invalid for the global zone."), 1583 cmd_to_str(cmd_num)); 1584 return (Z_ERR); 1585 } 1586 1587 if (strncmp(zone, "SUNW", 4) == 0) { 1588 zerror(gettext("%s operation is invalid for zones starting " 1589 "with SUNW."), cmd_to_str(cmd_num)); 1590 return (Z_ERR); 1591 } 1592 1593 if (!zonecfg_in_alt_root()) { 1594 zent = lookup_running_zone(zone); 1595 } else if ((fp = zonecfg_open_scratch("", B_FALSE)) == NULL) { 1596 zent = NULL; 1597 } else { 1598 if (zonecfg_find_scratch(fp, zone, zonecfg_get_root(), 1599 kernzone, sizeof (kernzone)) == 0) 1600 zent = lookup_running_zone(kernzone); 1601 else 1602 zent = NULL; 1603 zonecfg_close_scratch(fp); 1604 } 1605 1606 /* 1607 * Look up from the kernel for 'running' zones. 1608 */ 1609 if (running) { 1610 if (zent == NULL) { 1611 zerror(gettext("not running")); 1612 return (Z_ERR); 1613 } 1614 } else { 1615 int err; 1616 1617 if (unsafe_when_running && zent != NULL) { 1618 /* check whether the zone is ready or running */ 1619 if ((err = zone_get_state(zent->zname, 1620 &zent->zstate_num)) != Z_OK) { 1621 errno = err; 1622 zperror2(zent->zname, 1623 gettext("could not get state")); 1624 /* can't tell, so hedge */ 1625 zent->zstate_str = "ready/running"; 1626 } else { 1627 zent->zstate_str = 1628 zone_state_str(zent->zstate_num); 1629 } 1630 zerror(gettext("%s operation is invalid for %s zones."), 1631 cmd_to_str(cmd_num), zent->zstate_str); 1632 return (Z_ERR); 1633 } 1634 if ((err = zone_get_state(zone, &state)) != Z_OK) { 1635 errno = err; 1636 zperror2(zone, gettext("could not get state")); 1637 return (Z_ERR); 1638 } 1639 switch (cmd_num) { 1640 case CMD_UNINSTALL: 1641 if (state == ZONE_STATE_CONFIGURED) { 1642 zerror(gettext("is already in state '%s'."), 1643 zone_state_str(ZONE_STATE_CONFIGURED)); 1644 return (Z_ERR); 1645 } 1646 break; 1647 case CMD_ATTACH: 1648 case CMD_CLONE: 1649 case CMD_INSTALL: 1650 if (state == ZONE_STATE_INSTALLED) { 1651 zerror(gettext("is already %s."), 1652 zone_state_str(ZONE_STATE_INSTALLED)); 1653 return (Z_ERR); 1654 } else if (state == ZONE_STATE_INCOMPLETE) { 1655 zerror(gettext("zone is %s; %s required."), 1656 zone_state_str(ZONE_STATE_INCOMPLETE), 1657 cmd_to_str(CMD_UNINSTALL)); 1658 return (Z_ERR); 1659 } 1660 break; 1661 case CMD_DETACH: 1662 case CMD_MOVE: 1663 case CMD_READY: 1664 case CMD_BOOT: 1665 case CMD_MOUNT: 1666 if (state < ZONE_STATE_INSTALLED) { 1667 zerror(gettext("must be %s before %s."), 1668 zone_state_str(ZONE_STATE_INSTALLED), 1669 cmd_to_str(cmd_num)); 1670 return (Z_ERR); 1671 } 1672 break; 1673 case CMD_VERIFY: 1674 if (state == ZONE_STATE_INCOMPLETE) { 1675 zerror(gettext("zone is %s; %s required."), 1676 zone_state_str(ZONE_STATE_INCOMPLETE), 1677 cmd_to_str(CMD_UNINSTALL)); 1678 return (Z_ERR); 1679 } 1680 break; 1681 case CMD_UNMOUNT: 1682 if (state != ZONE_STATE_MOUNTED) { 1683 zerror(gettext("must be %s before %s."), 1684 zone_state_str(ZONE_STATE_MOUNTED), 1685 cmd_to_str(cmd_num)); 1686 return (Z_ERR); 1687 } 1688 break; 1689 } 1690 } 1691 return (Z_OK); 1692 } 1693 1694 static int 1695 halt_func(int argc, char *argv[]) 1696 { 1697 zone_cmd_arg_t zarg; 1698 int arg; 1699 1700 if (zonecfg_in_alt_root()) { 1701 zerror(gettext("cannot halt zone in alternate root")); 1702 return (Z_ERR); 1703 } 1704 1705 optind = 0; 1706 if ((arg = getopt(argc, argv, "?")) != EOF) { 1707 switch (arg) { 1708 case '?': 1709 sub_usage(SHELP_HALT, CMD_HALT); 1710 return (optopt == '?' ? Z_OK : Z_USAGE); 1711 default: 1712 sub_usage(SHELP_HALT, CMD_HALT); 1713 return (Z_USAGE); 1714 } 1715 } 1716 if (argc > optind) { 1717 sub_usage(SHELP_HALT, CMD_HALT); 1718 return (Z_USAGE); 1719 } 1720 /* 1721 * zoneadmd should be the one to decide whether or not to proceed, 1722 * so even though it seems that the fourth parameter below should 1723 * perhaps be B_TRUE, it really shouldn't be. 1724 */ 1725 if (sanity_check(target_zone, CMD_HALT, B_FALSE, B_FALSE) != Z_OK) 1726 return (Z_ERR); 1727 1728 zarg.cmd = Z_HALT; 1729 return ((call_zoneadmd(target_zone, &zarg) == 0) ? Z_OK : Z_ERR); 1730 } 1731 1732 static int 1733 reboot_func(int argc, char *argv[]) 1734 { 1735 zone_cmd_arg_t zarg; 1736 int arg; 1737 1738 if (zonecfg_in_alt_root()) { 1739 zerror(gettext("cannot reboot zone in alternate root")); 1740 return (Z_ERR); 1741 } 1742 1743 optind = 0; 1744 if ((arg = getopt(argc, argv, "?")) != EOF) { 1745 switch (arg) { 1746 case '?': 1747 sub_usage(SHELP_REBOOT, CMD_REBOOT); 1748 return (optopt == '?' ? Z_OK : Z_USAGE); 1749 default: 1750 sub_usage(SHELP_REBOOT, CMD_REBOOT); 1751 return (Z_USAGE); 1752 } 1753 } 1754 if (argc > 0) { 1755 sub_usage(SHELP_REBOOT, CMD_REBOOT); 1756 return (Z_USAGE); 1757 } 1758 /* 1759 * zoneadmd should be the one to decide whether or not to proceed, 1760 * so even though it seems that the fourth parameter below should 1761 * perhaps be B_TRUE, it really shouldn't be. 1762 */ 1763 if (sanity_check(target_zone, CMD_REBOOT, B_TRUE, B_FALSE) != Z_OK) 1764 return (Z_ERR); 1765 if (verify_details(CMD_REBOOT) != Z_OK) 1766 return (Z_ERR); 1767 1768 zarg.cmd = Z_REBOOT; 1769 return ((call_zoneadmd(target_zone, &zarg) == 0) ? Z_OK : Z_ERR); 1770 } 1771 1772 static int 1773 verify_rctls(zone_dochandle_t handle) 1774 { 1775 struct zone_rctltab rctltab; 1776 size_t rbs = rctlblk_size(); 1777 rctlblk_t *rctlblk; 1778 int error = Z_INVAL; 1779 1780 if ((rctlblk = malloc(rbs)) == NULL) { 1781 zerror(gettext("failed to allocate %lu bytes: %s"), rbs, 1782 strerror(errno)); 1783 return (Z_NOMEM); 1784 } 1785 1786 if (zonecfg_setrctlent(handle) != Z_OK) { 1787 zerror(gettext("zonecfg_setrctlent failed")); 1788 free(rctlblk); 1789 return (error); 1790 } 1791 1792 rctltab.zone_rctl_valptr = NULL; 1793 while (zonecfg_getrctlent(handle, &rctltab) == Z_OK) { 1794 struct zone_rctlvaltab *rctlval; 1795 const char *name = rctltab.zone_rctl_name; 1796 1797 if (!zonecfg_is_rctl(name)) { 1798 zerror(gettext("WARNING: Ignoring unrecognized rctl " 1799 "'%s'."), name); 1800 zonecfg_free_rctl_value_list(rctltab.zone_rctl_valptr); 1801 rctltab.zone_rctl_valptr = NULL; 1802 continue; 1803 } 1804 1805 for (rctlval = rctltab.zone_rctl_valptr; rctlval != NULL; 1806 rctlval = rctlval->zone_rctlval_next) { 1807 if (zonecfg_construct_rctlblk(rctlval, rctlblk) 1808 != Z_OK) { 1809 zerror(gettext("invalid rctl value: " 1810 "(priv=%s,limit=%s,action%s)"), 1811 rctlval->zone_rctlval_priv, 1812 rctlval->zone_rctlval_limit, 1813 rctlval->zone_rctlval_action); 1814 goto out; 1815 } 1816 if (!zonecfg_valid_rctl(name, rctlblk)) { 1817 zerror(gettext("(priv=%s,limit=%s,action=%s) " 1818 "is not a valid value for rctl '%s'"), 1819 rctlval->zone_rctlval_priv, 1820 rctlval->zone_rctlval_limit, 1821 rctlval->zone_rctlval_action, 1822 name); 1823 goto out; 1824 } 1825 } 1826 zonecfg_free_rctl_value_list(rctltab.zone_rctl_valptr); 1827 } 1828 rctltab.zone_rctl_valptr = NULL; 1829 error = Z_OK; 1830 out: 1831 zonecfg_free_rctl_value_list(rctltab.zone_rctl_valptr); 1832 (void) zonecfg_endrctlent(handle); 1833 free(rctlblk); 1834 return (error); 1835 } 1836 1837 static int 1838 verify_pool(zone_dochandle_t handle) 1839 { 1840 char poolname[MAXPATHLEN]; 1841 pool_conf_t *poolconf; 1842 pool_t *pool; 1843 int status; 1844 int error; 1845 1846 /* 1847 * This ends up being very similar to the check done in zoneadmd. 1848 */ 1849 error = zonecfg_get_pool(handle, poolname, sizeof (poolname)); 1850 if (error == Z_NO_ENTRY || (error == Z_OK && strlen(poolname) == 0)) { 1851 /* 1852 * No pool specified. 1853 */ 1854 return (0); 1855 } 1856 if (error != Z_OK) { 1857 zperror(gettext("Unable to retrieve pool name from " 1858 "configuration"), B_TRUE); 1859 return (error); 1860 } 1861 /* 1862 * Don't do anything if pools aren't enabled. 1863 */ 1864 if (pool_get_status(&status) != PO_SUCCESS || status != POOL_ENABLED) { 1865 zerror(gettext("WARNING: pools facility not active; " 1866 "zone will not be bound to pool '%s'."), poolname); 1867 return (Z_OK); 1868 } 1869 /* 1870 * Try to provide a sane error message if the requested pool doesn't 1871 * exist. It isn't clear that pools-related failures should 1872 * necessarily translate to a failure to verify the zone configuration, 1873 * hence they are not considered errors. 1874 */ 1875 if ((poolconf = pool_conf_alloc()) == NULL) { 1876 zerror(gettext("WARNING: pool_conf_alloc failed; " 1877 "using default pool")); 1878 return (Z_OK); 1879 } 1880 if (pool_conf_open(poolconf, pool_dynamic_location(), PO_RDONLY) != 1881 PO_SUCCESS) { 1882 zerror(gettext("WARNING: pool_conf_open failed; " 1883 "using default pool")); 1884 pool_conf_free(poolconf); 1885 return (Z_OK); 1886 } 1887 pool = pool_get_pool(poolconf, poolname); 1888 (void) pool_conf_close(poolconf); 1889 pool_conf_free(poolconf); 1890 if (pool == NULL) { 1891 zerror(gettext("WARNING: pool '%s' not found. " 1892 "using default pool"), poolname); 1893 } 1894 1895 return (Z_OK); 1896 } 1897 1898 static int 1899 verify_ipd(zone_dochandle_t handle) 1900 { 1901 int return_code = Z_OK; 1902 struct zone_fstab fstab; 1903 struct stat st; 1904 char specdir[MAXPATHLEN]; 1905 1906 if (zonecfg_setipdent(handle) != Z_OK) { 1907 /* 1908 * TRANSLATION_NOTE 1909 * inherit-pkg-dirs is a literal that should not be translated. 1910 */ 1911 (void) fprintf(stderr, gettext("could not verify " 1912 "inherit-pkg-dirs: unable to enumerate mounts\n")); 1913 return (Z_ERR); 1914 } 1915 while (zonecfg_getipdent(handle, &fstab) == Z_OK) { 1916 /* 1917 * Verify fs_dir exists. 1918 */ 1919 (void) snprintf(specdir, sizeof (specdir), "%s%s", 1920 zonecfg_get_root(), fstab.zone_fs_dir); 1921 if (stat(specdir, &st) != 0) { 1922 /* 1923 * TRANSLATION_NOTE 1924 * inherit-pkg-dir is a literal that should not be 1925 * translated. 1926 */ 1927 (void) fprintf(stderr, gettext("could not verify " 1928 "inherit-pkg-dir %s: %s\n"), 1929 fstab.zone_fs_dir, strerror(errno)); 1930 return_code = Z_ERR; 1931 } 1932 if (strcmp(st.st_fstype, MNTTYPE_NFS) == 0) { 1933 /* 1934 * TRANSLATION_NOTE 1935 * inherit-pkg-dir and NFS are literals that should 1936 * not be translated. 1937 */ 1938 (void) fprintf(stderr, gettext("cannot verify " 1939 "inherit-pkg-dir %s: NFS mounted file-system.\n" 1940 "\tA local file-system must be used.\n"), 1941 fstab.zone_fs_dir); 1942 return_code = Z_ERR; 1943 } 1944 } 1945 (void) zonecfg_endipdent(handle); 1946 1947 return (return_code); 1948 } 1949 1950 /* ARGSUSED */ 1951 static void 1952 zfs_fs_err_handler(const char *fmt, va_list ap) 1953 { 1954 /* 1955 * Do nothing - do not print the libzfs error messages. 1956 */ 1957 } 1958 1959 /* 1960 * Verify that the ZFS dataset exists, and its mountpoint 1961 * property is set to "legacy". 1962 */ 1963 static int 1964 verify_fs_zfs(struct zone_fstab *fstab) 1965 { 1966 zfs_handle_t *zhp; 1967 char propbuf[ZFS_MAXPROPLEN]; 1968 1969 zfs_set_error_handler(zfs_fs_err_handler); 1970 1971 if ((zhp = zfs_open(fstab->zone_fs_special, ZFS_TYPE_ANY)) == NULL) { 1972 (void) fprintf(stderr, gettext("could not verify fs %s: " 1973 "could not access zfs dataset '%s'\n"), 1974 fstab->zone_fs_dir, fstab->zone_fs_special); 1975 return (Z_ERR); 1976 } 1977 1978 if (zfs_get_type(zhp) != ZFS_TYPE_FILESYSTEM) { 1979 (void) fprintf(stderr, gettext("cannot verify fs %s: " 1980 "'%s' is not a filesystem\n"), 1981 fstab->zone_fs_dir, fstab->zone_fs_special); 1982 zfs_close(zhp); 1983 return (Z_ERR); 1984 } 1985 1986 if (zfs_prop_get(zhp, ZFS_PROP_MOUNTPOINT, propbuf, sizeof (propbuf), 1987 NULL, NULL, 0, 0) != 0 || strcmp(propbuf, "legacy") != 0) { 1988 (void) fprintf(stderr, gettext("could not verify fs %s: " 1989 "zfs '%s' mountpoint is not \"legacy\"\n"), 1990 fstab->zone_fs_dir, fstab->zone_fs_special); 1991 zfs_close(zhp); 1992 return (Z_ERR); 1993 } 1994 1995 zfs_close(zhp); 1996 return (Z_OK); 1997 } 1998 1999 /* 2000 * Verify that the special device/filesystem exists and is valid. 2001 */ 2002 static int 2003 verify_fs_special(struct zone_fstab *fstab) 2004 { 2005 struct stat st; 2006 2007 if (strcmp(fstab->zone_fs_type, MNTTYPE_ZFS) == 0) 2008 return (verify_fs_zfs(fstab)); 2009 2010 if (stat(fstab->zone_fs_special, &st) != 0) { 2011 (void) fprintf(stderr, gettext("could not verify fs " 2012 "%s: could not access %s: %s\n"), fstab->zone_fs_dir, 2013 fstab->zone_fs_special, strerror(errno)); 2014 return (Z_ERR); 2015 } 2016 2017 if (strcmp(st.st_fstype, MNTTYPE_NFS) == 0) { 2018 /* 2019 * TRANSLATION_NOTE 2020 * fs and NFS are literals that should 2021 * not be translated. 2022 */ 2023 (void) fprintf(stderr, gettext("cannot verify " 2024 "fs %s: NFS mounted file-system.\n" 2025 "\tA local file-system must be used.\n"), 2026 fstab->zone_fs_special); 2027 return (Z_ERR); 2028 } 2029 2030 return (Z_OK); 2031 } 2032 2033 static int 2034 verify_filesystems(zone_dochandle_t handle) 2035 { 2036 int return_code = Z_OK; 2037 struct zone_fstab fstab; 2038 char cmdbuf[MAXPATHLEN]; 2039 struct stat st; 2040 2041 /* 2042 * No need to verify inherit-pkg-dir fs types, as their type is 2043 * implicitly lofs, which is known. Therefore, the types are only 2044 * verified for regular filesystems below. 2045 * 2046 * Since the actual mount point is not known until the dependent mounts 2047 * are performed, we don't attempt any path validation here: that will 2048 * happen later when zoneadmd actually does the mounts. 2049 */ 2050 if (zonecfg_setfsent(handle) != Z_OK) { 2051 (void) fprintf(stderr, gettext("could not verify file-systems: " 2052 "unable to enumerate mounts\n")); 2053 return (Z_ERR); 2054 } 2055 while (zonecfg_getfsent(handle, &fstab) == Z_OK) { 2056 if (!zonecfg_valid_fs_type(fstab.zone_fs_type)) { 2057 (void) fprintf(stderr, gettext("cannot verify fs %s: " 2058 "type %s is not allowed.\n"), fstab.zone_fs_dir, 2059 fstab.zone_fs_type); 2060 return_code = Z_ERR; 2061 goto next_fs; 2062 } 2063 /* 2064 * Verify /usr/lib/fs/<fstype>/mount exists. 2065 */ 2066 if (snprintf(cmdbuf, sizeof (cmdbuf), "/usr/lib/fs/%s/mount", 2067 fstab.zone_fs_type) > sizeof (cmdbuf)) { 2068 (void) fprintf(stderr, gettext("cannot verify fs %s: " 2069 "type %s is too long.\n"), fstab.zone_fs_dir, 2070 fstab.zone_fs_type); 2071 return_code = Z_ERR; 2072 goto next_fs; 2073 } 2074 if (stat(cmdbuf, &st) != 0) { 2075 (void) fprintf(stderr, gettext("could not verify fs " 2076 "%s: could not access %s: %s\n"), fstab.zone_fs_dir, 2077 cmdbuf, strerror(errno)); 2078 return_code = Z_ERR; 2079 goto next_fs; 2080 } 2081 if (!S_ISREG(st.st_mode)) { 2082 (void) fprintf(stderr, gettext("could not verify fs " 2083 "%s: %s is not a regular file\n"), 2084 fstab.zone_fs_dir, cmdbuf); 2085 return_code = Z_ERR; 2086 goto next_fs; 2087 } 2088 /* 2089 * Verify /usr/lib/fs/<fstype>/fsck exists iff zone_fs_raw is 2090 * set. 2091 */ 2092 if (snprintf(cmdbuf, sizeof (cmdbuf), "/usr/lib/fs/%s/fsck", 2093 fstab.zone_fs_type) > sizeof (cmdbuf)) { 2094 (void) fprintf(stderr, gettext("cannot verify fs %s: " 2095 "type %s is too long.\n"), fstab.zone_fs_dir, 2096 fstab.zone_fs_type); 2097 return_code = Z_ERR; 2098 goto next_fs; 2099 } 2100 if (fstab.zone_fs_raw[0] == '\0' && stat(cmdbuf, &st) == 0) { 2101 (void) fprintf(stderr, gettext("could not verify fs " 2102 "%s: must specify 'raw' device for %s " 2103 "file-systems\n"), 2104 fstab.zone_fs_dir, fstab.zone_fs_type); 2105 return_code = Z_ERR; 2106 goto next_fs; 2107 } 2108 if (fstab.zone_fs_raw[0] != '\0' && 2109 (stat(cmdbuf, &st) != 0 || !S_ISREG(st.st_mode))) { 2110 (void) fprintf(stderr, gettext("cannot verify fs %s: " 2111 "'raw' device specified but " 2112 "no fsck executable exists for %s\n"), 2113 fstab.zone_fs_dir, fstab.zone_fs_type); 2114 return_code = Z_ERR; 2115 goto next_fs; 2116 } 2117 2118 /* Verify fs_special. */ 2119 if ((return_code = verify_fs_special(&fstab)) != Z_OK) 2120 goto next_fs; 2121 2122 /* Verify fs_raw. */ 2123 if (fstab.zone_fs_raw[0] != '\0' && 2124 stat(fstab.zone_fs_raw, &st) != 0) { 2125 /* 2126 * TRANSLATION_NOTE 2127 * fs is a literal that should not be translated. 2128 */ 2129 (void) fprintf(stderr, gettext("could not verify fs " 2130 "%s: could not access %s: %s\n"), fstab.zone_fs_dir, 2131 fstab.zone_fs_raw, strerror(errno)); 2132 return_code = Z_ERR; 2133 goto next_fs; 2134 } 2135 next_fs: 2136 zonecfg_free_fs_option_list(fstab.zone_fs_options); 2137 } 2138 (void) zonecfg_endfsent(handle); 2139 2140 return (return_code); 2141 } 2142 2143 const char *current_dataset; 2144 2145 /* 2146 * Custom error handler for errors incurred as part of the checks below. We 2147 * want to trim off the leading 'cannot open ...' to create a better error 2148 * message. The only other way this can fail is if we fail to set the 'zoned' 2149 * property. In this case we just pass the error on verbatim. 2150 */ 2151 static void 2152 zfs_error_handler(const char *fmt, va_list ap) 2153 { 2154 char buf[1024]; 2155 2156 (void) vsnprintf(buf, sizeof (buf), fmt, ap); 2157 2158 if (strncmp(gettext("cannot open "), buf, 2159 strlen(gettext("cannot open "))) == 0) 2160 /* 2161 * TRANSLATION_NOTE 2162 * zfs and dataset are literals that should not be translated. 2163 */ 2164 (void) fprintf(stderr, gettext("could not verify zfs " 2165 "dataset %s%s\n"), current_dataset, strchr(buf, ':')); 2166 else 2167 (void) fprintf(stderr, gettext("could not verify zfs dataset " 2168 "%s: %s\n"), current_dataset, buf); 2169 } 2170 2171 /* ARGSUSED */ 2172 static int 2173 check_zvol(zfs_handle_t *zhp, void *unused) 2174 { 2175 int ret; 2176 2177 if (zfs_get_type(zhp) == ZFS_TYPE_VOLUME) { 2178 /* 2179 * TRANSLATION_NOTE 2180 * zfs and dataset are literals that should not be translated. 2181 */ 2182 (void) fprintf(stderr, gettext("cannot verify zfs dataset %s: " 2183 "volumes cannot be specified as a zone dataset resource\n"), 2184 zfs_get_name(zhp)); 2185 ret = -1; 2186 } else { 2187 ret = zfs_iter_children(zhp, check_zvol, NULL); 2188 } 2189 2190 zfs_close(zhp); 2191 2192 return (ret); 2193 } 2194 2195 /* 2196 * Validate that the given dataset exists on the system, and that neither it nor 2197 * its children are zvols. 2198 * 2199 * Note that we don't do anything with the 'zoned' property here. All 2200 * management is done in zoneadmd when the zone is actually rebooted. This 2201 * allows us to automatically set the zoned property even when a zone is 2202 * rebooted by the administrator. 2203 */ 2204 static int 2205 verify_datasets(zone_dochandle_t handle) 2206 { 2207 int return_code = Z_OK; 2208 struct zone_dstab dstab; 2209 zfs_handle_t *zhp; 2210 char propbuf[ZFS_MAXPROPLEN]; 2211 char source[ZFS_MAXNAMELEN]; 2212 zfs_source_t srctype; 2213 2214 if (zonecfg_setdsent(handle) != Z_OK) { 2215 /* 2216 * TRANSLATION_NOTE 2217 * zfs and dataset are literals that should not be translated. 2218 */ 2219 (void) fprintf(stderr, gettext("could not verify zfs datasets: " 2220 "unable to enumerate datasets\n")); 2221 return (Z_ERR); 2222 } 2223 2224 zfs_set_error_handler(zfs_error_handler); 2225 2226 while (zonecfg_getdsent(handle, &dstab) == Z_OK) { 2227 2228 current_dataset = dstab.zone_dataset_name; 2229 2230 if ((zhp = zfs_open(dstab.zone_dataset_name, 2231 ZFS_TYPE_FILESYSTEM | ZFS_TYPE_VOLUME)) == NULL) { 2232 return_code = Z_ERR; 2233 continue; 2234 } 2235 2236 if (zfs_prop_get(zhp, ZFS_PROP_MOUNTPOINT, propbuf, 2237 sizeof (propbuf), &srctype, source, 2238 sizeof (source), 0) == 0 && 2239 (srctype == ZFS_SRC_INHERITED)) { 2240 (void) fprintf(stderr, gettext("could not verify zfs " 2241 "dataset %s: mountpoint cannot be inherited\n"), 2242 dstab.zone_dataset_name); 2243 return_code = Z_ERR; 2244 zfs_close(zhp); 2245 continue; 2246 } 2247 2248 if (zfs_get_type(zhp) == ZFS_TYPE_VOLUME) { 2249 (void) fprintf(stderr, gettext("cannot verify zfs " 2250 "dataset %s: volumes cannot be specified as a " 2251 "zone dataset resource\n"), 2252 dstab.zone_dataset_name); 2253 return_code = Z_ERR; 2254 } 2255 2256 if (zfs_iter_children(zhp, check_zvol, NULL) != 0) 2257 return_code = Z_ERR; 2258 2259 zfs_close(zhp); 2260 } 2261 (void) zonecfg_enddsent(handle); 2262 2263 return (return_code); 2264 } 2265 2266 static int 2267 verify_details(int cmd_num) 2268 { 2269 zone_dochandle_t handle; 2270 struct zone_nwiftab nwiftab; 2271 char zonepath[MAXPATHLEN], checkpath[MAXPATHLEN]; 2272 int return_code = Z_OK; 2273 int err; 2274 boolean_t in_alt_root; 2275 2276 if ((handle = zonecfg_init_handle()) == NULL) { 2277 zperror(cmd_to_str(cmd_num), B_TRUE); 2278 return (Z_ERR); 2279 } 2280 if ((err = zonecfg_get_handle(target_zone, handle)) != Z_OK) { 2281 errno = err; 2282 zperror(cmd_to_str(cmd_num), B_TRUE); 2283 zonecfg_fini_handle(handle); 2284 return (Z_ERR); 2285 } 2286 if ((err = zonecfg_get_zonepath(handle, zonepath, sizeof (zonepath))) != 2287 Z_OK) { 2288 errno = err; 2289 zperror(cmd_to_str(cmd_num), B_TRUE); 2290 zonecfg_fini_handle(handle); 2291 return (Z_ERR); 2292 } 2293 /* 2294 * zonecfg_get_zonepath() gets its data from the XML repository. 2295 * Verify this against the index file, which is checked first by 2296 * zone_get_zonepath(). If they don't match, bail out. 2297 */ 2298 if ((err = zone_get_zonepath(target_zone, checkpath, 2299 sizeof (checkpath))) != Z_OK) { 2300 errno = err; 2301 zperror2(target_zone, gettext("could not get zone path")); 2302 return (Z_ERR); 2303 } 2304 if (strcmp(zonepath, checkpath) != 0) { 2305 /* 2306 * TRANSLATION_NOTE 2307 * XML and zonepath are literals that should not be translated. 2308 */ 2309 (void) fprintf(stderr, gettext("The XML repository has " 2310 "zonepath '%s',\nbut the index file has zonepath '%s'.\n" 2311 "These must match, so fix the incorrect entry.\n"), 2312 zonepath, checkpath); 2313 return (Z_ERR); 2314 } 2315 if (validate_zonepath(zonepath, cmd_num) != Z_OK) { 2316 (void) fprintf(stderr, gettext("could not verify zonepath %s " 2317 "because of the above errors.\n"), zonepath); 2318 return_code = Z_ERR; 2319 } 2320 2321 in_alt_root = zonecfg_in_alt_root(); 2322 if (in_alt_root) 2323 goto no_net; 2324 2325 if ((err = zonecfg_setnwifent(handle)) != Z_OK) { 2326 errno = err; 2327 zperror(cmd_to_str(cmd_num), B_TRUE); 2328 zonecfg_fini_handle(handle); 2329 return (Z_ERR); 2330 } 2331 while (zonecfg_getnwifent(handle, &nwiftab) == Z_OK) { 2332 struct lifreq lifr; 2333 sa_family_t af; 2334 int so, res; 2335 2336 /* skip any loopback interfaces */ 2337 if (strcmp(nwiftab.zone_nwif_physical, "lo0") == 0) 2338 continue; 2339 if ((res = zonecfg_valid_net_address(nwiftab.zone_nwif_address, 2340 &lifr)) != Z_OK) { 2341 (void) fprintf(stderr, gettext("could not verify %s " 2342 "%s=%s %s=%s: %s\n"), "net", "address", 2343 nwiftab.zone_nwif_address, "physical", 2344 nwiftab.zone_nwif_physical, zonecfg_strerror(res)); 2345 return_code = Z_ERR; 2346 continue; 2347 } 2348 af = lifr.lifr_addr.ss_family; 2349 (void) memset(&lifr, 0, sizeof (lifr)); 2350 (void) strlcpy(lifr.lifr_name, nwiftab.zone_nwif_physical, 2351 sizeof (lifr.lifr_name)); 2352 lifr.lifr_addr.ss_family = af; 2353 if ((so = socket(af, SOCK_DGRAM, 0)) < 0) { 2354 (void) fprintf(stderr, gettext("could not verify %s " 2355 "%s=%s %s=%s: could not get socket: %s\n"), "net", 2356 "address", nwiftab.zone_nwif_address, "physical", 2357 nwiftab.zone_nwif_physical, strerror(errno)); 2358 return_code = Z_ERR; 2359 continue; 2360 } 2361 if (ioctl(so, SIOCGLIFFLAGS, (caddr_t)&lifr) < 0) { 2362 (void) fprintf(stderr, 2363 gettext("could not verify %s %s=%s %s=%s: %s\n"), 2364 "net", "address", nwiftab.zone_nwif_address, 2365 "physical", nwiftab.zone_nwif_physical, 2366 strerror(errno)); 2367 return_code = Z_ERR; 2368 } 2369 (void) close(so); 2370 } 2371 (void) zonecfg_endnwifent(handle); 2372 no_net: 2373 2374 if (verify_filesystems(handle) != Z_OK) 2375 return_code = Z_ERR; 2376 if (verify_ipd(handle) != Z_OK) 2377 return_code = Z_ERR; 2378 if (!in_alt_root && verify_rctls(handle) != Z_OK) 2379 return_code = Z_ERR; 2380 if (!in_alt_root && verify_pool(handle) != Z_OK) 2381 return_code = Z_ERR; 2382 if (!in_alt_root && verify_datasets(handle) != Z_OK) 2383 return_code = Z_ERR; 2384 zonecfg_fini_handle(handle); 2385 if (return_code == Z_ERR) 2386 (void) fprintf(stderr, 2387 gettext("%s: zone %s failed to verify\n"), 2388 execname, target_zone); 2389 return (return_code); 2390 } 2391 2392 static int 2393 verify_func(int argc, char *argv[]) 2394 { 2395 int arg; 2396 2397 optind = 0; 2398 if ((arg = getopt(argc, argv, "?")) != EOF) { 2399 switch (arg) { 2400 case '?': 2401 sub_usage(SHELP_VERIFY, CMD_VERIFY); 2402 return (optopt == '?' ? Z_OK : Z_USAGE); 2403 default: 2404 sub_usage(SHELP_VERIFY, CMD_VERIFY); 2405 return (Z_USAGE); 2406 } 2407 } 2408 if (argc > optind) { 2409 sub_usage(SHELP_VERIFY, CMD_VERIFY); 2410 return (Z_USAGE); 2411 } 2412 if (sanity_check(target_zone, CMD_VERIFY, B_FALSE, B_FALSE) != Z_OK) 2413 return (Z_ERR); 2414 return (verify_details(CMD_VERIFY)); 2415 } 2416 2417 #define LUCREATEZONE "/usr/lib/lu/lucreatezone" 2418 2419 static int 2420 install_func(int argc, char *argv[]) 2421 { 2422 /* 9: "exec " and " -z " */ 2423 char cmdbuf[sizeof (LUCREATEZONE) + ZONENAME_MAX + 9]; 2424 int lockfd; 2425 int err, arg; 2426 char zonepath[MAXPATHLEN]; 2427 int status; 2428 2429 if (zonecfg_in_alt_root()) { 2430 zerror(gettext("cannot install zone in alternate root")); 2431 return (Z_ERR); 2432 } 2433 2434 optind = 0; 2435 if ((arg = getopt(argc, argv, "?")) != EOF) { 2436 switch (arg) { 2437 case '?': 2438 sub_usage(SHELP_INSTALL, CMD_INSTALL); 2439 return (optopt == '?' ? Z_OK : Z_USAGE); 2440 default: 2441 sub_usage(SHELP_INSTALL, CMD_INSTALL); 2442 return (Z_USAGE); 2443 } 2444 } 2445 if (argc > optind) { 2446 sub_usage(SHELP_INSTALL, CMD_INSTALL); 2447 return (Z_USAGE); 2448 } 2449 if (sanity_check(target_zone, CMD_INSTALL, B_FALSE, B_TRUE) != Z_OK) 2450 return (Z_ERR); 2451 if (verify_details(CMD_INSTALL) != Z_OK) 2452 return (Z_ERR); 2453 2454 if (grab_lock_file(target_zone, &lockfd) != Z_OK) { 2455 zerror(gettext("another %s may have an operation in progress."), 2456 "zoneadm"); 2457 return (Z_ERR); 2458 } 2459 err = zone_set_state(target_zone, ZONE_STATE_INCOMPLETE); 2460 if (err != Z_OK) { 2461 errno = err; 2462 zperror2(target_zone, gettext("could not set state")); 2463 goto done; 2464 } 2465 2466 /* 2467 * According to the Application Packaging Developer's Guide, a 2468 * "checkinstall" script when included in a package is executed as 2469 * the user "install", if such a user exists, or by the user 2470 * "nobody". In order to support this dubious behavior, the path 2471 * to the zone being constructed is opened up during the life of 2472 * the command laying down the zone's root file system. Once this 2473 * has completed, regardless of whether it was successful, the 2474 * path to the zone is again restricted. 2475 */ 2476 if ((err = zone_get_zonepath(target_zone, zonepath, 2477 sizeof (zonepath))) != Z_OK) { 2478 errno = err; 2479 zperror2(target_zone, gettext("could not get zone path")); 2480 goto done; 2481 } 2482 if (chmod(zonepath, DEFAULT_DIR_MODE) != 0) { 2483 zperror(zonepath, B_FALSE); 2484 err = Z_ERR; 2485 goto done; 2486 } 2487 2488 /* 2489 * "exec" the command so that the returned status is that of 2490 * LUCREATEZONE and not the shell. 2491 */ 2492 (void) snprintf(cmdbuf, sizeof (cmdbuf), "exec " LUCREATEZONE " -z %s", 2493 target_zone); 2494 status = do_subproc(cmdbuf); 2495 if (chmod(zonepath, S_IRWXU) != 0) { 2496 zperror(zonepath, B_FALSE); 2497 err = Z_ERR; 2498 goto done; 2499 } 2500 if ((err = subproc_status(LUCREATEZONE, status)) != Z_OK) 2501 goto done; 2502 2503 if ((err = zone_set_state(target_zone, ZONE_STATE_INSTALLED)) != Z_OK) { 2504 errno = err; 2505 zperror2(target_zone, gettext("could not set state")); 2506 goto done; 2507 } 2508 2509 done: 2510 release_lock_file(lockfd); 2511 return ((err == Z_OK) ? Z_OK : Z_ERR); 2512 } 2513 2514 /* 2515 * Check that the inherited pkg dirs are the same for the clone and its source. 2516 * The easiest way to do that is check that the list of ipds is the same 2517 * by matching each one against the other. This algorithm should be fine since 2518 * the list of ipds should not be that long. 2519 */ 2520 static int 2521 valid_ipd_clone(zone_dochandle_t s_handle, char *source_zone, 2522 zone_dochandle_t t_handle, char *target_zone) 2523 { 2524 int err; 2525 int res = Z_OK; 2526 int s_cnt = 0; 2527 int t_cnt = 0; 2528 struct zone_fstab s_fstab; 2529 struct zone_fstab t_fstab; 2530 2531 /* 2532 * First check the source of the clone against the target. 2533 */ 2534 if ((err = zonecfg_setipdent(s_handle)) != Z_OK) { 2535 errno = err; 2536 zperror2(source_zone, gettext("could not enumerate " 2537 "inherit-pkg-dirs")); 2538 return (Z_ERR); 2539 } 2540 2541 while (zonecfg_getipdent(s_handle, &s_fstab) == Z_OK) { 2542 boolean_t match = B_FALSE; 2543 2544 s_cnt++; 2545 2546 if ((err = zonecfg_setipdent(t_handle)) != Z_OK) { 2547 errno = err; 2548 zperror2(target_zone, gettext("could not enumerate " 2549 "inherit-pkg-dirs")); 2550 (void) zonecfg_endipdent(s_handle); 2551 return (Z_ERR); 2552 } 2553 2554 while (zonecfg_getipdent(t_handle, &t_fstab) == Z_OK) { 2555 if (strcmp(s_fstab.zone_fs_dir, t_fstab.zone_fs_dir) 2556 == 0) { 2557 match = B_TRUE; 2558 break; 2559 } 2560 } 2561 (void) zonecfg_endipdent(t_handle); 2562 2563 if (!match) { 2564 (void) fprintf(stderr, gettext("inherit-pkg-dir " 2565 "'%s' is not configured in zone %s.\n"), 2566 s_fstab.zone_fs_dir, target_zone); 2567 res = Z_ERR; 2568 } 2569 } 2570 2571 (void) zonecfg_endipdent(s_handle); 2572 2573 /* skip the next check if we already have errors */ 2574 if (res == Z_ERR) 2575 return (res); 2576 2577 /* 2578 * Now check the number of ipds in the target so we can verify 2579 * that the source is not a subset of the target. 2580 */ 2581 if ((err = zonecfg_setipdent(t_handle)) != Z_OK) { 2582 errno = err; 2583 zperror2(target_zone, gettext("could not enumerate " 2584 "inherit-pkg-dirs")); 2585 return (Z_ERR); 2586 } 2587 2588 while (zonecfg_getipdent(t_handle, &t_fstab) == Z_OK) 2589 t_cnt++; 2590 2591 (void) zonecfg_endipdent(t_handle); 2592 2593 if (t_cnt != s_cnt) { 2594 (void) fprintf(stderr, gettext("Zone %s is configured " 2595 "with inherit-pkg-dirs that are not configured in zone " 2596 "%s.\n"), target_zone, source_zone); 2597 res = Z_ERR; 2598 } 2599 2600 return (res); 2601 } 2602 2603 static void 2604 warn_dev_match(zone_dochandle_t s_handle, char *source_zone, 2605 zone_dochandle_t t_handle, char *target_zone) 2606 { 2607 int err; 2608 struct zone_devtab s_devtab; 2609 struct zone_devtab t_devtab; 2610 2611 if ((err = zonecfg_setdevent(t_handle)) != Z_OK) { 2612 errno = err; 2613 zperror2(target_zone, gettext("could not enumerate devices")); 2614 return; 2615 } 2616 2617 while (zonecfg_getdevent(t_handle, &t_devtab) == Z_OK) { 2618 if ((err = zonecfg_setdevent(s_handle)) != Z_OK) { 2619 errno = err; 2620 zperror2(source_zone, 2621 gettext("could not enumerate devices")); 2622 (void) zonecfg_enddevent(t_handle); 2623 return; 2624 } 2625 2626 while (zonecfg_getdevent(s_handle, &s_devtab) == Z_OK) { 2627 /* 2628 * Use fnmatch to catch the case where wildcards 2629 * were used in one zone and the other has an 2630 * explicit entry (e.g. /dev/dsk/c0t0d0s6 vs. 2631 * /dev/\*dsk/c0t0d0s6). 2632 */ 2633 if (fnmatch(t_devtab.zone_dev_match, 2634 s_devtab.zone_dev_match, FNM_PATHNAME) == 0 || 2635 fnmatch(s_devtab.zone_dev_match, 2636 t_devtab.zone_dev_match, FNM_PATHNAME) == 0) { 2637 (void) fprintf(stderr, 2638 gettext("WARNING: device '%s' " 2639 "is configured in both zones.\n"), 2640 t_devtab.zone_dev_match); 2641 break; 2642 } 2643 } 2644 (void) zonecfg_enddevent(s_handle); 2645 } 2646 2647 (void) zonecfg_enddevent(t_handle); 2648 } 2649 2650 /* 2651 * Check if the specified mount option (opt) is contained within the 2652 * options string. 2653 */ 2654 static boolean_t 2655 opt_match(char *opt, char *options) 2656 { 2657 char *p; 2658 char *lastp; 2659 2660 if ((p = strtok_r(options, ",", &lastp)) != NULL) { 2661 if (strcmp(p, opt) == 0) 2662 return (B_TRUE); 2663 while ((p = strtok_r(NULL, ",", &lastp)) != NULL) { 2664 if (strcmp(p, opt) == 0) 2665 return (B_TRUE); 2666 } 2667 } 2668 2669 return (B_FALSE); 2670 } 2671 2672 #define RW_LOFS "WARNING: read-write lofs file-system on '%s' is configured " \ 2673 "in both zones.\n" 2674 2675 static void 2676 print_fs_warnings(struct zone_fstab *s_fstab, struct zone_fstab *t_fstab) 2677 { 2678 /* 2679 * It is ok to have shared lofs mounted fs but we want to warn if 2680 * either is rw since this will effect the other zone. 2681 */ 2682 if (strcmp(t_fstab->zone_fs_type, "lofs") == 0) { 2683 zone_fsopt_t *optp; 2684 2685 /* The default is rw so no options means rw */ 2686 if (t_fstab->zone_fs_options == NULL || 2687 s_fstab->zone_fs_options == NULL) { 2688 (void) fprintf(stderr, gettext(RW_LOFS), 2689 t_fstab->zone_fs_special); 2690 return; 2691 } 2692 2693 for (optp = s_fstab->zone_fs_options; optp != NULL; 2694 optp = optp->zone_fsopt_next) { 2695 if (opt_match("rw", optp->zone_fsopt_opt)) { 2696 (void) fprintf(stderr, gettext(RW_LOFS), 2697 s_fstab->zone_fs_special); 2698 return; 2699 } 2700 } 2701 2702 for (optp = t_fstab->zone_fs_options; optp != NULL; 2703 optp = optp->zone_fsopt_next) { 2704 if (opt_match("rw", optp->zone_fsopt_opt)) { 2705 (void) fprintf(stderr, gettext(RW_LOFS), 2706 t_fstab->zone_fs_special); 2707 return; 2708 } 2709 } 2710 2711 return; 2712 } 2713 2714 /* 2715 * TRANSLATION_NOTE 2716 * The first variable is the file-system type and the second is 2717 * the file-system special device. For example, 2718 * WARNING: ufs file-system on '/dev/dsk/c0t0d0s0' ... 2719 */ 2720 (void) fprintf(stderr, gettext("WARNING: %s file-system on '%s' " 2721 "is configured in both zones.\n"), t_fstab->zone_fs_type, 2722 t_fstab->zone_fs_special); 2723 } 2724 2725 static void 2726 warn_fs_match(zone_dochandle_t s_handle, char *source_zone, 2727 zone_dochandle_t t_handle, char *target_zone) 2728 { 2729 int err; 2730 struct zone_fstab s_fstab; 2731 struct zone_fstab t_fstab; 2732 2733 if ((err = zonecfg_setfsent(t_handle)) != Z_OK) { 2734 errno = err; 2735 zperror2(target_zone, 2736 gettext("could not enumerate file-systems")); 2737 return; 2738 } 2739 2740 while (zonecfg_getfsent(t_handle, &t_fstab) == Z_OK) { 2741 if ((err = zonecfg_setfsent(s_handle)) != Z_OK) { 2742 errno = err; 2743 zperror2(source_zone, 2744 gettext("could not enumerate file-systems")); 2745 (void) zonecfg_endfsent(t_handle); 2746 return; 2747 } 2748 2749 while (zonecfg_getfsent(s_handle, &s_fstab) == Z_OK) { 2750 if (strcmp(t_fstab.zone_fs_special, 2751 s_fstab.zone_fs_special) == 0) { 2752 print_fs_warnings(&s_fstab, &t_fstab); 2753 break; 2754 } 2755 } 2756 (void) zonecfg_endfsent(s_handle); 2757 } 2758 2759 (void) zonecfg_endfsent(t_handle); 2760 } 2761 2762 /* 2763 * We don't catch the case where you used the same IP address but 2764 * it is not an exact string match. For example, 192.9.0.128 vs. 192.09.0.128. 2765 * However, we're not going to worry about that but we will check for 2766 * a possible netmask on one of the addresses (e.g. 10.0.0.1 and 10.0.0.1/24) 2767 * and handle that case as a match. 2768 */ 2769 static void 2770 warn_ip_match(zone_dochandle_t s_handle, char *source_zone, 2771 zone_dochandle_t t_handle, char *target_zone) 2772 { 2773 int err; 2774 struct zone_nwiftab s_nwiftab; 2775 struct zone_nwiftab t_nwiftab; 2776 2777 if ((err = zonecfg_setnwifent(t_handle)) != Z_OK) { 2778 errno = err; 2779 zperror2(target_zone, 2780 gettext("could not enumerate network interfaces")); 2781 return; 2782 } 2783 2784 while (zonecfg_getnwifent(t_handle, &t_nwiftab) == Z_OK) { 2785 char *p; 2786 2787 /* remove an (optional) netmask from the address */ 2788 if ((p = strchr(t_nwiftab.zone_nwif_address, '/')) != NULL) 2789 *p = '\0'; 2790 2791 if ((err = zonecfg_setnwifent(s_handle)) != Z_OK) { 2792 errno = err; 2793 zperror2(source_zone, 2794 gettext("could not enumerate network interfaces")); 2795 (void) zonecfg_endnwifent(t_handle); 2796 return; 2797 } 2798 2799 while (zonecfg_getnwifent(s_handle, &s_nwiftab) == Z_OK) { 2800 /* remove an (optional) netmask from the address */ 2801 if ((p = strchr(s_nwiftab.zone_nwif_address, '/')) 2802 != NULL) 2803 *p = '\0'; 2804 2805 if (strcmp(t_nwiftab.zone_nwif_address, 2806 s_nwiftab.zone_nwif_address) == 0) { 2807 (void) fprintf(stderr, 2808 gettext("WARNING: network address '%s' " 2809 "is configured in both zones.\n"), 2810 t_nwiftab.zone_nwif_address); 2811 break; 2812 } 2813 } 2814 (void) zonecfg_endnwifent(s_handle); 2815 } 2816 2817 (void) zonecfg_endnwifent(t_handle); 2818 } 2819 2820 static void 2821 warn_dataset_match(zone_dochandle_t s_handle, char *source_zone, 2822 zone_dochandle_t t_handle, char *target_zone) 2823 { 2824 int err; 2825 struct zone_dstab s_dstab; 2826 struct zone_dstab t_dstab; 2827 2828 if ((err = zonecfg_setdsent(t_handle)) != Z_OK) { 2829 errno = err; 2830 zperror2(target_zone, gettext("could not enumerate datasets")); 2831 return; 2832 } 2833 2834 while (zonecfg_getdsent(t_handle, &t_dstab) == Z_OK) { 2835 if ((err = zonecfg_setdsent(s_handle)) != Z_OK) { 2836 errno = err; 2837 zperror2(source_zone, 2838 gettext("could not enumerate datasets")); 2839 (void) zonecfg_enddsent(t_handle); 2840 return; 2841 } 2842 2843 while (zonecfg_getdsent(s_handle, &s_dstab) == Z_OK) { 2844 if (strcmp(t_dstab.zone_dataset_name, 2845 s_dstab.zone_dataset_name) == 0) { 2846 (void) fprintf(stderr, 2847 gettext("WARNING: dataset '%s' " 2848 "is configured in both zones.\n"), 2849 t_dstab.zone_dataset_name); 2850 break; 2851 } 2852 } 2853 (void) zonecfg_enddsent(s_handle); 2854 } 2855 2856 (void) zonecfg_enddsent(t_handle); 2857 } 2858 2859 static int 2860 validate_clone(char *source_zone, char *target_zone) 2861 { 2862 int err = Z_OK; 2863 zone_dochandle_t s_handle; 2864 zone_dochandle_t t_handle; 2865 2866 if ((t_handle = zonecfg_init_handle()) == NULL) { 2867 zperror(cmd_to_str(CMD_CLONE), B_TRUE); 2868 return (Z_ERR); 2869 } 2870 if ((err = zonecfg_get_handle(target_zone, t_handle)) != Z_OK) { 2871 errno = err; 2872 zperror(cmd_to_str(CMD_CLONE), B_TRUE); 2873 zonecfg_fini_handle(t_handle); 2874 return (Z_ERR); 2875 } 2876 2877 if ((s_handle = zonecfg_init_handle()) == NULL) { 2878 zperror(cmd_to_str(CMD_CLONE), B_TRUE); 2879 zonecfg_fini_handle(t_handle); 2880 return (Z_ERR); 2881 } 2882 if ((err = zonecfg_get_handle(source_zone, s_handle)) != Z_OK) { 2883 errno = err; 2884 zperror(cmd_to_str(CMD_CLONE), B_TRUE); 2885 goto done; 2886 } 2887 2888 /* verify new zone has same inherit-pkg-dirs */ 2889 err = valid_ipd_clone(s_handle, source_zone, t_handle, target_zone); 2890 2891 /* warn about imported fs's which are the same */ 2892 warn_fs_match(s_handle, source_zone, t_handle, target_zone); 2893 2894 /* warn about imported IP addresses which are the same */ 2895 warn_ip_match(s_handle, source_zone, t_handle, target_zone); 2896 2897 /* warn about imported devices which are the same */ 2898 warn_dev_match(s_handle, source_zone, t_handle, target_zone); 2899 2900 /* warn about imported datasets which are the same */ 2901 warn_dataset_match(s_handle, source_zone, t_handle, target_zone); 2902 2903 done: 2904 zonecfg_fini_handle(t_handle); 2905 zonecfg_fini_handle(s_handle); 2906 2907 return ((err == Z_OK) ? Z_OK : Z_ERR); 2908 } 2909 2910 static int 2911 copy_zone(char *src, char *dst) 2912 { 2913 boolean_t out_null = B_FALSE; 2914 int status; 2915 int err; 2916 char *outfile; 2917 char cmdbuf[MAXPATHLEN * 2 + 128]; 2918 2919 if ((outfile = tempnam("/var/log", "zone")) == NULL) { 2920 outfile = "/dev/null"; 2921 out_null = B_TRUE; 2922 } 2923 2924 (void) snprintf(cmdbuf, sizeof (cmdbuf), 2925 "cd %s && /usr/bin/find . -depth -print | " 2926 "/usr/bin/egrep -v '^\\./\\.zfs$|^\\./\\.zfs/' | " 2927 "/usr/bin/cpio -pdmuP@ %s > %s 2>&1", 2928 src, dst, outfile); 2929 2930 status = do_subproc(cmdbuf); 2931 2932 if ((err = subproc_status("copy", status)) != Z_OK) { 2933 if (!out_null) 2934 (void) fprintf(stderr, gettext("\nThe copy failed.\n" 2935 "More information can be found in %s\n"), outfile); 2936 return (err); 2937 } 2938 2939 if (!out_null) 2940 (void) unlink(outfile); 2941 2942 return (Z_OK); 2943 } 2944 2945 /* 2946 * Run sys-unconfig on a zone. This will leave the zone in the installed 2947 * state as long as there were no errors during the sys-unconfig. 2948 */ 2949 static int 2950 unconfigure_zone(char *zonepath) 2951 { 2952 int err; 2953 int status; 2954 struct stat unconfig_buf; 2955 zone_cmd_arg_t zarg; 2956 char cmdbuf[MAXPATHLEN + 51]; 2957 2958 /* The zone has to be installed in order to mount the scratch zone. */ 2959 if ((err = zone_set_state(target_zone, ZONE_STATE_INSTALLED)) != Z_OK) { 2960 errno = err; 2961 zperror2(target_zone, gettext("could not set state")); 2962 return (Z_ERR); 2963 } 2964 2965 /* 2966 * Check if the zone is already sys-unconfiged. This saves us 2967 * the work of bringing up the scratch zone so we can unconfigure it. 2968 */ 2969 (void) snprintf(cmdbuf, sizeof (cmdbuf), "%s/root/etc/.UNCONFIGURED", 2970 zonepath); 2971 if (stat(cmdbuf, &unconfig_buf) == 0) 2972 return (Z_OK); 2973 2974 zarg.cmd = Z_MOUNT; 2975 if (call_zoneadmd(target_zone, &zarg) != 0) { 2976 zerror(gettext("call to %s failed"), "zoneadmd"); 2977 (void) zone_set_state(target_zone, ZONE_STATE_INCOMPLETE); 2978 return (Z_ERR); 2979 } 2980 2981 (void) snprintf(cmdbuf, sizeof (cmdbuf), 2982 "/usr/sbin/zlogin -S %s /usr/sbin/sys-unconfig -R /a", target_zone); 2983 2984 status = do_subproc(cmdbuf); 2985 if ((err = subproc_status("sys-unconfig", status)) != Z_OK) { 2986 errno = err; 2987 zperror2(target_zone, gettext("sys-unconfig failed\n")); 2988 (void) zone_set_state(target_zone, ZONE_STATE_INCOMPLETE); 2989 } 2990 2991 zarg.cmd = Z_UNMOUNT; 2992 if (call_zoneadmd(target_zone, &zarg) != 0) { 2993 zerror(gettext("call to %s failed"), "zoneadmd"); 2994 (void) fprintf(stderr, gettext("could not unmount zone\n")); 2995 return (Z_ERR); 2996 } 2997 2998 return ((err == Z_OK) ? Z_OK : Z_ERR); 2999 } 3000 3001 /* ARGSUSED */ 3002 int 3003 zfm_print(const char *p, void *r) { 3004 zerror(" %s\n", p); 3005 return (0); 3006 } 3007 3008 static int 3009 clone_func(int argc, char *argv[]) 3010 { 3011 char *source_zone = NULL; 3012 int lockfd; 3013 int err, arg; 3014 char zonepath[MAXPATHLEN]; 3015 char source_zonepath[MAXPATHLEN]; 3016 zone_state_t state; 3017 zone_entry_t *zent; 3018 char *method = "copy"; 3019 3020 if (zonecfg_in_alt_root()) { 3021 zerror(gettext("cannot clone zone in alternate root")); 3022 return (Z_ERR); 3023 } 3024 3025 optind = 0; 3026 if ((arg = getopt(argc, argv, "?m:")) != EOF) { 3027 switch (arg) { 3028 case '?': 3029 sub_usage(SHELP_CLONE, CMD_CLONE); 3030 return (optopt == '?' ? Z_OK : Z_USAGE); 3031 case 'm': 3032 method = optarg; 3033 break; 3034 default: 3035 sub_usage(SHELP_CLONE, CMD_CLONE); 3036 return (Z_USAGE); 3037 } 3038 } 3039 if (argc != (optind + 1) || strcmp(method, "copy") != 0) { 3040 sub_usage(SHELP_CLONE, CMD_CLONE); 3041 return (Z_USAGE); 3042 } 3043 source_zone = argv[optind]; 3044 if (sanity_check(target_zone, CMD_CLONE, B_FALSE, B_TRUE) != Z_OK) 3045 return (Z_ERR); 3046 if (verify_details(CMD_CLONE) != Z_OK) 3047 return (Z_ERR); 3048 3049 /* 3050 * We also need to do some extra validation on the source zone. 3051 */ 3052 3053 if (strcmp(source_zone, GLOBAL_ZONENAME) == 0) { 3054 zerror(gettext("%s operation is invalid for the global zone."), 3055 cmd_to_str(CMD_CLONE)); 3056 return (Z_ERR); 3057 } 3058 3059 if (strncmp(source_zone, "SUNW", 4) == 0) { 3060 zerror(gettext("%s operation is invalid for zones starting " 3061 "with SUNW."), cmd_to_str(CMD_CLONE)); 3062 return (Z_ERR); 3063 } 3064 3065 zent = lookup_running_zone(source_zone); 3066 if (zent != NULL) { 3067 /* check whether the zone is ready or running */ 3068 if ((err = zone_get_state(zent->zname, &zent->zstate_num)) 3069 != Z_OK) { 3070 errno = err; 3071 zperror2(zent->zname, gettext("could not get state")); 3072 /* can't tell, so hedge */ 3073 zent->zstate_str = "ready/running"; 3074 } else { 3075 zent->zstate_str = zone_state_str(zent->zstate_num); 3076 } 3077 zerror(gettext("%s operation is invalid for %s zones."), 3078 cmd_to_str(CMD_CLONE), zent->zstate_str); 3079 return (Z_ERR); 3080 } 3081 3082 if ((err = zone_get_state(source_zone, &state)) != Z_OK) { 3083 errno = err; 3084 zperror2(source_zone, gettext("could not get state")); 3085 return (Z_ERR); 3086 } 3087 if (state != ZONE_STATE_INSTALLED) { 3088 (void) fprintf(stderr, 3089 gettext("%s: zone %s is %s; %s is required.\n"), 3090 execname, source_zone, zone_state_str(state), 3091 zone_state_str(ZONE_STATE_INSTALLED)); 3092 return (Z_ERR); 3093 } 3094 3095 /* 3096 * The source zone checks out ok, continue with the clone. 3097 */ 3098 3099 if (validate_clone(source_zone, target_zone) != Z_OK) 3100 return (Z_ERR); 3101 3102 if (grab_lock_file(target_zone, &lockfd) != Z_OK) { 3103 zerror(gettext("another %s may have an operation in progress."), 3104 "zoneadm"); 3105 return (Z_ERR); 3106 } 3107 3108 if ((err = zone_get_zonepath(source_zone, source_zonepath, 3109 sizeof (source_zonepath))) != Z_OK) { 3110 errno = err; 3111 zperror2(source_zone, gettext("could not get zone path")); 3112 goto done; 3113 } 3114 3115 if ((err = zone_get_zonepath(target_zone, zonepath, sizeof (zonepath))) 3116 != Z_OK) { 3117 errno = err; 3118 zperror2(target_zone, gettext("could not get zone path")); 3119 goto done; 3120 } 3121 3122 /* Don't clone the zone if anything is still mounted there */ 3123 if (zonecfg_find_mounts(source_zonepath, NULL, NULL)) { 3124 zerror(gettext("These file-systems are mounted on " 3125 "subdirectories of %s.\n"), source_zonepath); 3126 (void) zonecfg_find_mounts(source_zonepath, zfm_print, NULL); 3127 err = Z_ERR; 3128 goto done; 3129 } 3130 3131 if ((err = zone_set_state(target_zone, ZONE_STATE_INCOMPLETE)) 3132 != Z_OK) { 3133 errno = err; 3134 zperror2(target_zone, gettext("could not set state")); 3135 goto done; 3136 } 3137 3138 (void) printf(gettext("Cloning zonepath %s..."), source_zonepath); 3139 (void) fflush(stdout); 3140 3141 err = copy_zone(source_zonepath, zonepath); 3142 (void) printf("\n"); 3143 if (err != Z_OK) 3144 goto done; 3145 3146 err = unconfigure_zone(zonepath); 3147 3148 done: 3149 release_lock_file(lockfd); 3150 return ((err == Z_OK) ? Z_OK : Z_ERR); 3151 } 3152 3153 #define RMCOMMAND "/usr/bin/rm -rf" 3154 3155 /* 3156 * Used when moving a zonepath (via copying) to clean up the old path or 3157 * the new path if there was an error. 3158 * 3159 * This function handles the case of a zonepath being a zfs filesystem. 3160 * If it is a zfs filesystem, we cannot just remove the whole zonepath 3161 * since we can't remove the filesystem itself. Instead, we have to remove 3162 * the contents of the filesystem, but not the .zfs directory. 3163 */ 3164 static int 3165 remove_zonepath(char *zonepath) 3166 { 3167 int status; 3168 boolean_t is_zfs = B_FALSE; 3169 struct stat buf; 3170 char cmdbuf[sizeof (RMCOMMAND) + MAXPATHLEN + 128]; 3171 3172 (void) snprintf(cmdbuf, sizeof (cmdbuf), "%s/.zfs", zonepath); 3173 3174 if (stat(cmdbuf, &buf) == 0 && S_ISDIR(buf.st_mode)) 3175 is_zfs = B_TRUE; 3176 3177 if (is_zfs) { 3178 /* 3179 * This doesn't handle the (unlikely) case that there are 3180 * directories or files in the top-level zonepath with white 3181 * space in the names. 3182 */ 3183 (void) snprintf(cmdbuf, sizeof (cmdbuf), 3184 "cd %s && /usr/bin/ls -A | /usr/bin/egrep -v '^\\.zfs$' | " 3185 "/usr/bin/xargs " RMCOMMAND, zonepath); 3186 } else { 3187 /* 3188 * "exec" the command so that the returned status is 3189 * that of rm and not the shell. 3190 */ 3191 (void) snprintf(cmdbuf, sizeof (cmdbuf), 3192 "exec " RMCOMMAND " %s", zonepath); 3193 } 3194 3195 status = do_subproc(cmdbuf); 3196 3197 return (subproc_status("rm", status)); 3198 3199 } 3200 3201 static int 3202 move_func(int argc, char *argv[]) 3203 { 3204 char *new_zonepath = NULL; 3205 int lockfd; 3206 int err, arg; 3207 char zonepath[MAXPATHLEN]; 3208 zone_dochandle_t handle; 3209 boolean_t fast; 3210 boolean_t revert; 3211 struct stat zonepath_buf; 3212 struct stat new_zonepath_buf; 3213 3214 if (zonecfg_in_alt_root()) { 3215 zerror(gettext("cannot move zone in alternate root")); 3216 return (Z_ERR); 3217 } 3218 3219 optind = 0; 3220 if ((arg = getopt(argc, argv, "?")) != EOF) { 3221 switch (arg) { 3222 case '?': 3223 sub_usage(SHELP_MOVE, CMD_MOVE); 3224 return (optopt == '?' ? Z_OK : Z_USAGE); 3225 default: 3226 sub_usage(SHELP_MOVE, CMD_MOVE); 3227 return (Z_USAGE); 3228 } 3229 } 3230 if (argc != (optind + 1)) { 3231 sub_usage(SHELP_MOVE, CMD_MOVE); 3232 return (Z_USAGE); 3233 } 3234 new_zonepath = argv[optind]; 3235 if (sanity_check(target_zone, CMD_MOVE, B_FALSE, B_TRUE) != Z_OK) 3236 return (Z_ERR); 3237 if (verify_details(CMD_MOVE) != Z_OK) 3238 return (Z_ERR); 3239 3240 /* 3241 * Check out the new zonepath. This has the side effect of creating 3242 * a directory for the new zonepath. We depend on this later when we 3243 * stat to see if we are doing a cross file-system move or not. 3244 */ 3245 if (validate_zonepath(new_zonepath, CMD_MOVE) != Z_OK) 3246 return (Z_ERR); 3247 3248 if ((err = zone_get_zonepath(target_zone, zonepath, sizeof (zonepath))) 3249 != Z_OK) { 3250 errno = err; 3251 zperror2(target_zone, gettext("could not get zone path")); 3252 return (Z_ERR); 3253 } 3254 3255 if (stat(zonepath, &zonepath_buf) == -1) { 3256 zperror(gettext("could not stat zone path"), B_FALSE); 3257 return (Z_ERR); 3258 } 3259 3260 if (stat(new_zonepath, &new_zonepath_buf) == -1) { 3261 zperror(gettext("could not stat new zone path"), B_FALSE); 3262 return (Z_ERR); 3263 } 3264 3265 /* Don't move the zone if anything is still mounted there */ 3266 if (zonecfg_find_mounts(zonepath, NULL, NULL)) { 3267 zerror(gettext("These file-systems are mounted on " 3268 "subdirectories of %s.\n"), zonepath); 3269 (void) zonecfg_find_mounts(zonepath, zfm_print, NULL); 3270 return (Z_ERR); 3271 } 3272 3273 /* 3274 * Check if we are moving in the same filesystem and can do a fast 3275 * move or if we are crossing filesystems and have to copy the data. 3276 */ 3277 fast = (zonepath_buf.st_dev == new_zonepath_buf.st_dev); 3278 3279 if ((handle = zonecfg_init_handle()) == NULL) { 3280 zperror(cmd_to_str(CMD_MOVE), B_TRUE); 3281 return (Z_ERR); 3282 } 3283 3284 if ((err = zonecfg_get_handle(target_zone, handle)) != Z_OK) { 3285 errno = err; 3286 zperror(cmd_to_str(CMD_MOVE), B_TRUE); 3287 zonecfg_fini_handle(handle); 3288 return (Z_ERR); 3289 } 3290 3291 if (grab_lock_file(target_zone, &lockfd) != Z_OK) { 3292 zerror(gettext("another %s may have an operation in progress."), 3293 "zoneadm"); 3294 zonecfg_fini_handle(handle); 3295 return (Z_ERR); 3296 } 3297 3298 /* 3299 * We're making some file-system changes now so we have to clean up 3300 * the file-system before we are done. This will either clean up the 3301 * new zonepath if the zonecfg update failed or it will clean up the 3302 * old zonepath if everything is ok. 3303 */ 3304 revert = B_TRUE; 3305 3306 if (fast) { 3307 /* same filesystem, use rename for a quick move */ 3308 3309 /* 3310 * Remove the new_zonepath directory that got created above 3311 * during the validation. It gets in the way of the rename. 3312 */ 3313 if (rmdir(new_zonepath) != 0) { 3314 zperror(gettext("could not rmdir new zone path"), 3315 B_FALSE); 3316 zonecfg_fini_handle(handle); 3317 release_lock_file(lockfd); 3318 return (Z_ERR); 3319 } 3320 3321 if (rename(zonepath, new_zonepath) != 0) { 3322 /* 3323 * If this fails we don't need to do all of the 3324 * cleanup that happens for the rest of the code 3325 * so just return from this error. 3326 */ 3327 zperror(gettext("could not move zone"), B_FALSE); 3328 zonecfg_fini_handle(handle); 3329 release_lock_file(lockfd); 3330 return (Z_ERR); 3331 } 3332 3333 } else { 3334 (void) printf(gettext( 3335 "Moving across file-systems; copying zonepath %s..."), 3336 zonepath); 3337 (void) fflush(stdout); 3338 3339 err = copy_zone(zonepath, new_zonepath); 3340 3341 (void) printf("\n"); 3342 if (err != Z_OK) 3343 goto done; 3344 } 3345 3346 if ((err = zonecfg_set_zonepath(handle, new_zonepath)) != Z_OK) { 3347 errno = err; 3348 zperror(gettext("could not set new zonepath"), B_TRUE); 3349 goto done; 3350 } 3351 3352 if ((err = zonecfg_save(handle)) != Z_OK) { 3353 errno = err; 3354 zperror(gettext("zonecfg save failed"), B_TRUE); 3355 goto done; 3356 } 3357 3358 revert = B_FALSE; 3359 3360 done: 3361 zonecfg_fini_handle(handle); 3362 release_lock_file(lockfd); 3363 3364 /* 3365 * Clean up the file-system based on how things went. We either 3366 * clean up the new zonepath if the operation failed for some reason 3367 * or we clean up the old zonepath if everything is ok. 3368 */ 3369 if (revert) { 3370 /* The zonecfg update failed, cleanup the new zonepath. */ 3371 if (fast) { 3372 if (rename(new_zonepath, zonepath) != 0) { 3373 zperror(gettext("could not restore zonepath"), 3374 B_FALSE); 3375 /* 3376 * err is already != Z_OK since we're reverting 3377 */ 3378 } 3379 } else { 3380 (void) printf(gettext("Cleaning up zonepath %s..."), 3381 new_zonepath); 3382 (void) fflush(stdout); 3383 err = remove_zonepath(new_zonepath); 3384 (void) printf("\n"); 3385 3386 if (err != Z_OK) { 3387 errno = err; 3388 zperror(gettext("could not remove new " 3389 "zonepath"), B_TRUE); 3390 } else { 3391 /* 3392 * Because we're reverting we know the mainline 3393 * code failed but we just reused the err 3394 * variable so we reset it back to Z_ERR. 3395 */ 3396 err = Z_ERR; 3397 } 3398 } 3399 3400 } else { 3401 /* The move was successful, cleanup the old zonepath. */ 3402 if (!fast) { 3403 (void) printf( 3404 gettext("Cleaning up zonepath %s..."), zonepath); 3405 (void) fflush(stdout); 3406 err = remove_zonepath(zonepath); 3407 (void) printf("\n"); 3408 3409 if (err != Z_OK) { 3410 errno = err; 3411 zperror(gettext("could not remove zonepath"), 3412 B_TRUE); 3413 } 3414 } 3415 } 3416 3417 return ((err == Z_OK) ? Z_OK : Z_ERR); 3418 } 3419 3420 static int 3421 detach_func(int argc, char *argv[]) 3422 { 3423 int lockfd; 3424 int err, arg; 3425 char zonepath[MAXPATHLEN]; 3426 zone_dochandle_t handle; 3427 3428 if (zonecfg_in_alt_root()) { 3429 zerror(gettext("cannot detach zone in alternate root")); 3430 return (Z_ERR); 3431 } 3432 3433 optind = 0; 3434 if ((arg = getopt(argc, argv, "?")) != EOF) { 3435 switch (arg) { 3436 case '?': 3437 sub_usage(SHELP_DETACH, CMD_DETACH); 3438 return (optopt == '?' ? Z_OK : Z_USAGE); 3439 default: 3440 sub_usage(SHELP_DETACH, CMD_DETACH); 3441 return (Z_USAGE); 3442 } 3443 } 3444 if (sanity_check(target_zone, CMD_DETACH, B_FALSE, B_TRUE) != Z_OK) 3445 return (Z_ERR); 3446 if (verify_details(CMD_DETACH) != Z_OK) 3447 return (Z_ERR); 3448 3449 if ((err = zone_get_zonepath(target_zone, zonepath, sizeof (zonepath))) 3450 != Z_OK) { 3451 errno = err; 3452 zperror2(target_zone, gettext("could not get zone path")); 3453 return (Z_ERR); 3454 } 3455 3456 /* Don't detach the zone if anything is still mounted there */ 3457 if (zonecfg_find_mounts(zonepath, NULL, NULL)) { 3458 zerror(gettext("These file-systems are mounted on " 3459 "subdirectories of %s.\n"), zonepath); 3460 (void) zonecfg_find_mounts(zonepath, zfm_print, NULL); 3461 return (Z_ERR); 3462 } 3463 3464 if ((handle = zonecfg_init_handle()) == NULL) { 3465 zperror(cmd_to_str(CMD_DETACH), B_TRUE); 3466 return (Z_ERR); 3467 } 3468 3469 if ((err = zonecfg_get_handle(target_zone, handle)) != Z_OK) { 3470 errno = err; 3471 zperror(cmd_to_str(CMD_DETACH), B_TRUE); 3472 zonecfg_fini_handle(handle); 3473 return (Z_ERR); 3474 } 3475 3476 if (grab_lock_file(target_zone, &lockfd) != Z_OK) { 3477 zerror(gettext("another %s may have an operation in progress."), 3478 "zoneadm"); 3479 zonecfg_fini_handle(handle); 3480 return (Z_ERR); 3481 } 3482 3483 if ((err = zonecfg_get_detach_info(handle, B_TRUE)) != Z_OK) { 3484 errno = err; 3485 zperror(gettext("getting the detach information failed"), 3486 B_TRUE); 3487 goto done; 3488 } 3489 3490 if ((err = zonecfg_detach_save(handle)) != Z_OK) { 3491 errno = err; 3492 zperror(gettext("saving the detach manifest failed"), B_TRUE); 3493 goto done; 3494 } 3495 3496 if ((err = zone_set_state(target_zone, ZONE_STATE_CONFIGURED)) 3497 != Z_OK) { 3498 errno = err; 3499 zperror(gettext("could not reset state"), B_TRUE); 3500 } 3501 3502 done: 3503 zonecfg_fini_handle(handle); 3504 release_lock_file(lockfd); 3505 3506 return ((err == Z_OK) ? Z_OK : Z_ERR); 3507 } 3508 3509 /* 3510 * Find the specified package in the sw inventory on the handle and check 3511 * if the version matches what is passed in. 3512 * Return 0 if the packages match 3513 * 1 if the package is found but we have a version mismatch 3514 * -1 if the package is not found 3515 */ 3516 static int 3517 pkg_cmp(zone_dochandle_t handle, char *pkg_name, char *pkg_vers, 3518 char *return_vers, int vers_size) 3519 { 3520 int res = -1; 3521 struct zone_pkgtab pkgtab; 3522 3523 if (zonecfg_setpkgent(handle) != Z_OK) { 3524 (void) fprintf(stderr, 3525 gettext("unable to enumerate packages\n")); 3526 return (Z_ERR); 3527 } 3528 3529 while (zonecfg_getpkgent(handle, &pkgtab) == Z_OK) { 3530 if (strcmp(pkg_name, pkgtab.zone_pkg_name) != 0) 3531 continue; 3532 3533 if (strcmp(pkg_vers, pkgtab.zone_pkg_version) == 0) { 3534 res = 0; 3535 break; 3536 } 3537 3538 (void) strlcpy(return_vers, pkgtab.zone_pkg_version, vers_size); 3539 res = 1; 3540 break; 3541 } 3542 3543 (void) zonecfg_endpkgent(handle); 3544 return (res); 3545 } 3546 3547 /* 3548 * Used in software comparisons to check the packages between the two zone 3549 * handles. The packages have to match or we print a message telling the 3550 * user what is out of sync. The src_cmp flag tells us if the first handle 3551 * is the source machine global zone or not. This is used to enable the 3552 * right messages to be printed and also to enable extra version checking 3553 * that is not needed for the opposite comparison. 3554 */ 3555 static int 3556 pkg_check(char *header, zone_dochandle_t handle1, zone_dochandle_t handle2, 3557 boolean_t src_cmp) 3558 { 3559 int err; 3560 int res = Z_OK; 3561 boolean_t do_header = B_TRUE; 3562 char other_vers[ZONE_PKG_VERSMAX]; 3563 struct zone_pkgtab pkgtab; 3564 3565 if (zonecfg_setpkgent(handle1) != Z_OK) { 3566 (void) fprintf(stderr, 3567 gettext("unable to enumerate packages\n")); 3568 return (Z_ERR); 3569 } 3570 3571 while (zonecfg_getpkgent(handle1, &pkgtab) == Z_OK) { 3572 if ((err = pkg_cmp(handle2, pkgtab.zone_pkg_name, 3573 pkgtab.zone_pkg_version, other_vers, sizeof (other_vers))) 3574 != 0) { 3575 if (do_header && (err < 0 || src_cmp)) { 3576 /* LINTED E_SEC_PRINTF_VAR_FMT */ 3577 (void) fprintf(stderr, header); 3578 do_header = B_FALSE; 3579 } 3580 if (err < 0) { 3581 (void) fprintf(stderr, 3582 (src_cmp == B_TRUE) ? 3583 gettext("\t%s: not installed\n\t\t(%s)\n") : 3584 gettext("\t%s (%s)\n"), 3585 pkgtab.zone_pkg_name, 3586 pkgtab.zone_pkg_version); 3587 res = Z_ERR; 3588 } else if (src_cmp) { 3589 (void) fprintf(stderr, gettext( 3590 "\t%s: version mismatch\n\t\t(%s)" 3591 "\n\t\t(%s)\n"), 3592 pkgtab.zone_pkg_name, 3593 pkgtab.zone_pkg_version, other_vers); 3594 res = Z_ERR; 3595 } 3596 } 3597 } 3598 3599 (void) zonecfg_endpkgent(handle1); 3600 3601 return (res); 3602 } 3603 3604 /* 3605 * Find the specified patch in the sw inventory on the handle and check 3606 * if the version matches what is passed in. 3607 * Return 0 if the patches match 3608 * 1 if the patches is found but we have a version mismatch 3609 * -1 if the patches is not found 3610 */ 3611 static int 3612 patch_cmp(zone_dochandle_t handle, char *patch_id, char *patch_vers, 3613 char *return_vers, int vers_size) 3614 { 3615 int res = -1; 3616 struct zone_patchtab patchtab; 3617 3618 if (zonecfg_setpatchent(handle) != Z_OK) { 3619 (void) fprintf(stderr, 3620 gettext("unable to enumerate patches\n")); 3621 return (Z_ERR); 3622 } 3623 3624 while (zonecfg_getpatchent(handle, &patchtab) == Z_OK) { 3625 char *p; 3626 3627 if ((p = strchr(patchtab.zone_patch_id, '-')) != NULL) 3628 *p++ = '\0'; 3629 else 3630 p = ""; 3631 3632 if (strcmp(patch_id, patchtab.zone_patch_id) != 0) 3633 continue; 3634 3635 if (strcmp(patch_vers, p) == 0) { 3636 res = 0; 3637 break; 3638 } 3639 3640 (void) strlcpy(return_vers, p, vers_size); 3641 /* 3642 * Keep checking. This handles the case where multiple 3643 * versions of the same patch is installed. 3644 */ 3645 res = 1; 3646 } 3647 3648 (void) zonecfg_endpatchent(handle); 3649 return (res); 3650 } 3651 3652 /* 3653 * Used in software comparisons to check the patches between the two zone 3654 * handles. The patches have to match or we print a message telling the 3655 * user what is out of sync. The src_cmp flag tells us if the first handle 3656 * is the source machine global zone or not. This is used to enable the 3657 * right messages to be printed and also to enable extra version checking 3658 * that is not needed for the opposite comparison. 3659 */ 3660 static int 3661 patch_check(char *header, zone_dochandle_t handle1, zone_dochandle_t handle2, 3662 boolean_t src_cmp) 3663 { 3664 int err; 3665 int res = Z_OK; 3666 boolean_t do_header = B_TRUE; 3667 char other_vers[MAXNAMELEN]; 3668 struct zone_patchtab patchtab; 3669 3670 if (zonecfg_setpatchent(handle1) != Z_OK) { 3671 (void) fprintf(stderr, 3672 gettext("unable to enumerate patches\n")); 3673 return (Z_ERR); 3674 } 3675 3676 while (zonecfg_getpatchent(handle1, &patchtab) == Z_OK) { 3677 char *patch_vers; 3678 3679 if ((patch_vers = strchr(patchtab.zone_patch_id, '-')) != NULL) 3680 *patch_vers++ = '\0'; 3681 else 3682 patch_vers = ""; 3683 3684 if ((err = patch_cmp(handle2, patchtab.zone_patch_id, 3685 patch_vers, other_vers, sizeof (other_vers))) != 0) { 3686 if (do_header && (err < 0 || src_cmp)) { 3687 /* LINTED E_SEC_PRINTF_VAR_FMT */ 3688 (void) fprintf(stderr, header); 3689 do_header = B_FALSE; 3690 } 3691 if (err < 0) { 3692 (void) fprintf(stderr, 3693 (src_cmp == B_TRUE) ? 3694 gettext("\t%s: not installed\n") : 3695 gettext("\t%s\n"), 3696 patchtab.zone_patch_id); 3697 res = Z_ERR; 3698 } else if (src_cmp) { 3699 (void) fprintf(stderr, 3700 gettext("\t%s: version mismatch\n\t\t(%s) " 3701 "(%s)\n"), patchtab.zone_patch_id, 3702 patch_vers, other_vers); 3703 res = Z_ERR; 3704 } 3705 } 3706 } 3707 3708 (void) zonecfg_endpatchent(handle1); 3709 3710 return (res); 3711 } 3712 3713 /* 3714 * Compare the software on the local global zone and source system global 3715 * zone. Used when we are trying to attach a zone during migration. 3716 * l_handle is for the local system and s_handle is for the source system. 3717 * These have a snapshot of the appropriate packages and patches in the global 3718 * zone for the two machines. 3719 * The functions called here will print any messages that are needed to 3720 * inform the user about package or patch problems. 3721 */ 3722 static int 3723 sw_cmp(zone_dochandle_t l_handle, zone_dochandle_t s_handle) 3724 { 3725 char *hdr; 3726 int res = Z_OK; 3727 3728 /* 3729 * Check the source host for pkgs (and versions) that are not on the 3730 * local host. 3731 */ 3732 hdr = gettext("These packages installed on the source system are " 3733 "inconsistent with this system:\n"); 3734 if (pkg_check(hdr, s_handle, l_handle, B_TRUE) != Z_OK) 3735 res = Z_ERR; 3736 3737 /* 3738 * Now check the local host for pkgs that were not on the source host. 3739 * We already handled version mismatches in the loop above. 3740 */ 3741 hdr = gettext("These packages installed on this system were " 3742 "not installed on the source system:\n"); 3743 if (pkg_check(hdr, l_handle, s_handle, B_FALSE) != Z_OK) 3744 res = Z_ERR; 3745 3746 /* 3747 * Check the source host for patches that are not on the local host. 3748 */ 3749 hdr = gettext("These patches installed on the source system are " 3750 "inconsistent with this system:\n"); 3751 if (patch_check(hdr, s_handle, l_handle, B_TRUE) != Z_OK) 3752 res = Z_ERR; 3753 3754 /* 3755 * Check the local host for patches that were not on the source host. 3756 * We already handled version mismatches in the loop above. 3757 */ 3758 hdr = gettext("These patches installed on this system were " 3759 "not installed on the source system:\n"); 3760 if (patch_check(hdr, l_handle, s_handle, B_FALSE) != Z_OK) 3761 res = Z_ERR; 3762 3763 return (res); 3764 } 3765 3766 /* 3767 * During attach we go through and fix up the /dev entries for the zone 3768 * we are attaching. In order to regenerate /dev with the correct devices, 3769 * the old /dev will be removed, the zone readied (which generates a new 3770 * /dev) then halted, then we use the info from the manifest to update 3771 * the modes, owners, etc. on the new /dev. 3772 */ 3773 static int 3774 dev_fix(zone_dochandle_t handle) 3775 { 3776 int res; 3777 int err; 3778 int status; 3779 struct zone_devpermtab devtab; 3780 zone_cmd_arg_t zarg; 3781 char devpath[MAXPATHLEN]; 3782 /* 6: "exec " and " " */ 3783 char cmdbuf[sizeof (RMCOMMAND) + MAXPATHLEN + 6]; 3784 3785 if ((res = zonecfg_get_zonepath(handle, devpath, sizeof (devpath))) 3786 != Z_OK) 3787 return (res); 3788 3789 if (strlcat(devpath, "/dev", sizeof (devpath)) >= sizeof (devpath)) 3790 return (Z_TOO_BIG); 3791 3792 /* 3793 * "exec" the command so that the returned status is that of 3794 * RMCOMMAND and not the shell. 3795 */ 3796 (void) snprintf(cmdbuf, sizeof (cmdbuf), "exec " RMCOMMAND " %s", 3797 devpath); 3798 status = do_subproc(cmdbuf); 3799 if ((err = subproc_status(RMCOMMAND, status)) != Z_OK) { 3800 (void) fprintf(stderr, 3801 gettext("could not remove existing /dev\n")); 3802 return (Z_ERR); 3803 } 3804 3805 /* In order to ready the zone, it must be in the installed state */ 3806 if ((err = zone_set_state(target_zone, ZONE_STATE_INSTALLED)) != Z_OK) { 3807 errno = err; 3808 zperror(gettext("could not reset state"), B_TRUE); 3809 return (Z_ERR); 3810 } 3811 3812 /* We have to ready the zone to regen the dev tree */ 3813 zarg.cmd = Z_READY; 3814 if (call_zoneadmd(target_zone, &zarg) != 0) { 3815 zerror(gettext("call to %s failed"), "zoneadmd"); 3816 return (Z_ERR); 3817 } 3818 3819 zarg.cmd = Z_HALT; 3820 if (call_zoneadmd(target_zone, &zarg) != 0) { 3821 zerror(gettext("call to %s failed"), "zoneadmd"); 3822 return (Z_ERR); 3823 } 3824 3825 if (zonecfg_setdevperment(handle) != Z_OK) { 3826 (void) fprintf(stderr, 3827 gettext("unable to enumerate device entries\n")); 3828 return (Z_ERR); 3829 } 3830 3831 while (zonecfg_getdevperment(handle, &devtab) == Z_OK) { 3832 int err; 3833 3834 if ((err = zonecfg_devperms_apply(handle, 3835 devtab.zone_devperm_name, devtab.zone_devperm_uid, 3836 devtab.zone_devperm_gid, devtab.zone_devperm_mode, 3837 devtab.zone_devperm_acl)) != Z_OK && err != Z_INVAL) 3838 (void) fprintf(stderr, gettext("error updating device " 3839 "%s: %s\n"), devtab.zone_devperm_name, 3840 zonecfg_strerror(err)); 3841 3842 free(devtab.zone_devperm_acl); 3843 } 3844 3845 (void) zonecfg_enddevperment(handle); 3846 3847 return (Z_OK); 3848 } 3849 3850 static int 3851 attach_func(int argc, char *argv[]) 3852 { 3853 int lockfd; 3854 int err, arg; 3855 boolean_t force = B_FALSE; 3856 zone_dochandle_t handle; 3857 zone_dochandle_t athandle = NULL; 3858 char zonepath[MAXPATHLEN]; 3859 3860 if (zonecfg_in_alt_root()) { 3861 zerror(gettext("cannot attach zone in alternate root")); 3862 return (Z_ERR); 3863 } 3864 3865 optind = 0; 3866 if ((arg = getopt(argc, argv, "?F")) != EOF) { 3867 switch (arg) { 3868 case '?': 3869 sub_usage(SHELP_ATTACH, CMD_ATTACH); 3870 return (optopt == '?' ? Z_OK : Z_USAGE); 3871 case 'F': 3872 force = B_TRUE; 3873 break; 3874 default: 3875 sub_usage(SHELP_ATTACH, CMD_ATTACH); 3876 return (Z_USAGE); 3877 } 3878 } 3879 if (sanity_check(target_zone, CMD_ATTACH, B_FALSE, B_TRUE) != Z_OK) 3880 return (Z_ERR); 3881 if (verify_details(CMD_ATTACH) != Z_OK) 3882 return (Z_ERR); 3883 3884 if ((err = zone_get_zonepath(target_zone, zonepath, sizeof (zonepath))) 3885 != Z_OK) { 3886 errno = err; 3887 zperror2(target_zone, gettext("could not get zone path")); 3888 return (Z_ERR); 3889 } 3890 3891 if ((handle = zonecfg_init_handle()) == NULL) { 3892 zperror(cmd_to_str(CMD_ATTACH), B_TRUE); 3893 return (Z_ERR); 3894 } 3895 3896 if ((err = zonecfg_get_handle(target_zone, handle)) != Z_OK) { 3897 errno = err; 3898 zperror(cmd_to_str(CMD_ATTACH), B_TRUE); 3899 zonecfg_fini_handle(handle); 3900 return (Z_ERR); 3901 } 3902 3903 if (grab_lock_file(target_zone, &lockfd) != Z_OK) { 3904 zerror(gettext("another %s may have an operation in progress."), 3905 "zoneadm"); 3906 zonecfg_fini_handle(handle); 3907 return (Z_ERR); 3908 } 3909 3910 if (force) 3911 goto forced; 3912 3913 if ((athandle = zonecfg_init_handle()) == NULL) { 3914 zperror(cmd_to_str(CMD_ATTACH), B_TRUE); 3915 goto done; 3916 } 3917 3918 if ((err = zonecfg_get_attach_handle(zonepath, target_zone, B_TRUE, 3919 athandle)) != Z_OK) { 3920 if (err == Z_NO_ZONE) 3921 zerror(gettext("Not a detached zone")); 3922 else if (err == Z_INVALID_DOCUMENT) 3923 zerror(gettext("Cannot attach to an earlier release " 3924 "of the operating system")); 3925 else 3926 zperror(cmd_to_str(CMD_ATTACH), B_TRUE); 3927 goto done; 3928 } 3929 3930 /* Get the detach information for the locally defined zone. */ 3931 if ((err = zonecfg_get_detach_info(handle, B_FALSE)) != Z_OK) { 3932 errno = err; 3933 zperror(gettext("getting the attach information failed"), 3934 B_TRUE); 3935 goto done; 3936 } 3937 3938 /* sw_cmp prints error msgs as necessary */ 3939 if ((err = sw_cmp(handle, athandle)) != Z_OK) 3940 goto done; 3941 3942 if ((err = dev_fix(athandle)) != Z_OK) 3943 goto done; 3944 3945 forced: 3946 3947 zonecfg_rm_detached(handle, force); 3948 3949 if ((err = zone_set_state(target_zone, ZONE_STATE_INSTALLED)) != Z_OK) { 3950 errno = err; 3951 zperror(gettext("could not reset state"), B_TRUE); 3952 } 3953 3954 done: 3955 zonecfg_fini_handle(handle); 3956 release_lock_file(lockfd); 3957 if (athandle != NULL) 3958 zonecfg_fini_handle(athandle); 3959 3960 return ((err == Z_OK) ? Z_OK : Z_ERR); 3961 } 3962 3963 /* 3964 * On input, TRUE => yes, FALSE => no. 3965 * On return, TRUE => 1, FALSE => 0, could not ask => -1. 3966 */ 3967 3968 static int 3969 ask_yesno(boolean_t default_answer, const char *question) 3970 { 3971 char line[64]; /* should be large enough to answer yes or no */ 3972 3973 if (!isatty(STDIN_FILENO)) 3974 return (-1); 3975 for (;;) { 3976 (void) printf("%s (%s)? ", question, 3977 default_answer ? "[y]/n" : "y/[n]"); 3978 if (fgets(line, sizeof (line), stdin) == NULL || 3979 line[0] == '\n') 3980 return (default_answer ? 1 : 0); 3981 if (tolower(line[0]) == 'y') 3982 return (1); 3983 if (tolower(line[0]) == 'n') 3984 return (0); 3985 } 3986 } 3987 3988 static int 3989 uninstall_func(int argc, char *argv[]) 3990 { 3991 /* 6: "exec " and " " */ 3992 char cmdbuf[sizeof (RMCOMMAND) + MAXPATHLEN + 6]; 3993 char line[ZONENAME_MAX + 128]; /* Enough for "Are you sure ..." */ 3994 char rootpath[MAXPATHLEN], devpath[MAXPATHLEN]; 3995 boolean_t force = B_FALSE; 3996 int lockfd, answer; 3997 int err, arg; 3998 int status; 3999 4000 if (zonecfg_in_alt_root()) { 4001 zerror(gettext("cannot uninstall zone in alternate root")); 4002 return (Z_ERR); 4003 } 4004 4005 optind = 0; 4006 while ((arg = getopt(argc, argv, "?F")) != EOF) { 4007 switch (arg) { 4008 case '?': 4009 sub_usage(SHELP_UNINSTALL, CMD_UNINSTALL); 4010 return (optopt == '?' ? Z_OK : Z_USAGE); 4011 case 'F': 4012 force = B_TRUE; 4013 break; 4014 default: 4015 sub_usage(SHELP_UNINSTALL, CMD_UNINSTALL); 4016 return (Z_USAGE); 4017 } 4018 } 4019 if (argc > optind) { 4020 sub_usage(SHELP_UNINSTALL, CMD_UNINSTALL); 4021 return (Z_USAGE); 4022 } 4023 4024 if (sanity_check(target_zone, CMD_UNINSTALL, B_FALSE, B_TRUE) != Z_OK) 4025 return (Z_ERR); 4026 4027 if (!force) { 4028 (void) snprintf(line, sizeof (line), 4029 gettext("Are you sure you want to %s zone %s"), 4030 cmd_to_str(CMD_UNINSTALL), target_zone); 4031 if ((answer = ask_yesno(B_FALSE, line)) == 0) { 4032 return (Z_OK); 4033 } else if (answer == -1) { 4034 zerror(gettext("Input not from terminal and -F " 4035 "not specified: %s not done."), 4036 cmd_to_str(CMD_UNINSTALL)); 4037 return (Z_ERR); 4038 } 4039 } 4040 4041 if ((err = zone_get_zonepath(target_zone, devpath, 4042 sizeof (devpath))) != Z_OK) { 4043 errno = err; 4044 zperror2(target_zone, gettext("could not get zone path")); 4045 return (Z_ERR); 4046 } 4047 (void) strlcat(devpath, "/dev", sizeof (devpath)); 4048 if ((err = zone_get_rootpath(target_zone, rootpath, 4049 sizeof (rootpath))) != Z_OK) { 4050 errno = err; 4051 zperror2(target_zone, gettext("could not get root path")); 4052 return (Z_ERR); 4053 } 4054 4055 /* 4056 * If there seems to be a zoneadmd running for this zone, call it 4057 * to tell it that an uninstall is happening; if all goes well it 4058 * will then shut itself down. 4059 */ 4060 if (ping_zoneadmd(target_zone) == Z_OK) { 4061 zone_cmd_arg_t zarg; 4062 zarg.cmd = Z_NOTE_UNINSTALLING; 4063 /* we don't care too much if this fails... just plow on */ 4064 (void) call_zoneadmd(target_zone, &zarg); 4065 } 4066 4067 if (grab_lock_file(target_zone, &lockfd) != Z_OK) { 4068 zerror(gettext("another %s may have an operation in progress."), 4069 "zoneadm"); 4070 return (Z_ERR); 4071 } 4072 4073 /* Don't uninstall the zone if anything is mounted there */ 4074 err = zonecfg_find_mounts(rootpath, NULL, NULL); 4075 if (err) { 4076 zerror(gettext("These file-systems are mounted on " 4077 "subdirectories of %s.\n"), rootpath); 4078 (void) zonecfg_find_mounts(rootpath, zfm_print, NULL); 4079 return (Z_ERR); 4080 } 4081 4082 err = zone_set_state(target_zone, ZONE_STATE_INCOMPLETE); 4083 if (err != Z_OK) { 4084 errno = err; 4085 zperror2(target_zone, gettext("could not set state")); 4086 goto bad; 4087 } 4088 4089 /* 4090 * "exec" the command so that the returned status is that of 4091 * RMCOMMAND and not the shell. 4092 */ 4093 (void) snprintf(cmdbuf, sizeof (cmdbuf), "exec " RMCOMMAND " %s", 4094 devpath); 4095 status = do_subproc(cmdbuf); 4096 if ((err = subproc_status(RMCOMMAND, status)) != Z_OK) 4097 goto bad; 4098 (void) snprintf(cmdbuf, sizeof (cmdbuf), "exec " RMCOMMAND " %s", 4099 rootpath); 4100 status = do_subproc(cmdbuf); 4101 if ((err = subproc_status(RMCOMMAND, status)) != Z_OK) 4102 goto bad; 4103 err = zone_set_state(target_zone, ZONE_STATE_CONFIGURED); 4104 if (err != Z_OK) { 4105 errno = err; 4106 zperror2(target_zone, gettext("could not reset state")); 4107 } 4108 bad: 4109 release_lock_file(lockfd); 4110 return (err); 4111 } 4112 4113 /* ARGSUSED */ 4114 static int 4115 mount_func(int argc, char *argv[]) 4116 { 4117 zone_cmd_arg_t zarg; 4118 4119 if (argc > 0) 4120 return (Z_USAGE); 4121 if (sanity_check(target_zone, CMD_MOUNT, B_FALSE, B_FALSE) != Z_OK) 4122 return (Z_ERR); 4123 if (verify_details(CMD_MOUNT) != Z_OK) 4124 return (Z_ERR); 4125 4126 zarg.cmd = Z_MOUNT; 4127 if (call_zoneadmd(target_zone, &zarg) != 0) { 4128 zerror(gettext("call to %s failed"), "zoneadmd"); 4129 return (Z_ERR); 4130 } 4131 return (Z_OK); 4132 } 4133 4134 /* ARGSUSED */ 4135 static int 4136 unmount_func(int argc, char *argv[]) 4137 { 4138 zone_cmd_arg_t zarg; 4139 4140 if (argc > 0) 4141 return (Z_USAGE); 4142 if (sanity_check(target_zone, CMD_UNMOUNT, B_FALSE, B_FALSE) != Z_OK) 4143 return (Z_ERR); 4144 4145 zarg.cmd = Z_UNMOUNT; 4146 if (call_zoneadmd(target_zone, &zarg) != 0) { 4147 zerror(gettext("call to %s failed"), "zoneadmd"); 4148 return (Z_ERR); 4149 } 4150 return (Z_OK); 4151 } 4152 4153 static int 4154 help_func(int argc, char *argv[]) 4155 { 4156 int arg, cmd_num; 4157 4158 if (argc == 0) { 4159 (void) usage(B_TRUE); 4160 return (Z_OK); 4161 } 4162 optind = 0; 4163 if ((arg = getopt(argc, argv, "?")) != EOF) { 4164 switch (arg) { 4165 case '?': 4166 sub_usage(SHELP_HELP, CMD_HELP); 4167 return (optopt == '?' ? Z_OK : Z_USAGE); 4168 default: 4169 sub_usage(SHELP_HELP, CMD_HELP); 4170 return (Z_USAGE); 4171 } 4172 } 4173 while (optind < argc) { 4174 /* Private commands have NULL short_usage; omit them */ 4175 if ((cmd_num = cmd_match(argv[optind])) < 0 || 4176 cmdtab[cmd_num].short_usage == NULL) { 4177 sub_usage(SHELP_HELP, CMD_HELP); 4178 return (Z_USAGE); 4179 } 4180 sub_usage(cmdtab[cmd_num].short_usage, cmd_num); 4181 optind++; 4182 } 4183 return (Z_OK); 4184 } 4185 4186 /* 4187 * Returns: CMD_MIN thru CMD_MAX on success, -1 on error 4188 */ 4189 4190 static int 4191 cmd_match(char *cmd) 4192 { 4193 int i; 4194 4195 for (i = CMD_MIN; i <= CMD_MAX; i++) { 4196 /* return only if there is an exact match */ 4197 if (strcmp(cmd, cmdtab[i].cmd_name) == 0) 4198 return (cmdtab[i].cmd_num); 4199 } 4200 return (-1); 4201 } 4202 4203 static int 4204 parse_and_run(int argc, char *argv[]) 4205 { 4206 int i = cmd_match(argv[0]); 4207 4208 if (i < 0) 4209 return (usage(B_FALSE)); 4210 return (cmdtab[i].handler(argc - 1, &(argv[1]))); 4211 } 4212 4213 static char * 4214 get_execbasename(char *execfullname) 4215 { 4216 char *last_slash, *execbasename; 4217 4218 /* guard against '/' at end of command invocation */ 4219 for (;;) { 4220 last_slash = strrchr(execfullname, '/'); 4221 if (last_slash == NULL) { 4222 execbasename = execfullname; 4223 break; 4224 } else { 4225 execbasename = last_slash + 1; 4226 if (*execbasename == '\0') { 4227 *last_slash = '\0'; 4228 continue; 4229 } 4230 break; 4231 } 4232 } 4233 return (execbasename); 4234 } 4235 4236 int 4237 main(int argc, char **argv) 4238 { 4239 int arg; 4240 zoneid_t zid; 4241 struct stat st; 4242 4243 if ((locale = setlocale(LC_ALL, "")) == NULL) 4244 locale = "C"; 4245 (void) textdomain(TEXT_DOMAIN); 4246 setbuf(stdout, NULL); 4247 (void) sigset(SIGHUP, SIG_IGN); 4248 execname = get_execbasename(argv[0]); 4249 target_zone = NULL; 4250 if (chdir("/") != 0) { 4251 zerror(gettext("could not change directory to /.")); 4252 exit(Z_ERR); 4253 } 4254 4255 while ((arg = getopt(argc, argv, "?z:R:")) != EOF) { 4256 switch (arg) { 4257 case '?': 4258 return (usage(B_TRUE)); 4259 case 'z': 4260 target_zone = optarg; 4261 break; 4262 case 'R': /* private option for admin/install use */ 4263 if (*optarg != '/') { 4264 zerror(gettext("root path must be absolute.")); 4265 exit(Z_ERR); 4266 } 4267 if (stat(optarg, &st) == -1 || !S_ISDIR(st.st_mode)) { 4268 zerror( 4269 gettext("root path must be a directory.")); 4270 exit(Z_ERR); 4271 } 4272 zonecfg_set_root(optarg); 4273 break; 4274 default: 4275 return (usage(B_FALSE)); 4276 } 4277 } 4278 4279 if (optind >= argc) 4280 return (usage(B_FALSE)); 4281 if (target_zone != NULL && zone_get_id(target_zone, &zid) != 0) { 4282 errno = Z_NO_ZONE; 4283 zperror(target_zone, B_TRUE); 4284 exit(Z_ERR); 4285 } 4286 return (parse_and_run(argc - optind, &argv[optind])); 4287 } 4288