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