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