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 2009 Sun Microsystems, Inc. All rights reserved. 24 * Use is subject to license terms. 25 */ 26 27 /* 28 * zoneadm is a command interpreter for zone administration. It is all in 29 * C (i.e., no lex/yacc), and all the argument passing is argc/argv based. 30 * main() calls parse_and_run() which calls cmd_match(), then invokes the 31 * appropriate command's handler function. The rest of the program is the 32 * handler functions and their helper functions. 33 * 34 * Some of the helper functions are used largely to simplify I18N: reducing 35 * the need for translation notes. This is particularly true of many of 36 * the zerror() calls: doing e.g. zerror(gettext("%s failed"), "foo") rather 37 * than zerror(gettext("foo failed")) with a translation note indicating 38 * that "foo" need not be translated. 39 */ 40 41 #include <stdio.h> 42 #include <errno.h> 43 #include <unistd.h> 44 #include <signal.h> 45 #include <stdarg.h> 46 #include <ctype.h> 47 #include <stdlib.h> 48 #include <string.h> 49 #include <wait.h> 50 #include <zone.h> 51 #include <priv.h> 52 #include <locale.h> 53 #include <libintl.h> 54 #include <libzonecfg.h> 55 #include <bsm/adt.h> 56 #include <sys/brand.h> 57 #include <sys/param.h> 58 #include <sys/types.h> 59 #include <sys/stat.h> 60 #include <sys/statvfs.h> 61 #include <assert.h> 62 #include <sys/sockio.h> 63 #include <sys/mntent.h> 64 #include <limits.h> 65 #include <dirent.h> 66 #include <uuid/uuid.h> 67 #include <fcntl.h> 68 #include <door.h> 69 #include <macros.h> 70 #include <libgen.h> 71 #include <fnmatch.h> 72 #include <sys/modctl.h> 73 #include <libbrand.h> 74 #include <libscf.h> 75 #include <procfs.h> 76 #include <strings.h> 77 #include <pool.h> 78 #include <sys/pool.h> 79 #include <sys/priocntl.h> 80 #include <sys/fsspriocntl.h> 81 #include <libdladm.h> 82 #include <libdllink.h> 83 84 #include "zoneadm.h" 85 86 #define MAXARGS 8 87 88 /* Reflects kernel zone entries */ 89 typedef struct zone_entry { 90 zoneid_t zid; 91 char zname[ZONENAME_MAX]; 92 char *zstate_str; 93 zone_state_t zstate_num; 94 char zbrand[MAXNAMELEN]; 95 char zroot[MAXPATHLEN]; 96 char zuuid[UUID_PRINTABLE_STRING_LENGTH]; 97 zone_iptype_t ziptype; 98 } zone_entry_t; 99 100 #define CLUSTER_BRAND_NAME "cluster" 101 102 static zone_entry_t *zents; 103 static size_t nzents; 104 105 #define LOOPBACK_IF "lo0" 106 #define SOCKET_AF(af) (((af) == AF_UNSPEC) ? AF_INET : (af)) 107 108 struct net_if { 109 char *name; 110 int af; 111 }; 112 113 /* 0755 is the default directory mode. */ 114 #define DEFAULT_DIR_MODE \ 115 (S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH) 116 117 struct cmd { 118 uint_t cmd_num; /* command number */ 119 char *cmd_name; /* command name */ 120 char *short_usage; /* short form help */ 121 int (*handler)(int argc, char *argv[]); /* function to call */ 122 123 }; 124 125 #define SHELP_HELP "help" 126 #define SHELP_BOOT "boot [-- boot_arguments]" 127 #define SHELP_HALT "halt" 128 #define SHELP_READY "ready" 129 #define SHELP_REBOOT "reboot [-- boot_arguments]" 130 #define SHELP_LIST "list [-cipv]" 131 #define SHELP_VERIFY "verify" 132 #define SHELP_INSTALL "install [-x nodataset] [brand-specific args]" 133 #define SHELP_UNINSTALL "uninstall [-F] [brand-specific args]" 134 #define SHELP_CLONE "clone [-m method] [-s <ZFS snapshot>] "\ 135 "[brand-specific args] zonename" 136 #define SHELP_MOVE "move zonepath" 137 #define SHELP_DETACH "detach [-n] [brand-specific args]" 138 #define SHELP_ATTACH "attach [-F] [-n <path>] [brand-specific args]" 139 #define SHELP_MARK "mark incomplete" 140 141 #define EXEC_PREFIX "exec " 142 #define EXEC_LEN (strlen(EXEC_PREFIX)) 143 #define RMCOMMAND "/usr/bin/rm -rf" 144 145 static int cleanup_zonepath(char *, boolean_t); 146 147 148 static int help_func(int argc, char *argv[]); 149 static int ready_func(int argc, char *argv[]); 150 static int boot_func(int argc, char *argv[]); 151 static int halt_func(int argc, char *argv[]); 152 static int reboot_func(int argc, char *argv[]); 153 static int list_func(int argc, char *argv[]); 154 static int verify_func(int argc, char *argv[]); 155 static int install_func(int argc, char *argv[]); 156 static int uninstall_func(int argc, char *argv[]); 157 static int mount_func(int argc, char *argv[]); 158 static int unmount_func(int argc, char *argv[]); 159 static int clone_func(int argc, char *argv[]); 160 static int move_func(int argc, char *argv[]); 161 static int detach_func(int argc, char *argv[]); 162 static int attach_func(int argc, char *argv[]); 163 static int mark_func(int argc, char *argv[]); 164 static int apply_func(int argc, char *argv[]); 165 static int sysboot_func(int argc, char *argv[]); 166 static int sanity_check(char *zone, int cmd_num, boolean_t running, 167 boolean_t unsafe_when_running, boolean_t force); 168 static int cmd_match(char *cmd); 169 static int verify_details(int, char *argv[]); 170 static int verify_brand(zone_dochandle_t, int, char *argv[]); 171 static int invoke_brand_handler(int, char *argv[]); 172 173 static struct cmd cmdtab[] = { 174 { CMD_HELP, "help", SHELP_HELP, help_func }, 175 { CMD_BOOT, "boot", SHELP_BOOT, boot_func }, 176 { CMD_HALT, "halt", SHELP_HALT, halt_func }, 177 { CMD_READY, "ready", SHELP_READY, ready_func }, 178 { CMD_REBOOT, "reboot", SHELP_REBOOT, reboot_func }, 179 { CMD_LIST, "list", SHELP_LIST, list_func }, 180 { CMD_VERIFY, "verify", SHELP_VERIFY, verify_func }, 181 { CMD_INSTALL, "install", SHELP_INSTALL, install_func }, 182 { CMD_UNINSTALL, "uninstall", SHELP_UNINSTALL, 183 uninstall_func }, 184 /* mount and unmount are private commands for admin/install */ 185 { CMD_MOUNT, "mount", NULL, mount_func }, 186 { CMD_UNMOUNT, "unmount", NULL, unmount_func }, 187 { CMD_CLONE, "clone", SHELP_CLONE, clone_func }, 188 { CMD_MOVE, "move", SHELP_MOVE, move_func }, 189 { CMD_DETACH, "detach", SHELP_DETACH, detach_func }, 190 { CMD_ATTACH, "attach", SHELP_ATTACH, attach_func }, 191 { CMD_MARK, "mark", SHELP_MARK, mark_func }, 192 { CMD_APPLY, "apply", NULL, apply_func }, 193 { CMD_SYSBOOT, "sysboot", NULL, sysboot_func } 194 }; 195 196 /* global variables */ 197 198 /* set early in main(), never modified thereafter, used all over the place */ 199 static char *execname; 200 static char target_brand[MAXNAMELEN]; 201 static char default_brand[MAXPATHLEN]; 202 static char *locale; 203 char *target_zone; 204 static char *target_uuid; 205 206 char * 207 cmd_to_str(int cmd_num) 208 { 209 assert(cmd_num >= CMD_MIN && cmd_num <= CMD_MAX); 210 return (cmdtab[cmd_num].cmd_name); 211 } 212 213 /* This is a separate function because of gettext() wrapping. */ 214 static char * 215 long_help(int cmd_num) 216 { 217 assert(cmd_num >= CMD_MIN && cmd_num <= CMD_MAX); 218 switch (cmd_num) { 219 case CMD_HELP: 220 return (gettext("Print usage message.")); 221 case CMD_BOOT: 222 return (gettext("Activates (boots) specified zone. See " 223 "zoneadm(1m) for valid boot\n\targuments.")); 224 case CMD_HALT: 225 return (gettext("Halts specified zone, bypassing shutdown " 226 "scripts and removing runtime\n\tresources of the zone.")); 227 case CMD_READY: 228 return (gettext("Prepares a zone for running applications but " 229 "does not start any user\n\tprocesses in the zone.")); 230 case CMD_REBOOT: 231 return (gettext("Restarts the zone (equivalent to a halt / " 232 "boot sequence).\n\tFails if the zone is not active. " 233 "See zoneadm(1m) for valid boot\n\targuments.")); 234 case CMD_LIST: 235 return (gettext("Lists the current zones, or a " 236 "specific zone if indicated. By default,\n\tall " 237 "running zones are listed, though this can be " 238 "expanded to all\n\tinstalled zones with the -i " 239 "option or all configured zones with the\n\t-c " 240 "option. When used with the general -z <zone> and/or -u " 241 "<uuid-match>\n\toptions, lists only the specified " 242 "matching zone, but lists it\n\tregardless of its state, " 243 "and the -i and -c options are disallowed. The\n\t-v " 244 "option can be used to display verbose information: zone " 245 "name, id,\n\tcurrent state, root directory and options. " 246 "The -p option can be used\n\tto request machine-parsable " 247 "output. The -v and -p options are mutually\n\texclusive." 248 " If neither -v nor -p is used, just the zone name is " 249 "listed.")); 250 case CMD_VERIFY: 251 return (gettext("Check to make sure the configuration " 252 "can safely be instantiated\n\ton the machine: " 253 "physical network interfaces exist, etc.")); 254 case CMD_INSTALL: 255 return (gettext("Install the configuration on to the system. " 256 "The -x nodataset option\n\tcan be used to prevent the " 257 "creation of a new ZFS file system for the\n\tzone " 258 "(assuming the zonepath is within a ZFS file system).\n\t" 259 "All other arguments are passed to the brand installation " 260 "function;\n\tsee brands(5) for more information.")); 261 case CMD_UNINSTALL: 262 return (gettext("Uninstall the configuration from the system. " 263 "The -F flag can be used\n\tto force the action. All " 264 "other arguments are passed to the brand\n\tuninstall " 265 "function; see brands(5) for more information.")); 266 case CMD_CLONE: 267 return (gettext("Clone the installation of another zone. " 268 "The -m option can be used to\n\tspecify 'copy' which " 269 "forces a copy of the source zone. The -s option\n\t" 270 "can be used to specify the name of a ZFS snapshot " 271 "that was taken from\n\ta previous clone command. The " 272 "snapshot will be used as the source\n\tinstead of " 273 "creating a new ZFS snapshot. All other arguments are " 274 "passed\n\tto the brand clone function; see " 275 "brands(5) for more information.")); 276 case CMD_MOVE: 277 return (gettext("Move the zone to a new zonepath.")); 278 case CMD_DETACH: 279 return (gettext("Detach the zone from the system. The zone " 280 "state is changed to\n\t'configured' (but the files under " 281 "the zonepath are untouched).\n\tThe zone can subsequently " 282 "be attached, or can be moved to another\n\tsystem and " 283 "attached there. The -n option can be used to specify\n\t" 284 "'no-execute' mode. When -n is used, the information " 285 "needed to attach\n\tthe zone is sent to standard output " 286 "but the zone is not actually\n\tdetached. All other " 287 "arguments are passed to the brand detach function;\n\tsee " 288 "brands(5) for more information.")); 289 case CMD_ATTACH: 290 return (gettext("Attach the zone to the system. The zone " 291 "state must be 'configured'\n\tprior to attach; upon " 292 "successful completion, the zone state will be\n\t" 293 "'installed'. The system software on the current " 294 "system must be\n\tcompatible with the software on the " 295 "zone's original system.\n\tSpecify -F " 296 "to force the attach and skip software compatibility " 297 "tests.\n\tThe -n option can be used to specify " 298 "'no-execute' mode. When -n is\n\tused, the information " 299 "needed to attach the zone is read from the\n\tspecified " 300 "path and the configuration is only validated. The path " 301 "can\n\tbe '-' to specify standard input. The -F and -n " 302 "options are mutually\n\texclusive. All other arguments " 303 "are passed to the brand attach\n\tfunction; see " 304 "brands(5) for more information.")); 305 case CMD_MARK: 306 return (gettext("Set the state of the zone. This can be used " 307 "to force the zone\n\tstate to 'incomplete' " 308 "administratively if some activity has rendered\n\tthe " 309 "zone permanently unusable. The only valid state that " 310 "may be\n\tspecified is 'incomplete'.")); 311 default: 312 return (""); 313 } 314 /* NOTREACHED */ 315 return (NULL); 316 } 317 318 /* 319 * Called with explicit B_TRUE when help is explicitly requested, B_FALSE for 320 * unexpected errors. 321 */ 322 323 static int 324 usage(boolean_t explicit) 325 { 326 int i; 327 FILE *fd = explicit ? stdout : stderr; 328 329 (void) fprintf(fd, "%s:\t%s help\n", gettext("usage"), execname); 330 (void) fprintf(fd, "\t%s [-z <zone>] [-u <uuid-match>] list\n", 331 execname); 332 (void) fprintf(fd, "\t%s {-z <zone>|-u <uuid-match>} <%s>\n", execname, 333 gettext("subcommand")); 334 (void) fprintf(fd, "\n%s:\n\n", gettext("Subcommands")); 335 for (i = CMD_MIN; i <= CMD_MAX; i++) { 336 if (cmdtab[i].short_usage == NULL) 337 continue; 338 (void) fprintf(fd, "%s\n", cmdtab[i].short_usage); 339 if (explicit) 340 (void) fprintf(fd, "\t%s\n\n", long_help(i)); 341 } 342 if (!explicit) 343 (void) fputs("\n", fd); 344 return (Z_USAGE); 345 } 346 347 static void 348 sub_usage(char *short_usage, int cmd_num) 349 { 350 (void) fprintf(stderr, "%s:\t%s\n", gettext("usage"), short_usage); 351 (void) fprintf(stderr, "\t%s\n", long_help(cmd_num)); 352 } 353 354 /* 355 * zperror() is like perror(3c) except that this also prints the executable 356 * name at the start of the message, and takes a boolean indicating whether 357 * to call libc'c strerror() or that from libzonecfg. 358 */ 359 360 void 361 zperror(const char *str, boolean_t zonecfg_error) 362 { 363 (void) fprintf(stderr, "%s: %s: %s\n", execname, str, 364 zonecfg_error ? zonecfg_strerror(errno) : strerror(errno)); 365 } 366 367 /* 368 * zperror2() is very similar to zperror() above, except it also prints a 369 * supplied zone name after the executable. 370 * 371 * All current consumers of this function want libzonecfg's strerror() rather 372 * than libc's; if this ever changes, this function can be made more generic 373 * like zperror() above. 374 */ 375 376 void 377 zperror2(const char *zone, const char *str) 378 { 379 (void) fprintf(stderr, "%s: %s: %s: %s\n", execname, zone, str, 380 zonecfg_strerror(errno)); 381 } 382 383 /* PRINTFLIKE1 */ 384 void 385 zerror(const char *fmt, ...) 386 { 387 va_list alist; 388 389 va_start(alist, fmt); 390 (void) fprintf(stderr, "%s: ", execname); 391 if (target_zone != NULL) 392 (void) fprintf(stderr, "zone '%s': ", target_zone); 393 (void) vfprintf(stderr, fmt, alist); 394 (void) fprintf(stderr, "\n"); 395 va_end(alist); 396 } 397 398 static void * 399 safe_calloc(size_t nelem, size_t elsize) 400 { 401 void *r = calloc(nelem, elsize); 402 403 if (r == NULL) { 404 zerror(gettext("failed to allocate %lu bytes: %s"), 405 (ulong_t)nelem * elsize, strerror(errno)); 406 exit(Z_ERR); 407 } 408 return (r); 409 } 410 411 static void 412 zone_print(zone_entry_t *zent, boolean_t verbose, boolean_t parsable) 413 { 414 static boolean_t firsttime = B_TRUE; 415 char *ip_type_str; 416 417 /* Skip a zone that shutdown while we were collecting data. */ 418 if (zent->zname[0] == '\0') 419 return; 420 421 if (zent->ziptype == ZS_EXCLUSIVE) 422 ip_type_str = "excl"; 423 else 424 ip_type_str = "shared"; 425 426 assert(!(verbose && parsable)); 427 if (firsttime && verbose) { 428 firsttime = B_FALSE; 429 (void) printf("%*s %-16s %-10s %-30s %-8s %-6s\n", 430 ZONEID_WIDTH, "ID", "NAME", "STATUS", "PATH", "BRAND", 431 "IP"); 432 } 433 if (!verbose) { 434 char *cp, *clim; 435 436 if (!parsable) { 437 (void) printf("%s\n", zent->zname); 438 return; 439 } 440 if (zent->zid == ZONE_ID_UNDEFINED) 441 (void) printf("-"); 442 else 443 (void) printf("%lu", zent->zid); 444 (void) printf(":%s:%s:", zent->zname, zent->zstate_str); 445 cp = zent->zroot; 446 while ((clim = strchr(cp, ':')) != NULL) { 447 (void) printf("%.*s\\:", clim - cp, cp); 448 cp = clim + 1; 449 } 450 (void) printf("%s:%s:%s:%s\n", cp, zent->zuuid, zent->zbrand, 451 ip_type_str); 452 return; 453 } 454 if (zent->zstate_str != NULL) { 455 if (zent->zid == ZONE_ID_UNDEFINED) 456 (void) printf("%*s", ZONEID_WIDTH, "-"); 457 else 458 (void) printf("%*lu", ZONEID_WIDTH, zent->zid); 459 (void) printf(" %-16s %-10s %-30s %-8s %-6s\n", zent->zname, 460 zent->zstate_str, zent->zroot, zent->zbrand, ip_type_str); 461 } 462 } 463 464 static int 465 lookup_zone_info(const char *zone_name, zoneid_t zid, zone_entry_t *zent) 466 { 467 char root[MAXPATHLEN], *cp; 468 int err; 469 uuid_t uuid; 470 zone_dochandle_t handle; 471 472 (void) strlcpy(zent->zname, zone_name, sizeof (zent->zname)); 473 (void) strlcpy(zent->zroot, "???", sizeof (zent->zroot)); 474 (void) strlcpy(zent->zbrand, "???", sizeof (zent->zbrand)); 475 zent->zstate_str = "???"; 476 477 zent->zid = zid; 478 479 if (zonecfg_get_uuid(zone_name, uuid) == Z_OK && 480 !uuid_is_null(uuid)) 481 uuid_unparse(uuid, zent->zuuid); 482 else 483 zent->zuuid[0] = '\0'; 484 485 /* 486 * For labeled zones which query the zone path of lower-level 487 * zones, the path needs to be adjusted to drop the final 488 * "/root" component. This adjusted path is then useful 489 * for reading down any exported directories from the 490 * lower-level zone. 491 */ 492 if (is_system_labeled() && zent->zid != ZONE_ID_UNDEFINED) { 493 if (zone_getattr(zent->zid, ZONE_ATTR_ROOT, zent->zroot, 494 sizeof (zent->zroot)) == -1) { 495 zperror2(zent->zname, 496 gettext("could not get zone path.")); 497 return (Z_ERR); 498 } 499 cp = zent->zroot + strlen(zent->zroot) - 5; 500 if (cp > zent->zroot && strcmp(cp, "/root") == 0) 501 *cp = 0; 502 } else { 503 if ((err = zone_get_zonepath(zent->zname, root, 504 sizeof (root))) != Z_OK) { 505 errno = err; 506 zperror2(zent->zname, 507 gettext("could not get zone path.")); 508 return (Z_ERR); 509 } 510 (void) strlcpy(zent->zroot, root, sizeof (zent->zroot)); 511 } 512 513 if ((err = zone_get_state(zent->zname, &zent->zstate_num)) != Z_OK) { 514 errno = err; 515 zperror2(zent->zname, gettext("could not get state")); 516 return (Z_ERR); 517 } 518 zent->zstate_str = zone_state_str(zent->zstate_num); 519 520 /* 521 * A zone's brand is only available in the .xml file describing it, 522 * which is only visible to the global zone. This causes 523 * zone_get_brand() to fail when called from within a non-global 524 * zone. Fortunately we only do this on labeled systems, where we 525 * know all zones are native. 526 */ 527 if (getzoneid() != GLOBAL_ZONEID) { 528 assert(is_system_labeled() != 0); 529 (void) strlcpy(zent->zbrand, default_brand, 530 sizeof (zent->zbrand)); 531 } else if (zone_get_brand(zent->zname, zent->zbrand, 532 sizeof (zent->zbrand)) != Z_OK) { 533 zperror2(zent->zname, gettext("could not get brand name")); 534 return (Z_ERR); 535 } 536 537 /* 538 * Get ip type of the zone. 539 * Note for global zone, ZS_SHARED is set always. 540 */ 541 if (zid == GLOBAL_ZONEID) { 542 zent->ziptype = ZS_SHARED; 543 return (Z_OK); 544 } 545 546 /* 547 * There is a race condition where the zone could boot while 548 * we're walking the index file. In this case the zone state 549 * could be seen as running from the call above, but the zoneid 550 * would be undefined. 551 * 552 * There is also a race condition where the zone could shutdown after 553 * we got its running state above. This is also not an error and 554 * we fall back to getting the ziptype from the zone configuration. 555 */ 556 if (zent->zstate_num == ZONE_STATE_RUNNING && 557 zid != ZONE_ID_UNDEFINED) { 558 ushort_t flags; 559 560 if (zone_getattr(zid, ZONE_ATTR_FLAGS, &flags, 561 sizeof (flags)) >= 0) { 562 if (flags & ZF_NET_EXCL) 563 zent->ziptype = ZS_EXCLUSIVE; 564 else 565 zent->ziptype = ZS_SHARED; 566 return (Z_OK); 567 } 568 } 569 570 if ((handle = zonecfg_init_handle()) == NULL) { 571 zperror2(zent->zname, gettext("could not init handle")); 572 return (Z_ERR); 573 } 574 if ((err = zonecfg_get_handle(zent->zname, handle)) != Z_OK) { 575 zperror2(zent->zname, gettext("could not get handle")); 576 zonecfg_fini_handle(handle); 577 return (Z_ERR); 578 } 579 580 if ((err = zonecfg_get_iptype(handle, &zent->ziptype)) != Z_OK) { 581 zperror2(zent->zname, gettext("could not get ip-type")); 582 zonecfg_fini_handle(handle); 583 return (Z_ERR); 584 } 585 zonecfg_fini_handle(handle); 586 587 return (Z_OK); 588 } 589 590 /* 591 * fetch_zents() calls zone_list(2) to find out how many zones are running 592 * (which is stored in the global nzents), then calls zone_list(2) again 593 * to fetch the list of running zones (stored in the global zents). This 594 * function may be called multiple times, so if zents is already set, we 595 * return immediately to save work. 596 * 597 * Note that the data about running zones can change while this function 598 * is running, so its possible that the list of zones will have empty slots 599 * at the end. 600 */ 601 602 static int 603 fetch_zents(void) 604 { 605 zoneid_t *zids = NULL; 606 uint_t nzents_saved; 607 int i, retv; 608 FILE *fp; 609 boolean_t inaltroot; 610 zone_entry_t *zentp; 611 612 if (nzents > 0) 613 return (Z_OK); 614 615 if (zone_list(NULL, &nzents) != 0) { 616 zperror(gettext("failed to get zoneid list"), B_FALSE); 617 return (Z_ERR); 618 } 619 620 again: 621 if (nzents == 0) 622 return (Z_OK); 623 624 zids = safe_calloc(nzents, sizeof (zoneid_t)); 625 nzents_saved = nzents; 626 627 if (zone_list(zids, &nzents) != 0) { 628 zperror(gettext("failed to get zone list"), B_FALSE); 629 free(zids); 630 return (Z_ERR); 631 } 632 if (nzents != nzents_saved) { 633 /* list changed, try again */ 634 free(zids); 635 goto again; 636 } 637 638 zents = safe_calloc(nzents, sizeof (zone_entry_t)); 639 640 inaltroot = zonecfg_in_alt_root(); 641 if (inaltroot) 642 fp = zonecfg_open_scratch("", B_FALSE); 643 else 644 fp = NULL; 645 zentp = zents; 646 retv = Z_OK; 647 for (i = 0; i < nzents; i++) { 648 char name[ZONENAME_MAX]; 649 char altname[ZONENAME_MAX]; 650 651 if (getzonenamebyid(zids[i], name, sizeof (name)) < 0) { 652 /* 653 * There is a race condition where the zone may have 654 * shutdown since we retrieved the number of running 655 * zones above. This is not an error, there will be 656 * an empty slot at the end of the list. 657 */ 658 continue; 659 } 660 if (zonecfg_is_scratch(name)) { 661 /* Ignore scratch zones by default */ 662 if (!inaltroot) 663 continue; 664 if (fp == NULL || 665 zonecfg_reverse_scratch(fp, name, altname, 666 sizeof (altname), NULL, 0) == -1) { 667 zerror(gettext("could not resolve scratch " 668 "zone %s"), name); 669 retv = Z_ERR; 670 continue; 671 } 672 (void) strcpy(name, altname); 673 } else { 674 /* Ignore non-scratch when in an alternate root */ 675 if (inaltroot && strcmp(name, GLOBAL_ZONENAME) != 0) 676 continue; 677 } 678 if (lookup_zone_info(name, zids[i], zentp) != Z_OK) { 679 /* 680 * There is a race condition where the zone may have 681 * shutdown since we retrieved the number of running 682 * zones above. This is not an error, there will be 683 * an empty slot at the end of the list. 684 */ 685 continue; 686 } 687 zentp++; 688 } 689 nzents = zentp - zents; 690 if (fp != NULL) 691 zonecfg_close_scratch(fp); 692 693 free(zids); 694 return (retv); 695 } 696 697 static int 698 zone_print_list(zone_state_t min_state, boolean_t verbose, boolean_t parsable) 699 { 700 int i; 701 zone_entry_t zent; 702 FILE *cookie; 703 char *name; 704 705 /* 706 * First get the list of running zones from the kernel and print them. 707 * If that is all we need, then return. 708 */ 709 if ((i = fetch_zents()) != Z_OK) { 710 /* 711 * No need for error messages; fetch_zents() has already taken 712 * care of this. 713 */ 714 return (i); 715 } 716 for (i = 0; i < nzents; i++) 717 zone_print(&zents[i], verbose, parsable); 718 if (min_state >= ZONE_STATE_RUNNING) 719 return (Z_OK); 720 /* 721 * Next, get the full list of zones from the configuration, skipping 722 * any we have already printed. 723 */ 724 cookie = setzoneent(); 725 while ((name = getzoneent(cookie)) != NULL) { 726 for (i = 0; i < nzents; i++) { 727 if (strcmp(zents[i].zname, name) == 0) 728 break; 729 } 730 if (i < nzents) { 731 free(name); 732 continue; 733 } 734 if (lookup_zone_info(name, ZONE_ID_UNDEFINED, &zent) != Z_OK) { 735 free(name); 736 continue; 737 } 738 free(name); 739 if (zent.zstate_num >= min_state) 740 zone_print(&zent, verbose, parsable); 741 } 742 endzoneent(cookie); 743 return (Z_OK); 744 } 745 746 /* 747 * Retrieve a zone entry by name. Returns NULL if no such zone exists. 748 */ 749 static zone_entry_t * 750 lookup_running_zone(const char *str) 751 { 752 int i; 753 754 if (fetch_zents() != Z_OK) 755 return (NULL); 756 757 for (i = 0; i < nzents; i++) { 758 if (strcmp(str, zents[i].zname) == 0) 759 return (&zents[i]); 760 } 761 return (NULL); 762 } 763 764 /* 765 * Check a bit in a mode_t: if on is B_TRUE, that bit should be on; if 766 * B_FALSE, it should be off. Return B_TRUE if the mode is bad (incorrect). 767 */ 768 static boolean_t 769 bad_mode_bit(mode_t mode, mode_t bit, boolean_t on, char *file) 770 { 771 char *str; 772 773 assert(bit == S_IRUSR || bit == S_IWUSR || bit == S_IXUSR || 774 bit == S_IRGRP || bit == S_IWGRP || bit == S_IXGRP || 775 bit == S_IROTH || bit == S_IWOTH || bit == S_IXOTH); 776 /* 777 * TRANSLATION_NOTE 778 * The strings below will be used as part of a larger message, 779 * either: 780 * (file name) must be (owner|group|world) (read|writ|execut)able 781 * or 782 * (file name) must not be (owner|group|world) (read|writ|execut)able 783 */ 784 switch (bit) { 785 case S_IRUSR: 786 str = gettext("owner readable"); 787 break; 788 case S_IWUSR: 789 str = gettext("owner writable"); 790 break; 791 case S_IXUSR: 792 str = gettext("owner executable"); 793 break; 794 case S_IRGRP: 795 str = gettext("group readable"); 796 break; 797 case S_IWGRP: 798 str = gettext("group writable"); 799 break; 800 case S_IXGRP: 801 str = gettext("group executable"); 802 break; 803 case S_IROTH: 804 str = gettext("world readable"); 805 break; 806 case S_IWOTH: 807 str = gettext("world writable"); 808 break; 809 case S_IXOTH: 810 str = gettext("world executable"); 811 break; 812 } 813 if ((mode & bit) == (on ? 0 : bit)) { 814 /* 815 * TRANSLATION_NOTE 816 * The first parameter below is a file name; the second 817 * is one of the "(owner|group|world) (read|writ|execut)able" 818 * strings from above. 819 */ 820 /* 821 * The code below could be simplified but not in a way 822 * that would easily translate to non-English locales. 823 */ 824 if (on) { 825 (void) fprintf(stderr, gettext("%s must be %s.\n"), 826 file, str); 827 } else { 828 (void) fprintf(stderr, gettext("%s must not be %s.\n"), 829 file, str); 830 } 831 return (B_TRUE); 832 } 833 return (B_FALSE); 834 } 835 836 /* 837 * We want to make sure that no zone has its zone path as a child node 838 * (in the directory sense) of any other. We do that by comparing this 839 * zone's path to the path of all other (non-global) zones. The comparison 840 * in each case is simple: add '/' to the end of the path, then do a 841 * strncmp() of the two paths, using the length of the shorter one. 842 */ 843 844 static int 845 crosscheck_zonepaths(char *path) 846 { 847 char rpath[MAXPATHLEN]; /* resolved path */ 848 char path_copy[MAXPATHLEN]; /* copy of original path */ 849 char rpath_copy[MAXPATHLEN]; /* copy of original rpath */ 850 struct zoneent *ze; 851 int res, err; 852 FILE *cookie; 853 854 cookie = setzoneent(); 855 while ((ze = getzoneent_private(cookie)) != NULL) { 856 /* Skip zones which are not installed. */ 857 if (ze->zone_state < ZONE_STATE_INSTALLED) { 858 free(ze); 859 continue; 860 } 861 /* Skip the global zone and the current target zone. */ 862 if (strcmp(ze->zone_name, GLOBAL_ZONENAME) == 0 || 863 strcmp(ze->zone_name, target_zone) == 0) { 864 free(ze); 865 continue; 866 } 867 if (strlen(ze->zone_path) == 0) { 868 /* old index file without path, fall back */ 869 if ((err = zone_get_zonepath(ze->zone_name, 870 ze->zone_path, sizeof (ze->zone_path))) != Z_OK) { 871 errno = err; 872 zperror2(ze->zone_name, 873 gettext("could not get zone path")); 874 free(ze); 875 continue; 876 } 877 } 878 (void) snprintf(path_copy, sizeof (path_copy), "%s%s", 879 zonecfg_get_root(), ze->zone_path); 880 res = resolvepath(path_copy, rpath, sizeof (rpath)); 881 if (res == -1) { 882 if (errno != ENOENT) { 883 zperror(path_copy, B_FALSE); 884 free(ze); 885 return (Z_ERR); 886 } 887 (void) printf(gettext("WARNING: zone %s is installed, " 888 "but its %s %s does not exist.\n"), ze->zone_name, 889 "zonepath", path_copy); 890 free(ze); 891 continue; 892 } 893 rpath[res] = '\0'; 894 (void) snprintf(path_copy, sizeof (path_copy), "%s/", path); 895 (void) snprintf(rpath_copy, sizeof (rpath_copy), "%s/", rpath); 896 if (strncmp(path_copy, rpath_copy, 897 min(strlen(path_copy), strlen(rpath_copy))) == 0) { 898 /* 899 * TRANSLATION_NOTE 900 * zonepath is a literal that should not be translated. 901 */ 902 (void) fprintf(stderr, gettext("%s zonepath (%s) and " 903 "%s zonepath (%s) overlap.\n"), 904 target_zone, path, ze->zone_name, rpath); 905 free(ze); 906 return (Z_ERR); 907 } 908 free(ze); 909 } 910 endzoneent(cookie); 911 return (Z_OK); 912 } 913 914 static int 915 validate_zonepath(char *path, int cmd_num) 916 { 917 int res; /* result of last library/system call */ 918 boolean_t err = B_FALSE; /* have we run into an error? */ 919 struct stat stbuf; 920 struct statvfs64 vfsbuf; 921 char rpath[MAXPATHLEN]; /* resolved path */ 922 char ppath[MAXPATHLEN]; /* parent path */ 923 char rppath[MAXPATHLEN]; /* resolved parent path */ 924 char rootpath[MAXPATHLEN]; /* root path */ 925 zone_state_t state; 926 927 if (path[0] != '/') { 928 (void) fprintf(stderr, 929 gettext("%s is not an absolute path.\n"), path); 930 return (Z_ERR); 931 } 932 if ((res = resolvepath(path, rpath, sizeof (rpath))) == -1) { 933 if ((errno != ENOENT) || 934 (cmd_num != CMD_VERIFY && cmd_num != CMD_INSTALL && 935 cmd_num != CMD_CLONE && cmd_num != CMD_MOVE)) { 936 zperror(path, B_FALSE); 937 return (Z_ERR); 938 } 939 if (cmd_num == CMD_VERIFY) { 940 /* 941 * TRANSLATION_NOTE 942 * zoneadm is a literal that should not be translated. 943 */ 944 (void) fprintf(stderr, gettext("WARNING: %s does not " 945 "exist, so it could not be verified.\nWhen " 946 "'zoneadm %s' is run, '%s' will try to create\n%s, " 947 "and '%s' will be tried again,\nbut the '%s' may " 948 "fail if:\nthe parent directory of %s is group- or " 949 "other-writable\nor\n%s overlaps with any other " 950 "installed zones.\n"), path, 951 cmd_to_str(CMD_INSTALL), cmd_to_str(CMD_INSTALL), 952 path, cmd_to_str(CMD_VERIFY), 953 cmd_to_str(CMD_VERIFY), path, path); 954 return (Z_OK); 955 } 956 /* 957 * The zonepath is supposed to be mode 700 but its 958 * parent(s) 755. So use 755 on the mkdirp() then 959 * chmod() the zonepath itself to 700. 960 */ 961 if (mkdirp(path, DEFAULT_DIR_MODE) < 0) { 962 zperror(path, B_FALSE); 963 return (Z_ERR); 964 } 965 /* 966 * If the chmod() fails, report the error, but might 967 * as well continue the verify procedure. 968 */ 969 if (chmod(path, S_IRWXU) != 0) 970 zperror(path, B_FALSE); 971 /* 972 * Since the mkdir() succeeded, we should not have to 973 * worry about a subsequent ENOENT, thus this should 974 * only recurse once. 975 */ 976 return (validate_zonepath(path, cmd_num)); 977 } 978 rpath[res] = '\0'; 979 if (strcmp(path, rpath) != 0) { 980 errno = Z_RESOLVED_PATH; 981 zperror(path, B_TRUE); 982 return (Z_ERR); 983 } 984 if ((res = stat(rpath, &stbuf)) != 0) { 985 zperror(rpath, B_FALSE); 986 return (Z_ERR); 987 } 988 if (!S_ISDIR(stbuf.st_mode)) { 989 (void) fprintf(stderr, gettext("%s is not a directory.\n"), 990 rpath); 991 return (Z_ERR); 992 } 993 if (strcmp(stbuf.st_fstype, MNTTYPE_TMPFS) == 0) { 994 (void) printf(gettext("WARNING: %s is on a temporary " 995 "file system.\n"), rpath); 996 } 997 if (crosscheck_zonepaths(rpath) != Z_OK) 998 return (Z_ERR); 999 /* 1000 * Try to collect and report as many minor errors as possible 1001 * before returning, so the user can learn everything that needs 1002 * to be fixed up front. 1003 */ 1004 if (stbuf.st_uid != 0) { 1005 (void) fprintf(stderr, gettext("%s is not owned by root.\n"), 1006 rpath); 1007 err = B_TRUE; 1008 } 1009 err |= bad_mode_bit(stbuf.st_mode, S_IRUSR, B_TRUE, rpath); 1010 err |= bad_mode_bit(stbuf.st_mode, S_IWUSR, B_TRUE, rpath); 1011 err |= bad_mode_bit(stbuf.st_mode, S_IXUSR, B_TRUE, rpath); 1012 err |= bad_mode_bit(stbuf.st_mode, S_IRGRP, B_FALSE, rpath); 1013 err |= bad_mode_bit(stbuf.st_mode, S_IWGRP, B_FALSE, rpath); 1014 err |= bad_mode_bit(stbuf.st_mode, S_IXGRP, B_FALSE, rpath); 1015 err |= bad_mode_bit(stbuf.st_mode, S_IROTH, B_FALSE, rpath); 1016 err |= bad_mode_bit(stbuf.st_mode, S_IWOTH, B_FALSE, rpath); 1017 err |= bad_mode_bit(stbuf.st_mode, S_IXOTH, B_FALSE, rpath); 1018 1019 (void) snprintf(ppath, sizeof (ppath), "%s/..", path); 1020 if ((res = resolvepath(ppath, rppath, sizeof (rppath))) == -1) { 1021 zperror(ppath, B_FALSE); 1022 return (Z_ERR); 1023 } 1024 rppath[res] = '\0'; 1025 if ((res = stat(rppath, &stbuf)) != 0) { 1026 zperror(rppath, B_FALSE); 1027 return (Z_ERR); 1028 } 1029 /* theoretically impossible */ 1030 if (!S_ISDIR(stbuf.st_mode)) { 1031 (void) fprintf(stderr, gettext("%s is not a directory.\n"), 1032 rppath); 1033 return (Z_ERR); 1034 } 1035 if (stbuf.st_uid != 0) { 1036 (void) fprintf(stderr, gettext("%s is not owned by root.\n"), 1037 rppath); 1038 err = B_TRUE; 1039 } 1040 err |= bad_mode_bit(stbuf.st_mode, S_IRUSR, B_TRUE, rppath); 1041 err |= bad_mode_bit(stbuf.st_mode, S_IWUSR, B_TRUE, rppath); 1042 err |= bad_mode_bit(stbuf.st_mode, S_IXUSR, B_TRUE, rppath); 1043 err |= bad_mode_bit(stbuf.st_mode, S_IWGRP, B_FALSE, rppath); 1044 err |= bad_mode_bit(stbuf.st_mode, S_IWOTH, B_FALSE, rppath); 1045 if (strcmp(rpath, rppath) == 0) { 1046 (void) fprintf(stderr, gettext("%s is its own parent.\n"), 1047 rppath); 1048 err = B_TRUE; 1049 } 1050 1051 if (statvfs64(rpath, &vfsbuf) != 0) { 1052 zperror(rpath, B_FALSE); 1053 return (Z_ERR); 1054 } 1055 if (strcmp(vfsbuf.f_basetype, MNTTYPE_NFS) == 0) { 1056 /* 1057 * TRANSLATION_NOTE 1058 * Zonepath and NFS are literals that should not be translated. 1059 */ 1060 (void) fprintf(stderr, gettext("Zonepath %s is on an NFS " 1061 "mounted file system.\n" 1062 "\tA local file system must be used.\n"), rpath); 1063 return (Z_ERR); 1064 } 1065 if (vfsbuf.f_flag & ST_NOSUID) { 1066 /* 1067 * TRANSLATION_NOTE 1068 * Zonepath and nosuid are literals that should not be 1069 * translated. 1070 */ 1071 (void) fprintf(stderr, gettext("Zonepath %s is on a nosuid " 1072 "file system.\n"), rpath); 1073 return (Z_ERR); 1074 } 1075 1076 if ((res = zone_get_state(target_zone, &state)) != Z_OK) { 1077 errno = res; 1078 zperror2(target_zone, gettext("could not get state")); 1079 return (Z_ERR); 1080 } 1081 /* 1082 * The existence of the root path is only bad in the configured state, 1083 * as it is *supposed* to be there at the installed and later states. 1084 * However, the root path is expected to be there if the zone is 1085 * detached. 1086 * State/command mismatches are caught earlier in verify_details(). 1087 */ 1088 if (state == ZONE_STATE_CONFIGURED && cmd_num != CMD_ATTACH) { 1089 if (snprintf(rootpath, sizeof (rootpath), "%s/root", rpath) >= 1090 sizeof (rootpath)) { 1091 /* 1092 * TRANSLATION_NOTE 1093 * Zonepath is a literal that should not be translated. 1094 */ 1095 (void) fprintf(stderr, 1096 gettext("Zonepath %s is too long.\n"), rpath); 1097 return (Z_ERR); 1098 } 1099 if ((res = stat(rootpath, &stbuf)) == 0) { 1100 if (zonecfg_detached(rpath)) { 1101 (void) fprintf(stderr, 1102 gettext("Cannot %s detached " 1103 "zone.\nUse attach or remove %s " 1104 "directory.\n"), cmd_to_str(cmd_num), 1105 rpath); 1106 return (Z_ERR); 1107 } 1108 1109 /* Not detached, check if it really looks ok. */ 1110 1111 if (!S_ISDIR(stbuf.st_mode)) { 1112 (void) fprintf(stderr, gettext("%s is not a " 1113 "directory.\n"), rootpath); 1114 return (Z_ERR); 1115 } 1116 1117 if (stbuf.st_uid != 0) { 1118 (void) fprintf(stderr, gettext("%s is not " 1119 "owned by root.\n"), rootpath); 1120 return (Z_ERR); 1121 } 1122 1123 if ((stbuf.st_mode & 0777) != 0755) { 1124 (void) fprintf(stderr, gettext("%s mode is not " 1125 "0755.\n"), rootpath); 1126 return (Z_ERR); 1127 } 1128 } 1129 } 1130 1131 return (err ? Z_ERR : Z_OK); 1132 } 1133 1134 static int 1135 invoke_brand_handler(int cmd_num, char *argv[]) 1136 { 1137 zone_dochandle_t handle; 1138 int err; 1139 1140 if ((handle = zonecfg_init_handle()) == NULL) { 1141 zperror(cmd_to_str(cmd_num), B_TRUE); 1142 return (Z_ERR); 1143 } 1144 if ((err = zonecfg_get_handle(target_zone, handle)) != Z_OK) { 1145 errno = err; 1146 zperror(cmd_to_str(cmd_num), B_TRUE); 1147 zonecfg_fini_handle(handle); 1148 return (Z_ERR); 1149 } 1150 if (verify_brand(handle, cmd_num, argv) != Z_OK) { 1151 zonecfg_fini_handle(handle); 1152 return (Z_ERR); 1153 } 1154 zonecfg_fini_handle(handle); 1155 return (Z_OK); 1156 } 1157 1158 static int 1159 ready_func(int argc, char *argv[]) 1160 { 1161 zone_cmd_arg_t zarg; 1162 int arg; 1163 1164 if (zonecfg_in_alt_root()) { 1165 zerror(gettext("cannot ready zone in alternate root")); 1166 return (Z_ERR); 1167 } 1168 1169 optind = 0; 1170 if ((arg = getopt(argc, argv, "?")) != EOF) { 1171 switch (arg) { 1172 case '?': 1173 sub_usage(SHELP_READY, CMD_READY); 1174 return (optopt == '?' ? Z_OK : Z_USAGE); 1175 default: 1176 sub_usage(SHELP_READY, CMD_READY); 1177 return (Z_USAGE); 1178 } 1179 } 1180 if (argc > optind) { 1181 sub_usage(SHELP_READY, CMD_READY); 1182 return (Z_USAGE); 1183 } 1184 if (sanity_check(target_zone, CMD_READY, B_FALSE, B_FALSE, B_FALSE) 1185 != Z_OK) 1186 return (Z_ERR); 1187 if (verify_details(CMD_READY, argv) != Z_OK) 1188 return (Z_ERR); 1189 1190 zarg.cmd = Z_READY; 1191 if (zonecfg_call_zoneadmd(target_zone, &zarg, locale, B_TRUE) != 0) { 1192 zerror(gettext("call to %s failed"), "zoneadmd"); 1193 return (Z_ERR); 1194 } 1195 return (Z_OK); 1196 } 1197 1198 static int 1199 boot_func(int argc, char *argv[]) 1200 { 1201 zone_cmd_arg_t zarg; 1202 boolean_t force = B_FALSE; 1203 int arg; 1204 1205 if (zonecfg_in_alt_root()) { 1206 zerror(gettext("cannot boot zone in alternate root")); 1207 return (Z_ERR); 1208 } 1209 1210 zarg.bootbuf[0] = '\0'; 1211 1212 /* 1213 * The following getopt processes arguments to zone boot; that 1214 * is to say, the [here] portion of the argument string: 1215 * 1216 * zoneadm -z myzone boot [here] -- -v -m verbose 1217 * 1218 * Where [here] can either be nothing, -? (in which case we bail 1219 * and print usage), -f (a private option to indicate that the 1220 * boot operation should be 'forced'), or -s. Support for -s is 1221 * vestigal and obsolete, but is retained because it was a 1222 * documented interface and there are known consumers including 1223 * admin/install; the proper way to specify boot arguments like -s 1224 * is: 1225 * 1226 * zoneadm -z myzone boot -- -s -v -m verbose. 1227 */ 1228 optind = 0; 1229 while ((arg = getopt(argc, argv, "?fs")) != EOF) { 1230 switch (arg) { 1231 case '?': 1232 sub_usage(SHELP_BOOT, CMD_BOOT); 1233 return (optopt == '?' ? Z_OK : Z_USAGE); 1234 case 's': 1235 (void) strlcpy(zarg.bootbuf, "-s", 1236 sizeof (zarg.bootbuf)); 1237 break; 1238 case 'f': 1239 force = B_TRUE; 1240 break; 1241 default: 1242 sub_usage(SHELP_BOOT, CMD_BOOT); 1243 return (Z_USAGE); 1244 } 1245 } 1246 1247 for (; optind < argc; optind++) { 1248 if (strlcat(zarg.bootbuf, argv[optind], 1249 sizeof (zarg.bootbuf)) >= sizeof (zarg.bootbuf)) { 1250 zerror(gettext("Boot argument list too long")); 1251 return (Z_ERR); 1252 } 1253 if (optind < argc - 1) 1254 if (strlcat(zarg.bootbuf, " ", sizeof (zarg.bootbuf)) >= 1255 sizeof (zarg.bootbuf)) { 1256 zerror(gettext("Boot argument list too long")); 1257 return (Z_ERR); 1258 } 1259 } 1260 if (sanity_check(target_zone, CMD_BOOT, B_FALSE, B_FALSE, force) 1261 != Z_OK) 1262 return (Z_ERR); 1263 if (verify_details(CMD_BOOT, argv) != Z_OK) 1264 return (Z_ERR); 1265 zarg.cmd = force ? Z_FORCEBOOT : Z_BOOT; 1266 if (zonecfg_call_zoneadmd(target_zone, &zarg, locale, B_TRUE) != 0) { 1267 zerror(gettext("call to %s failed"), "zoneadmd"); 1268 return (Z_ERR); 1269 } 1270 1271 return (Z_OK); 1272 } 1273 1274 static void 1275 fake_up_local_zone(zoneid_t zid, zone_entry_t *zeptr) 1276 { 1277 ssize_t result; 1278 uuid_t uuid; 1279 FILE *fp; 1280 ushort_t flags; 1281 1282 (void) memset(zeptr, 0, sizeof (*zeptr)); 1283 1284 zeptr->zid = zid; 1285 1286 /* 1287 * Since we're looking up our own (non-global) zone name, 1288 * we can be assured that it will succeed. 1289 */ 1290 result = getzonenamebyid(zid, zeptr->zname, sizeof (zeptr->zname)); 1291 assert(result >= 0); 1292 if (zonecfg_is_scratch(zeptr->zname) && 1293 (fp = zonecfg_open_scratch("", B_FALSE)) != NULL) { 1294 (void) zonecfg_reverse_scratch(fp, zeptr->zname, zeptr->zname, 1295 sizeof (zeptr->zname), NULL, 0); 1296 zonecfg_close_scratch(fp); 1297 } 1298 1299 if (is_system_labeled()) { 1300 (void) zone_getattr(zid, ZONE_ATTR_ROOT, zeptr->zroot, 1301 sizeof (zeptr->zroot)); 1302 (void) strlcpy(zeptr->zbrand, NATIVE_BRAND_NAME, 1303 sizeof (zeptr->zbrand)); 1304 } else { 1305 (void) strlcpy(zeptr->zroot, "/", sizeof (zeptr->zroot)); 1306 (void) zone_getattr(zid, ZONE_ATTR_BRAND, zeptr->zbrand, 1307 sizeof (zeptr->zbrand)); 1308 } 1309 1310 zeptr->zstate_str = "running"; 1311 if (zonecfg_get_uuid(zeptr->zname, uuid) == Z_OK && 1312 !uuid_is_null(uuid)) 1313 uuid_unparse(uuid, zeptr->zuuid); 1314 1315 if (zone_getattr(zid, ZONE_ATTR_FLAGS, &flags, sizeof (flags)) < 0) { 1316 zperror2(zeptr->zname, gettext("could not get zone flags")); 1317 exit(Z_ERR); 1318 } 1319 if (flags & ZF_NET_EXCL) 1320 zeptr->ziptype = ZS_EXCLUSIVE; 1321 else 1322 zeptr->ziptype = ZS_SHARED; 1323 } 1324 1325 static int 1326 list_func(int argc, char *argv[]) 1327 { 1328 zone_entry_t *zentp, zent; 1329 int arg, retv; 1330 boolean_t output = B_FALSE, verbose = B_FALSE, parsable = B_FALSE; 1331 zone_state_t min_state = ZONE_STATE_RUNNING; 1332 zoneid_t zone_id = getzoneid(); 1333 1334 if (target_zone == NULL) { 1335 /* all zones: default view to running but allow override */ 1336 optind = 0; 1337 while ((arg = getopt(argc, argv, "?cipv")) != EOF) { 1338 switch (arg) { 1339 case '?': 1340 sub_usage(SHELP_LIST, CMD_LIST); 1341 return (optopt == '?' ? Z_OK : Z_USAGE); 1342 /* 1343 * The 'i' and 'c' options are not mutually 1344 * exclusive so if 'c' is given, then min_state 1345 * is set to 0 (ZONE_STATE_CONFIGURED) which is 1346 * the lowest possible state. If 'i' is given, 1347 * then min_state is set to be the lowest state 1348 * so far. 1349 */ 1350 case 'c': 1351 min_state = ZONE_STATE_CONFIGURED; 1352 break; 1353 case 'i': 1354 min_state = min(ZONE_STATE_INSTALLED, 1355 min_state); 1356 1357 break; 1358 case 'p': 1359 parsable = B_TRUE; 1360 break; 1361 case 'v': 1362 verbose = B_TRUE; 1363 break; 1364 default: 1365 sub_usage(SHELP_LIST, CMD_LIST); 1366 return (Z_USAGE); 1367 } 1368 } 1369 if (parsable && verbose) { 1370 zerror(gettext("%s -p and -v are mutually exclusive."), 1371 cmd_to_str(CMD_LIST)); 1372 return (Z_ERR); 1373 } 1374 if (zone_id == GLOBAL_ZONEID || is_system_labeled()) { 1375 retv = zone_print_list(min_state, verbose, parsable); 1376 } else { 1377 fake_up_local_zone(zone_id, &zent); 1378 retv = Z_OK; 1379 zone_print(&zent, verbose, parsable); 1380 } 1381 return (retv); 1382 } 1383 1384 /* 1385 * Specific target zone: disallow -i/-c suboptions. 1386 */ 1387 optind = 0; 1388 while ((arg = getopt(argc, argv, "?pv")) != EOF) { 1389 switch (arg) { 1390 case '?': 1391 sub_usage(SHELP_LIST, CMD_LIST); 1392 return (optopt == '?' ? Z_OK : Z_USAGE); 1393 case 'p': 1394 parsable = B_TRUE; 1395 break; 1396 case 'v': 1397 verbose = B_TRUE; 1398 break; 1399 default: 1400 sub_usage(SHELP_LIST, CMD_LIST); 1401 return (Z_USAGE); 1402 } 1403 } 1404 if (parsable && verbose) { 1405 zerror(gettext("%s -p and -v are mutually exclusive."), 1406 cmd_to_str(CMD_LIST)); 1407 return (Z_ERR); 1408 } 1409 if (argc > optind) { 1410 sub_usage(SHELP_LIST, CMD_LIST); 1411 return (Z_USAGE); 1412 } 1413 if (zone_id != GLOBAL_ZONEID && !is_system_labeled()) { 1414 fake_up_local_zone(zone_id, &zent); 1415 /* 1416 * main() will issue a Z_NO_ZONE error if it cannot get an 1417 * id for target_zone, which in a non-global zone should 1418 * happen for any zone name except `zonename`. Thus we 1419 * assert() that here but don't otherwise check. 1420 */ 1421 assert(strcmp(zent.zname, target_zone) == 0); 1422 zone_print(&zent, verbose, parsable); 1423 output = B_TRUE; 1424 } else if ((zentp = lookup_running_zone(target_zone)) != NULL) { 1425 zone_print(zentp, verbose, parsable); 1426 output = B_TRUE; 1427 } else if (lookup_zone_info(target_zone, ZONE_ID_UNDEFINED, 1428 &zent) == Z_OK) { 1429 zone_print(&zent, verbose, parsable); 1430 output = B_TRUE; 1431 } 1432 1433 /* 1434 * Invoke brand-specific handler. Note that we do this 1435 * only if we're in the global zone, and target_zone is specified 1436 * and it is not the global zone. 1437 */ 1438 if (zone_id == GLOBAL_ZONEID && target_zone != NULL && 1439 strcmp(target_zone, GLOBAL_ZONENAME) != 0) 1440 if (invoke_brand_handler(CMD_LIST, argv) != Z_OK) 1441 return (Z_ERR); 1442 1443 return (output ? Z_OK : Z_ERR); 1444 } 1445 1446 int 1447 do_subproc(char *cmdbuf) 1448 { 1449 void (*saveint)(int); 1450 void (*saveterm)(int); 1451 void (*savequit)(int); 1452 void (*savehup)(int); 1453 int pid, child, status; 1454 1455 if ((child = vfork()) == 0) { 1456 (void) execl("/bin/sh", "sh", "-c", cmdbuf, (char *)NULL); 1457 } 1458 1459 if (child == -1) 1460 return (-1); 1461 1462 saveint = sigset(SIGINT, SIG_IGN); 1463 saveterm = sigset(SIGTERM, SIG_IGN); 1464 savequit = sigset(SIGQUIT, SIG_IGN); 1465 savehup = sigset(SIGHUP, SIG_IGN); 1466 1467 while ((pid = waitpid(child, &status, 0)) != child && pid != -1) 1468 ; 1469 1470 (void) sigset(SIGINT, saveint); 1471 (void) sigset(SIGTERM, saveterm); 1472 (void) sigset(SIGQUIT, savequit); 1473 (void) sigset(SIGHUP, savehup); 1474 1475 return (pid == -1 ? -1 : status); 1476 } 1477 1478 int 1479 subproc_status(const char *cmd, int status, boolean_t verbose_failure) 1480 { 1481 if (WIFEXITED(status)) { 1482 int exit_code = WEXITSTATUS(status); 1483 1484 if ((verbose_failure) && (exit_code != ZONE_SUBPROC_OK)) 1485 zerror(gettext("'%s' failed with exit code %d."), cmd, 1486 exit_code); 1487 1488 return (exit_code); 1489 } else if (WIFSIGNALED(status)) { 1490 int signal = WTERMSIG(status); 1491 char sigstr[SIG2STR_MAX]; 1492 1493 if (sig2str(signal, sigstr) == 0) { 1494 zerror(gettext("'%s' terminated by signal SIG%s."), cmd, 1495 sigstr); 1496 } else { 1497 zerror(gettext("'%s' terminated by an unknown signal."), 1498 cmd); 1499 } 1500 } else { 1501 zerror(gettext("'%s' failed for unknown reasons."), cmd); 1502 } 1503 1504 /* 1505 * Assume a subprocess that died due to a signal or an unknown error 1506 * should be considered an exit code of ZONE_SUBPROC_FATAL, as the 1507 * user will likely need to do some manual cleanup. 1508 */ 1509 return (ZONE_SUBPROC_FATAL); 1510 } 1511 1512 /* 1513 * Various sanity checks; make sure: 1514 * 1. We're in the global zone. 1515 * 2. The calling user has sufficient privilege. 1516 * 3. The target zone is neither the global zone nor anything starting with 1517 * "SUNW". 1518 * 4a. If we're looking for a 'not running' (i.e., configured or installed) 1519 * zone, the name service knows about it. 1520 * 4b. For some operations which expect a zone not to be running, that it is 1521 * not already running (or ready). 1522 */ 1523 static int 1524 sanity_check(char *zone, int cmd_num, boolean_t running, 1525 boolean_t unsafe_when_running, boolean_t force) 1526 { 1527 zone_entry_t *zent; 1528 priv_set_t *privset; 1529 zone_state_t state, min_state; 1530 char kernzone[ZONENAME_MAX]; 1531 FILE *fp; 1532 1533 if (getzoneid() != GLOBAL_ZONEID) { 1534 switch (cmd_num) { 1535 case CMD_HALT: 1536 zerror(gettext("use %s to %s this zone."), "halt(1M)", 1537 cmd_to_str(cmd_num)); 1538 break; 1539 case CMD_REBOOT: 1540 zerror(gettext("use %s to %s this zone."), 1541 "reboot(1M)", cmd_to_str(cmd_num)); 1542 break; 1543 default: 1544 zerror(gettext("must be in the global zone to %s a " 1545 "zone."), cmd_to_str(cmd_num)); 1546 break; 1547 } 1548 return (Z_ERR); 1549 } 1550 1551 if ((privset = priv_allocset()) == NULL) { 1552 zerror(gettext("%s failed"), "priv_allocset"); 1553 return (Z_ERR); 1554 } 1555 1556 if (getppriv(PRIV_EFFECTIVE, privset) != 0) { 1557 zerror(gettext("%s failed"), "getppriv"); 1558 priv_freeset(privset); 1559 return (Z_ERR); 1560 } 1561 1562 if (priv_isfullset(privset) == B_FALSE) { 1563 zerror(gettext("only a privileged user may %s a zone."), 1564 cmd_to_str(cmd_num)); 1565 priv_freeset(privset); 1566 return (Z_ERR); 1567 } 1568 priv_freeset(privset); 1569 1570 if (zone == NULL) { 1571 zerror(gettext("no zone specified")); 1572 return (Z_ERR); 1573 } 1574 1575 if (strcmp(zone, GLOBAL_ZONENAME) == 0) { 1576 zerror(gettext("%s operation is invalid for the global zone."), 1577 cmd_to_str(cmd_num)); 1578 return (Z_ERR); 1579 } 1580 1581 if (strncmp(zone, "SUNW", 4) == 0) { 1582 zerror(gettext("%s operation is invalid for zones starting " 1583 "with SUNW."), cmd_to_str(cmd_num)); 1584 return (Z_ERR); 1585 } 1586 1587 if (!zonecfg_in_alt_root()) { 1588 zent = lookup_running_zone(zone); 1589 } else if ((fp = zonecfg_open_scratch("", B_FALSE)) == NULL) { 1590 zent = NULL; 1591 } else { 1592 if (zonecfg_find_scratch(fp, zone, zonecfg_get_root(), 1593 kernzone, sizeof (kernzone)) == 0) 1594 zent = lookup_running_zone(kernzone); 1595 else 1596 zent = NULL; 1597 zonecfg_close_scratch(fp); 1598 } 1599 1600 /* 1601 * Look up from the kernel for 'running' zones. 1602 */ 1603 if (running && !force) { 1604 if (zent == NULL) { 1605 zerror(gettext("not running")); 1606 return (Z_ERR); 1607 } 1608 } else { 1609 int err; 1610 1611 if (unsafe_when_running && zent != NULL) { 1612 /* check whether the zone is ready or running */ 1613 if ((err = zone_get_state(zent->zname, 1614 &zent->zstate_num)) != Z_OK) { 1615 errno = err; 1616 zperror2(zent->zname, 1617 gettext("could not get state")); 1618 /* can't tell, so hedge */ 1619 zent->zstate_str = "ready/running"; 1620 } else { 1621 zent->zstate_str = 1622 zone_state_str(zent->zstate_num); 1623 } 1624 zerror(gettext("%s operation is invalid for %s zones."), 1625 cmd_to_str(cmd_num), zent->zstate_str); 1626 return (Z_ERR); 1627 } 1628 if ((err = zone_get_state(zone, &state)) != Z_OK) { 1629 errno = err; 1630 zperror2(zone, gettext("could not get state")); 1631 return (Z_ERR); 1632 } 1633 switch (cmd_num) { 1634 case CMD_UNINSTALL: 1635 if (state == ZONE_STATE_CONFIGURED) { 1636 zerror(gettext("is already in state '%s'."), 1637 zone_state_str(ZONE_STATE_CONFIGURED)); 1638 return (Z_ERR); 1639 } 1640 break; 1641 case CMD_ATTACH: 1642 if (state == ZONE_STATE_INSTALLED) { 1643 zerror(gettext("is already %s."), 1644 zone_state_str(ZONE_STATE_INSTALLED)); 1645 return (Z_ERR); 1646 } else if (state == ZONE_STATE_INCOMPLETE && !force) { 1647 zerror(gettext("zone is %s; %s required."), 1648 zone_state_str(ZONE_STATE_INCOMPLETE), 1649 cmd_to_str(CMD_UNINSTALL)); 1650 return (Z_ERR); 1651 } 1652 break; 1653 case CMD_CLONE: 1654 case CMD_INSTALL: 1655 if (state == ZONE_STATE_INSTALLED) { 1656 zerror(gettext("is already %s."), 1657 zone_state_str(ZONE_STATE_INSTALLED)); 1658 return (Z_ERR); 1659 } else if (state == ZONE_STATE_INCOMPLETE) { 1660 zerror(gettext("zone is %s; %s required."), 1661 zone_state_str(ZONE_STATE_INCOMPLETE), 1662 cmd_to_str(CMD_UNINSTALL)); 1663 return (Z_ERR); 1664 } 1665 break; 1666 case CMD_DETACH: 1667 case CMD_MOVE: 1668 case CMD_READY: 1669 case CMD_BOOT: 1670 case CMD_MOUNT: 1671 case CMD_MARK: 1672 if ((cmd_num == CMD_BOOT || cmd_num == CMD_MOUNT) && 1673 force) 1674 min_state = ZONE_STATE_INCOMPLETE; 1675 else if (cmd_num == CMD_MARK) 1676 min_state = ZONE_STATE_CONFIGURED; 1677 else 1678 min_state = ZONE_STATE_INSTALLED; 1679 1680 if (state < min_state) { 1681 zerror(gettext("must be %s before %s."), 1682 zone_state_str(min_state), 1683 cmd_to_str(cmd_num)); 1684 return (Z_ERR); 1685 } 1686 break; 1687 case CMD_VERIFY: 1688 if (state == ZONE_STATE_INCOMPLETE) { 1689 zerror(gettext("zone is %s; %s required."), 1690 zone_state_str(ZONE_STATE_INCOMPLETE), 1691 cmd_to_str(CMD_UNINSTALL)); 1692 return (Z_ERR); 1693 } 1694 break; 1695 case CMD_UNMOUNT: 1696 if (state != ZONE_STATE_MOUNTED) { 1697 zerror(gettext("must be %s before %s."), 1698 zone_state_str(ZONE_STATE_MOUNTED), 1699 cmd_to_str(cmd_num)); 1700 return (Z_ERR); 1701 } 1702 break; 1703 case CMD_SYSBOOT: 1704 if (state != ZONE_STATE_INSTALLED) { 1705 zerror(gettext("%s operation is invalid for %s " 1706 "zones."), cmd_to_str(cmd_num), 1707 zone_state_str(state)); 1708 return (Z_ERR); 1709 } 1710 break; 1711 } 1712 } 1713 return (Z_OK); 1714 } 1715 1716 static int 1717 halt_func(int argc, char *argv[]) 1718 { 1719 zone_cmd_arg_t zarg; 1720 int arg; 1721 1722 if (zonecfg_in_alt_root()) { 1723 zerror(gettext("cannot halt zone in alternate root")); 1724 return (Z_ERR); 1725 } 1726 1727 optind = 0; 1728 if ((arg = getopt(argc, argv, "?")) != EOF) { 1729 switch (arg) { 1730 case '?': 1731 sub_usage(SHELP_HALT, CMD_HALT); 1732 return (optopt == '?' ? Z_OK : Z_USAGE); 1733 default: 1734 sub_usage(SHELP_HALT, CMD_HALT); 1735 return (Z_USAGE); 1736 } 1737 } 1738 if (argc > optind) { 1739 sub_usage(SHELP_HALT, CMD_HALT); 1740 return (Z_USAGE); 1741 } 1742 /* 1743 * zoneadmd should be the one to decide whether or not to proceed, 1744 * so even though it seems that the fourth parameter below should 1745 * perhaps be B_TRUE, it really shouldn't be. 1746 */ 1747 if (sanity_check(target_zone, CMD_HALT, B_FALSE, B_FALSE, B_FALSE) 1748 != Z_OK) 1749 return (Z_ERR); 1750 1751 /* 1752 * Invoke brand-specific handler. 1753 */ 1754 if (invoke_brand_handler(CMD_HALT, argv) != Z_OK) 1755 return (Z_ERR); 1756 1757 zarg.cmd = Z_HALT; 1758 return ((zonecfg_call_zoneadmd(target_zone, &zarg, locale, 1759 B_TRUE) == 0) ? Z_OK : Z_ERR); 1760 } 1761 1762 static int 1763 reboot_func(int argc, char *argv[]) 1764 { 1765 zone_cmd_arg_t zarg; 1766 int arg; 1767 1768 if (zonecfg_in_alt_root()) { 1769 zerror(gettext("cannot reboot zone in alternate root")); 1770 return (Z_ERR); 1771 } 1772 1773 optind = 0; 1774 if ((arg = getopt(argc, argv, "?")) != EOF) { 1775 switch (arg) { 1776 case '?': 1777 sub_usage(SHELP_REBOOT, CMD_REBOOT); 1778 return (optopt == '?' ? Z_OK : Z_USAGE); 1779 default: 1780 sub_usage(SHELP_REBOOT, CMD_REBOOT); 1781 return (Z_USAGE); 1782 } 1783 } 1784 1785 zarg.bootbuf[0] = '\0'; 1786 for (; optind < argc; optind++) { 1787 if (strlcat(zarg.bootbuf, argv[optind], 1788 sizeof (zarg.bootbuf)) >= sizeof (zarg.bootbuf)) { 1789 zerror(gettext("Boot argument list too long")); 1790 return (Z_ERR); 1791 } 1792 if (optind < argc - 1) 1793 if (strlcat(zarg.bootbuf, " ", sizeof (zarg.bootbuf)) >= 1794 sizeof (zarg.bootbuf)) { 1795 zerror(gettext("Boot argument list too long")); 1796 return (Z_ERR); 1797 } 1798 } 1799 1800 1801 /* 1802 * zoneadmd should be the one to decide whether or not to proceed, 1803 * so even though it seems that the fourth parameter below should 1804 * perhaps be B_TRUE, it really shouldn't be. 1805 */ 1806 if (sanity_check(target_zone, CMD_REBOOT, B_TRUE, B_FALSE, B_FALSE) 1807 != Z_OK) 1808 return (Z_ERR); 1809 if (verify_details(CMD_REBOOT, argv) != Z_OK) 1810 return (Z_ERR); 1811 1812 zarg.cmd = Z_REBOOT; 1813 return ((zonecfg_call_zoneadmd(target_zone, &zarg, locale, B_TRUE) == 0) 1814 ? Z_OK : Z_ERR); 1815 } 1816 1817 static int 1818 get_hook(brand_handle_t bh, char *cmd, size_t len, int (*bp)(brand_handle_t, 1819 const char *, const char *, char *, size_t), char *zonename, char *zonepath) 1820 { 1821 if (strlcpy(cmd, EXEC_PREFIX, len) >= len) 1822 return (Z_ERR); 1823 1824 if (bp(bh, zonename, zonepath, cmd + EXEC_LEN, len - EXEC_LEN) != 0) 1825 return (Z_ERR); 1826 1827 if (strlen(cmd) <= EXEC_LEN) 1828 cmd[0] = '\0'; 1829 1830 return (Z_OK); 1831 } 1832 1833 static int 1834 verify_brand(zone_dochandle_t handle, int cmd_num, char *argv[]) 1835 { 1836 char cmdbuf[MAXPATHLEN]; 1837 int err; 1838 char zonepath[MAXPATHLEN]; 1839 brand_handle_t bh = NULL; 1840 int status, i; 1841 1842 /* 1843 * Fetch the verify command from the brand configuration. 1844 * "exec" the command so that the returned status is that of 1845 * the command and not the shell. 1846 */ 1847 if (handle == NULL) { 1848 (void) strlcpy(zonepath, "-", sizeof (zonepath)); 1849 } else if ((err = zonecfg_get_zonepath(handle, zonepath, 1850 sizeof (zonepath))) != Z_OK) { 1851 errno = err; 1852 zperror(cmd_to_str(cmd_num), B_TRUE); 1853 return (Z_ERR); 1854 } 1855 if ((bh = brand_open(target_brand)) == NULL) { 1856 zerror(gettext("missing or invalid brand")); 1857 return (Z_ERR); 1858 } 1859 1860 /* 1861 * If the brand has its own verification routine, execute it now. 1862 * The verification routine validates the intended zoneadm 1863 * operation for the specific brand. The zoneadm subcommand and 1864 * all its arguments are passed to the routine. 1865 */ 1866 err = get_hook(bh, cmdbuf, sizeof (cmdbuf), brand_get_verify_adm, 1867 target_zone, zonepath); 1868 brand_close(bh); 1869 if (err != Z_OK) 1870 return (Z_BRAND_ERROR); 1871 if (cmdbuf[0] == '\0') 1872 return (Z_OK); 1873 1874 if (strlcat(cmdbuf, cmd_to_str(cmd_num), 1875 sizeof (cmdbuf)) >= sizeof (cmdbuf)) 1876 return (Z_ERR); 1877 1878 /* Build the argv string */ 1879 i = 0; 1880 while (argv[i] != NULL) { 1881 if ((strlcat(cmdbuf, " ", 1882 sizeof (cmdbuf)) >= sizeof (cmdbuf)) || 1883 (strlcat(cmdbuf, argv[i++], 1884 sizeof (cmdbuf)) >= sizeof (cmdbuf))) 1885 return (Z_ERR); 1886 } 1887 1888 status = do_subproc(cmdbuf); 1889 err = subproc_status(gettext("brand-specific verification"), 1890 status, B_FALSE); 1891 1892 return ((err == ZONE_SUBPROC_OK) ? Z_OK : Z_BRAND_ERROR); 1893 } 1894 1895 static int 1896 verify_rctls(zone_dochandle_t handle) 1897 { 1898 struct zone_rctltab rctltab; 1899 size_t rbs = rctlblk_size(); 1900 rctlblk_t *rctlblk; 1901 int error = Z_INVAL; 1902 1903 if ((rctlblk = malloc(rbs)) == NULL) { 1904 zerror(gettext("failed to allocate %lu bytes: %s"), rbs, 1905 strerror(errno)); 1906 return (Z_NOMEM); 1907 } 1908 1909 if (zonecfg_setrctlent(handle) != Z_OK) { 1910 zerror(gettext("zonecfg_setrctlent failed")); 1911 free(rctlblk); 1912 return (error); 1913 } 1914 1915 rctltab.zone_rctl_valptr = NULL; 1916 while (zonecfg_getrctlent(handle, &rctltab) == Z_OK) { 1917 struct zone_rctlvaltab *rctlval; 1918 const char *name = rctltab.zone_rctl_name; 1919 1920 if (!zonecfg_is_rctl(name)) { 1921 zerror(gettext("WARNING: Ignoring unrecognized rctl " 1922 "'%s'."), name); 1923 zonecfg_free_rctl_value_list(rctltab.zone_rctl_valptr); 1924 rctltab.zone_rctl_valptr = NULL; 1925 continue; 1926 } 1927 1928 for (rctlval = rctltab.zone_rctl_valptr; rctlval != NULL; 1929 rctlval = rctlval->zone_rctlval_next) { 1930 if (zonecfg_construct_rctlblk(rctlval, rctlblk) 1931 != Z_OK) { 1932 zerror(gettext("invalid rctl value: " 1933 "(priv=%s,limit=%s,action%s)"), 1934 rctlval->zone_rctlval_priv, 1935 rctlval->zone_rctlval_limit, 1936 rctlval->zone_rctlval_action); 1937 goto out; 1938 } 1939 if (!zonecfg_valid_rctl(name, rctlblk)) { 1940 zerror(gettext("(priv=%s,limit=%s,action=%s) " 1941 "is not a valid value for rctl '%s'"), 1942 rctlval->zone_rctlval_priv, 1943 rctlval->zone_rctlval_limit, 1944 rctlval->zone_rctlval_action, 1945 name); 1946 goto out; 1947 } 1948 } 1949 zonecfg_free_rctl_value_list(rctltab.zone_rctl_valptr); 1950 } 1951 rctltab.zone_rctl_valptr = NULL; 1952 error = Z_OK; 1953 out: 1954 zonecfg_free_rctl_value_list(rctltab.zone_rctl_valptr); 1955 (void) zonecfg_endrctlent(handle); 1956 free(rctlblk); 1957 return (error); 1958 } 1959 1960 static int 1961 verify_pool(zone_dochandle_t handle) 1962 { 1963 char poolname[MAXPATHLEN]; 1964 pool_conf_t *poolconf; 1965 pool_t *pool; 1966 int status; 1967 int error; 1968 1969 /* 1970 * This ends up being very similar to the check done in zoneadmd. 1971 */ 1972 error = zonecfg_get_pool(handle, poolname, sizeof (poolname)); 1973 if (error == Z_NO_ENTRY || (error == Z_OK && strlen(poolname) == 0)) { 1974 /* 1975 * No pool specified. 1976 */ 1977 return (0); 1978 } 1979 if (error != Z_OK) { 1980 zperror(gettext("Unable to retrieve pool name from " 1981 "configuration"), B_TRUE); 1982 return (error); 1983 } 1984 /* 1985 * Don't do anything if pools aren't enabled. 1986 */ 1987 if (pool_get_status(&status) != PO_SUCCESS || status != POOL_ENABLED) { 1988 zerror(gettext("WARNING: pools facility not active; " 1989 "zone will not be bound to pool '%s'."), poolname); 1990 return (Z_OK); 1991 } 1992 /* 1993 * Try to provide a sane error message if the requested pool doesn't 1994 * exist. It isn't clear that pools-related failures should 1995 * necessarily translate to a failure to verify the zone configuration, 1996 * hence they are not considered errors. 1997 */ 1998 if ((poolconf = pool_conf_alloc()) == NULL) { 1999 zerror(gettext("WARNING: pool_conf_alloc failed; " 2000 "using default pool")); 2001 return (Z_OK); 2002 } 2003 if (pool_conf_open(poolconf, pool_dynamic_location(), PO_RDONLY) != 2004 PO_SUCCESS) { 2005 zerror(gettext("WARNING: pool_conf_open failed; " 2006 "using default pool")); 2007 pool_conf_free(poolconf); 2008 return (Z_OK); 2009 } 2010 pool = pool_get_pool(poolconf, poolname); 2011 (void) pool_conf_close(poolconf); 2012 pool_conf_free(poolconf); 2013 if (pool == NULL) { 2014 zerror(gettext("WARNING: pool '%s' not found. " 2015 "using default pool"), poolname); 2016 } 2017 2018 return (Z_OK); 2019 } 2020 2021 static int 2022 verify_ipd(zone_dochandle_t handle) 2023 { 2024 int return_code = Z_OK; 2025 struct zone_fstab fstab; 2026 struct stat st; 2027 char specdir[MAXPATHLEN]; 2028 2029 if (zonecfg_setipdent(handle) != Z_OK) { 2030 /* 2031 * TRANSLATION_NOTE 2032 * inherit-pkg-dirs is a literal that should not be translated. 2033 */ 2034 (void) fprintf(stderr, gettext("could not verify " 2035 "inherit-pkg-dirs: unable to enumerate mounts\n")); 2036 return (Z_ERR); 2037 } 2038 while (zonecfg_getipdent(handle, &fstab) == Z_OK) { 2039 /* 2040 * Verify fs_dir exists. 2041 */ 2042 (void) snprintf(specdir, sizeof (specdir), "%s%s", 2043 zonecfg_get_root(), fstab.zone_fs_dir); 2044 if (stat(specdir, &st) != 0) { 2045 /* 2046 * TRANSLATION_NOTE 2047 * inherit-pkg-dir is a literal that should not be 2048 * translated. 2049 */ 2050 (void) fprintf(stderr, gettext("could not verify " 2051 "inherit-pkg-dir %s: %s\n"), 2052 fstab.zone_fs_dir, strerror(errno)); 2053 return_code = Z_ERR; 2054 } 2055 if (strcmp(st.st_fstype, MNTTYPE_NFS) == 0) { 2056 /* 2057 * TRANSLATION_NOTE 2058 * inherit-pkg-dir and NFS are literals that should 2059 * not be translated. 2060 */ 2061 (void) fprintf(stderr, gettext("cannot verify " 2062 "inherit-pkg-dir %s: NFS mounted file system.\n" 2063 "\tA local file system must be used.\n"), 2064 fstab.zone_fs_dir); 2065 return_code = Z_ERR; 2066 } 2067 } 2068 (void) zonecfg_endipdent(handle); 2069 2070 return (return_code); 2071 } 2072 2073 /* 2074 * Verify that the special device/file system exists and is valid. 2075 */ 2076 static int 2077 verify_fs_special(struct zone_fstab *fstab) 2078 { 2079 struct stat64 st; 2080 2081 /* 2082 * This validation is really intended for standard zone administration. 2083 * If we are in a mini-root or some other upgrade situation where 2084 * we are using the scratch zone, just by-pass this. 2085 */ 2086 if (zonecfg_in_alt_root()) 2087 return (Z_OK); 2088 2089 if (strcmp(fstab->zone_fs_type, MNTTYPE_ZFS) == 0) 2090 return (verify_fs_zfs(fstab)); 2091 2092 if (stat64(fstab->zone_fs_special, &st) != 0) { 2093 (void) fprintf(stderr, gettext("could not verify fs " 2094 "%s: could not access %s: %s\n"), fstab->zone_fs_dir, 2095 fstab->zone_fs_special, strerror(errno)); 2096 return (Z_ERR); 2097 } 2098 2099 if (strcmp(st.st_fstype, MNTTYPE_NFS) == 0) { 2100 /* 2101 * TRANSLATION_NOTE 2102 * fs and NFS are literals that should 2103 * not be translated. 2104 */ 2105 (void) fprintf(stderr, gettext("cannot verify " 2106 "fs %s: NFS mounted file system.\n" 2107 "\tA local file system must be used.\n"), 2108 fstab->zone_fs_special); 2109 return (Z_ERR); 2110 } 2111 2112 return (Z_OK); 2113 } 2114 2115 static int 2116 isregfile(const char *path) 2117 { 2118 struct stat64 st; 2119 2120 if (stat64(path, &st) == -1) 2121 return (-1); 2122 2123 return (S_ISREG(st.st_mode)); 2124 } 2125 2126 static int 2127 verify_filesystems(zone_dochandle_t handle) 2128 { 2129 int return_code = Z_OK; 2130 struct zone_fstab fstab; 2131 char cmdbuf[MAXPATHLEN]; 2132 struct stat st; 2133 2134 /* 2135 * No need to verify inherit-pkg-dir fs types, as their type is 2136 * implicitly lofs, which is known. Therefore, the types are only 2137 * verified for regular file systems below. 2138 * 2139 * Since the actual mount point is not known until the dependent mounts 2140 * are performed, we don't attempt any path validation here: that will 2141 * happen later when zoneadmd actually does the mounts. 2142 */ 2143 if (zonecfg_setfsent(handle) != Z_OK) { 2144 (void) fprintf(stderr, gettext("could not verify file systems: " 2145 "unable to enumerate mounts\n")); 2146 return (Z_ERR); 2147 } 2148 while (zonecfg_getfsent(handle, &fstab) == Z_OK) { 2149 if (!zonecfg_valid_fs_type(fstab.zone_fs_type)) { 2150 (void) fprintf(stderr, gettext("cannot verify fs %s: " 2151 "type %s is not allowed.\n"), fstab.zone_fs_dir, 2152 fstab.zone_fs_type); 2153 return_code = Z_ERR; 2154 goto next_fs; 2155 } 2156 /* 2157 * Verify /usr/lib/fs/<fstype>/mount exists. 2158 */ 2159 if (snprintf(cmdbuf, sizeof (cmdbuf), "/usr/lib/fs/%s/mount", 2160 fstab.zone_fs_type) > sizeof (cmdbuf)) { 2161 (void) fprintf(stderr, gettext("cannot verify fs %s: " 2162 "type %s is too long.\n"), fstab.zone_fs_dir, 2163 fstab.zone_fs_type); 2164 return_code = Z_ERR; 2165 goto next_fs; 2166 } 2167 if (stat(cmdbuf, &st) != 0) { 2168 (void) fprintf(stderr, gettext("could not verify fs " 2169 "%s: could not access %s: %s\n"), fstab.zone_fs_dir, 2170 cmdbuf, strerror(errno)); 2171 return_code = Z_ERR; 2172 goto next_fs; 2173 } 2174 if (!S_ISREG(st.st_mode)) { 2175 (void) fprintf(stderr, gettext("could not verify fs " 2176 "%s: %s is not a regular file\n"), 2177 fstab.zone_fs_dir, cmdbuf); 2178 return_code = Z_ERR; 2179 goto next_fs; 2180 } 2181 /* 2182 * If zone_fs_raw is set, verify that there's an fsck 2183 * binary for it. If zone_fs_raw is not set, and it's 2184 * not a regular file (lofi mount), and there's an fsck 2185 * binary for it, complain. 2186 */ 2187 if (snprintf(cmdbuf, sizeof (cmdbuf), "/usr/lib/fs/%s/fsck", 2188 fstab.zone_fs_type) > sizeof (cmdbuf)) { 2189 (void) fprintf(stderr, gettext("cannot verify fs %s: " 2190 "type %s is too long.\n"), fstab.zone_fs_dir, 2191 fstab.zone_fs_type); 2192 return_code = Z_ERR; 2193 goto next_fs; 2194 } 2195 if (fstab.zone_fs_raw[0] != '\0' && 2196 (stat(cmdbuf, &st) != 0 || !S_ISREG(st.st_mode))) { 2197 (void) fprintf(stderr, gettext("cannot verify fs %s: " 2198 "'raw' device specified but " 2199 "no fsck executable exists for %s\n"), 2200 fstab.zone_fs_dir, fstab.zone_fs_type); 2201 return_code = Z_ERR; 2202 goto next_fs; 2203 } else if (fstab.zone_fs_raw[0] == '\0' && 2204 stat(cmdbuf, &st) == 0 && 2205 isregfile(fstab.zone_fs_special) != 1) { 2206 (void) fprintf(stderr, gettext("could not verify fs " 2207 "%s: must specify 'raw' device for %s " 2208 "file systems\n"), 2209 fstab.zone_fs_dir, fstab.zone_fs_type); 2210 return_code = Z_ERR; 2211 goto next_fs; 2212 } 2213 2214 /* Verify fs_special. */ 2215 if ((return_code = verify_fs_special(&fstab)) != Z_OK) 2216 goto next_fs; 2217 2218 /* Verify fs_raw. */ 2219 if (fstab.zone_fs_raw[0] != '\0' && 2220 stat(fstab.zone_fs_raw, &st) != 0) { 2221 /* 2222 * TRANSLATION_NOTE 2223 * fs is a literal that should not be translated. 2224 */ 2225 (void) fprintf(stderr, gettext("could not verify fs " 2226 "%s: could not access %s: %s\n"), fstab.zone_fs_dir, 2227 fstab.zone_fs_raw, strerror(errno)); 2228 return_code = Z_ERR; 2229 goto next_fs; 2230 } 2231 next_fs: 2232 zonecfg_free_fs_option_list(fstab.zone_fs_options); 2233 } 2234 (void) zonecfg_endfsent(handle); 2235 2236 return (return_code); 2237 } 2238 2239 static int 2240 verify_limitpriv(zone_dochandle_t handle) 2241 { 2242 char *privname = NULL; 2243 int err; 2244 priv_set_t *privs; 2245 2246 if ((privs = priv_allocset()) == NULL) { 2247 zperror(gettext("failed to allocate privilege set"), B_FALSE); 2248 return (Z_NOMEM); 2249 } 2250 err = zonecfg_get_privset(handle, privs, &privname); 2251 switch (err) { 2252 case Z_OK: 2253 break; 2254 case Z_PRIV_PROHIBITED: 2255 (void) fprintf(stderr, gettext("privilege \"%s\" is not " 2256 "permitted within the zone's privilege set\n"), privname); 2257 break; 2258 case Z_PRIV_REQUIRED: 2259 (void) fprintf(stderr, gettext("required privilege \"%s\" is " 2260 "missing from the zone's privilege set\n"), privname); 2261 break; 2262 case Z_PRIV_UNKNOWN: 2263 (void) fprintf(stderr, gettext("unknown privilege \"%s\" " 2264 "specified in the zone's privilege set\n"), privname); 2265 break; 2266 default: 2267 zperror( 2268 gettext("failed to determine the zone's privilege set"), 2269 B_TRUE); 2270 break; 2271 } 2272 free(privname); 2273 priv_freeset(privs); 2274 return (err); 2275 } 2276 2277 static void 2278 free_local_netifs(int if_cnt, struct net_if **if_list) 2279 { 2280 int i; 2281 2282 for (i = 0; i < if_cnt; i++) { 2283 free(if_list[i]->name); 2284 free(if_list[i]); 2285 } 2286 free(if_list); 2287 } 2288 2289 /* 2290 * Get a list of the network interfaces, along with their address families, 2291 * that are plumbed in the global zone. See if_tcp(7p) for a description 2292 * of the ioctls used here. 2293 */ 2294 static int 2295 get_local_netifs(int *if_cnt, struct net_if ***if_list) 2296 { 2297 int s; 2298 int i; 2299 int res = Z_OK; 2300 int space_needed; 2301 int cnt = 0; 2302 struct lifnum if_num; 2303 struct lifconf if_conf; 2304 struct lifreq *if_reqp; 2305 char *if_buf; 2306 struct net_if **local_ifs = NULL; 2307 2308 *if_cnt = 0; 2309 *if_list = NULL; 2310 2311 if ((s = socket(SOCKET_AF(AF_INET), SOCK_DGRAM, 0)) < 0) 2312 return (Z_ERR); 2313 2314 /* 2315 * Come back here in the unlikely event that the number of interfaces 2316 * increases between the time we get the count and the time we do the 2317 * SIOCGLIFCONF ioctl. 2318 */ 2319 retry: 2320 /* Get the number of interfaces. */ 2321 if_num.lifn_family = AF_UNSPEC; 2322 if_num.lifn_flags = LIFC_NOXMIT; 2323 if (ioctl(s, SIOCGLIFNUM, &if_num) < 0) { 2324 (void) close(s); 2325 return (Z_ERR); 2326 } 2327 2328 /* Get the interface configuration list. */ 2329 space_needed = if_num.lifn_count * sizeof (struct lifreq); 2330 if ((if_buf = malloc(space_needed)) == NULL) { 2331 (void) close(s); 2332 return (Z_ERR); 2333 } 2334 if_conf.lifc_family = AF_UNSPEC; 2335 if_conf.lifc_flags = LIFC_NOXMIT; 2336 if_conf.lifc_len = space_needed; 2337 if_conf.lifc_buf = if_buf; 2338 if (ioctl(s, SIOCGLIFCONF, &if_conf) < 0) { 2339 free(if_buf); 2340 /* 2341 * SIOCGLIFCONF returns EINVAL if the buffer we passed in is 2342 * too small. In this case go back and get the new if cnt. 2343 */ 2344 if (errno == EINVAL) 2345 goto retry; 2346 2347 (void) close(s); 2348 return (Z_ERR); 2349 } 2350 (void) close(s); 2351 2352 /* Get the name and address family for each interface. */ 2353 if_reqp = if_conf.lifc_req; 2354 for (i = 0; i < (if_conf.lifc_len / sizeof (struct lifreq)); i++) { 2355 struct net_if **p; 2356 struct lifreq req; 2357 2358 if (strcmp(LOOPBACK_IF, if_reqp->lifr_name) == 0) { 2359 if_reqp++; 2360 continue; 2361 } 2362 2363 if ((s = socket(SOCKET_AF(if_reqp->lifr_addr.ss_family), 2364 SOCK_DGRAM, 0)) == -1) { 2365 res = Z_ERR; 2366 break; 2367 } 2368 2369 (void) strncpy(req.lifr_name, if_reqp->lifr_name, 2370 sizeof (req.lifr_name)); 2371 if (ioctl(s, SIOCGLIFADDR, &req) < 0) { 2372 (void) close(s); 2373 if_reqp++; 2374 continue; 2375 } 2376 2377 if ((p = (struct net_if **)realloc(local_ifs, 2378 sizeof (struct net_if *) * (cnt + 1))) == NULL) { 2379 res = Z_ERR; 2380 break; 2381 } 2382 local_ifs = p; 2383 2384 if ((local_ifs[cnt] = malloc(sizeof (struct net_if))) == NULL) { 2385 res = Z_ERR; 2386 break; 2387 } 2388 2389 if ((local_ifs[cnt]->name = strdup(if_reqp->lifr_name)) 2390 == NULL) { 2391 free(local_ifs[cnt]); 2392 res = Z_ERR; 2393 break; 2394 } 2395 local_ifs[cnt]->af = req.lifr_addr.ss_family; 2396 cnt++; 2397 2398 (void) close(s); 2399 if_reqp++; 2400 } 2401 2402 free(if_buf); 2403 2404 if (res != Z_OK) { 2405 free_local_netifs(cnt, local_ifs); 2406 } else { 2407 *if_cnt = cnt; 2408 *if_list = local_ifs; 2409 } 2410 2411 return (res); 2412 } 2413 2414 static char * 2415 af2str(int af) 2416 { 2417 switch (af) { 2418 case AF_INET: 2419 return ("IPv4"); 2420 case AF_INET6: 2421 return ("IPv6"); 2422 default: 2423 return ("Unknown"); 2424 } 2425 } 2426 2427 /* 2428 * Cross check the network interface name and address family with the 2429 * interfaces that are set up in the global zone so that we can print the 2430 * appropriate error message. 2431 */ 2432 static void 2433 print_net_err(char *phys, char *addr, int af, char *msg) 2434 { 2435 int i; 2436 int local_if_cnt = 0; 2437 struct net_if **local_ifs = NULL; 2438 boolean_t found_if = B_FALSE; 2439 boolean_t found_af = B_FALSE; 2440 2441 if (get_local_netifs(&local_if_cnt, &local_ifs) != Z_OK) { 2442 (void) fprintf(stderr, 2443 gettext("could not verify %s %s=%s %s=%s\n\t%s\n"), 2444 "net", "address", addr, "physical", phys, msg); 2445 return; 2446 } 2447 2448 for (i = 0; i < local_if_cnt; i++) { 2449 if (strcmp(phys, local_ifs[i]->name) == 0) { 2450 found_if = B_TRUE; 2451 if (af == local_ifs[i]->af) { 2452 found_af = B_TRUE; 2453 break; 2454 } 2455 } 2456 } 2457 2458 free_local_netifs(local_if_cnt, local_ifs); 2459 2460 if (!found_if) { 2461 (void) fprintf(stderr, 2462 gettext("could not verify %s %s=%s\n\t" 2463 "network interface %s is not plumbed in the global zone\n"), 2464 "net", "physical", phys, phys); 2465 return; 2466 } 2467 2468 /* 2469 * Print this error if we were unable to find the address family 2470 * for this interface. If the af variable is not initialized to 2471 * to something meaningful by the caller (not AF_UNSPEC) then we 2472 * also skip this message since it wouldn't be informative. 2473 */ 2474 if (!found_af && af != AF_UNSPEC) { 2475 (void) fprintf(stderr, 2476 gettext("could not verify %s %s=%s %s=%s\n\tthe %s address " 2477 "family is not configured on this network interface in " 2478 "the\n\tglobal zone\n"), 2479 "net", "address", addr, "physical", phys, af2str(af)); 2480 return; 2481 } 2482 2483 (void) fprintf(stderr, 2484 gettext("could not verify %s %s=%s %s=%s\n\t%s\n"), 2485 "net", "address", addr, "physical", phys, msg); 2486 } 2487 2488 static int 2489 verify_handle(int cmd_num, zone_dochandle_t handle, char *argv[]) 2490 { 2491 struct zone_nwiftab nwiftab; 2492 int return_code = Z_OK; 2493 int err; 2494 boolean_t in_alt_root; 2495 zone_iptype_t iptype; 2496 dladm_handle_t dh; 2497 dladm_status_t status; 2498 datalink_id_t linkid; 2499 char errmsg[DLADM_STRSIZE]; 2500 2501 in_alt_root = zonecfg_in_alt_root(); 2502 if (in_alt_root) 2503 goto no_net; 2504 2505 if ((err = zonecfg_get_iptype(handle, &iptype)) != Z_OK) { 2506 errno = err; 2507 zperror(cmd_to_str(cmd_num), B_TRUE); 2508 zonecfg_fini_handle(handle); 2509 return (Z_ERR); 2510 } 2511 if ((err = zonecfg_setnwifent(handle)) != Z_OK) { 2512 errno = err; 2513 zperror(cmd_to_str(cmd_num), B_TRUE); 2514 zonecfg_fini_handle(handle); 2515 return (Z_ERR); 2516 } 2517 while (zonecfg_getnwifent(handle, &nwiftab) == Z_OK) { 2518 struct lifreq lifr; 2519 sa_family_t af = AF_UNSPEC; 2520 char dl_owner_zname[ZONENAME_MAX]; 2521 zoneid_t dl_owner_zid; 2522 zoneid_t target_zid; 2523 int res; 2524 2525 /* skip any loopback interfaces */ 2526 if (strcmp(nwiftab.zone_nwif_physical, "lo0") == 0) 2527 continue; 2528 switch (iptype) { 2529 case ZS_SHARED: 2530 if ((res = zonecfg_valid_net_address( 2531 nwiftab.zone_nwif_address, &lifr)) != Z_OK) { 2532 print_net_err(nwiftab.zone_nwif_physical, 2533 nwiftab.zone_nwif_address, af, 2534 zonecfg_strerror(res)); 2535 return_code = Z_ERR; 2536 continue; 2537 } 2538 af = lifr.lifr_addr.ss_family; 2539 if (!zonecfg_ifname_exists(af, 2540 nwiftab.zone_nwif_physical)) { 2541 /* 2542 * The interface failed to come up. We continue 2543 * on anyway for the sake of consistency: a 2544 * zone is not shut down if the interface fails 2545 * any time after boot, nor does the global zone 2546 * fail to boot if an interface fails. 2547 */ 2548 (void) fprintf(stderr, 2549 gettext("WARNING: skipping network " 2550 "interface '%s' which may not be " 2551 "present/plumbed in the global " 2552 "zone.\n"), 2553 nwiftab.zone_nwif_physical); 2554 } 2555 break; 2556 case ZS_EXCLUSIVE: 2557 /* Warning if it exists for either IPv4 or IPv6 */ 2558 2559 if (zonecfg_ifname_exists(AF_INET, 2560 nwiftab.zone_nwif_physical) || 2561 zonecfg_ifname_exists(AF_INET6, 2562 nwiftab.zone_nwif_physical)) { 2563 (void) fprintf(stderr, 2564 gettext("WARNING: skipping network " 2565 "interface '%s' which is used in the " 2566 "global zone.\n"), 2567 nwiftab.zone_nwif_physical); 2568 break; 2569 } 2570 2571 /* 2572 * Verify that the datalink exists and that it isn't 2573 * already assigned to a zone. 2574 */ 2575 if ((status = dladm_open(&dh)) == DLADM_STATUS_OK) { 2576 status = dladm_name2info(dh, 2577 nwiftab.zone_nwif_physical, &linkid, NULL, 2578 NULL, NULL); 2579 dladm_close(dh); 2580 } 2581 if (status != DLADM_STATUS_OK) { 2582 (void) fprintf(stderr, 2583 gettext("WARNING: skipping network " 2584 "interface '%s': %s\n"), 2585 nwiftab.zone_nwif_physical, 2586 dladm_status2str(status, errmsg)); 2587 break; 2588 } 2589 dl_owner_zid = ALL_ZONES; 2590 if (zone_check_datalink(&dl_owner_zid, linkid) != 0) 2591 break; 2592 2593 /* 2594 * If the zone being verified is 2595 * running and owns the interface 2596 */ 2597 target_zid = getzoneidbyname(target_zone); 2598 if (target_zid == dl_owner_zid) 2599 break; 2600 2601 /* Zone id match failed, use name to check */ 2602 if (getzonenamebyid(dl_owner_zid, dl_owner_zname, 2603 ZONENAME_MAX) < 0) { 2604 /* No name, show ID instead */ 2605 (void) snprintf(dl_owner_zname, ZONENAME_MAX, 2606 "<%d>", dl_owner_zid); 2607 } else if (strcmp(dl_owner_zname, target_zone) == 0) 2608 break; 2609 2610 /* 2611 * Note here we only report a warning that 2612 * the interface is already in use by another 2613 * running zone, and the verify process just 2614 * goes on, if the interface is still in use 2615 * when this zone really boots up, zoneadmd 2616 * will find it. If the name of the zone which 2617 * owns this interface cannot be determined, 2618 * then it is not possible to determine if there 2619 * is a conflict so just report it as a warning. 2620 */ 2621 (void) fprintf(stderr, 2622 gettext("WARNING: skipping network interface " 2623 "'%s' which is used by the non-global zone " 2624 "'%s'.\n"), nwiftab.zone_nwif_physical, 2625 dl_owner_zname); 2626 break; 2627 } 2628 } 2629 (void) zonecfg_endnwifent(handle); 2630 no_net: 2631 2632 /* verify that lofs has not been excluded from the kernel */ 2633 if (!(cmd_num == CMD_DETACH || cmd_num == CMD_ATTACH || 2634 cmd_num == CMD_MOVE || cmd_num == CMD_CLONE) && 2635 modctl(MODLOAD, 1, "fs/lofs", NULL) != 0) { 2636 if (errno == ENXIO) 2637 (void) fprintf(stderr, gettext("could not verify " 2638 "lofs(7FS): possibly excluded in /etc/system\n")); 2639 else 2640 (void) fprintf(stderr, gettext("could not verify " 2641 "lofs(7FS): %s\n"), strerror(errno)); 2642 return_code = Z_ERR; 2643 } 2644 2645 if (verify_filesystems(handle) != Z_OK) 2646 return_code = Z_ERR; 2647 if (verify_ipd(handle) != Z_OK) 2648 return_code = Z_ERR; 2649 if (!in_alt_root && verify_rctls(handle) != Z_OK) 2650 return_code = Z_ERR; 2651 if (!in_alt_root && verify_pool(handle) != Z_OK) 2652 return_code = Z_ERR; 2653 if (!in_alt_root && verify_brand(handle, cmd_num, argv) != Z_OK) 2654 return_code = Z_ERR; 2655 if (!in_alt_root && verify_datasets(handle) != Z_OK) 2656 return_code = Z_ERR; 2657 2658 /* 2659 * As the "mount" command is used for patching/upgrading of zones 2660 * or other maintenance processes, the zone's privilege set is not 2661 * checked in this case. Instead, the default, safe set of 2662 * privileges will be used when this zone is created in the 2663 * kernel. 2664 */ 2665 if (!in_alt_root && cmd_num != CMD_MOUNT && 2666 verify_limitpriv(handle) != Z_OK) 2667 return_code = Z_ERR; 2668 2669 return (return_code); 2670 } 2671 2672 static int 2673 verify_details(int cmd_num, char *argv[]) 2674 { 2675 zone_dochandle_t handle; 2676 char zonepath[MAXPATHLEN], checkpath[MAXPATHLEN]; 2677 int return_code = Z_OK; 2678 int err; 2679 2680 if ((handle = zonecfg_init_handle()) == NULL) { 2681 zperror(cmd_to_str(cmd_num), B_TRUE); 2682 return (Z_ERR); 2683 } 2684 if ((err = zonecfg_get_handle(target_zone, handle)) != Z_OK) { 2685 errno = err; 2686 zperror(cmd_to_str(cmd_num), B_TRUE); 2687 zonecfg_fini_handle(handle); 2688 return (Z_ERR); 2689 } 2690 if ((err = zonecfg_get_zonepath(handle, zonepath, sizeof (zonepath))) != 2691 Z_OK) { 2692 errno = err; 2693 zperror(cmd_to_str(cmd_num), B_TRUE); 2694 zonecfg_fini_handle(handle); 2695 return (Z_ERR); 2696 } 2697 /* 2698 * zonecfg_get_zonepath() gets its data from the XML repository. 2699 * Verify this against the index file, which is checked first by 2700 * zone_get_zonepath(). If they don't match, bail out. 2701 */ 2702 if ((err = zone_get_zonepath(target_zone, checkpath, 2703 sizeof (checkpath))) != Z_OK) { 2704 errno = err; 2705 zperror2(target_zone, gettext("could not get zone path")); 2706 zonecfg_fini_handle(handle); 2707 return (Z_ERR); 2708 } 2709 if (strcmp(zonepath, checkpath) != 0) { 2710 /* 2711 * TRANSLATION_NOTE 2712 * XML and zonepath are literals that should not be translated. 2713 */ 2714 (void) fprintf(stderr, gettext("The XML repository has " 2715 "zonepath '%s',\nbut the index file has zonepath '%s'.\n" 2716 "These must match, so fix the incorrect entry.\n"), 2717 zonepath, checkpath); 2718 zonecfg_fini_handle(handle); 2719 return (Z_ERR); 2720 } 2721 if (cmd_num != CMD_ATTACH && 2722 validate_zonepath(zonepath, cmd_num) != Z_OK) { 2723 (void) fprintf(stderr, gettext("could not verify zonepath %s " 2724 "because of the above errors.\n"), zonepath); 2725 return_code = Z_ERR; 2726 } 2727 2728 if (verify_handle(cmd_num, handle, argv) != Z_OK) 2729 return_code = Z_ERR; 2730 2731 zonecfg_fini_handle(handle); 2732 if (return_code == Z_ERR) 2733 (void) fprintf(stderr, 2734 gettext("%s: zone %s failed to verify\n"), 2735 execname, target_zone); 2736 return (return_code); 2737 } 2738 2739 static int 2740 verify_func(int argc, char *argv[]) 2741 { 2742 int arg; 2743 2744 optind = 0; 2745 if ((arg = getopt(argc, argv, "?")) != EOF) { 2746 switch (arg) { 2747 case '?': 2748 sub_usage(SHELP_VERIFY, CMD_VERIFY); 2749 return (optopt == '?' ? Z_OK : Z_USAGE); 2750 default: 2751 sub_usage(SHELP_VERIFY, CMD_VERIFY); 2752 return (Z_USAGE); 2753 } 2754 } 2755 if (argc > optind) { 2756 sub_usage(SHELP_VERIFY, CMD_VERIFY); 2757 return (Z_USAGE); 2758 } 2759 if (sanity_check(target_zone, CMD_VERIFY, B_FALSE, B_FALSE, B_FALSE) 2760 != Z_OK) 2761 return (Z_ERR); 2762 return (verify_details(CMD_VERIFY, argv)); 2763 } 2764 2765 static int 2766 addoptions(char *buf, char *argv[], size_t len) 2767 { 2768 int i = 0; 2769 2770 if (buf[0] == '\0') 2771 return (Z_OK); 2772 2773 while (argv[i] != NULL) { 2774 if (strlcat(buf, " ", len) >= len || 2775 strlcat(buf, argv[i++], len) >= len) { 2776 zerror("Command line too long"); 2777 return (Z_ERR); 2778 } 2779 } 2780 2781 return (Z_OK); 2782 } 2783 2784 static int 2785 addopt(char *buf, int opt, char *optarg, size_t bufsize) 2786 { 2787 char optstring[4]; 2788 2789 if (opt > 0) 2790 (void) sprintf(optstring, " -%c", opt); 2791 else 2792 (void) strcpy(optstring, " "); 2793 2794 if ((strlcat(buf, optstring, bufsize) > bufsize)) 2795 return (Z_ERR); 2796 2797 if ((optarg != NULL) && (strlcat(buf, optarg, bufsize) > bufsize)) 2798 return (Z_ERR); 2799 2800 return (Z_OK); 2801 } 2802 2803 /* ARGSUSED */ 2804 static int 2805 install_func(int argc, char *argv[]) 2806 { 2807 char cmdbuf[MAXPATHLEN]; 2808 char postcmdbuf[MAXPATHLEN]; 2809 int lockfd; 2810 int arg, err, subproc_err; 2811 char zonepath[MAXPATHLEN]; 2812 brand_handle_t bh = NULL; 2813 int status; 2814 boolean_t nodataset = B_FALSE; 2815 boolean_t do_postinstall = B_FALSE; 2816 boolean_t brand_help = B_FALSE; 2817 char opts[128]; 2818 2819 if (target_zone == NULL) { 2820 sub_usage(SHELP_INSTALL, CMD_INSTALL); 2821 return (Z_USAGE); 2822 } 2823 2824 if (zonecfg_in_alt_root()) { 2825 zerror(gettext("cannot install zone in alternate root")); 2826 return (Z_ERR); 2827 } 2828 2829 if ((err = zone_get_zonepath(target_zone, zonepath, 2830 sizeof (zonepath))) != Z_OK) { 2831 errno = err; 2832 zperror2(target_zone, gettext("could not get zone path")); 2833 return (Z_ERR); 2834 } 2835 2836 /* Fetch the install command from the brand configuration. */ 2837 if ((bh = brand_open(target_brand)) == NULL) { 2838 zerror(gettext("missing or invalid brand")); 2839 return (Z_ERR); 2840 } 2841 2842 if (get_hook(bh, cmdbuf, sizeof (cmdbuf), brand_get_install, 2843 target_zone, zonepath) != Z_OK) { 2844 zerror("invalid brand configuration: missing install resource"); 2845 brand_close(bh); 2846 return (Z_ERR); 2847 } 2848 2849 if (get_hook(bh, postcmdbuf, sizeof (postcmdbuf), brand_get_postinstall, 2850 target_zone, zonepath) != Z_OK) { 2851 zerror("invalid brand configuration: missing postinstall " 2852 "resource"); 2853 brand_close(bh); 2854 return (Z_ERR); 2855 } 2856 2857 if (postcmdbuf[0] != '\0') 2858 do_postinstall = B_TRUE; 2859 2860 (void) strcpy(opts, "?x:"); 2861 /* 2862 * Fetch the list of recognized command-line options from 2863 * the brand configuration file. 2864 */ 2865 if (brand_get_installopts(bh, opts + strlen(opts), 2866 sizeof (opts) - strlen(opts)) != 0) { 2867 zerror("invalid brand configuration: missing " 2868 "install options resource"); 2869 brand_close(bh); 2870 return (Z_ERR); 2871 } 2872 2873 brand_close(bh); 2874 2875 if (cmdbuf[0] == '\0') { 2876 zerror("Missing brand install command"); 2877 return (Z_ERR); 2878 } 2879 2880 /* Check the argv string for args we handle internally */ 2881 optind = 0; 2882 opterr = 0; 2883 while ((arg = getopt(argc, argv, opts)) != EOF) { 2884 switch (arg) { 2885 case '?': 2886 if (optopt == '?') { 2887 sub_usage(SHELP_INSTALL, CMD_INSTALL); 2888 brand_help = B_TRUE; 2889 } 2890 /* Ignore unknown options - may be brand specific. */ 2891 break; 2892 case 'x': 2893 /* Handle this option internally, don't pass to brand */ 2894 if (strcmp(optarg, "nodataset") == 0) { 2895 /* Handle this option internally */ 2896 nodataset = B_TRUE; 2897 } 2898 continue; 2899 default: 2900 /* Ignore unknown options - may be brand specific. */ 2901 break; 2902 } 2903 2904 /* 2905 * Append the option to the command line passed to the 2906 * brand-specific install and postinstall routines. 2907 */ 2908 if (addopt(cmdbuf, optopt, optarg, sizeof (cmdbuf)) != Z_OK) { 2909 zerror("Install command line too long"); 2910 return (Z_ERR); 2911 } 2912 if (addopt(postcmdbuf, optopt, optarg, sizeof (postcmdbuf)) 2913 != Z_OK) { 2914 zerror("Post-Install command line too long"); 2915 return (Z_ERR); 2916 } 2917 } 2918 2919 for (; optind < argc; optind++) { 2920 if (addopt(cmdbuf, 0, argv[optind], sizeof (cmdbuf)) != Z_OK) { 2921 zerror("Install command line too long"); 2922 return (Z_ERR); 2923 } 2924 2925 if (addopt(postcmdbuf, 0, argv[optind], sizeof (postcmdbuf)) 2926 != Z_OK) { 2927 zerror("Post-Install command line too long"); 2928 return (Z_ERR); 2929 } 2930 } 2931 2932 if (!brand_help) { 2933 if (sanity_check(target_zone, CMD_INSTALL, B_FALSE, B_TRUE, 2934 B_FALSE) != Z_OK) 2935 return (Z_ERR); 2936 if (verify_details(CMD_INSTALL, argv) != Z_OK) 2937 return (Z_ERR); 2938 2939 if (zonecfg_grab_lock_file(target_zone, &lockfd) != Z_OK) { 2940 zerror(gettext("another %s may have an operation in " 2941 "progress."), "zoneadm"); 2942 return (Z_ERR); 2943 } 2944 err = zone_set_state(target_zone, ZONE_STATE_INCOMPLETE); 2945 if (err != Z_OK) { 2946 errno = err; 2947 zperror2(target_zone, gettext("could not set state")); 2948 goto done; 2949 } 2950 2951 if (!nodataset) 2952 create_zfs_zonepath(zonepath); 2953 } 2954 2955 status = do_subproc(cmdbuf); 2956 if ((subproc_err = 2957 subproc_status(gettext("brand-specific installation"), status, 2958 B_FALSE)) != ZONE_SUBPROC_OK) { 2959 if (subproc_err == ZONE_SUBPROC_USAGE && !brand_help) { 2960 sub_usage(SHELP_INSTALL, CMD_INSTALL); 2961 zonecfg_release_lock_file(target_zone, lockfd); 2962 return (Z_ERR); 2963 } 2964 err = Z_ERR; 2965 goto done; 2966 } 2967 2968 if (brand_help) 2969 return (Z_OK); 2970 2971 if ((err = zone_set_state(target_zone, ZONE_STATE_INSTALLED)) != Z_OK) { 2972 errno = err; 2973 zperror2(target_zone, gettext("could not set state")); 2974 goto done; 2975 } 2976 2977 if (do_postinstall) { 2978 status = do_subproc(postcmdbuf); 2979 2980 if ((subproc_err = 2981 subproc_status(gettext("brand-specific post-install"), 2982 status, B_FALSE)) != ZONE_SUBPROC_OK) { 2983 err = Z_ERR; 2984 (void) zone_set_state(target_zone, 2985 ZONE_STATE_INCOMPLETE); 2986 } 2987 } 2988 2989 done: 2990 /* 2991 * If the install script exited with ZONE_SUBPROC_NOTCOMPLETE, try to 2992 * clean up the zone and leave the zone in the CONFIGURED state so that 2993 * another install can be attempted without requiring an uninstall 2994 * first. 2995 */ 2996 if (subproc_err == ZONE_SUBPROC_NOTCOMPLETE) { 2997 if ((err = cleanup_zonepath(zonepath, B_FALSE)) != Z_OK) { 2998 errno = err; 2999 zperror2(target_zone, 3000 gettext("cleaning up zonepath failed")); 3001 } else if ((err = zone_set_state(target_zone, 3002 ZONE_STATE_CONFIGURED)) != Z_OK) { 3003 errno = err; 3004 zperror2(target_zone, gettext("could not set state")); 3005 } 3006 } 3007 3008 if (!brand_help) 3009 zonecfg_release_lock_file(target_zone, lockfd); 3010 return ((err == Z_OK) ? Z_OK : Z_ERR); 3011 } 3012 3013 /* 3014 * Check that the inherited pkg dirs are the same for the clone and its source. 3015 * The easiest way to do that is check that the list of ipds is the same 3016 * by matching each one against the other. This algorithm should be fine since 3017 * the list of ipds should not be that long. 3018 */ 3019 static int 3020 valid_ipd_clone(zone_dochandle_t s_handle, char *source_zone, 3021 zone_dochandle_t t_handle, char *target_zone) 3022 { 3023 int err; 3024 int res = Z_OK; 3025 int s_cnt = 0; 3026 int t_cnt = 0; 3027 struct zone_fstab s_fstab; 3028 struct zone_fstab t_fstab; 3029 3030 /* 3031 * First check the source of the clone against the target. 3032 */ 3033 if ((err = zonecfg_setipdent(s_handle)) != Z_OK) { 3034 errno = err; 3035 zperror2(source_zone, gettext("could not enumerate " 3036 "inherit-pkg-dirs")); 3037 return (Z_ERR); 3038 } 3039 3040 while (zonecfg_getipdent(s_handle, &s_fstab) == Z_OK) { 3041 boolean_t match = B_FALSE; 3042 3043 s_cnt++; 3044 3045 if ((err = zonecfg_setipdent(t_handle)) != Z_OK) { 3046 errno = err; 3047 zperror2(target_zone, gettext("could not enumerate " 3048 "inherit-pkg-dirs")); 3049 (void) zonecfg_endipdent(s_handle); 3050 return (Z_ERR); 3051 } 3052 3053 while (zonecfg_getipdent(t_handle, &t_fstab) == Z_OK) { 3054 if (strcmp(s_fstab.zone_fs_dir, t_fstab.zone_fs_dir) 3055 == 0) { 3056 match = B_TRUE; 3057 break; 3058 } 3059 } 3060 (void) zonecfg_endipdent(t_handle); 3061 3062 if (!match) { 3063 (void) fprintf(stderr, gettext("inherit-pkg-dir " 3064 "'%s' is not configured in zone %s.\n"), 3065 s_fstab.zone_fs_dir, target_zone); 3066 res = Z_ERR; 3067 } 3068 } 3069 3070 (void) zonecfg_endipdent(s_handle); 3071 3072 /* skip the next check if we already have errors */ 3073 if (res == Z_ERR) 3074 return (res); 3075 3076 /* 3077 * Now check the number of ipds in the target so we can verify 3078 * that the source is not a subset of the target. 3079 */ 3080 if ((err = zonecfg_setipdent(t_handle)) != Z_OK) { 3081 errno = err; 3082 zperror2(target_zone, gettext("could not enumerate " 3083 "inherit-pkg-dirs")); 3084 return (Z_ERR); 3085 } 3086 3087 while (zonecfg_getipdent(t_handle, &t_fstab) == Z_OK) 3088 t_cnt++; 3089 3090 (void) zonecfg_endipdent(t_handle); 3091 3092 if (t_cnt != s_cnt) { 3093 (void) fprintf(stderr, gettext("Zone %s is configured " 3094 "with inherit-pkg-dirs that are not configured in zone " 3095 "%s.\n"), target_zone, source_zone); 3096 res = Z_ERR; 3097 } 3098 3099 return (res); 3100 } 3101 3102 static void 3103 warn_dev_match(zone_dochandle_t s_handle, char *source_zone, 3104 zone_dochandle_t t_handle, char *target_zone) 3105 { 3106 int err; 3107 struct zone_devtab s_devtab; 3108 struct zone_devtab t_devtab; 3109 3110 if ((err = zonecfg_setdevent(t_handle)) != Z_OK) { 3111 errno = err; 3112 zperror2(target_zone, gettext("could not enumerate devices")); 3113 return; 3114 } 3115 3116 while (zonecfg_getdevent(t_handle, &t_devtab) == Z_OK) { 3117 if ((err = zonecfg_setdevent(s_handle)) != Z_OK) { 3118 errno = err; 3119 zperror2(source_zone, 3120 gettext("could not enumerate devices")); 3121 (void) zonecfg_enddevent(t_handle); 3122 return; 3123 } 3124 3125 while (zonecfg_getdevent(s_handle, &s_devtab) == Z_OK) { 3126 /* 3127 * Use fnmatch to catch the case where wildcards 3128 * were used in one zone and the other has an 3129 * explicit entry (e.g. /dev/dsk/c0t0d0s6 vs. 3130 * /dev/\*dsk/c0t0d0s6). 3131 */ 3132 if (fnmatch(t_devtab.zone_dev_match, 3133 s_devtab.zone_dev_match, FNM_PATHNAME) == 0 || 3134 fnmatch(s_devtab.zone_dev_match, 3135 t_devtab.zone_dev_match, FNM_PATHNAME) == 0) { 3136 (void) fprintf(stderr, 3137 gettext("WARNING: device '%s' " 3138 "is configured in both zones.\n"), 3139 t_devtab.zone_dev_match); 3140 break; 3141 } 3142 } 3143 (void) zonecfg_enddevent(s_handle); 3144 } 3145 3146 (void) zonecfg_enddevent(t_handle); 3147 } 3148 3149 /* 3150 * Check if the specified mount option (opt) is contained within the 3151 * options string. 3152 */ 3153 static boolean_t 3154 opt_match(char *opt, char *options) 3155 { 3156 char *p; 3157 char *lastp; 3158 3159 if ((p = strtok_r(options, ",", &lastp)) != NULL) { 3160 if (strcmp(p, opt) == 0) 3161 return (B_TRUE); 3162 while ((p = strtok_r(NULL, ",", &lastp)) != NULL) { 3163 if (strcmp(p, opt) == 0) 3164 return (B_TRUE); 3165 } 3166 } 3167 3168 return (B_FALSE); 3169 } 3170 3171 #define RW_LOFS "WARNING: read-write lofs file system on '%s' is configured " \ 3172 "in both zones.\n" 3173 3174 static void 3175 print_fs_warnings(struct zone_fstab *s_fstab, struct zone_fstab *t_fstab) 3176 { 3177 /* 3178 * It is ok to have shared lofs mounted fs but we want to warn if 3179 * either is rw since this will effect the other zone. 3180 */ 3181 if (strcmp(t_fstab->zone_fs_type, "lofs") == 0) { 3182 zone_fsopt_t *optp; 3183 3184 /* The default is rw so no options means rw */ 3185 if (t_fstab->zone_fs_options == NULL || 3186 s_fstab->zone_fs_options == NULL) { 3187 (void) fprintf(stderr, gettext(RW_LOFS), 3188 t_fstab->zone_fs_special); 3189 return; 3190 } 3191 3192 for (optp = s_fstab->zone_fs_options; optp != NULL; 3193 optp = optp->zone_fsopt_next) { 3194 if (opt_match("rw", optp->zone_fsopt_opt)) { 3195 (void) fprintf(stderr, gettext(RW_LOFS), 3196 s_fstab->zone_fs_special); 3197 return; 3198 } 3199 } 3200 3201 for (optp = t_fstab->zone_fs_options; optp != NULL; 3202 optp = optp->zone_fsopt_next) { 3203 if (opt_match("rw", optp->zone_fsopt_opt)) { 3204 (void) fprintf(stderr, gettext(RW_LOFS), 3205 t_fstab->zone_fs_special); 3206 return; 3207 } 3208 } 3209 3210 return; 3211 } 3212 3213 /* 3214 * TRANSLATION_NOTE 3215 * The first variable is the file system type and the second is 3216 * the file system special device. For example, 3217 * WARNING: ufs file system on '/dev/dsk/c0t0d0s0' ... 3218 */ 3219 (void) fprintf(stderr, gettext("WARNING: %s file system on '%s' " 3220 "is configured in both zones.\n"), t_fstab->zone_fs_type, 3221 t_fstab->zone_fs_special); 3222 } 3223 3224 static void 3225 warn_fs_match(zone_dochandle_t s_handle, char *source_zone, 3226 zone_dochandle_t t_handle, char *target_zone) 3227 { 3228 int err; 3229 struct zone_fstab s_fstab; 3230 struct zone_fstab t_fstab; 3231 3232 if ((err = zonecfg_setfsent(t_handle)) != Z_OK) { 3233 errno = err; 3234 zperror2(target_zone, 3235 gettext("could not enumerate file systems")); 3236 return; 3237 } 3238 3239 while (zonecfg_getfsent(t_handle, &t_fstab) == Z_OK) { 3240 if ((err = zonecfg_setfsent(s_handle)) != Z_OK) { 3241 errno = err; 3242 zperror2(source_zone, 3243 gettext("could not enumerate file systems")); 3244 (void) zonecfg_endfsent(t_handle); 3245 return; 3246 } 3247 3248 while (zonecfg_getfsent(s_handle, &s_fstab) == Z_OK) { 3249 if (strcmp(t_fstab.zone_fs_special, 3250 s_fstab.zone_fs_special) == 0) { 3251 print_fs_warnings(&s_fstab, &t_fstab); 3252 break; 3253 } 3254 } 3255 (void) zonecfg_endfsent(s_handle); 3256 } 3257 3258 (void) zonecfg_endfsent(t_handle); 3259 } 3260 3261 /* 3262 * We don't catch the case where you used the same IP address but 3263 * it is not an exact string match. For example, 192.9.0.128 vs. 192.09.0.128. 3264 * However, we're not going to worry about that but we will check for 3265 * a possible netmask on one of the addresses (e.g. 10.0.0.1 and 10.0.0.1/24) 3266 * and handle that case as a match. 3267 */ 3268 static void 3269 warn_ip_match(zone_dochandle_t s_handle, char *source_zone, 3270 zone_dochandle_t t_handle, char *target_zone) 3271 { 3272 int err; 3273 struct zone_nwiftab s_nwiftab; 3274 struct zone_nwiftab t_nwiftab; 3275 3276 if ((err = zonecfg_setnwifent(t_handle)) != Z_OK) { 3277 errno = err; 3278 zperror2(target_zone, 3279 gettext("could not enumerate network interfaces")); 3280 return; 3281 } 3282 3283 while (zonecfg_getnwifent(t_handle, &t_nwiftab) == Z_OK) { 3284 char *p; 3285 3286 /* remove an (optional) netmask from the address */ 3287 if ((p = strchr(t_nwiftab.zone_nwif_address, '/')) != NULL) 3288 *p = '\0'; 3289 3290 if ((err = zonecfg_setnwifent(s_handle)) != Z_OK) { 3291 errno = err; 3292 zperror2(source_zone, 3293 gettext("could not enumerate network interfaces")); 3294 (void) zonecfg_endnwifent(t_handle); 3295 return; 3296 } 3297 3298 while (zonecfg_getnwifent(s_handle, &s_nwiftab) == Z_OK) { 3299 /* remove an (optional) netmask from the address */ 3300 if ((p = strchr(s_nwiftab.zone_nwif_address, '/')) 3301 != NULL) 3302 *p = '\0'; 3303 3304 /* For exclusive-IP zones, address is not specified. */ 3305 if (strlen(s_nwiftab.zone_nwif_address) == 0) 3306 continue; 3307 3308 if (strcmp(t_nwiftab.zone_nwif_address, 3309 s_nwiftab.zone_nwif_address) == 0) { 3310 (void) fprintf(stderr, 3311 gettext("WARNING: network address '%s' " 3312 "is configured in both zones.\n"), 3313 t_nwiftab.zone_nwif_address); 3314 break; 3315 } 3316 } 3317 (void) zonecfg_endnwifent(s_handle); 3318 } 3319 3320 (void) zonecfg_endnwifent(t_handle); 3321 } 3322 3323 static void 3324 warn_dataset_match(zone_dochandle_t s_handle, char *source, 3325 zone_dochandle_t t_handle, char *target) 3326 { 3327 int err; 3328 struct zone_dstab s_dstab; 3329 struct zone_dstab t_dstab; 3330 3331 if ((err = zonecfg_setdsent(t_handle)) != Z_OK) { 3332 errno = err; 3333 zperror2(target, gettext("could not enumerate datasets")); 3334 return; 3335 } 3336 3337 while (zonecfg_getdsent(t_handle, &t_dstab) == Z_OK) { 3338 if ((err = zonecfg_setdsent(s_handle)) != Z_OK) { 3339 errno = err; 3340 zperror2(source, 3341 gettext("could not enumerate datasets")); 3342 (void) zonecfg_enddsent(t_handle); 3343 return; 3344 } 3345 3346 while (zonecfg_getdsent(s_handle, &s_dstab) == Z_OK) { 3347 if (strcmp(t_dstab.zone_dataset_name, 3348 s_dstab.zone_dataset_name) == 0) { 3349 target_zone = source; 3350 zerror(gettext("WARNING: dataset '%s' " 3351 "is configured in both zones.\n"), 3352 t_dstab.zone_dataset_name); 3353 break; 3354 } 3355 } 3356 (void) zonecfg_enddsent(s_handle); 3357 } 3358 3359 (void) zonecfg_enddsent(t_handle); 3360 } 3361 3362 /* 3363 * Check that the clone and its source have the same brand type. 3364 */ 3365 static int 3366 valid_brand_clone(char *source_zone, char *target_zone) 3367 { 3368 brand_handle_t bh; 3369 char source_brand[MAXNAMELEN]; 3370 3371 if ((zone_get_brand(source_zone, source_brand, 3372 sizeof (source_brand))) != Z_OK) { 3373 (void) fprintf(stderr, "%s: zone '%s': %s\n", 3374 execname, source_zone, gettext("missing or invalid brand")); 3375 return (Z_ERR); 3376 } 3377 3378 if (strcmp(source_brand, target_brand) != NULL) { 3379 (void) fprintf(stderr, 3380 gettext("%s: Zones '%s' and '%s' have different brand " 3381 "types.\n"), execname, source_zone, target_zone); 3382 return (Z_ERR); 3383 } 3384 3385 if ((bh = brand_open(target_brand)) == NULL) { 3386 zerror(gettext("missing or invalid brand")); 3387 return (Z_ERR); 3388 } 3389 brand_close(bh); 3390 return (Z_OK); 3391 } 3392 3393 static int 3394 validate_clone(char *source_zone, char *target_zone) 3395 { 3396 int err = Z_OK; 3397 zone_dochandle_t s_handle; 3398 zone_dochandle_t t_handle; 3399 3400 if ((t_handle = zonecfg_init_handle()) == NULL) { 3401 zperror(cmd_to_str(CMD_CLONE), B_TRUE); 3402 return (Z_ERR); 3403 } 3404 if ((err = zonecfg_get_handle(target_zone, t_handle)) != Z_OK) { 3405 errno = err; 3406 zperror(cmd_to_str(CMD_CLONE), B_TRUE); 3407 zonecfg_fini_handle(t_handle); 3408 return (Z_ERR); 3409 } 3410 3411 if ((s_handle = zonecfg_init_handle()) == NULL) { 3412 zperror(cmd_to_str(CMD_CLONE), B_TRUE); 3413 zonecfg_fini_handle(t_handle); 3414 return (Z_ERR); 3415 } 3416 if ((err = zonecfg_get_handle(source_zone, s_handle)) != Z_OK) { 3417 errno = err; 3418 zperror(cmd_to_str(CMD_CLONE), B_TRUE); 3419 goto done; 3420 } 3421 3422 /* verify new zone has same brand type */ 3423 err = valid_brand_clone(source_zone, target_zone); 3424 if (err != Z_OK) 3425 goto done; 3426 3427 /* verify new zone has same inherit-pkg-dirs */ 3428 err = valid_ipd_clone(s_handle, source_zone, t_handle, target_zone); 3429 3430 /* warn about imported fs's which are the same */ 3431 warn_fs_match(s_handle, source_zone, t_handle, target_zone); 3432 3433 /* warn about imported IP addresses which are the same */ 3434 warn_ip_match(s_handle, source_zone, t_handle, target_zone); 3435 3436 /* warn about imported devices which are the same */ 3437 warn_dev_match(s_handle, source_zone, t_handle, target_zone); 3438 3439 /* warn about imported datasets which are the same */ 3440 warn_dataset_match(s_handle, source_zone, t_handle, target_zone); 3441 3442 done: 3443 zonecfg_fini_handle(t_handle); 3444 zonecfg_fini_handle(s_handle); 3445 3446 return ((err == Z_OK) ? Z_OK : Z_ERR); 3447 } 3448 3449 static int 3450 copy_zone(char *src, char *dst) 3451 { 3452 boolean_t out_null = B_FALSE; 3453 int status; 3454 char *outfile; 3455 char cmdbuf[MAXPATHLEN * 2 + 128]; 3456 3457 if ((outfile = tempnam("/var/log", "zone")) == NULL) { 3458 outfile = "/dev/null"; 3459 out_null = B_TRUE; 3460 } 3461 3462 /* 3463 * Use find to get the list of files to copy. We need to skip 3464 * files of type "socket" since cpio can't handle those but that 3465 * should be ok since the app will recreate the socket when it runs. 3466 * We also need to filter out anything under the .zfs subdir. Since 3467 * find is running depth-first, we need the extra egrep to filter .zfs. 3468 */ 3469 (void) snprintf(cmdbuf, sizeof (cmdbuf), 3470 "cd %s && /usr/bin/find . -type s -prune -o -depth -print | " 3471 "/usr/bin/egrep -v '^\\./\\.zfs$|^\\./\\.zfs/' | " 3472 "/usr/bin/cpio -pdmuP@ %s > %s 2>&1", 3473 src, dst, outfile); 3474 3475 status = do_subproc(cmdbuf); 3476 3477 if (subproc_status("copy", status, B_TRUE) != ZONE_SUBPROC_OK) { 3478 if (!out_null) 3479 (void) fprintf(stderr, gettext("\nThe copy failed.\n" 3480 "More information can be found in %s\n"), outfile); 3481 return (Z_ERR); 3482 } 3483 3484 if (!out_null) 3485 (void) unlink(outfile); 3486 3487 return (Z_OK); 3488 } 3489 3490 /* ARGSUSED */ 3491 static int 3492 zfm_print(const char *p, void *r) { 3493 zerror(" %s\n", p); 3494 return (0); 3495 } 3496 3497 int 3498 clone_copy(char *source_zonepath, char *zonepath) 3499 { 3500 int err; 3501 3502 /* Don't clone the zone if anything is still mounted there */ 3503 if (zonecfg_find_mounts(source_zonepath, NULL, NULL)) { 3504 zerror(gettext("These file systems are mounted on " 3505 "subdirectories of %s.\n"), source_zonepath); 3506 (void) zonecfg_find_mounts(source_zonepath, zfm_print, NULL); 3507 return (Z_ERR); 3508 } 3509 3510 /* 3511 * Attempt to create a ZFS fs for the zonepath. As usual, we don't 3512 * care if this works or not since we always have the default behavior 3513 * of a simple directory for the zonepath. 3514 */ 3515 create_zfs_zonepath(zonepath); 3516 3517 (void) printf(gettext("Copying %s..."), source_zonepath); 3518 (void) fflush(stdout); 3519 3520 err = copy_zone(source_zonepath, zonepath); 3521 3522 (void) printf("\n"); 3523 3524 return (err); 3525 } 3526 3527 static int 3528 clone_func(int argc, char *argv[]) 3529 { 3530 char *source_zone = NULL; 3531 int lockfd; 3532 int err, arg; 3533 char zonepath[MAXPATHLEN]; 3534 char source_zonepath[MAXPATHLEN]; 3535 zone_state_t state; 3536 zone_entry_t *zent; 3537 char *method = NULL; 3538 char *snapshot = NULL; 3539 char cmdbuf[MAXPATHLEN]; 3540 char postcmdbuf[MAXPATHLEN]; 3541 char presnapbuf[MAXPATHLEN]; 3542 char postsnapbuf[MAXPATHLEN]; 3543 char validsnapbuf[MAXPATHLEN]; 3544 brand_handle_t bh = NULL; 3545 int status; 3546 boolean_t brand_help = B_FALSE; 3547 3548 if (zonecfg_in_alt_root()) { 3549 zerror(gettext("cannot clone zone in alternate root")); 3550 return (Z_ERR); 3551 } 3552 3553 /* Check the argv string for args we handle internally */ 3554 optind = 0; 3555 opterr = 0; 3556 while ((arg = getopt(argc, argv, "?m:s:")) != EOF) { 3557 switch (arg) { 3558 case '?': 3559 if (optopt == '?') { 3560 sub_usage(SHELP_CLONE, CMD_CLONE); 3561 brand_help = B_TRUE; 3562 } 3563 /* Ignore unknown options - may be brand specific. */ 3564 break; 3565 case 'm': 3566 method = optarg; 3567 break; 3568 case 's': 3569 snapshot = optarg; 3570 break; 3571 default: 3572 /* Ignore unknown options - may be brand specific. */ 3573 break; 3574 } 3575 } 3576 3577 if (argc != (optind + 1)) { 3578 sub_usage(SHELP_CLONE, CMD_CLONE); 3579 return (Z_USAGE); 3580 } 3581 3582 source_zone = argv[optind]; 3583 3584 if (!brand_help) { 3585 if (sanity_check(target_zone, CMD_CLONE, B_FALSE, B_TRUE, 3586 B_FALSE) != Z_OK) 3587 return (Z_ERR); 3588 if (verify_details(CMD_CLONE, argv) != Z_OK) 3589 return (Z_ERR); 3590 3591 /* 3592 * We also need to do some extra validation on the source zone. 3593 */ 3594 if (strcmp(source_zone, GLOBAL_ZONENAME) == 0) { 3595 zerror(gettext("%s operation is invalid for the " 3596 "global zone."), cmd_to_str(CMD_CLONE)); 3597 return (Z_ERR); 3598 } 3599 3600 if (strncmp(source_zone, "SUNW", 4) == 0) { 3601 zerror(gettext("%s operation is invalid for zones " 3602 "starting with SUNW."), cmd_to_str(CMD_CLONE)); 3603 return (Z_ERR); 3604 } 3605 3606 zent = lookup_running_zone(source_zone); 3607 if (zent != NULL) { 3608 /* check whether the zone is ready or running */ 3609 if ((err = zone_get_state(zent->zname, 3610 &zent->zstate_num)) != Z_OK) { 3611 errno = err; 3612 zperror2(zent->zname, gettext("could not get " 3613 "state")); 3614 /* can't tell, so hedge */ 3615 zent->zstate_str = "ready/running"; 3616 } else { 3617 zent->zstate_str = 3618 zone_state_str(zent->zstate_num); 3619 } 3620 zerror(gettext("%s operation is invalid for %s zones."), 3621 cmd_to_str(CMD_CLONE), zent->zstate_str); 3622 return (Z_ERR); 3623 } 3624 3625 if ((err = zone_get_state(source_zone, &state)) != Z_OK) { 3626 errno = err; 3627 zperror2(source_zone, gettext("could not get state")); 3628 return (Z_ERR); 3629 } 3630 if (state != ZONE_STATE_INSTALLED) { 3631 (void) fprintf(stderr, 3632 gettext("%s: zone %s is %s; %s is required.\n"), 3633 execname, source_zone, zone_state_str(state), 3634 zone_state_str(ZONE_STATE_INSTALLED)); 3635 return (Z_ERR); 3636 } 3637 3638 /* 3639 * The source zone checks out ok, continue with the clone. 3640 */ 3641 3642 if (validate_clone(source_zone, target_zone) != Z_OK) 3643 return (Z_ERR); 3644 3645 if (zonecfg_grab_lock_file(target_zone, &lockfd) != Z_OK) { 3646 zerror(gettext("another %s may have an operation in " 3647 "progress."), "zoneadm"); 3648 return (Z_ERR); 3649 } 3650 } 3651 3652 if ((err = zone_get_zonepath(source_zone, source_zonepath, 3653 sizeof (source_zonepath))) != Z_OK) { 3654 errno = err; 3655 zperror2(source_zone, gettext("could not get zone path")); 3656 goto done; 3657 } 3658 3659 if ((err = zone_get_zonepath(target_zone, zonepath, sizeof (zonepath))) 3660 != Z_OK) { 3661 errno = err; 3662 zperror2(target_zone, gettext("could not get zone path")); 3663 goto done; 3664 } 3665 3666 /* 3667 * Fetch the clone and postclone hooks from the brand configuration. 3668 */ 3669 if ((bh = brand_open(target_brand)) == NULL) { 3670 zerror(gettext("missing or invalid brand")); 3671 err = Z_ERR; 3672 goto done; 3673 } 3674 3675 if (get_hook(bh, cmdbuf, sizeof (cmdbuf), brand_get_clone, target_zone, 3676 zonepath) != Z_OK) { 3677 zerror("invalid brand configuration: missing clone resource"); 3678 brand_close(bh); 3679 err = Z_ERR; 3680 goto done; 3681 } 3682 3683 if (get_hook(bh, postcmdbuf, sizeof (postcmdbuf), brand_get_postclone, 3684 target_zone, zonepath) != Z_OK) { 3685 zerror("invalid brand configuration: missing postclone " 3686 "resource"); 3687 brand_close(bh); 3688 err = Z_ERR; 3689 goto done; 3690 } 3691 3692 if (get_hook(bh, presnapbuf, sizeof (presnapbuf), brand_get_presnap, 3693 source_zone, source_zonepath) != Z_OK) { 3694 zerror("invalid brand configuration: missing presnap " 3695 "resource"); 3696 brand_close(bh); 3697 err = Z_ERR; 3698 goto done; 3699 } 3700 3701 if (get_hook(bh, postsnapbuf, sizeof (postsnapbuf), brand_get_postsnap, 3702 source_zone, source_zonepath) != Z_OK) { 3703 zerror("invalid brand configuration: missing postsnap " 3704 "resource"); 3705 brand_close(bh); 3706 err = Z_ERR; 3707 goto done; 3708 } 3709 3710 if (get_hook(bh, validsnapbuf, sizeof (validsnapbuf), 3711 brand_get_validatesnap, target_zone, zonepath) != Z_OK) { 3712 zerror("invalid brand configuration: missing validatesnap " 3713 "resource"); 3714 brand_close(bh); 3715 err = Z_ERR; 3716 goto done; 3717 } 3718 brand_close(bh); 3719 3720 /* Append all options to clone hook. */ 3721 if (addoptions(cmdbuf, argv, sizeof (cmdbuf)) != Z_OK) { 3722 err = Z_ERR; 3723 goto done; 3724 } 3725 3726 /* Append all options to postclone hook. */ 3727 if (addoptions(postcmdbuf, argv, sizeof (postcmdbuf)) != Z_OK) { 3728 err = Z_ERR; 3729 goto done; 3730 } 3731 3732 if (!brand_help) { 3733 if ((err = zone_set_state(target_zone, ZONE_STATE_INCOMPLETE)) 3734 != Z_OK) { 3735 errno = err; 3736 zperror2(target_zone, gettext("could not set state")); 3737 goto done; 3738 } 3739 } 3740 3741 /* 3742 * The clone hook is optional. If it exists, use the hook for 3743 * cloning, otherwise use the built-in clone support 3744 */ 3745 if (cmdbuf[0] != '\0') { 3746 /* Run the clone hook */ 3747 status = do_subproc(cmdbuf); 3748 if ((status = subproc_status(gettext("brand-specific clone"), 3749 status, B_FALSE)) != ZONE_SUBPROC_OK) { 3750 if (status == ZONE_SUBPROC_USAGE && !brand_help) 3751 sub_usage(SHELP_CLONE, CMD_CLONE); 3752 err = Z_ERR; 3753 goto done; 3754 } 3755 3756 if (brand_help) 3757 return (Z_OK); 3758 3759 } else { 3760 /* If just help, we're done since there is no brand help. */ 3761 if (brand_help) 3762 return (Z_OK); 3763 3764 /* Run the built-in clone support. */ 3765 3766 /* The only explicit built-in method is "copy". */ 3767 if (method != NULL && strcmp(method, "copy") != 0) { 3768 sub_usage(SHELP_CLONE, CMD_CLONE); 3769 err = Z_USAGE; 3770 goto done; 3771 } 3772 3773 if (snapshot != NULL) { 3774 err = clone_snapshot_zfs(snapshot, zonepath, 3775 validsnapbuf); 3776 } else { 3777 /* 3778 * We always copy the clone unless the source is ZFS 3779 * and a ZFS clone worked. We fallback to copying if 3780 * the ZFS clone fails for some reason. 3781 */ 3782 err = Z_ERR; 3783 if (method == NULL && is_zonepath_zfs(source_zonepath)) 3784 err = clone_zfs(source_zonepath, zonepath, 3785 presnapbuf, postsnapbuf); 3786 3787 if (err != Z_OK) 3788 err = clone_copy(source_zonepath, zonepath); 3789 } 3790 } 3791 3792 if (err == Z_OK && postcmdbuf[0] != '\0') { 3793 status = do_subproc(postcmdbuf); 3794 if ((err = subproc_status("postclone", status, B_FALSE)) 3795 != ZONE_SUBPROC_OK) { 3796 zerror(gettext("post-clone configuration failed.")); 3797 err = Z_ERR; 3798 } 3799 } 3800 3801 done: 3802 /* 3803 * If everything went well, we mark the zone as installed. 3804 */ 3805 if (err == Z_OK) { 3806 err = zone_set_state(target_zone, ZONE_STATE_INSTALLED); 3807 if (err != Z_OK) { 3808 errno = err; 3809 zperror2(target_zone, gettext("could not set state")); 3810 } 3811 } 3812 if (!brand_help) 3813 zonecfg_release_lock_file(target_zone, lockfd); 3814 return ((err == Z_OK) ? Z_OK : Z_ERR); 3815 } 3816 3817 /* 3818 * Used when removing a zonepath after uninstalling or cleaning up after 3819 * the move subcommand. This handles a zonepath that has non-standard 3820 * contents so that we will only cleanup the stuff we know about and leave 3821 * any user data alone. 3822 * 3823 * If the "all" parameter is true then we should remove the whole zonepath 3824 * even if it has non-standard files/directories in it. This can be used when 3825 * we need to cleanup after moving the zonepath across file systems. 3826 * 3827 * We "exec" the RMCOMMAND so that the returned status is that of RMCOMMAND 3828 * and not the shell. 3829 */ 3830 static int 3831 cleanup_zonepath(char *zonepath, boolean_t all) 3832 { 3833 int status; 3834 int i; 3835 boolean_t non_std = B_FALSE; 3836 struct dirent *dp; 3837 DIR *dirp; 3838 /* 3839 * The SUNWattached.xml file is expected since it might 3840 * exist if the zone was force-attached after a 3841 * migration. 3842 */ 3843 char *std_entries[] = {"dev", "lu", "root", 3844 "SUNWattached.xml", NULL}; 3845 /* (MAXPATHLEN * 3) is for the 3 std_entries dirs */ 3846 char cmdbuf[sizeof (RMCOMMAND) + (MAXPATHLEN * 3) + 64]; 3847 3848 /* 3849 * We shouldn't need these checks but lets be paranoid since we 3850 * could blow away the whole system here if we got the wrong zonepath. 3851 */ 3852 if (*zonepath == NULL || strcmp(zonepath, "/") == 0) { 3853 (void) fprintf(stderr, "invalid zonepath '%s'\n", zonepath); 3854 return (Z_INVAL); 3855 } 3856 3857 /* 3858 * If the dirpath is already gone (maybe it was manually removed) then 3859 * we just return Z_OK so that the cleanup is successful. 3860 */ 3861 if ((dirp = opendir(zonepath)) == NULL) 3862 return (Z_OK); 3863 3864 /* 3865 * Look through the zonepath directory to see if there are any 3866 * non-standard files/dirs. Also skip .zfs since that might be 3867 * there but we'll handle ZFS file systems as a special case. 3868 */ 3869 while ((dp = readdir(dirp)) != NULL) { 3870 if (strcmp(dp->d_name, ".") == 0 || 3871 strcmp(dp->d_name, "..") == 0 || 3872 strcmp(dp->d_name, ".zfs") == 0) 3873 continue; 3874 3875 for (i = 0; std_entries[i] != NULL; i++) 3876 if (strcmp(dp->d_name, std_entries[i]) == 0) 3877 break; 3878 3879 if (std_entries[i] == NULL) 3880 non_std = B_TRUE; 3881 } 3882 (void) closedir(dirp); 3883 3884 if (!all && non_std) { 3885 /* 3886 * There are extra, non-standard directories/files in the 3887 * zonepath so we don't want to remove the zonepath. We 3888 * just want to remove the standard directories and leave 3889 * the user data alone. 3890 */ 3891 (void) snprintf(cmdbuf, sizeof (cmdbuf), "exec " RMCOMMAND); 3892 3893 for (i = 0; std_entries[i] != NULL; i++) { 3894 char tmpbuf[MAXPATHLEN]; 3895 3896 if (snprintf(tmpbuf, sizeof (tmpbuf), " %s/%s", 3897 zonepath, std_entries[i]) >= sizeof (tmpbuf) || 3898 strlcat(cmdbuf, tmpbuf, sizeof (cmdbuf)) >= 3899 sizeof (cmdbuf)) { 3900 (void) fprintf(stderr, 3901 gettext("path is too long\n")); 3902 return (Z_INVAL); 3903 } 3904 } 3905 3906 status = do_subproc(cmdbuf); 3907 3908 (void) fprintf(stderr, gettext("WARNING: Unable to completely " 3909 "remove %s\nbecause it contains additional user data. " 3910 "Only the standard directory\nentries have been " 3911 "removed.\n"), 3912 zonepath); 3913 3914 return ((subproc_status(RMCOMMAND, status, B_TRUE) == 3915 ZONE_SUBPROC_OK) ? Z_OK : Z_ERR); 3916 } 3917 3918 /* 3919 * There is nothing unexpected in the zonepath, try to get rid of the 3920 * whole zonepath directory. 3921 * 3922 * If the zonepath is its own zfs file system, try to destroy the 3923 * file system. If that fails for some reason (e.g. it has clones) 3924 * then we'll just remove the contents of the zonepath. 3925 */ 3926 if (is_zonepath_zfs(zonepath)) { 3927 if (destroy_zfs(zonepath) == Z_OK) 3928 return (Z_OK); 3929 (void) snprintf(cmdbuf, sizeof (cmdbuf), "exec " RMCOMMAND 3930 " %s/*", zonepath); 3931 status = do_subproc(cmdbuf); 3932 return ((subproc_status(RMCOMMAND, status, B_TRUE) == 3933 ZONE_SUBPROC_OK) ? Z_OK : Z_ERR); 3934 } 3935 3936 (void) snprintf(cmdbuf, sizeof (cmdbuf), "exec " RMCOMMAND " %s", 3937 zonepath); 3938 status = do_subproc(cmdbuf); 3939 3940 return ((subproc_status(RMCOMMAND, status, B_TRUE) == ZONE_SUBPROC_OK) 3941 ? Z_OK : Z_ERR); 3942 } 3943 3944 static int 3945 move_func(int argc, char *argv[]) 3946 { 3947 char *new_zonepath = NULL; 3948 int lockfd; 3949 int err, arg; 3950 char zonepath[MAXPATHLEN]; 3951 zone_dochandle_t handle; 3952 boolean_t fast; 3953 boolean_t is_zfs = B_FALSE; 3954 struct dirent *dp; 3955 DIR *dirp; 3956 boolean_t empty = B_TRUE; 3957 boolean_t revert; 3958 struct stat zonepath_buf; 3959 struct stat new_zonepath_buf; 3960 3961 if (zonecfg_in_alt_root()) { 3962 zerror(gettext("cannot move zone in alternate root")); 3963 return (Z_ERR); 3964 } 3965 3966 optind = 0; 3967 if ((arg = getopt(argc, argv, "?")) != EOF) { 3968 switch (arg) { 3969 case '?': 3970 sub_usage(SHELP_MOVE, CMD_MOVE); 3971 return (optopt == '?' ? Z_OK : Z_USAGE); 3972 default: 3973 sub_usage(SHELP_MOVE, CMD_MOVE); 3974 return (Z_USAGE); 3975 } 3976 } 3977 if (argc != (optind + 1)) { 3978 sub_usage(SHELP_MOVE, CMD_MOVE); 3979 return (Z_USAGE); 3980 } 3981 new_zonepath = argv[optind]; 3982 if (sanity_check(target_zone, CMD_MOVE, B_FALSE, B_TRUE, B_FALSE) 3983 != Z_OK) 3984 return (Z_ERR); 3985 if (verify_details(CMD_MOVE, argv) != Z_OK) 3986 return (Z_ERR); 3987 3988 /* 3989 * Check out the new zonepath. This has the side effect of creating 3990 * a directory for the new zonepath. We depend on this later when we 3991 * stat to see if we are doing a cross file system move or not. 3992 */ 3993 if (validate_zonepath(new_zonepath, CMD_MOVE) != Z_OK) 3994 return (Z_ERR); 3995 3996 if ((err = zone_get_zonepath(target_zone, zonepath, sizeof (zonepath))) 3997 != Z_OK) { 3998 errno = err; 3999 zperror2(target_zone, gettext("could not get zone path")); 4000 return (Z_ERR); 4001 } 4002 4003 if (stat(zonepath, &zonepath_buf) == -1) { 4004 zperror(gettext("could not stat zone path"), B_FALSE); 4005 return (Z_ERR); 4006 } 4007 4008 if (stat(new_zonepath, &new_zonepath_buf) == -1) { 4009 zperror(gettext("could not stat new zone path"), B_FALSE); 4010 return (Z_ERR); 4011 } 4012 4013 /* 4014 * Check if the destination directory is empty. 4015 */ 4016 if ((dirp = opendir(new_zonepath)) == NULL) { 4017 zperror(gettext("could not open new zone path"), B_FALSE); 4018 return (Z_ERR); 4019 } 4020 while ((dp = readdir(dirp)) != (struct dirent *)0) { 4021 if (strcmp(dp->d_name, ".") == 0 || 4022 strcmp(dp->d_name, "..") == 0) 4023 continue; 4024 empty = B_FALSE; 4025 break; 4026 } 4027 (void) closedir(dirp); 4028 4029 /* Error if there is anything in the destination directory. */ 4030 if (!empty) { 4031 (void) fprintf(stderr, gettext("could not move zone to %s: " 4032 "directory not empty\n"), new_zonepath); 4033 return (Z_ERR); 4034 } 4035 4036 /* Don't move the zone if anything is still mounted there */ 4037 if (zonecfg_find_mounts(zonepath, NULL, NULL)) { 4038 zerror(gettext("These file systems are mounted on " 4039 "subdirectories of %s.\n"), zonepath); 4040 (void) zonecfg_find_mounts(zonepath, zfm_print, NULL); 4041 return (Z_ERR); 4042 } 4043 4044 /* 4045 * Check if we are moving in the same file system and can do a fast 4046 * move or if we are crossing file systems and have to copy the data. 4047 */ 4048 fast = (zonepath_buf.st_dev == new_zonepath_buf.st_dev); 4049 4050 if ((handle = zonecfg_init_handle()) == NULL) { 4051 zperror(cmd_to_str(CMD_MOVE), B_TRUE); 4052 return (Z_ERR); 4053 } 4054 4055 if ((err = zonecfg_get_handle(target_zone, handle)) != Z_OK) { 4056 errno = err; 4057 zperror(cmd_to_str(CMD_MOVE), B_TRUE); 4058 zonecfg_fini_handle(handle); 4059 return (Z_ERR); 4060 } 4061 4062 if (zonecfg_grab_lock_file(target_zone, &lockfd) != Z_OK) { 4063 zerror(gettext("another %s may have an operation in progress."), 4064 "zoneadm"); 4065 zonecfg_fini_handle(handle); 4066 return (Z_ERR); 4067 } 4068 4069 /* 4070 * We're making some file system changes now so we have to clean up 4071 * the file system before we are done. This will either clean up the 4072 * new zonepath if the zonecfg update failed or it will clean up the 4073 * old zonepath if everything is ok. 4074 */ 4075 revert = B_TRUE; 4076 4077 if (is_zonepath_zfs(zonepath) && 4078 move_zfs(zonepath, new_zonepath) != Z_ERR) { 4079 is_zfs = B_TRUE; 4080 4081 } else if (fast) { 4082 /* same file system, use rename for a quick move */ 4083 4084 /* 4085 * Remove the new_zonepath directory that got created above 4086 * during the validation. It gets in the way of the rename. 4087 */ 4088 if (rmdir(new_zonepath) != 0) { 4089 zperror(gettext("could not rmdir new zone path"), 4090 B_FALSE); 4091 zonecfg_fini_handle(handle); 4092 zonecfg_release_lock_file(target_zone, lockfd); 4093 return (Z_ERR); 4094 } 4095 4096 if (rename(zonepath, new_zonepath) != 0) { 4097 /* 4098 * If this fails we don't need to do all of the 4099 * cleanup that happens for the rest of the code 4100 * so just return from this error. 4101 */ 4102 zperror(gettext("could not move zone"), B_FALSE); 4103 zonecfg_fini_handle(handle); 4104 zonecfg_release_lock_file(target_zone, lockfd); 4105 return (Z_ERR); 4106 } 4107 4108 } else { 4109 /* 4110 * Attempt to create a ZFS fs for the new zonepath. As usual, 4111 * we don't care if this works or not since we always have the 4112 * default behavior of a simple directory for the zonepath. 4113 */ 4114 create_zfs_zonepath(new_zonepath); 4115 4116 (void) printf(gettext( 4117 "Moving across file systems; copying zonepath %s..."), 4118 zonepath); 4119 (void) fflush(stdout); 4120 4121 err = copy_zone(zonepath, new_zonepath); 4122 4123 (void) printf("\n"); 4124 if (err != Z_OK) 4125 goto done; 4126 } 4127 4128 if ((err = zonecfg_set_zonepath(handle, new_zonepath)) != Z_OK) { 4129 errno = err; 4130 zperror(gettext("could not set new zonepath"), B_TRUE); 4131 goto done; 4132 } 4133 4134 if ((err = zonecfg_save(handle)) != Z_OK) { 4135 errno = err; 4136 zperror(gettext("zonecfg save failed"), B_TRUE); 4137 goto done; 4138 } 4139 4140 revert = B_FALSE; 4141 4142 done: 4143 zonecfg_fini_handle(handle); 4144 zonecfg_release_lock_file(target_zone, lockfd); 4145 4146 /* 4147 * Clean up the file system based on how things went. We either 4148 * clean up the new zonepath if the operation failed for some reason 4149 * or we clean up the old zonepath if everything is ok. 4150 */ 4151 if (revert) { 4152 /* The zonecfg update failed, cleanup the new zonepath. */ 4153 if (is_zfs) { 4154 if (move_zfs(new_zonepath, zonepath) == Z_ERR) { 4155 (void) fprintf(stderr, gettext("could not " 4156 "restore zonepath, the zfs mountpoint is " 4157 "set as:\n%s\n"), new_zonepath); 4158 /* 4159 * err is already != Z_OK since we're reverting 4160 */ 4161 } 4162 4163 } else if (fast) { 4164 if (rename(new_zonepath, zonepath) != 0) { 4165 zperror(gettext("could not restore zonepath"), 4166 B_FALSE); 4167 /* 4168 * err is already != Z_OK since we're reverting 4169 */ 4170 } 4171 } else { 4172 (void) printf(gettext("Cleaning up zonepath %s..."), 4173 new_zonepath); 4174 (void) fflush(stdout); 4175 err = cleanup_zonepath(new_zonepath, B_TRUE); 4176 (void) printf("\n"); 4177 4178 if (err != Z_OK) { 4179 errno = err; 4180 zperror(gettext("could not remove new " 4181 "zonepath"), B_TRUE); 4182 } else { 4183 /* 4184 * Because we're reverting we know the mainline 4185 * code failed but we just reused the err 4186 * variable so we reset it back to Z_ERR. 4187 */ 4188 err = Z_ERR; 4189 } 4190 } 4191 4192 } else { 4193 /* The move was successful, cleanup the old zonepath. */ 4194 if (!is_zfs && !fast) { 4195 (void) printf( 4196 gettext("Cleaning up zonepath %s..."), zonepath); 4197 (void) fflush(stdout); 4198 err = cleanup_zonepath(zonepath, B_TRUE); 4199 (void) printf("\n"); 4200 4201 if (err != Z_OK) { 4202 errno = err; 4203 zperror(gettext("could not remove zonepath"), 4204 B_TRUE); 4205 } 4206 } 4207 } 4208 4209 return ((err == Z_OK) ? Z_OK : Z_ERR); 4210 } 4211 4212 /* ARGSUSED */ 4213 static int 4214 detach_func(int argc, char *argv[]) 4215 { 4216 int lockfd = -1; 4217 int err, arg; 4218 char zonepath[MAXPATHLEN]; 4219 char cmdbuf[MAXPATHLEN]; 4220 char precmdbuf[MAXPATHLEN]; 4221 boolean_t execute = B_TRUE; 4222 boolean_t brand_help = B_FALSE; 4223 brand_handle_t bh = NULL; 4224 int status; 4225 4226 if (zonecfg_in_alt_root()) { 4227 zerror(gettext("cannot detach zone in alternate root")); 4228 return (Z_ERR); 4229 } 4230 4231 /* Check the argv string for args we handle internally */ 4232 optind = 0; 4233 opterr = 0; 4234 while ((arg = getopt(argc, argv, "?n")) != EOF) { 4235 switch (arg) { 4236 case '?': 4237 if (optopt == '?') { 4238 sub_usage(SHELP_DETACH, CMD_DETACH); 4239 brand_help = B_TRUE; 4240 } 4241 /* Ignore unknown options - may be brand specific. */ 4242 break; 4243 case 'n': 4244 execute = B_FALSE; 4245 break; 4246 default: 4247 /* Ignore unknown options - may be brand specific. */ 4248 break; 4249 } 4250 } 4251 4252 if (brand_help) 4253 execute = B_FALSE; 4254 4255 if (execute) { 4256 if (sanity_check(target_zone, CMD_DETACH, B_FALSE, B_TRUE, 4257 B_FALSE) != Z_OK) 4258 return (Z_ERR); 4259 if (verify_details(CMD_DETACH, argv) != Z_OK) 4260 return (Z_ERR); 4261 } else { 4262 /* 4263 * We want a dry-run to work for a non-privileged user so we 4264 * only do minimal validation. 4265 */ 4266 if (target_zone == NULL) { 4267 zerror(gettext("no zone specified")); 4268 return (Z_ERR); 4269 } 4270 4271 if (strcmp(target_zone, GLOBAL_ZONENAME) == 0) { 4272 zerror(gettext("%s operation is invalid for the " 4273 "global zone."), cmd_to_str(CMD_DETACH)); 4274 return (Z_ERR); 4275 } 4276 } 4277 4278 if ((err = zone_get_zonepath(target_zone, zonepath, sizeof (zonepath))) 4279 != Z_OK) { 4280 errno = err; 4281 zperror2(target_zone, gettext("could not get zone path")); 4282 return (Z_ERR); 4283 } 4284 4285 /* Fetch the detach and predetach hooks from the brand configuration. */ 4286 if ((bh = brand_open(target_brand)) == NULL) { 4287 zerror(gettext("missing or invalid brand")); 4288 return (Z_ERR); 4289 } 4290 4291 if (get_hook(bh, cmdbuf, sizeof (cmdbuf), brand_get_detach, target_zone, 4292 zonepath) != Z_OK) { 4293 zerror("invalid brand configuration: missing detach resource"); 4294 brand_close(bh); 4295 return (Z_ERR); 4296 } 4297 4298 if (get_hook(bh, precmdbuf, sizeof (precmdbuf), brand_get_predetach, 4299 target_zone, zonepath) != Z_OK) { 4300 zerror("invalid brand configuration: missing predetach " 4301 "resource"); 4302 brand_close(bh); 4303 return (Z_ERR); 4304 } 4305 brand_close(bh); 4306 4307 /* Append all options to predetach hook. */ 4308 if (addoptions(precmdbuf, argv, sizeof (precmdbuf)) != Z_OK) 4309 return (Z_ERR); 4310 4311 /* Append all options to detach hook. */ 4312 if (addoptions(cmdbuf, argv, sizeof (cmdbuf)) != Z_OK) 4313 return (Z_ERR); 4314 4315 if (execute && zonecfg_grab_lock_file(target_zone, &lockfd) != Z_OK) { 4316 zerror(gettext("another %s may have an operation in progress."), 4317 "zoneadm"); 4318 return (Z_ERR); 4319 } 4320 4321 /* If we have a brand predetach hook, run it. */ 4322 if (!brand_help && precmdbuf[0] != '\0') { 4323 status = do_subproc(precmdbuf); 4324 if (subproc_status(gettext("brand-specific predetach"), 4325 status, B_FALSE) != ZONE_SUBPROC_OK) { 4326 4327 if (execute) { 4328 assert(lockfd >= 0); 4329 zonecfg_release_lock_file(target_zone, lockfd); 4330 lockfd = -1; 4331 } 4332 4333 assert(lockfd == -1); 4334 return (Z_ERR); 4335 } 4336 } 4337 4338 if (cmdbuf[0] != '\0') { 4339 /* Run the detach hook */ 4340 status = do_subproc(cmdbuf); 4341 if ((status = subproc_status(gettext("brand-specific detach"), 4342 status, B_FALSE)) != ZONE_SUBPROC_OK) { 4343 if (status == ZONE_SUBPROC_USAGE && !brand_help) 4344 sub_usage(SHELP_DETACH, CMD_DETACH); 4345 4346 if (execute) { 4347 assert(lockfd >= 0); 4348 zonecfg_release_lock_file(target_zone, lockfd); 4349 lockfd = -1; 4350 } 4351 4352 assert(lockfd == -1); 4353 return (Z_ERR); 4354 } 4355 4356 } else { 4357 zone_dochandle_t handle; 4358 4359 /* If just help, we're done since there is no brand help. */ 4360 if (brand_help) { 4361 assert(lockfd == -1); 4362 return (Z_OK); 4363 } 4364 4365 /* 4366 * Run the built-in detach support. Just generate a simple 4367 * zone definition XML file and detach. 4368 */ 4369 4370 /* Don't detach the zone if anything is still mounted there */ 4371 if (execute && zonecfg_find_mounts(zonepath, NULL, NULL)) { 4372 (void) fprintf(stderr, gettext("These file systems are " 4373 "mounted on subdirectories of %s.\n"), zonepath); 4374 (void) zonecfg_find_mounts(zonepath, zfm_print, NULL); 4375 err = ZONE_SUBPROC_NOTCOMPLETE; 4376 goto done; 4377 } 4378 4379 if ((handle = zonecfg_init_handle()) == NULL) { 4380 zperror(cmd_to_str(CMD_DETACH), B_TRUE); 4381 err = ZONE_SUBPROC_NOTCOMPLETE; 4382 goto done; 4383 } 4384 4385 if ((err = zonecfg_get_handle(target_zone, handle)) != Z_OK) { 4386 errno = err; 4387 zperror(cmd_to_str(CMD_DETACH), B_TRUE); 4388 4389 } else if ((err = zonecfg_detach_save(handle, 4390 (execute ? 0 : ZONE_DRY_RUN))) != Z_OK) { 4391 errno = err; 4392 zperror(gettext("saving the detach manifest failed"), 4393 B_TRUE); 4394 } 4395 4396 zonecfg_fini_handle(handle); 4397 if (err != Z_OK) 4398 goto done; 4399 } 4400 4401 /* 4402 * Set the zone state back to configured unless we are running with the 4403 * no-execute option. 4404 */ 4405 if (execute && (err = zone_set_state(target_zone, 4406 ZONE_STATE_CONFIGURED)) != Z_OK) { 4407 errno = err; 4408 zperror(gettext("could not reset state"), B_TRUE); 4409 } 4410 4411 done: 4412 if (execute) { 4413 assert(lockfd >= 0); 4414 zonecfg_release_lock_file(target_zone, lockfd); 4415 lockfd = -1; 4416 } 4417 4418 assert(lockfd == -1); 4419 return ((err == Z_OK) ? Z_OK : Z_ERR); 4420 } 4421 4422 /* 4423 * Determine the brand when doing a dry-run attach. The zone does not have to 4424 * exist, so we have to read the incoming manifest to determine the zone's 4425 * brand. 4426 * 4427 * Because the manifest has to be processed twice; once to determine the brand 4428 * and once to do the brand-specific attach logic, we always read it into a tmp 4429 * file. This handles the manifest coming from stdin or a regular file. The 4430 * tmpname parameter returns the name of the temporary file that the manifest 4431 * was read into. 4432 */ 4433 static int 4434 dryrun_get_brand(char *manifest_path, char *tmpname, int size) 4435 { 4436 int fd; 4437 int err; 4438 int res = Z_OK; 4439 zone_dochandle_t local_handle; 4440 zone_dochandle_t rem_handle = NULL; 4441 int len; 4442 int ofd; 4443 char buf[512]; 4444 4445 if (strcmp(manifest_path, "-") == 0) { 4446 fd = STDIN_FILENO; 4447 } else { 4448 if ((fd = open(manifest_path, O_RDONLY)) < 0) { 4449 if (getcwd(buf, sizeof (buf)) == NULL) 4450 (void) strlcpy(buf, "/", sizeof (buf)); 4451 zerror(gettext("could not open manifest path %s%s: %s"), 4452 (*manifest_path == '/' ? "" : buf), manifest_path, 4453 strerror(errno)); 4454 return (Z_ERR); 4455 } 4456 } 4457 4458 (void) snprintf(tmpname, size, "/var/run/zone.%d", getpid()); 4459 4460 if ((ofd = open(tmpname, O_WRONLY | O_CREAT, S_IRUSR | S_IWUSR)) < 0) { 4461 zperror(gettext("could not save manifest"), B_FALSE); 4462 (void) close(fd); 4463 return (Z_ERR); 4464 } 4465 4466 while ((len = read(fd, buf, sizeof (buf))) > 0) { 4467 if (write(ofd, buf, len) == -1) { 4468 zperror(gettext("could not save manifest"), B_FALSE); 4469 (void) close(ofd); 4470 (void) close(fd); 4471 return (Z_ERR); 4472 } 4473 } 4474 4475 if (close(ofd) != 0) { 4476 zperror(gettext("could not save manifest"), B_FALSE); 4477 (void) close(fd); 4478 return (Z_ERR); 4479 } 4480 4481 (void) close(fd); 4482 4483 if ((fd = open(tmpname, O_RDONLY)) < 0) { 4484 zperror(gettext("could not open manifest path"), B_FALSE); 4485 return (Z_ERR); 4486 } 4487 4488 if ((local_handle = zonecfg_init_handle()) == NULL) { 4489 zperror(cmd_to_str(CMD_ATTACH), B_TRUE); 4490 res = Z_ERR; 4491 goto done; 4492 } 4493 4494 if ((rem_handle = zonecfg_init_handle()) == NULL) { 4495 zperror(cmd_to_str(CMD_ATTACH), B_TRUE); 4496 res = Z_ERR; 4497 goto done; 4498 } 4499 4500 if ((err = zonecfg_attach_manifest(fd, local_handle, rem_handle)) 4501 != Z_OK) { 4502 res = Z_ERR; 4503 4504 if (err == Z_INVALID_DOCUMENT) { 4505 struct stat st; 4506 char buf[6]; 4507 4508 if (strcmp(manifest_path, "-") == 0) { 4509 zerror(gettext("Input is not a valid XML " 4510 "file")); 4511 goto done; 4512 } 4513 4514 if (fstat(fd, &st) == -1 || !S_ISREG(st.st_mode)) { 4515 zerror(gettext("%s is not an XML file"), 4516 manifest_path); 4517 goto done; 4518 } 4519 4520 bzero(buf, sizeof (buf)); 4521 (void) lseek(fd, 0L, SEEK_SET); 4522 if (read(fd, buf, sizeof (buf) - 1) < 0 || 4523 strncmp(buf, "<?xml", 5) != 0) 4524 zerror(gettext("%s is not an XML file"), 4525 manifest_path); 4526 else 4527 zerror(gettext("Cannot attach to an earlier " 4528 "release of the operating system")); 4529 } else { 4530 zperror(cmd_to_str(CMD_ATTACH), B_TRUE); 4531 } 4532 goto done; 4533 } 4534 4535 /* Retrieve remote handle brand type. */ 4536 if (zonecfg_get_brand(rem_handle, target_brand, sizeof (target_brand)) 4537 != Z_OK) { 4538 zerror(gettext("missing or invalid brand")); 4539 exit(Z_ERR); 4540 } 4541 4542 done: 4543 zonecfg_fini_handle(local_handle); 4544 zonecfg_fini_handle(rem_handle); 4545 (void) close(fd); 4546 4547 return ((res == Z_OK) ? Z_OK : Z_ERR); 4548 } 4549 4550 /* ARGSUSED */ 4551 static int 4552 attach_func(int argc, char *argv[]) 4553 { 4554 int lockfd = -1; 4555 int err, arg; 4556 boolean_t force = B_FALSE; 4557 zone_dochandle_t handle; 4558 char zonepath[MAXPATHLEN]; 4559 char cmdbuf[MAXPATHLEN]; 4560 char postcmdbuf[MAXPATHLEN]; 4561 boolean_t execute = B_TRUE; 4562 boolean_t brand_help = B_FALSE; 4563 char *manifest_path; 4564 char tmpmanifest[80]; 4565 int manifest_pos; 4566 brand_handle_t bh = NULL; 4567 int status; 4568 int last_index = 0; 4569 int offset; 4570 char *up; 4571 boolean_t forced_update = B_FALSE; 4572 4573 if (zonecfg_in_alt_root()) { 4574 zerror(gettext("cannot attach zone in alternate root")); 4575 return (Z_ERR); 4576 } 4577 4578 /* Check the argv string for args we handle internally */ 4579 optind = 0; 4580 opterr = 0; 4581 while ((arg = getopt(argc, argv, "?Fn:U")) != EOF) { 4582 switch (arg) { 4583 case '?': 4584 if (optopt == '?') { 4585 sub_usage(SHELP_ATTACH, CMD_ATTACH); 4586 brand_help = B_TRUE; 4587 } 4588 /* Ignore unknown options - may be brand specific. */ 4589 break; 4590 case 'F': 4591 force = B_TRUE; 4592 break; 4593 case 'n': 4594 execute = B_FALSE; 4595 manifest_path = optarg; 4596 manifest_pos = optind - 1; 4597 break; 4598 case 'U': 4599 /* 4600 * Undocumented 'force update' option for p2v update on 4601 * attach when zone is in the incomplete state. Change 4602 * the option back to 'u' and set forced_update flag. 4603 */ 4604 if (optind == last_index) 4605 offset = optind; 4606 else 4607 offset = optind - 1; 4608 if ((up = index(argv[offset], 'U')) != NULL) 4609 *up = 'u'; 4610 forced_update = B_TRUE; 4611 break; 4612 default: 4613 /* Ignore unknown options - may be brand specific. */ 4614 break; 4615 } 4616 last_index = optind; 4617 } 4618 4619 if (brand_help) { 4620 force = B_FALSE; 4621 execute = B_TRUE; 4622 } 4623 4624 /* dry-run and force flags are mutually exclusive */ 4625 if (!execute && force) { 4626 zerror(gettext("-F and -n flags are mutually exclusive")); 4627 return (Z_ERR); 4628 } 4629 4630 /* 4631 * If the no-execute option was specified, we don't do validation and 4632 * need to figure out the brand, since there is no zone required to be 4633 * configured for this option. 4634 */ 4635 if (execute) { 4636 if (!brand_help) { 4637 if (sanity_check(target_zone, CMD_ATTACH, B_FALSE, 4638 B_TRUE, forced_update) != Z_OK) 4639 return (Z_ERR); 4640 if (verify_details(CMD_ATTACH, argv) != Z_OK) 4641 return (Z_ERR); 4642 } 4643 4644 if ((err = zone_get_zonepath(target_zone, zonepath, 4645 sizeof (zonepath))) != Z_OK) { 4646 errno = err; 4647 zperror2(target_zone, 4648 gettext("could not get zone path")); 4649 return (Z_ERR); 4650 } 4651 } else { 4652 if (dryrun_get_brand(manifest_path, tmpmanifest, 4653 sizeof (tmpmanifest)) != Z_OK) 4654 return (Z_ERR); 4655 4656 argv[manifest_pos] = tmpmanifest; 4657 target_zone = "-"; 4658 (void) strlcpy(zonepath, "-", sizeof (zonepath)); 4659 4660 /* Run the brand's verify_adm hook. */ 4661 if (verify_brand(NULL, CMD_ATTACH, argv) != Z_OK) 4662 return (Z_ERR); 4663 } 4664 4665 /* 4666 * Fetch the attach and postattach hooks from the brand configuration. 4667 */ 4668 if ((bh = brand_open(target_brand)) == NULL) { 4669 zerror(gettext("missing or invalid brand")); 4670 return (Z_ERR); 4671 } 4672 4673 if (get_hook(bh, cmdbuf, sizeof (cmdbuf), brand_get_attach, target_zone, 4674 zonepath) != Z_OK) { 4675 zerror("invalid brand configuration: missing attach resource"); 4676 brand_close(bh); 4677 return (Z_ERR); 4678 } 4679 4680 if (get_hook(bh, postcmdbuf, sizeof (postcmdbuf), brand_get_postattach, 4681 target_zone, zonepath) != Z_OK) { 4682 zerror("invalid brand configuration: missing postattach " 4683 "resource"); 4684 brand_close(bh); 4685 return (Z_ERR); 4686 } 4687 brand_close(bh); 4688 4689 /* Append all options to attach hook. */ 4690 if (addoptions(cmdbuf, argv, sizeof (cmdbuf)) != Z_OK) 4691 return (Z_ERR); 4692 4693 /* Append all options to postattach hook. */ 4694 if (addoptions(postcmdbuf, argv, sizeof (postcmdbuf)) != Z_OK) 4695 return (Z_ERR); 4696 4697 if (execute && !brand_help) { 4698 if (zonecfg_grab_lock_file(target_zone, &lockfd) != Z_OK) { 4699 zerror(gettext("another %s may have an operation in " 4700 "progress."), "zoneadm"); 4701 return (Z_ERR); 4702 } 4703 } 4704 4705 if (!force) { 4706 /* 4707 * Not a force-attach, so we need to actually do the work. 4708 */ 4709 if (cmdbuf[0] != '\0') { 4710 /* Run the attach hook */ 4711 status = do_subproc(cmdbuf); 4712 if ((status = subproc_status(gettext("brand-specific " 4713 "attach"), status, B_FALSE)) != ZONE_SUBPROC_OK) { 4714 if (status == ZONE_SUBPROC_USAGE && !brand_help) 4715 sub_usage(SHELP_ATTACH, CMD_ATTACH); 4716 4717 if (execute && !brand_help) { 4718 assert(zonecfg_lock_file_held(&lockfd)); 4719 zonecfg_release_lock_file(target_zone, 4720 lockfd); 4721 lockfd = -1; 4722 } 4723 4724 assert(lockfd == -1); 4725 return (Z_ERR); 4726 } 4727 } 4728 4729 /* 4730 * Else run the built-in attach support. 4731 * This is a no-op since there is nothing to validate. 4732 */ 4733 4734 /* If dry-run or help, then we're done. */ 4735 if (!execute || brand_help) { 4736 if (!execute) 4737 (void) unlink(tmpmanifest); 4738 assert(lockfd == -1); 4739 return (Z_OK); 4740 } 4741 } 4742 4743 /* Now we can validate that the zonepath exists. */ 4744 if (validate_zonepath(zonepath, CMD_ATTACH) != Z_OK) { 4745 (void) fprintf(stderr, gettext("could not verify zonepath %s " 4746 "because of the above errors.\n"), zonepath); 4747 4748 assert(zonecfg_lock_file_held(&lockfd)); 4749 zonecfg_release_lock_file(target_zone, lockfd); 4750 return (Z_ERR); 4751 } 4752 4753 if ((handle = zonecfg_init_handle()) == NULL) { 4754 zperror(cmd_to_str(CMD_ATTACH), B_TRUE); 4755 err = Z_ERR; 4756 } else if ((err = zonecfg_get_handle(target_zone, handle)) != Z_OK) { 4757 errno = err; 4758 zperror(cmd_to_str(CMD_ATTACH), B_TRUE); 4759 zonecfg_fini_handle(handle); 4760 } else { 4761 zonecfg_rm_detached(handle, force); 4762 zonecfg_fini_handle(handle); 4763 } 4764 4765 if (err == Z_OK && 4766 (err = zone_set_state(target_zone, ZONE_STATE_INSTALLED)) != Z_OK) { 4767 errno = err; 4768 zperror(gettext("could not reset state"), B_TRUE); 4769 } 4770 4771 assert(zonecfg_lock_file_held(&lockfd)); 4772 zonecfg_release_lock_file(target_zone, lockfd); 4773 lockfd = -1; 4774 4775 /* If we have a brand postattach hook, run it. */ 4776 if (err == Z_OK && !force && postcmdbuf[0] != '\0') { 4777 status = do_subproc(postcmdbuf); 4778 if (subproc_status(gettext("brand-specific postattach"), 4779 status, B_FALSE) != ZONE_SUBPROC_OK) { 4780 if ((err = zone_set_state(target_zone, 4781 ZONE_STATE_CONFIGURED)) != Z_OK) { 4782 errno = err; 4783 zperror(gettext("could not reset state"), 4784 B_TRUE); 4785 } 4786 } 4787 } 4788 4789 assert(lockfd == -1); 4790 return ((err == Z_OK) ? Z_OK : Z_ERR); 4791 } 4792 4793 /* 4794 * On input, TRUE => yes, FALSE => no. 4795 * On return, TRUE => 1, FALSE => 0, could not ask => -1. 4796 */ 4797 4798 static int 4799 ask_yesno(boolean_t default_answer, const char *question) 4800 { 4801 char line[64]; /* should be large enough to answer yes or no */ 4802 4803 if (!isatty(STDIN_FILENO)) 4804 return (-1); 4805 for (;;) { 4806 (void) printf("%s (%s)? ", question, 4807 default_answer ? "[y]/n" : "y/[n]"); 4808 if (fgets(line, sizeof (line), stdin) == NULL || 4809 line[0] == '\n') 4810 return (default_answer ? 1 : 0); 4811 if (tolower(line[0]) == 'y') 4812 return (1); 4813 if (tolower(line[0]) == 'n') 4814 return (0); 4815 } 4816 } 4817 4818 /* ARGSUSED */ 4819 static int 4820 uninstall_func(int argc, char *argv[]) 4821 { 4822 char line[ZONENAME_MAX + 128]; /* Enough for "Are you sure ..." */ 4823 char rootpath[MAXPATHLEN], zonepath[MAXPATHLEN]; 4824 char cmdbuf[MAXPATHLEN]; 4825 char precmdbuf[MAXPATHLEN]; 4826 boolean_t force = B_FALSE; 4827 int lockfd, answer; 4828 int err, arg; 4829 boolean_t brand_help = B_FALSE; 4830 brand_handle_t bh = NULL; 4831 int status; 4832 4833 if (zonecfg_in_alt_root()) { 4834 zerror(gettext("cannot uninstall zone in alternate root")); 4835 return (Z_ERR); 4836 } 4837 4838 /* Check the argv string for args we handle internally */ 4839 optind = 0; 4840 opterr = 0; 4841 while ((arg = getopt(argc, argv, "?F")) != EOF) { 4842 switch (arg) { 4843 case '?': 4844 if (optopt == '?') { 4845 sub_usage(SHELP_UNINSTALL, CMD_UNINSTALL); 4846 brand_help = B_TRUE; 4847 } 4848 /* Ignore unknown options - may be brand specific. */ 4849 break; 4850 case 'F': 4851 force = B_TRUE; 4852 break; 4853 default: 4854 /* Ignore unknown options - may be brand specific. */ 4855 break; 4856 } 4857 } 4858 4859 if (!brand_help) { 4860 if (sanity_check(target_zone, CMD_UNINSTALL, B_FALSE, B_TRUE, 4861 B_FALSE) != Z_OK) 4862 return (Z_ERR); 4863 4864 /* 4865 * Invoke brand-specific handler. 4866 */ 4867 if (invoke_brand_handler(CMD_UNINSTALL, argv) != Z_OK) 4868 return (Z_ERR); 4869 4870 if (!force) { 4871 (void) snprintf(line, sizeof (line), 4872 gettext("Are you sure you want to %s zone %s"), 4873 cmd_to_str(CMD_UNINSTALL), target_zone); 4874 if ((answer = ask_yesno(B_FALSE, line)) == 0) { 4875 return (Z_OK); 4876 } else if (answer == -1) { 4877 zerror(gettext("Input not from terminal and -F " 4878 "not specified: %s not done."), 4879 cmd_to_str(CMD_UNINSTALL)); 4880 return (Z_ERR); 4881 } 4882 } 4883 } 4884 4885 if ((err = zone_get_zonepath(target_zone, zonepath, 4886 sizeof (zonepath))) != Z_OK) { 4887 errno = err; 4888 zperror2(target_zone, gettext("could not get zone path")); 4889 return (Z_ERR); 4890 } 4891 4892 /* 4893 * Fetch the uninstall and preuninstall hooks from the brand 4894 * configuration. 4895 */ 4896 if ((bh = brand_open(target_brand)) == NULL) { 4897 zerror(gettext("missing or invalid brand")); 4898 return (Z_ERR); 4899 } 4900 4901 if (get_hook(bh, cmdbuf, sizeof (cmdbuf), brand_get_uninstall, 4902 target_zone, zonepath) != Z_OK) { 4903 zerror("invalid brand configuration: missing uninstall " 4904 "resource"); 4905 brand_close(bh); 4906 return (Z_ERR); 4907 } 4908 4909 if (get_hook(bh, precmdbuf, sizeof (precmdbuf), brand_get_preuninstall, 4910 target_zone, zonepath) != Z_OK) { 4911 zerror("invalid brand configuration: missing preuninstall " 4912 "resource"); 4913 brand_close(bh); 4914 return (Z_ERR); 4915 } 4916 brand_close(bh); 4917 4918 /* Append all options to preuninstall hook. */ 4919 if (addoptions(precmdbuf, argv, sizeof (precmdbuf)) != Z_OK) 4920 return (Z_ERR); 4921 4922 /* Append all options to uninstall hook. */ 4923 if (addoptions(cmdbuf, argv, sizeof (cmdbuf)) != Z_OK) 4924 return (Z_ERR); 4925 4926 if (!brand_help) { 4927 if ((err = zone_get_rootpath(target_zone, rootpath, 4928 sizeof (rootpath))) != Z_OK) { 4929 errno = err; 4930 zperror2(target_zone, gettext("could not get root " 4931 "path")); 4932 return (Z_ERR); 4933 } 4934 4935 /* 4936 * If there seems to be a zoneadmd running for this zone, call 4937 * it to tell it that an uninstall is happening; if all goes 4938 * well it will then shut itself down. 4939 */ 4940 if (zonecfg_ping_zoneadmd(target_zone) == Z_OK) { 4941 zone_cmd_arg_t zarg; 4942 zarg.cmd = Z_NOTE_UNINSTALLING; 4943 /* we don't care too much if this fails, just plow on */ 4944 (void) zonecfg_call_zoneadmd(target_zone, &zarg, locale, 4945 B_TRUE); 4946 } 4947 4948 if (zonecfg_grab_lock_file(target_zone, &lockfd) != Z_OK) { 4949 zerror(gettext("another %s may have an operation in " 4950 "progress."), "zoneadm"); 4951 return (Z_ERR); 4952 } 4953 4954 /* Don't uninstall the zone if anything is mounted there */ 4955 err = zonecfg_find_mounts(rootpath, NULL, NULL); 4956 if (err) { 4957 zerror(gettext("These file systems are mounted on " 4958 "subdirectories of %s.\n"), rootpath); 4959 (void) zonecfg_find_mounts(rootpath, zfm_print, NULL); 4960 zonecfg_release_lock_file(target_zone, lockfd); 4961 return (Z_ERR); 4962 } 4963 } 4964 4965 /* If we have a brand preuninstall hook, run it. */ 4966 if (!brand_help && precmdbuf[0] != '\0') { 4967 status = do_subproc(cmdbuf); 4968 if (subproc_status(gettext("brand-specific preuninstall"), 4969 status, B_FALSE) != ZONE_SUBPROC_OK) { 4970 zonecfg_release_lock_file(target_zone, lockfd); 4971 return (Z_ERR); 4972 } 4973 } 4974 4975 if (!brand_help) { 4976 err = zone_set_state(target_zone, ZONE_STATE_INCOMPLETE); 4977 if (err != Z_OK) { 4978 errno = err; 4979 zperror2(target_zone, gettext("could not set state")); 4980 goto bad; 4981 } 4982 } 4983 4984 /* 4985 * If there is a brand uninstall hook, use it, otherwise use the 4986 * built-in uninstall code. 4987 */ 4988 if (cmdbuf[0] != '\0') { 4989 /* Run the uninstall hook */ 4990 status = do_subproc(cmdbuf); 4991 if ((status = subproc_status(gettext("brand-specific " 4992 "uninstall"), status, B_FALSE)) != ZONE_SUBPROC_OK) { 4993 if (status == ZONE_SUBPROC_USAGE && !brand_help) 4994 sub_usage(SHELP_UNINSTALL, CMD_UNINSTALL); 4995 if (!brand_help) 4996 zonecfg_release_lock_file(target_zone, lockfd); 4997 return (Z_ERR); 4998 } 4999 5000 if (brand_help) 5001 return (Z_OK); 5002 } else { 5003 /* If just help, we're done since there is no brand help. */ 5004 if (brand_help) 5005 return (Z_OK); 5006 5007 /* Run the built-in uninstall support. */ 5008 if ((err = cleanup_zonepath(zonepath, B_FALSE)) != Z_OK) { 5009 errno = err; 5010 zperror2(target_zone, gettext("cleaning up zonepath " 5011 "failed")); 5012 goto bad; 5013 } 5014 } 5015 5016 err = zone_set_state(target_zone, ZONE_STATE_CONFIGURED); 5017 if (err != Z_OK) { 5018 errno = err; 5019 zperror2(target_zone, gettext("could not reset state")); 5020 } 5021 bad: 5022 zonecfg_release_lock_file(target_zone, lockfd); 5023 return (err); 5024 } 5025 5026 /* ARGSUSED */ 5027 static int 5028 mount_func(int argc, char *argv[]) 5029 { 5030 zone_cmd_arg_t zarg; 5031 boolean_t force = B_FALSE; 5032 int arg; 5033 5034 /* 5035 * The only supported subargument to the "mount" subcommand is 5036 * "-f", which forces us to mount a zone in the INCOMPLETE state. 5037 */ 5038 optind = 0; 5039 if ((arg = getopt(argc, argv, "f")) != EOF) { 5040 switch (arg) { 5041 case 'f': 5042 force = B_TRUE; 5043 break; 5044 default: 5045 return (Z_USAGE); 5046 } 5047 } 5048 if (argc > optind) 5049 return (Z_USAGE); 5050 5051 if (sanity_check(target_zone, CMD_MOUNT, B_FALSE, B_FALSE, force) 5052 != Z_OK) 5053 return (Z_ERR); 5054 if (verify_details(CMD_MOUNT, argv) != Z_OK) 5055 return (Z_ERR); 5056 5057 zarg.cmd = force ? Z_FORCEMOUNT : Z_MOUNT; 5058 zarg.bootbuf[0] = '\0'; 5059 if (zonecfg_call_zoneadmd(target_zone, &zarg, locale, B_TRUE) != 0) { 5060 zerror(gettext("call to %s failed"), "zoneadmd"); 5061 return (Z_ERR); 5062 } 5063 return (Z_OK); 5064 } 5065 5066 /* ARGSUSED */ 5067 static int 5068 unmount_func(int argc, char *argv[]) 5069 { 5070 zone_cmd_arg_t zarg; 5071 5072 if (argc > 0) 5073 return (Z_USAGE); 5074 if (sanity_check(target_zone, CMD_UNMOUNT, B_FALSE, B_FALSE, B_FALSE) 5075 != Z_OK) 5076 return (Z_ERR); 5077 5078 zarg.cmd = Z_UNMOUNT; 5079 if (zonecfg_call_zoneadmd(target_zone, &zarg, locale, B_TRUE) != 0) { 5080 zerror(gettext("call to %s failed"), "zoneadmd"); 5081 return (Z_ERR); 5082 } 5083 return (Z_OK); 5084 } 5085 5086 static int 5087 mark_func(int argc, char *argv[]) 5088 { 5089 int err, lockfd; 5090 int arg; 5091 boolean_t force = B_FALSE; 5092 int state; 5093 5094 optind = 0; 5095 opterr = 0; 5096 while ((arg = getopt(argc, argv, "F")) != EOF) { 5097 switch (arg) { 5098 case 'F': 5099 force = B_TRUE; 5100 break; 5101 default: 5102 return (Z_USAGE); 5103 } 5104 } 5105 5106 if (argc != (optind + 1)) 5107 return (Z_USAGE); 5108 5109 if (strcmp(argv[optind], "configured") == 0) 5110 state = ZONE_STATE_CONFIGURED; 5111 else if (strcmp(argv[optind], "incomplete") == 0) 5112 state = ZONE_STATE_INCOMPLETE; 5113 else if (strcmp(argv[optind], "installed") == 0) 5114 state = ZONE_STATE_INSTALLED; 5115 else 5116 return (Z_USAGE); 5117 5118 if (state != ZONE_STATE_INCOMPLETE && !force) 5119 return (Z_USAGE); 5120 5121 if (sanity_check(target_zone, CMD_MARK, B_FALSE, B_TRUE, B_FALSE) 5122 != Z_OK) 5123 return (Z_ERR); 5124 5125 /* 5126 * Invoke brand-specific handler. 5127 */ 5128 if (invoke_brand_handler(CMD_MARK, argv) != Z_OK) 5129 return (Z_ERR); 5130 5131 if (zonecfg_grab_lock_file(target_zone, &lockfd) != Z_OK) { 5132 zerror(gettext("another %s may have an operation in progress."), 5133 "zoneadm"); 5134 return (Z_ERR); 5135 } 5136 5137 err = zone_set_state(target_zone, state); 5138 if (err != Z_OK) { 5139 errno = err; 5140 zperror2(target_zone, gettext("could not set state")); 5141 } 5142 zonecfg_release_lock_file(target_zone, lockfd); 5143 5144 return (err); 5145 } 5146 5147 /* 5148 * Check what scheduling class we're running under and print a warning if 5149 * we're not using FSS. 5150 */ 5151 static int 5152 check_sched_fss(zone_dochandle_t handle) 5153 { 5154 char class_name[PC_CLNMSZ]; 5155 5156 if (zonecfg_get_dflt_sched_class(handle, class_name, 5157 sizeof (class_name)) != Z_OK) { 5158 zerror(gettext("WARNING: unable to determine the zone's " 5159 "scheduling class")); 5160 } else if (strcmp("FSS", class_name) != 0) { 5161 zerror(gettext("WARNING: The zone.cpu-shares rctl is set but\n" 5162 "FSS is not the default scheduling class for this zone. " 5163 "FSS will be\nused for processes in the zone but to get " 5164 "the full benefit of FSS,\nit should be the default " 5165 "scheduling class. See dispadmin(1M) for\nmore details.")); 5166 return (Z_SYSTEM); 5167 } 5168 5169 return (Z_OK); 5170 } 5171 5172 static int 5173 check_cpu_shares_sched(zone_dochandle_t handle) 5174 { 5175 int err; 5176 int res = Z_OK; 5177 struct zone_rctltab rctl; 5178 5179 if ((err = zonecfg_setrctlent(handle)) != Z_OK) { 5180 errno = err; 5181 zperror(cmd_to_str(CMD_APPLY), B_TRUE); 5182 return (err); 5183 } 5184 5185 while (zonecfg_getrctlent(handle, &rctl) == Z_OK) { 5186 if (strcmp(rctl.zone_rctl_name, "zone.cpu-shares") == 0) { 5187 if (check_sched_fss(handle) != Z_OK) 5188 res = Z_SYSTEM; 5189 break; 5190 } 5191 } 5192 5193 (void) zonecfg_endrctlent(handle); 5194 5195 return (res); 5196 } 5197 5198 /* 5199 * Check if there is a mix of processes running in different pools within the 5200 * zone. This is currently only going to be called for the global zone from 5201 * apply_func but that could be generalized in the future. 5202 */ 5203 static boolean_t 5204 mixed_pools(zoneid_t zoneid) 5205 { 5206 DIR *dirp; 5207 dirent_t *dent; 5208 boolean_t mixed = B_FALSE; 5209 boolean_t poolid_set = B_FALSE; 5210 poolid_t last_poolid = 0; 5211 5212 if ((dirp = opendir("/proc")) == NULL) { 5213 zerror(gettext("could not open /proc")); 5214 return (B_FALSE); 5215 } 5216 5217 while ((dent = readdir(dirp)) != NULL) { 5218 int procfd; 5219 psinfo_t ps; 5220 char procpath[MAXPATHLEN]; 5221 5222 if (dent->d_name[0] == '.') 5223 continue; 5224 5225 (void) snprintf(procpath, sizeof (procpath), "/proc/%s/psinfo", 5226 dent->d_name); 5227 5228 if ((procfd = open(procpath, O_RDONLY)) == -1) 5229 continue; 5230 5231 if (read(procfd, &ps, sizeof (ps)) == sizeof (psinfo_t)) { 5232 /* skip processes in other zones and system processes */ 5233 if (zoneid != ps.pr_zoneid || ps.pr_flag & SSYS) { 5234 (void) close(procfd); 5235 continue; 5236 } 5237 5238 if (poolid_set) { 5239 if (ps.pr_poolid != last_poolid) 5240 mixed = B_TRUE; 5241 } else { 5242 last_poolid = ps.pr_poolid; 5243 poolid_set = B_TRUE; 5244 } 5245 } 5246 5247 (void) close(procfd); 5248 5249 if (mixed) 5250 break; 5251 } 5252 5253 (void) closedir(dirp); 5254 5255 return (mixed); 5256 } 5257 5258 /* 5259 * Check if a persistent or temporary pool is configured for the zone. 5260 * This is currently only going to be called for the global zone from 5261 * apply_func but that could be generalized in the future. 5262 */ 5263 static boolean_t 5264 pool_configured(zone_dochandle_t handle) 5265 { 5266 int err1, err2; 5267 struct zone_psettab pset_tab; 5268 char poolname[MAXPATHLEN]; 5269 5270 err1 = zonecfg_lookup_pset(handle, &pset_tab); 5271 err2 = zonecfg_get_pool(handle, poolname, sizeof (poolname)); 5272 5273 if (err1 == Z_NO_ENTRY && 5274 (err2 == Z_NO_ENTRY || (err2 == Z_OK && strlen(poolname) == 0))) 5275 return (B_FALSE); 5276 5277 return (B_TRUE); 5278 } 5279 5280 /* 5281 * This is an undocumented interface which is currently only used to apply 5282 * the global zone resource management settings when the system boots. 5283 * This function does not yet properly handle updating a running system so 5284 * any projects running in the zone would be trashed if this function 5285 * were to run after the zone had booted. It also does not reset any 5286 * rctl settings that were removed from zonecfg. There is still work to be 5287 * done before we can properly support dynamically updating the resource 5288 * management settings for a running zone (global or non-global). Thus, this 5289 * functionality is undocumented for now. 5290 */ 5291 /* ARGSUSED */ 5292 static int 5293 apply_func(int argc, char *argv[]) 5294 { 5295 int err; 5296 int res = Z_OK; 5297 priv_set_t *privset; 5298 zoneid_t zoneid; 5299 zone_dochandle_t handle; 5300 struct zone_mcaptab mcap; 5301 char pool_err[128]; 5302 5303 zoneid = getzoneid(); 5304 5305 if (zonecfg_in_alt_root() || zoneid != GLOBAL_ZONEID || 5306 target_zone == NULL || strcmp(target_zone, GLOBAL_ZONENAME) != 0) 5307 return (usage(B_FALSE)); 5308 5309 if ((privset = priv_allocset()) == NULL) { 5310 zerror(gettext("%s failed"), "priv_allocset"); 5311 return (Z_ERR); 5312 } 5313 5314 if (getppriv(PRIV_EFFECTIVE, privset) != 0) { 5315 zerror(gettext("%s failed"), "getppriv"); 5316 priv_freeset(privset); 5317 return (Z_ERR); 5318 } 5319 5320 if (priv_isfullset(privset) == B_FALSE) { 5321 (void) usage(B_FALSE); 5322 priv_freeset(privset); 5323 return (Z_ERR); 5324 } 5325 priv_freeset(privset); 5326 5327 if ((handle = zonecfg_init_handle()) == NULL) { 5328 zperror(cmd_to_str(CMD_APPLY), B_TRUE); 5329 return (Z_ERR); 5330 } 5331 5332 if ((err = zonecfg_get_handle(target_zone, handle)) != Z_OK) { 5333 errno = err; 5334 zperror(cmd_to_str(CMD_APPLY), B_TRUE); 5335 zonecfg_fini_handle(handle); 5336 return (Z_ERR); 5337 } 5338 5339 /* specific error msgs are printed within apply_rctls */ 5340 if ((err = zonecfg_apply_rctls(target_zone, handle)) != Z_OK) { 5341 errno = err; 5342 zperror(cmd_to_str(CMD_APPLY), B_TRUE); 5343 res = Z_ERR; 5344 } 5345 5346 if ((err = check_cpu_shares_sched(handle)) != Z_OK) 5347 res = Z_ERR; 5348 5349 if (pool_configured(handle)) { 5350 if (mixed_pools(zoneid)) { 5351 zerror(gettext("Zone is using multiple resource " 5352 "pools. The pool\nconfiguration cannot be " 5353 "applied without rebooting.")); 5354 res = Z_ERR; 5355 } else { 5356 5357 /* 5358 * The next two blocks of code attempt to set up 5359 * temporary pools as well as persistent pools. In 5360 * both cases we call the functions unconditionally. 5361 * Within each funtion the code will check if the zone 5362 * is actually configured for a temporary pool or 5363 * persistent pool and just return if there is nothing 5364 * to do. 5365 */ 5366 if ((err = zonecfg_bind_tmp_pool(handle, zoneid, 5367 pool_err, sizeof (pool_err))) != Z_OK) { 5368 if (err == Z_POOL || err == Z_POOL_CREATE || 5369 err == Z_POOL_BIND) 5370 zerror("%s: %s", zonecfg_strerror(err), 5371 pool_err); 5372 else 5373 zerror(gettext("could not bind zone to " 5374 "temporary pool: %s"), 5375 zonecfg_strerror(err)); 5376 res = Z_ERR; 5377 } 5378 5379 if ((err = zonecfg_bind_pool(handle, zoneid, pool_err, 5380 sizeof (pool_err))) != Z_OK) { 5381 if (err == Z_POOL || err == Z_POOL_BIND) 5382 zerror("%s: %s", zonecfg_strerror(err), 5383 pool_err); 5384 else 5385 zerror("%s", zonecfg_strerror(err)); 5386 } 5387 } 5388 } 5389 5390 /* 5391 * If a memory cap is configured, set the cap in the kernel using 5392 * zone_setattr() and make sure the rcapd SMF service is enabled. 5393 */ 5394 if (zonecfg_getmcapent(handle, &mcap) == Z_OK) { 5395 uint64_t num; 5396 char smf_err[128]; 5397 5398 num = (uint64_t)strtoll(mcap.zone_physmem_cap, NULL, 10); 5399 if (zone_setattr(zoneid, ZONE_ATTR_PHYS_MCAP, &num, 0) == -1) { 5400 zerror(gettext("could not set zone memory cap")); 5401 res = Z_ERR; 5402 } 5403 5404 if (zonecfg_enable_rcapd(smf_err, sizeof (smf_err)) != Z_OK) { 5405 zerror(gettext("enabling system/rcap service failed: " 5406 "%s"), smf_err); 5407 res = Z_ERR; 5408 } 5409 } 5410 5411 zonecfg_fini_handle(handle); 5412 5413 return (res); 5414 } 5415 5416 /* 5417 * This is an undocumented interface that is invoked by the zones SMF service 5418 * for installed zones that won't automatically boot. 5419 */ 5420 /* ARGSUSED */ 5421 static int 5422 sysboot_func(int argc, char *argv[]) 5423 { 5424 int err; 5425 zone_dochandle_t zone_handle; 5426 brand_handle_t brand_handle; 5427 char cmdbuf[MAXPATHLEN]; 5428 char zonepath[MAXPATHLEN]; 5429 5430 /* 5431 * This subcommand can only be executed in the global zone on non-global 5432 * zones. 5433 */ 5434 if (zonecfg_in_alt_root()) 5435 return (usage(B_FALSE)); 5436 if (sanity_check(target_zone, CMD_SYSBOOT, B_FALSE, B_TRUE, B_FALSE) != 5437 Z_OK) 5438 return (Z_ERR); 5439 5440 /* 5441 * Fetch the sysboot hook from the target zone's brand. 5442 */ 5443 if ((zone_handle = zonecfg_init_handle()) == NULL) { 5444 zperror(cmd_to_str(CMD_SYSBOOT), B_TRUE); 5445 return (Z_ERR); 5446 } 5447 if ((err = zonecfg_get_handle(target_zone, zone_handle)) != Z_OK) { 5448 errno = err; 5449 zperror(cmd_to_str(CMD_SYSBOOT), B_TRUE); 5450 zonecfg_fini_handle(zone_handle); 5451 return (Z_ERR); 5452 } 5453 if ((err = zonecfg_get_zonepath(zone_handle, zonepath, 5454 sizeof (zonepath))) != Z_OK) { 5455 errno = err; 5456 zperror(cmd_to_str(CMD_SYSBOOT), B_TRUE); 5457 zonecfg_fini_handle(zone_handle); 5458 return (Z_ERR); 5459 } 5460 if ((brand_handle = brand_open(target_brand)) == NULL) { 5461 zerror(gettext("missing or invalid brand during %s operation: " 5462 "%s"), cmd_to_str(CMD_SYSBOOT), target_brand); 5463 zonecfg_fini_handle(zone_handle); 5464 return (Z_ERR); 5465 } 5466 err = get_hook(brand_handle, cmdbuf, sizeof (cmdbuf), brand_get_sysboot, 5467 target_zone, zonepath); 5468 brand_close(brand_handle); 5469 zonecfg_fini_handle(zone_handle); 5470 if (err != Z_OK) { 5471 zerror(gettext("unable to get brand hook from brand %s for %s " 5472 "operation"), target_brand, cmd_to_str(CMD_SYSBOOT)); 5473 return (Z_ERR); 5474 } 5475 5476 /* 5477 * If the hook wasn't defined (which is OK), then indicate success and 5478 * return. Otherwise, execute the hook. 5479 */ 5480 if (cmdbuf[0] != '\0') 5481 return ((subproc_status(gettext("brand sysboot operation"), 5482 do_subproc(cmdbuf), B_FALSE) == ZONE_SUBPROC_OK) ? Z_OK : 5483 Z_BRAND_ERROR); 5484 return (Z_OK); 5485 } 5486 5487 static int 5488 help_func(int argc, char *argv[]) 5489 { 5490 int arg, cmd_num; 5491 5492 if (argc == 0) { 5493 (void) usage(B_TRUE); 5494 return (Z_OK); 5495 } 5496 optind = 0; 5497 if ((arg = getopt(argc, argv, "?")) != EOF) { 5498 switch (arg) { 5499 case '?': 5500 sub_usage(SHELP_HELP, CMD_HELP); 5501 return (optopt == '?' ? Z_OK : Z_USAGE); 5502 default: 5503 sub_usage(SHELP_HELP, CMD_HELP); 5504 return (Z_USAGE); 5505 } 5506 } 5507 while (optind < argc) { 5508 /* Private commands have NULL short_usage; omit them */ 5509 if ((cmd_num = cmd_match(argv[optind])) < 0 || 5510 cmdtab[cmd_num].short_usage == NULL) { 5511 sub_usage(SHELP_HELP, CMD_HELP); 5512 return (Z_USAGE); 5513 } 5514 sub_usage(cmdtab[cmd_num].short_usage, cmd_num); 5515 optind++; 5516 } 5517 return (Z_OK); 5518 } 5519 5520 /* 5521 * Returns: CMD_MIN thru CMD_MAX on success, -1 on error 5522 */ 5523 5524 static int 5525 cmd_match(char *cmd) 5526 { 5527 int i; 5528 5529 for (i = CMD_MIN; i <= CMD_MAX; i++) { 5530 /* return only if there is an exact match */ 5531 if (strcmp(cmd, cmdtab[i].cmd_name) == 0) 5532 return (cmdtab[i].cmd_num); 5533 } 5534 return (-1); 5535 } 5536 5537 static int 5538 parse_and_run(int argc, char *argv[]) 5539 { 5540 int i = cmd_match(argv[0]); 5541 5542 if (i < 0) 5543 return (usage(B_FALSE)); 5544 return (cmdtab[i].handler(argc - 1, &(argv[1]))); 5545 } 5546 5547 static char * 5548 get_execbasename(char *execfullname) 5549 { 5550 char *last_slash, *execbasename; 5551 5552 /* guard against '/' at end of command invocation */ 5553 for (;;) { 5554 last_slash = strrchr(execfullname, '/'); 5555 if (last_slash == NULL) { 5556 execbasename = execfullname; 5557 break; 5558 } else { 5559 execbasename = last_slash + 1; 5560 if (*execbasename == '\0') { 5561 *last_slash = '\0'; 5562 continue; 5563 } 5564 break; 5565 } 5566 } 5567 return (execbasename); 5568 } 5569 5570 int 5571 main(int argc, char **argv) 5572 { 5573 int arg; 5574 zoneid_t zid; 5575 struct stat st; 5576 char *zone_lock_env; 5577 int err; 5578 5579 if ((locale = setlocale(LC_ALL, "")) == NULL) 5580 locale = "C"; 5581 (void) textdomain(TEXT_DOMAIN); 5582 setbuf(stdout, NULL); 5583 (void) sigset(SIGHUP, SIG_IGN); 5584 execname = get_execbasename(argv[0]); 5585 target_zone = NULL; 5586 if (chdir("/") != 0) { 5587 zerror(gettext("could not change directory to /.")); 5588 exit(Z_ERR); 5589 } 5590 /* 5591 * Use the default system mask rather than anything that may have been 5592 * set by the caller. 5593 */ 5594 (void) umask(CMASK); 5595 5596 if (init_zfs() != Z_OK) 5597 exit(Z_ERR); 5598 5599 while ((arg = getopt(argc, argv, "?u:z:R:")) != EOF) { 5600 switch (arg) { 5601 case '?': 5602 return (usage(B_TRUE)); 5603 case 'u': 5604 target_uuid = optarg; 5605 break; 5606 case 'z': 5607 target_zone = optarg; 5608 break; 5609 case 'R': /* private option for admin/install use */ 5610 if (*optarg != '/') { 5611 zerror(gettext("root path must be absolute.")); 5612 exit(Z_ERR); 5613 } 5614 if (stat(optarg, &st) == -1 || !S_ISDIR(st.st_mode)) { 5615 zerror( 5616 gettext("root path must be a directory.")); 5617 exit(Z_ERR); 5618 } 5619 zonecfg_set_root(optarg); 5620 break; 5621 default: 5622 return (usage(B_FALSE)); 5623 } 5624 } 5625 5626 if (optind >= argc) 5627 return (usage(B_FALSE)); 5628 5629 if (target_uuid != NULL && *target_uuid != '\0') { 5630 uuid_t uuid; 5631 static char newtarget[ZONENAME_MAX]; 5632 5633 if (uuid_parse(target_uuid, uuid) == -1) { 5634 zerror(gettext("illegal UUID value specified")); 5635 exit(Z_ERR); 5636 } 5637 if (zonecfg_get_name_by_uuid(uuid, newtarget, 5638 sizeof (newtarget)) == Z_OK) 5639 target_zone = newtarget; 5640 } 5641 5642 if (target_zone != NULL && zone_get_id(target_zone, &zid) != 0) { 5643 errno = Z_NO_ZONE; 5644 zperror(target_zone, B_TRUE); 5645 exit(Z_ERR); 5646 } 5647 5648 /* 5649 * See if we have inherited the right to manipulate this zone from 5650 * a zoneadm instance in our ancestry. If so, set zone_lock_cnt to 5651 * indicate it. If not, make that explicit in our environment. 5652 */ 5653 zonecfg_init_lock_file(target_zone, &zone_lock_env); 5654 5655 /* Figure out what the system's default brand is */ 5656 if (zonecfg_default_brand(default_brand, 5657 sizeof (default_brand)) != Z_OK) { 5658 zerror(gettext("unable to determine default brand")); 5659 return (Z_ERR); 5660 } 5661 5662 /* 5663 * If we are going to be operating on a single zone, retrieve its 5664 * brand type and determine whether it is native or not. 5665 */ 5666 if ((target_zone != NULL) && 5667 (strcmp(target_zone, GLOBAL_ZONENAME) != 0)) { 5668 if (zone_get_brand(target_zone, target_brand, 5669 sizeof (target_brand)) != Z_OK) { 5670 zerror(gettext("missing or invalid brand")); 5671 exit(Z_ERR); 5672 } 5673 /* 5674 * In the alternate root environment, the only supported 5675 * operations are mount and unmount. In this case, just treat 5676 * the zone as native if it is cluster. Cluster zones can be 5677 * native for the purpose of LU or upgrade, and the cluster 5678 * brand may not exist in the miniroot (such as in net install 5679 * upgrade). 5680 */ 5681 if (strcmp(target_brand, CLUSTER_BRAND_NAME) == 0) { 5682 if (zonecfg_in_alt_root()) { 5683 (void) strlcpy(target_brand, default_brand, 5684 sizeof (target_brand)); 5685 } 5686 } 5687 } 5688 5689 err = parse_and_run(argc - optind, &argv[optind]); 5690 5691 return (err); 5692 } 5693