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