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, Version 1.0 only 6 * (the "License"). You may not use this file except in compliance 7 * with the License. 8 * 9 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 10 * or http://www.opensolaris.org/os/licensing. 11 * See the License for the specific language governing permissions 12 * and limitations under the License. 13 * 14 * When distributing Covered Code, include this CDDL HEADER in each 15 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 16 * If applicable, add the following below this CDDL HEADER, with the 17 * fields enclosed by brackets "[]" replaced with your own identifying 18 * information: Portions Copyright [yyyy] [name of copyright owner] 19 * 20 * CDDL HEADER END 21 */ 22 23 /* 24 * Copyright 2005 Sun Microsystems, Inc. All rights reserved. 25 * Use is subject to license terms. 26 */ 27 28 #pragma ident "%Z%%M% %I% %E% SMI" 29 30 /* 31 * zoneadm is a command interpreter for zone administration. It is all in 32 * C (i.e., no lex/yacc), and all the argument passing is argc/argv based. 33 * main() calls parse_and_run() which calls cmd_match(), then invokes the 34 * appropriate command's handler function. The rest of the program is the 35 * handler functions and their helper functions. 36 * 37 * Some of the helper functions are used largely to simplify I18N: reducing 38 * the need for translation notes. This is particularly true of many of 39 * the zerror() calls: doing e.g. zerror(gettext("%s failed"), "foo") rather 40 * than zerror(gettext("foo failed")) with a translation note indicating 41 * that "foo" need not be translated. 42 */ 43 44 #include <stdio.h> 45 #include <errno.h> 46 #include <unistd.h> 47 #include <signal.h> 48 #include <stdarg.h> 49 #include <ctype.h> 50 #include <stdlib.h> 51 #include <string.h> 52 #include <wait.h> 53 #include <zone.h> 54 #include <priv.h> 55 #include <locale.h> 56 #include <libintl.h> 57 #include <libzonecfg.h> 58 #include <bsm/adt.h> 59 #include <sys/utsname.h> 60 #include <sys/param.h> 61 #include <sys/types.h> 62 #include <sys/stat.h> 63 #include <sys/statvfs.h> 64 #include <assert.h> 65 #include <sys/sockio.h> 66 #include <sys/mntent.h> 67 #include <limits.h> 68 69 #include <fcntl.h> 70 #include <door.h> 71 #include <macros.h> 72 #include <libgen.h> 73 74 #include <pool.h> 75 #include <sys/pool.h> 76 77 #define MAXARGS 8 78 79 /* Reflects kernel zone entries */ 80 typedef struct zone_entry { 81 zoneid_t zid; 82 char zname[ZONENAME_MAX]; 83 char *zstate_str; 84 zone_state_t zstate_num; 85 char zroot[MAXPATHLEN]; 86 } zone_entry_t; 87 88 static zone_entry_t *zents; 89 static size_t nzents; 90 91 #if !defined(TEXT_DOMAIN) /* should be defined by cc -D */ 92 #define TEXT_DOMAIN "SYS_TEST" /* Use this only if it wasn't */ 93 #endif 94 95 #define Z_ERR 1 96 #define Z_USAGE 2 97 98 /* 0755 is the default directory mode. */ 99 #define DEFAULT_DIR_MODE \ 100 (S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH) 101 102 #define CMD_HELP 0 103 #define CMD_BOOT 1 104 #define CMD_HALT 2 105 #define CMD_READY 3 106 #define CMD_REBOOT 4 107 #define CMD_LIST 5 108 #define CMD_VERIFY 6 109 #define CMD_INSTALL 7 110 #define CMD_UNINSTALL 8 111 112 #define CMD_MIN CMD_HELP 113 #define CMD_MAX CMD_UNINSTALL 114 115 struct cmd { 116 uint_t cmd_num; /* command number */ 117 char *cmd_name; /* command name */ 118 char *short_usage; /* short form help */ 119 int (*handler)(int argc, char *argv[]); /* function to call */ 120 121 }; 122 123 #define SHELP_HELP "help" 124 #define SHELP_BOOT "boot [-s]" 125 #define SHELP_HALT "halt" 126 #define SHELP_READY "ready" 127 #define SHELP_REBOOT "reboot" 128 #define SHELP_LIST "list [-cipv]" 129 #define SHELP_VERIFY "verify" 130 #define SHELP_INSTALL "install" 131 #define SHELP_UNINSTALL "uninstall [-F]" 132 133 static int help_func(int argc, char *argv[]); 134 static int ready_func(int argc, char *argv[]); 135 static int boot_func(int argc, char *argv[]); 136 static int halt_func(int argc, char *argv[]); 137 static int reboot_func(int argc, char *argv[]); 138 static int list_func(int argc, char *argv[]); 139 static int verify_func(int argc, char *argv[]); 140 static int install_func(int argc, char *argv[]); 141 static int uninstall_func(int argc, char *argv[]); 142 static int sanity_check(char *zone, int cmd_num, boolean_t running, 143 boolean_t unsafe_when_running); 144 static int cmd_match(char *cmd); 145 static int verify_details(int); 146 147 static struct cmd cmdtab[] = { 148 { CMD_HELP, "help", SHELP_HELP, help_func }, 149 { CMD_BOOT, "boot", SHELP_BOOT, boot_func }, 150 { CMD_HALT, "halt", SHELP_HALT, halt_func }, 151 { CMD_READY, "ready", SHELP_READY, ready_func }, 152 { CMD_REBOOT, "reboot", SHELP_REBOOT, reboot_func }, 153 { CMD_LIST, "list", SHELP_LIST, list_func }, 154 { CMD_VERIFY, "verify", SHELP_VERIFY, verify_func }, 155 { CMD_INSTALL, "install", SHELP_INSTALL, install_func }, 156 { CMD_UNINSTALL, "uninstall", SHELP_UNINSTALL, 157 uninstall_func } 158 }; 159 160 /* global variables */ 161 162 /* set early in main(), never modified thereafter, used all over the place */ 163 static char *execname; 164 static char *target_zone; 165 static char *locale; 166 167 /* used in do_subproc() and signal handler */ 168 static volatile boolean_t child_killed; 169 170 static char * 171 cmd_to_str(int cmd_num) 172 { 173 assert(cmd_num >= CMD_MIN && cmd_num <= CMD_MAX); 174 return (cmdtab[cmd_num].cmd_name); 175 } 176 177 /* This is a separate function because of gettext() wrapping. */ 178 static char * 179 long_help(int cmd_num) 180 { 181 assert(cmd_num >= CMD_MIN && cmd_num <= CMD_MAX); 182 switch (cmd_num) { 183 case CMD_HELP: 184 return (gettext("Print usage message.")); 185 case CMD_BOOT: 186 return (gettext("Activates (boots) specified zone. " 187 "The -s flag can be used\n\tto boot the zone in " 188 "the single-user state.")); 189 case CMD_HALT: 190 return (gettext("Halts specified zone, bypassing " 191 "shutdown scripts and removing runtime\n\t" 192 "resources of the zone.")); 193 case CMD_READY: 194 return (gettext("Prepares a zone for running " 195 "applications but does not start any user\n\t" 196 "processes in the zone.")); 197 case CMD_REBOOT: 198 return (gettext("Restarts the zone (equivalent to a " 199 "halt / boot sequence).\n\tFails if the zone is " 200 "not active.")); 201 case CMD_LIST: 202 return (gettext("Lists the current zones, or a " 203 "specific zone if indicated. By default,\n\tall " 204 "running zones are listed, though this can be " 205 "expanded to all\n\tinstalled zones with the -i " 206 "option or all configured zones with the\n\t-c " 207 "option. When used with the general -z <zone> " 208 "option, lists only the\n\tspecified zone, but " 209 "lists it regardless of its state, and the -i " 210 "and -c\n\toptions are disallowed. The -v option " 211 "can be used to display verbose\n\tinformation: " 212 "zone name, id, current state, root directory and " 213 "options.\n\tThe -p option can be used to request " 214 "machine-parsable output. The -v\n\tand -p " 215 "options are mutually exclusive. If neither -v " 216 "nor -p is used,\n\tjust the zone name is " 217 "listed.")); 218 case CMD_VERIFY: 219 return (gettext("Check to make sure the configuration " 220 "can safely be instantiated\n\ton the machine: " 221 "physical network interfaces exist, etc.")); 222 case CMD_INSTALL: 223 return (gettext("Install the configuration on to the " 224 "system.")); 225 case CMD_UNINSTALL: 226 return (gettext("Uninstall the configuration from the " 227 "system. The -F flag can be used\n\tto force the " 228 "action.")); 229 } 230 /* NOTREACHED */ 231 return (NULL); 232 } 233 234 /* 235 * Called with explicit B_TRUE when help is explicitly requested, B_FALSE for 236 * unexpected errors. 237 */ 238 239 static int 240 usage(boolean_t explicit) 241 { 242 int i; 243 FILE *fd = explicit ? stdout : stderr; 244 245 (void) fprintf(fd, "%s:\t%s help\n", gettext("usage"), execname); 246 (void) fprintf(fd, "\t%s [-z <zone>] list\n", execname); 247 (void) fprintf(fd, "\t%s -z <zone> <%s>\n", execname, 248 gettext("subcommand")); 249 (void) fprintf(fd, "\n%s:\n\n", gettext("Subcommands")); 250 for (i = CMD_MIN; i <= CMD_MAX; i++) { 251 (void) fprintf(fd, "%s\n", cmdtab[i].short_usage); 252 if (explicit) 253 (void) fprintf(fd, "\t%s\n\n", long_help(i)); 254 } 255 if (!explicit) 256 (void) fputs("\n", fd); 257 return (Z_USAGE); 258 } 259 260 static void 261 sub_usage(char *short_usage, int cmd_num) 262 { 263 (void) fprintf(stderr, "%s:\t%s\n", gettext("usage"), short_usage); 264 (void) fprintf(stderr, "\t%s\n", long_help(cmd_num)); 265 } 266 267 /* 268 * zperror() is like perror(3c) except that this also prints the executable 269 * name at the start of the message, and takes a boolean indicating whether 270 * to call libc'c strerror() or that from libzonecfg. 271 */ 272 273 static void 274 zperror(const char *str, boolean_t zonecfg_error) 275 { 276 (void) fprintf(stderr, "%s: %s: %s\n", execname, str, 277 zonecfg_error ? zonecfg_strerror(errno) : strerror(errno)); 278 } 279 280 /* 281 * zperror2() is very similar to zperror() above, except it also prints a 282 * supplied zone name after the executable. 283 * 284 * All current consumers of this function want libzonecfg's strerror() rather 285 * than libc's; if this ever changes, this function can be made more generic 286 * like zperror() above. 287 */ 288 289 static void 290 zperror2(const char *zone, const char *str) 291 { 292 (void) fprintf(stderr, "%s: %s: %s: %s\n", execname, zone, str, 293 zonecfg_strerror(errno)); 294 } 295 296 /* PRINTFLIKE1 */ 297 static void 298 zerror(const char *fmt, ...) 299 { 300 va_list alist; 301 302 va_start(alist, fmt); 303 (void) fprintf(stderr, "%s: ", execname); 304 if (target_zone != NULL) 305 (void) fprintf(stderr, "zone '%s': ", target_zone); 306 (void) vfprintf(stderr, fmt, alist); 307 (void) fprintf(stderr, "\n"); 308 va_end(alist); 309 } 310 311 static void * 312 safe_calloc(size_t nelem, size_t elsize) 313 { 314 void *r = calloc(nelem, elsize); 315 316 if (r == NULL) { 317 zerror(gettext("failed to allocate %lu bytes: %s"), 318 (ulong_t)nelem * elsize, strerror(errno)); 319 exit(Z_ERR); 320 } 321 return (r); 322 } 323 324 static void 325 zone_print(zone_entry_t *zent, boolean_t verbose, boolean_t parsable) 326 { 327 static boolean_t firsttime = B_TRUE; 328 329 assert(!(verbose && parsable)); 330 if (firsttime && verbose) { 331 firsttime = B_FALSE; 332 (void) printf("%*s %-16s %-14s %-30s\n", ZONEID_WIDTH, "ID", 333 "NAME", "STATUS", "PATH"); 334 } 335 if (!verbose) { 336 if (!parsable) { 337 (void) printf("%s\n", zent->zname); 338 return; 339 } 340 if (zent->zid == ZONE_ID_UNDEFINED) 341 (void) printf("-"); 342 else 343 (void) printf("%lu", zent->zid); 344 (void) printf(":%s:%s:%s\n", zent->zname, zent->zstate_str, 345 zent->zroot); 346 return; 347 } 348 if (zent->zstate_str != NULL) { 349 if (zent->zid == ZONE_ID_UNDEFINED) 350 (void) printf("%*s", ZONEID_WIDTH, "-"); 351 else 352 (void) printf("%*lu", ZONEID_WIDTH, zent->zid); 353 (void) printf(" %-16s %-14s %-30s\n", zent->zname, 354 zent->zstate_str, zent->zroot); 355 } 356 } 357 358 static int 359 lookup_zone_info(char *zone_name, zone_entry_t *zent) 360 { 361 char root[MAXPATHLEN]; 362 int err; 363 364 (void) strlcpy(zent->zname, zone_name, sizeof (zent->zname)); 365 (void) strlcpy(zent->zroot, "???", sizeof (zent->zroot)); 366 zent->zstate_str = "???"; 367 368 if ((zent->zid = getzoneidbyname(zone_name)) == -1) 369 zent->zid = ZONE_ID_UNDEFINED; 370 371 if ((err = zone_get_zonepath(zent->zname, root, sizeof (root))) != 372 Z_OK) { 373 errno = err; 374 zperror2(zent->zname, gettext("could not get zone path")); 375 return (Z_ERR); 376 } 377 (void) strlcpy(zent->zroot, root, sizeof (zent->zroot)); 378 379 if ((err = zone_get_state(zent->zname, &zent->zstate_num)) != Z_OK) { 380 errno = err; 381 zperror2(zent->zname, gettext("could not get state")); 382 return (Z_ERR); 383 } 384 zent->zstate_str = zone_state_str(zent->zstate_num); 385 386 return (Z_OK); 387 } 388 389 /* 390 * fetch_zents() calls zone_list(2) to find out how many zones are running 391 * (which is stored in the global nzents), then calls zone_list(2) again 392 * to fetch the list of running zones (stored in the global zents). This 393 * function may be called multiple times, so if zents is already set, we 394 * return immediately to save work. 395 */ 396 397 static int 398 fetch_zents() 399 { 400 zoneid_t *zids = NULL; 401 uint_t nzents_saved; 402 int i; 403 404 if (nzents > 0) 405 return (Z_OK); 406 407 if (zone_list(NULL, &nzents) != 0) { 408 zperror(gettext("failed to get zoneid list"), B_FALSE); 409 return (Z_ERR); 410 } 411 412 again: 413 if (nzents == 0) 414 return (Z_OK); 415 416 zids = safe_calloc(nzents, sizeof (zoneid_t)); 417 nzents_saved = nzents; 418 419 if (zone_list(zids, &nzents) != 0) { 420 zperror(gettext("failed to get zone list"), B_FALSE); 421 free(zids); 422 return (Z_ERR); 423 } 424 if (nzents != nzents_saved) { 425 /* list changed, try again */ 426 free(zids); 427 goto again; 428 } 429 430 zents = safe_calloc(nzents, sizeof (zone_entry_t)); 431 432 for (i = 0; i < nzents; i++) { 433 char name[ZONENAME_MAX]; 434 435 if (getzonenamebyid(zids[i], name, sizeof (name)) < 0) 436 zperror(gettext("failed to get zone name"), B_FALSE); 437 else if (lookup_zone_info(name, &zents[i]) != Z_OK) 438 zerror(gettext("failed to get zone list")); 439 } 440 441 free(zids); 442 return (Z_OK); 443 } 444 445 static void 446 zone_print_list(zone_state_t min_state, boolean_t verbose, boolean_t parsable) 447 { 448 int i; 449 zone_entry_t zent; 450 FILE *cookie; 451 char *name; 452 453 /* 454 * First get the list of running zones from the kernel and print them. 455 * If that is all we need, then return. 456 */ 457 if (fetch_zents() != Z_OK) { 458 /* 459 * No need for error messages; fetch_zents() has already taken 460 * care of this. 461 */ 462 return; 463 } 464 for (i = 0; i < nzents; i++) { 465 if (!verbose && !parsable) { 466 zone_print(&zents[i], verbose, parsable); 467 continue; 468 } 469 zone_print(&zents[i], verbose, parsable); 470 } 471 if (min_state >= ZONE_STATE_RUNNING) 472 return; 473 /* 474 * Next, get the full list of zones from the configuration, skipping 475 * any we have already printed. 476 */ 477 cookie = setzoneent(); 478 while ((name = getzoneent(cookie)) != NULL) { 479 for (i = 0; i < nzents; i++) { 480 if (strcmp(zents[i].zname, name) == 0) 481 break; 482 } 483 if (i < nzents) { 484 free(name); 485 continue; 486 } 487 if (lookup_zone_info(name, &zent) != Z_OK) { 488 free(name); 489 continue; 490 } 491 free(name); 492 if (zent.zstate_num >= min_state) 493 zone_print(&zent, verbose, parsable); 494 } 495 endzoneent(cookie); 496 } 497 498 static zone_entry_t * 499 lookup_running_zone(char *str) 500 { 501 zoneid_t zoneid; 502 char *cp; 503 int i; 504 505 if (fetch_zents() != Z_OK) 506 return (NULL); 507 508 for (i = 0; i < nzents; i++) { 509 if (strcmp(str, zents[i].zname) == 0) 510 return (&zents[i]); 511 } 512 errno = 0; 513 zoneid = strtol(str, &cp, 0); 514 if (zoneid < MIN_ZONEID || zoneid > MAX_ZONEID || 515 errno != 0 || *cp != '\0') 516 return (NULL); 517 for (i = 0; i < nzents; i++) { 518 if (zoneid == zents[i].zid) 519 return (&zents[i]); 520 } 521 return (NULL); 522 } 523 524 /* 525 * Check a bit in a mode_t: if on is B_TRUE, that bit should be on; if 526 * B_FALSE, it should be off. Return B_TRUE if the mode is bad (incorrect). 527 */ 528 static boolean_t 529 bad_mode_bit(mode_t mode, mode_t bit, boolean_t on, char *file) 530 { 531 char *str; 532 533 assert(bit == S_IRUSR || bit == S_IWUSR || bit == S_IXUSR || 534 bit == S_IRGRP || bit == S_IWGRP || bit == S_IXGRP || 535 bit == S_IROTH || bit == S_IWOTH || bit == S_IXOTH); 536 /* 537 * TRANSLATION_NOTE 538 * The strings below will be used as part of a larger message, 539 * either: 540 * (file name) must be (owner|group|world) (read|writ|execut)able 541 * or 542 * (file name) must not be (owner|group|world) (read|writ|execut)able 543 */ 544 switch (bit) { 545 case S_IRUSR: 546 str = gettext("owner readable"); 547 break; 548 case S_IWUSR: 549 str = gettext("owner writable"); 550 break; 551 case S_IXUSR: 552 str = gettext("owner executable"); 553 break; 554 case S_IRGRP: 555 str = gettext("group readable"); 556 break; 557 case S_IWGRP: 558 str = gettext("group writable"); 559 break; 560 case S_IXGRP: 561 str = gettext("group executable"); 562 break; 563 case S_IROTH: 564 str = gettext("world readable"); 565 break; 566 case S_IWOTH: 567 str = gettext("world writable"); 568 break; 569 case S_IXOTH: 570 str = gettext("world executable"); 571 break; 572 } 573 if ((mode & bit) == (on ? 0 : bit)) { 574 /* 575 * TRANSLATION_NOTE 576 * The first parameter below is a file name; the second 577 * is one of the "(owner|group|world) (read|writ|execut)able" 578 * strings from above. 579 */ 580 /* 581 * The code below could be simplified but not in a way 582 * that would easily translate to non-English locales. 583 */ 584 if (on) { 585 (void) fprintf(stderr, gettext("%s must be %s.\n"), 586 file, str); 587 } else { 588 (void) fprintf(stderr, gettext("%s must not be %s.\n"), 589 file, str); 590 } 591 return (B_TRUE); 592 } 593 return (B_FALSE); 594 } 595 596 /* 597 * We want to make sure that no zone has its zone path as a child node 598 * (in the directory sense) of any other. We do that by comparing this 599 * zone's path to the path of all other (non-global) zones. The comparison 600 * in each case is simple: add '/' to the end of the path, then do a 601 * strncmp() of the two paths, using the length of the shorter one. 602 */ 603 604 static int 605 crosscheck_zonepaths(char *path) 606 { 607 char rpath[MAXPATHLEN]; /* resolved path */ 608 char path_copy[MAXPATHLEN]; /* copy of original path */ 609 char rpath_copy[MAXPATHLEN]; /* copy of original rpath */ 610 struct zoneent *ze; 611 int res, err; 612 FILE *cookie; 613 614 cookie = setzoneent(); 615 while ((ze = getzoneent_private(cookie)) != NULL) { 616 /* Skip zones which are not installed. */ 617 if (ze->zone_state < ZONE_STATE_INSTALLED) { 618 free(ze); 619 continue; 620 } 621 /* Skip the global zone and the current target zone. */ 622 if (strcmp(ze->zone_name, GLOBAL_ZONENAME) == 0 || 623 strcmp(ze->zone_name, target_zone) == 0) { 624 free(ze); 625 continue; 626 } 627 if (strlen(ze->zone_path) == 0) { 628 /* old index file without path, fall back */ 629 if ((err = zone_get_zonepath(ze->zone_name, 630 ze->zone_path, sizeof (ze->zone_path))) != Z_OK) { 631 errno = err; 632 zperror2(ze->zone_name, 633 gettext("could not get zone path")); 634 free(ze); 635 continue; 636 } 637 } 638 res = resolvepath(ze->zone_path, rpath, sizeof (rpath)); 639 if (res == -1) { 640 if (errno != ENOENT) { 641 zperror(ze->zone_path, B_FALSE); 642 free(ze); 643 return (Z_ERR); 644 } 645 (void) printf(gettext("WARNING: zone %s is installed, " 646 "but its %s %s does not exist.\n"), ze->zone_name, 647 "zonepath", ze->zone_path); 648 free(ze); 649 continue; 650 } 651 rpath[res] = '\0'; 652 (void) snprintf(path_copy, sizeof (path_copy), "%s/", path); 653 (void) snprintf(rpath_copy, sizeof (rpath_copy), "%s/", rpath); 654 if (strncmp(path_copy, rpath_copy, 655 min(strlen(path_copy), strlen(rpath_copy))) == 0) { 656 (void) fprintf(stderr, gettext("%s zonepath (%s) and " 657 "%s zonepath (%s) overlap.\n"), 658 target_zone, path, ze->zone_name, rpath); 659 free(ze); 660 return (Z_ERR); 661 } 662 free(ze); 663 } 664 endzoneent(cookie); 665 return (Z_OK); 666 } 667 668 static int 669 validate_zonepath(char *path, int cmd_num) 670 { 671 int res; /* result of last library/system call */ 672 boolean_t err = B_FALSE; /* have we run into an error? */ 673 struct stat stbuf; 674 struct statvfs vfsbuf; 675 char rpath[MAXPATHLEN]; /* resolved path */ 676 char ppath[MAXPATHLEN]; /* parent path */ 677 char rppath[MAXPATHLEN]; /* resolved parent path */ 678 char rootpath[MAXPATHLEN]; /* root path */ 679 zone_state_t state; 680 681 if (path[0] != '/') { 682 (void) fprintf(stderr, 683 gettext("%s is not an absolute path.\n"), path); 684 return (Z_ERR); 685 } 686 if ((res = resolvepath(path, rpath, sizeof (rpath))) == -1) { 687 if ((errno != ENOENT) || 688 (cmd_num != CMD_VERIFY && cmd_num != CMD_INSTALL)) { 689 zperror(path, B_FALSE); 690 return (Z_ERR); 691 } 692 if (cmd_num == CMD_VERIFY) { 693 (void) fprintf(stderr, gettext("WARNING: %s does not " 694 "exist, so it cannot be verified.\nWhen 'zoneadm " 695 "%s' is run, '%s' will try to create\n%s, and '%s' " 696 "will be tried again,\nbut the '%s' may fail if:\n" 697 "the parent directory of %s is group- or other-" 698 "writable\nor\n%s overlaps with any other " 699 "installed zones.\n"), path, 700 cmd_to_str(CMD_INSTALL), cmd_to_str(CMD_INSTALL), 701 path, cmd_to_str(CMD_VERIFY), 702 cmd_to_str(CMD_VERIFY), path, path); 703 return (Z_OK); 704 } 705 /* 706 * The zonepath is supposed to be mode 700 but its 707 * parent(s) 755. So use 755 on the mkdirp() then 708 * chmod() the zonepath itself to 700. 709 */ 710 if (mkdirp(path, DEFAULT_DIR_MODE) < 0) { 711 zperror(path, B_FALSE); 712 return (Z_ERR); 713 } 714 /* 715 * If the chmod() fails, report the error, but might 716 * as well continue the verify procedure. 717 */ 718 if (chmod(path, S_IRWXU) != 0) 719 zperror(path, B_FALSE); 720 /* 721 * Since the mkdir() succeeded, we should not have to 722 * worry about a subsequent ENOENT, thus this should 723 * only recurse once. 724 */ 725 return (validate_zonepath(path, CMD_INSTALL)); 726 } 727 rpath[res] = '\0'; 728 if (strcmp(path, rpath) != 0) { 729 errno = Z_RESOLVED_PATH; 730 zperror(path, B_TRUE); 731 return (Z_ERR); 732 } 733 if ((res = stat(rpath, &stbuf)) != 0) { 734 zperror(rpath, B_FALSE); 735 return (Z_ERR); 736 } 737 if (!S_ISDIR(stbuf.st_mode)) { 738 (void) fprintf(stderr, gettext("%s is not a directory.\n"), 739 rpath); 740 return (Z_ERR); 741 } 742 if ((strcmp(stbuf.st_fstype, MNTTYPE_TMPFS) == 0) || 743 (strcmp(stbuf.st_fstype, MNTTYPE_XMEMFS) == 0)) { 744 (void) printf(gettext("WARNING: %s is on a temporary " 745 "file-system.\n"), rpath); 746 } 747 if (crosscheck_zonepaths(rpath) != Z_OK) 748 return (Z_ERR); 749 /* 750 * Try to collect and report as many minor errors as possible 751 * before returning, so the user can learn everything that needs 752 * to be fixed up front. 753 */ 754 if (stbuf.st_uid != 0) { 755 (void) fprintf(stderr, gettext("%s is not owned by root.\n"), 756 rpath); 757 err = B_TRUE; 758 } 759 err |= bad_mode_bit(stbuf.st_mode, S_IRUSR, B_TRUE, rpath); 760 err |= bad_mode_bit(stbuf.st_mode, S_IWUSR, B_TRUE, rpath); 761 err |= bad_mode_bit(stbuf.st_mode, S_IXUSR, B_TRUE, rpath); 762 err |= bad_mode_bit(stbuf.st_mode, S_IRGRP, B_FALSE, rpath); 763 err |= bad_mode_bit(stbuf.st_mode, S_IWGRP, B_FALSE, rpath); 764 err |= bad_mode_bit(stbuf.st_mode, S_IXGRP, B_FALSE, rpath); 765 err |= bad_mode_bit(stbuf.st_mode, S_IROTH, B_FALSE, rpath); 766 err |= bad_mode_bit(stbuf.st_mode, S_IWOTH, B_FALSE, rpath); 767 err |= bad_mode_bit(stbuf.st_mode, S_IXOTH, B_FALSE, rpath); 768 769 (void) snprintf(ppath, sizeof (ppath), "%s/..", path); 770 if ((res = resolvepath(ppath, rppath, sizeof (rppath))) == -1) { 771 zperror(ppath, B_FALSE); 772 return (Z_ERR); 773 } 774 rppath[res] = '\0'; 775 if ((res = stat(rppath, &stbuf)) != 0) { 776 zperror(rppath, B_FALSE); 777 return (Z_ERR); 778 } 779 /* theoretically impossible */ 780 if (!S_ISDIR(stbuf.st_mode)) { 781 (void) fprintf(stderr, gettext("%s is not a directory.\n"), 782 rppath); 783 return (Z_ERR); 784 } 785 if (stbuf.st_uid != 0) { 786 (void) fprintf(stderr, gettext("%s is not owned by root.\n"), 787 rppath); 788 err = B_TRUE; 789 } 790 err |= bad_mode_bit(stbuf.st_mode, S_IRUSR, B_TRUE, rppath); 791 err |= bad_mode_bit(stbuf.st_mode, S_IWUSR, B_TRUE, rppath); 792 err |= bad_mode_bit(stbuf.st_mode, S_IXUSR, B_TRUE, rppath); 793 err |= bad_mode_bit(stbuf.st_mode, S_IWGRP, B_FALSE, rppath); 794 err |= bad_mode_bit(stbuf.st_mode, S_IWOTH, B_FALSE, rppath); 795 if (strcmp(rpath, rppath) == 0) { 796 (void) fprintf(stderr, gettext("%s is its own parent.\n"), 797 rppath); 798 err = B_TRUE; 799 } 800 801 if (statvfs(rpath, &vfsbuf) != 0) { 802 zperror(rpath, B_FALSE); 803 return (Z_ERR); 804 } 805 if (strncmp(vfsbuf.f_basetype, "nfs", 3) == 0) { 806 (void) fprintf(stderr, gettext("Zonepath %s is over NFS, " 807 "which is not currently supported.\n"), rpath); 808 return (Z_ERR); 809 } 810 811 if ((res = zone_get_state(target_zone, &state)) != Z_OK) { 812 errno = res; 813 zperror2(target_zone, gettext("could not get state")); 814 return (Z_ERR); 815 } 816 /* 817 * The existence of the root path is only bad in the configured state, 818 * as it is *supposed* to be there at the installed and later states. 819 * State/command mismatches are caught earlier in verify_details(). 820 */ 821 if (state == ZONE_STATE_CONFIGURED) { 822 if (snprintf(rootpath, sizeof (rootpath), "%s/root", rpath) >= 823 sizeof (rootpath)) { 824 (void) fprintf(stderr, 825 gettext("Zonepath %s is too long.\n"), rpath); 826 return (Z_ERR); 827 } 828 if ((res = stat(rootpath, &stbuf)) == 0) { 829 (void) fprintf(stderr, gettext("Rootpath %s exists; " 830 "remove or move aside prior to %s.\n"), rootpath, 831 cmd_to_str(CMD_INSTALL)); 832 return (Z_ERR); 833 } 834 } 835 836 return (err ? Z_ERR : Z_OK); 837 } 838 839 static void 840 release_lock_file(int lockfd) 841 { 842 (void) close(lockfd); 843 } 844 845 static int 846 grab_lock_file(const char *zone_name, int *lockfd) 847 { 848 char pathbuf[PATH_MAX]; 849 struct flock flock; 850 851 if (mkdir(ZONES_TMPDIR, S_IRWXU) < 0 && errno != EEXIST) { 852 zerror(gettext("could not mkdir %s: %s"), ZONES_TMPDIR, 853 strerror(errno)); 854 return (Z_ERR); 855 } 856 (void) chmod(ZONES_TMPDIR, S_IRWXU); 857 858 /* 859 * One of these lock files is created for each zone (when needed). 860 * The lock files are not cleaned up (except on system reboot), 861 * but since there is only one per zone, there is no resource 862 * starvation issue. 863 */ 864 (void) snprintf(pathbuf, sizeof (pathbuf), "%s/%s.zoneadm.lock", 865 ZONES_TMPDIR, zone_name); 866 if ((*lockfd = open(pathbuf, O_RDWR|O_CREAT, S_IRUSR|S_IWUSR)) < 0) { 867 zerror(gettext("could not open %s: %s"), pathbuf, 868 strerror(errno)); 869 return (Z_ERR); 870 } 871 /* 872 * Lock the file to synchronize with other zoneadmds 873 */ 874 flock.l_type = F_WRLCK; 875 flock.l_whence = SEEK_SET; 876 flock.l_start = (off_t)0; 877 flock.l_len = (off_t)0; 878 if (fcntl(*lockfd, F_SETLKW, &flock) < 0) { 879 zerror(gettext("unable to lock %s: %s"), pathbuf, 880 strerror(errno)); 881 release_lock_file(*lockfd); 882 return (Z_ERR); 883 } 884 return (Z_OK); 885 } 886 887 static void 888 get_doorname(const char *zone_name, char *buffer) 889 { 890 (void) snprintf(buffer, PATH_MAX, ZONE_DOOR_PATH, zone_name); 891 } 892 893 /* 894 * system daemons are not audited. For the global zone, this occurs 895 * "naturally" since init is started with the default audit 896 * characteristics. Since zoneadmd is a system daemon and it starts 897 * init for a zone, it is necessary to clear out the audit 898 * characteristics inherited from whomever started zoneadmd. This is 899 * indicated by the audit id, which is set from the ruid parameter of 900 * adt_set_user(), below. 901 */ 902 903 static void 904 prepare_audit_context() 905 { 906 adt_session_data_t *ah; 907 char *failure = gettext("audit failure: %s"); 908 909 if (adt_start_session(&ah, NULL, 0)) { 910 zerror(failure, strerror(errno)); 911 return; 912 } 913 if (adt_set_user(ah, ADT_NO_AUDIT, ADT_NO_AUDIT, 914 ADT_NO_AUDIT, ADT_NO_AUDIT, NULL, ADT_NEW)) { 915 zerror(failure, strerror(errno)); 916 (void) adt_end_session(ah); 917 return; 918 } 919 if (adt_set_proc(ah)) 920 zerror(failure, strerror(errno)); 921 922 (void) adt_end_session(ah); 923 } 924 925 static int 926 start_zoneadmd(const char *zone_name) 927 { 928 char doorpath[PATH_MAX]; 929 pid_t child_pid; 930 int error = Z_ERR; 931 int doorfd, lockfd; 932 struct door_info info; 933 934 get_doorname(zone_name, doorpath); 935 936 if (grab_lock_file(zone_name, &lockfd) != Z_OK) 937 return (Z_ERR); 938 939 /* 940 * Now that we have the lock, re-confirm that the daemon is 941 * *not* up and working fine. If it is still down, we have a green 942 * light to start it. 943 */ 944 if ((doorfd = open(doorpath, O_RDONLY)) < 0) { 945 if (errno != ENOENT) { 946 zperror(doorpath, B_FALSE); 947 goto out; 948 } 949 } else { 950 if (door_info(doorfd, &info) == 0 && 951 ((info.di_attributes & DOOR_REVOKED) == 0)) { 952 error = Z_OK; 953 (void) close(doorfd); 954 goto out; 955 } 956 (void) close(doorfd); 957 } 958 959 if ((child_pid = fork()) == -1) { 960 zperror(gettext("could not fork"), B_FALSE); 961 goto out; 962 } else if (child_pid == 0) { 963 /* child process */ 964 965 prepare_audit_context(); 966 967 (void) execl("/usr/lib/zones/zoneadmd", "zoneadmd", "-z", 968 zone_name, NULL); 969 zperror(gettext("could not exec zoneadmd"), B_FALSE); 970 _exit(Z_ERR); 971 } else { 972 /* parent process */ 973 pid_t retval; 974 int pstatus = 0; 975 976 do { 977 retval = waitpid(child_pid, &pstatus, 0); 978 } while (retval != child_pid); 979 if (WIFSIGNALED(pstatus) || (WIFEXITED(pstatus) && 980 WEXITSTATUS(pstatus) != 0)) { 981 zerror(gettext("could not start %s"), "zoneadmd"); 982 goto out; 983 } 984 } 985 error = Z_OK; 986 out: 987 release_lock_file(lockfd); 988 return (error); 989 } 990 991 static int 992 ping_zoneadmd(const char *zone_name) 993 { 994 char doorpath[PATH_MAX]; 995 int doorfd; 996 struct door_info info; 997 998 get_doorname(zone_name, doorpath); 999 1000 if ((doorfd = open(doorpath, O_RDONLY)) < 0) { 1001 return (Z_ERR); 1002 } 1003 if (door_info(doorfd, &info) == 0 && 1004 ((info.di_attributes & DOOR_REVOKED) == 0)) { 1005 (void) close(doorfd); 1006 return (Z_OK); 1007 } 1008 (void) close(doorfd); 1009 return (Z_ERR); 1010 } 1011 1012 static int 1013 call_zoneadmd(const char *zone_name, zone_cmd_arg_t *arg) 1014 { 1015 char doorpath[PATH_MAX]; 1016 int doorfd, result; 1017 door_arg_t darg; 1018 1019 zoneid_t zoneid; 1020 uint64_t uniqid = 0; 1021 1022 zone_cmd_rval_t *rvalp; 1023 size_t rlen; 1024 char *cp, *errbuf; 1025 1026 rlen = getpagesize(); 1027 if ((rvalp = malloc(rlen)) == NULL) { 1028 zerror(gettext("failed to allocate %lu bytes: %s"), rlen, 1029 strerror(errno)); 1030 return (-1); 1031 } 1032 1033 if ((zoneid = getzoneidbyname(zone_name)) != ZONE_ID_UNDEFINED) { 1034 (void) zone_getattr(zoneid, ZONE_ATTR_UNIQID, &uniqid, 1035 sizeof (uniqid)); 1036 } 1037 arg->uniqid = uniqid; 1038 (void) strlcpy(arg->locale, locale, sizeof (arg->locale)); 1039 get_doorname(zone_name, doorpath); 1040 1041 /* 1042 * Loop trying to start zoneadmd; if something goes seriously 1043 * wrong we break out and fail. 1044 */ 1045 for (;;) { 1046 if (start_zoneadmd(zone_name) != Z_OK) 1047 break; 1048 1049 if ((doorfd = open(doorpath, O_RDONLY)) < 0) { 1050 zperror(gettext("failed to open zone door"), B_FALSE); 1051 break; 1052 } 1053 1054 darg.data_ptr = (char *)arg; 1055 darg.data_size = sizeof (*arg); 1056 darg.desc_ptr = NULL; 1057 darg.desc_num = 0; 1058 darg.rbuf = (char *)rvalp; 1059 darg.rsize = rlen; 1060 if (door_call(doorfd, &darg) != 0) { 1061 (void) close(doorfd); 1062 /* 1063 * We'll get EBADF if the door has been revoked. 1064 */ 1065 if (errno != EBADF) { 1066 zperror(gettext("door_call failed"), B_FALSE); 1067 break; 1068 } 1069 continue; /* take another lap */ 1070 } 1071 (void) close(doorfd); 1072 1073 if (darg.data_size == 0) { 1074 /* Door server is going away; kick it again. */ 1075 continue; 1076 } 1077 1078 errbuf = rvalp->errbuf; 1079 while (*errbuf != '\0') { 1080 /* 1081 * Remove any newlines since zerror() 1082 * will append one automatically. 1083 */ 1084 cp = strchr(errbuf, '\n'); 1085 if (cp != NULL) 1086 *cp = '\0'; 1087 zerror("%s", errbuf); 1088 if (cp == NULL) 1089 break; 1090 errbuf = cp + 1; 1091 } 1092 result = rvalp->rval == 0 ? 0 : -1; 1093 free(rvalp); 1094 return (result); 1095 } 1096 1097 free(rvalp); 1098 return (-1); 1099 } 1100 1101 static int 1102 ready_func(int argc, char *argv[]) 1103 { 1104 zone_cmd_arg_t zarg; 1105 int arg; 1106 1107 optind = 0; 1108 if ((arg = getopt(argc, argv, "?")) != EOF) { 1109 switch (arg) { 1110 case '?': 1111 sub_usage(SHELP_READY, CMD_READY); 1112 return (optopt == '?' ? Z_OK : Z_USAGE); 1113 default: 1114 sub_usage(SHELP_READY, CMD_READY); 1115 return (Z_USAGE); 1116 } 1117 } 1118 if (argc > optind) { 1119 sub_usage(SHELP_READY, CMD_READY); 1120 return (Z_USAGE); 1121 } 1122 if (sanity_check(target_zone, CMD_READY, B_FALSE, B_FALSE) != Z_OK) 1123 return (Z_ERR); 1124 if (verify_details(CMD_READY) != Z_OK) 1125 return (Z_ERR); 1126 1127 zarg.cmd = Z_READY; 1128 if (call_zoneadmd(target_zone, &zarg) != 0) { 1129 zerror(gettext("call to %s failed"), "zoneadmd"); 1130 return (Z_ERR); 1131 } 1132 return (Z_OK); 1133 } 1134 1135 static int 1136 boot_func(int argc, char *argv[]) 1137 { 1138 zone_cmd_arg_t zarg; 1139 int arg; 1140 1141 zarg.bootbuf[0] = '\0'; 1142 1143 /* 1144 * At the current time, the only supported subargument to the 1145 * "boot" subcommand is "-s" which specifies a single-user boot. 1146 * In the future, other boot arguments should be supported 1147 * including "-m" for specifying alternate smf(5) milestones. 1148 */ 1149 optind = 0; 1150 if ((arg = getopt(argc, argv, "?s")) != EOF) { 1151 switch (arg) { 1152 case '?': 1153 sub_usage(SHELP_BOOT, CMD_BOOT); 1154 return (optopt == '?' ? Z_OK : Z_USAGE); 1155 case 's': 1156 (void) strlcpy(zarg.bootbuf, "-s", 1157 sizeof (zarg.bootbuf)); 1158 break; 1159 default: 1160 sub_usage(SHELP_BOOT, CMD_BOOT); 1161 return (Z_USAGE); 1162 } 1163 } 1164 if (argc > optind) { 1165 sub_usage(SHELP_BOOT, CMD_BOOT); 1166 return (Z_USAGE); 1167 } 1168 if (sanity_check(target_zone, CMD_BOOT, B_FALSE, B_FALSE) != Z_OK) 1169 return (Z_ERR); 1170 if (verify_details(CMD_BOOT) != Z_OK) 1171 return (Z_ERR); 1172 zarg.cmd = Z_BOOT; 1173 if (call_zoneadmd(target_zone, &zarg) != 0) { 1174 zerror(gettext("call to %s failed"), "zoneadmd"); 1175 return (Z_ERR); 1176 } 1177 return (Z_OK); 1178 } 1179 1180 static void 1181 fake_up_local_zone(zoneid_t zid, zone_entry_t *zeptr) 1182 { 1183 ssize_t result; 1184 1185 zeptr->zid = zid; 1186 /* 1187 * Since we're looking up our own (non-global) zone name, 1188 * we can be assured that it will succeed. 1189 */ 1190 result = getzonenamebyid(zid, zeptr->zname, sizeof (zeptr->zname)); 1191 assert(result >= 0); 1192 (void) strlcpy(zeptr->zroot, "/", sizeof (zeptr->zroot)); 1193 zeptr->zstate_str = "running"; 1194 } 1195 1196 static int 1197 list_func(int argc, char *argv[]) 1198 { 1199 zone_entry_t *zentp, zent; 1200 int arg; 1201 boolean_t output = B_FALSE, verbose = B_FALSE, parsable = B_FALSE; 1202 zone_state_t min_state = ZONE_STATE_RUNNING; 1203 zoneid_t zone_id = getzoneid(); 1204 1205 if (target_zone == NULL) { 1206 /* all zones: default view to running but allow override */ 1207 optind = 0; 1208 while ((arg = getopt(argc, argv, "?cipv")) != EOF) { 1209 switch (arg) { 1210 case '?': 1211 sub_usage(SHELP_LIST, CMD_LIST); 1212 return (optopt == '?' ? Z_OK : Z_USAGE); 1213 case 'c': 1214 min_state = ZONE_STATE_CONFIGURED; 1215 break; 1216 case 'i': 1217 min_state = ZONE_STATE_INSTALLED; 1218 break; 1219 case 'p': 1220 parsable = B_TRUE; 1221 break; 1222 case 'v': 1223 verbose = B_TRUE; 1224 break; 1225 default: 1226 sub_usage(SHELP_LIST, CMD_LIST); 1227 return (Z_USAGE); 1228 } 1229 } 1230 if (parsable && verbose) { 1231 zerror(gettext("%s -p and -v are mutually exclusive."), 1232 cmd_to_str(CMD_LIST)); 1233 return (Z_ERR); 1234 } 1235 if (zone_id == GLOBAL_ZONEID) { 1236 zone_print_list(min_state, verbose, parsable); 1237 } else { 1238 fake_up_local_zone(zone_id, &zent); 1239 zone_print(&zent, verbose, parsable); 1240 } 1241 return (Z_OK); 1242 } 1243 1244 /* 1245 * Specific target zone: disallow -i/-c suboptions. 1246 */ 1247 optind = 0; 1248 while ((arg = getopt(argc, argv, "?pv")) != EOF) { 1249 switch (arg) { 1250 case '?': 1251 sub_usage(SHELP_LIST, CMD_LIST); 1252 return (optopt == '?' ? Z_OK : Z_USAGE); 1253 case 'p': 1254 parsable = B_TRUE; 1255 break; 1256 case 'v': 1257 verbose = B_TRUE; 1258 break; 1259 default: 1260 sub_usage(SHELP_LIST, CMD_LIST); 1261 return (Z_USAGE); 1262 } 1263 } 1264 if (parsable && verbose) { 1265 zerror(gettext("%s -p and -v are mutually exclusive."), 1266 cmd_to_str(CMD_LIST)); 1267 return (Z_ERR); 1268 } 1269 if (argc > optind) { 1270 sub_usage(SHELP_LIST, CMD_LIST); 1271 return (Z_USAGE); 1272 } 1273 if (zone_id != GLOBAL_ZONEID) { 1274 fake_up_local_zone(zone_id, &zent); 1275 /* 1276 * main() will issue a Z_NO_ZONE error if it cannot get an 1277 * id for target_zone, which in a non-global zone should 1278 * happen for any zone name except `zonename`. Thus we 1279 * assert() that here but don't otherwise check. 1280 */ 1281 assert(strcmp(zent.zname, target_zone) == 0); 1282 zone_print(&zent, verbose, parsable); 1283 output = B_TRUE; 1284 } else if ((zentp = lookup_running_zone(target_zone)) != NULL) { 1285 zone_print(zentp, verbose, parsable); 1286 output = B_TRUE; 1287 } else if (lookup_zone_info(target_zone, &zent) == Z_OK) { 1288 zone_print(&zent, verbose, parsable); 1289 output = B_TRUE; 1290 } 1291 return (output ? Z_OK : Z_ERR); 1292 } 1293 1294 static void 1295 sigterm(int sig) 1296 { 1297 /* 1298 * Ignore SIG{INT,TERM}, so we don't end up in an infinite loop, 1299 * then propagate the signal to our process group. 1300 */ 1301 (void) sigset(SIGINT, SIG_IGN); 1302 (void) sigset(SIGTERM, SIG_IGN); 1303 (void) kill(0, sig); 1304 child_killed = B_TRUE; 1305 } 1306 1307 static int 1308 do_subproc(char *cmdbuf) 1309 { 1310 char inbuf[1024]; /* arbitrary large amount */ 1311 FILE *file; 1312 1313 child_killed = B_FALSE; 1314 /* 1315 * We use popen(3c) to launch child processes for [un]install; 1316 * this library call does not return a PID, so we have to kill 1317 * the whole process group. To avoid killing our parent, we 1318 * become a process group leader here. But doing so can wreak 1319 * havoc with reading from stdin when launched by a non-job-control 1320 * shell, so we close stdin and reopen it as /dev/null first. 1321 */ 1322 (void) close(STDIN_FILENO); 1323 (void) open("/dev/null", O_RDONLY); 1324 (void) setpgid(0, 0); 1325 (void) sigset(SIGINT, sigterm); 1326 (void) sigset(SIGTERM, sigterm); 1327 file = popen(cmdbuf, "r"); 1328 for (;;) { 1329 if (child_killed || fgets(inbuf, sizeof (inbuf), file) == NULL) 1330 break; 1331 (void) fputs(inbuf, stdout); 1332 } 1333 (void) sigset(SIGINT, SIG_DFL); 1334 (void) sigset(SIGTERM, SIG_DFL); 1335 return (pclose(file)); 1336 } 1337 1338 static int 1339 subproc_status(const char *cmd, int status) 1340 { 1341 if (WIFEXITED(status)) { 1342 int exit_code = WEXITSTATUS(status); 1343 1344 if (exit_code == 0) 1345 return (Z_OK); 1346 zerror(gettext("'%s' failed with exit code %d."), cmd, 1347 exit_code); 1348 } else if (WIFSIGNALED(status)) { 1349 int signal = WTERMSIG(status); 1350 char sigstr[SIG2STR_MAX]; 1351 1352 if (sig2str(signal, sigstr) == 0) { 1353 zerror(gettext("'%s' terminated by signal SIG%s."), cmd, 1354 sigstr); 1355 } else { 1356 zerror(gettext("'%s' terminated by an unknown signal."), 1357 cmd); 1358 } 1359 } else { 1360 zerror(gettext("'%s' failed for unknown reasons."), cmd); 1361 } 1362 return (Z_ERR); 1363 } 1364 1365 /* 1366 * Various sanity checks; make sure: 1367 * 1. We're in the global zone. 1368 * 2. The calling user has sufficient privilege. 1369 * 3. The target zone is neither the global zone nor anything starting with 1370 * "SUNW". 1371 * 4a. If we're looking for a 'not running' (i.e., configured or installed) 1372 * zone, the name service knows about it. 1373 * 4b. For some operations which expect a zone not to be running, that it is 1374 * not already running (or ready). 1375 */ 1376 static int 1377 sanity_check(char *zone, int cmd_num, boolean_t running, 1378 boolean_t unsafe_when_running) 1379 { 1380 zone_entry_t *zent; 1381 priv_set_t *privset; 1382 zone_state_t state; 1383 1384 if (getzoneid() != GLOBAL_ZONEID) { 1385 zerror(gettext("must be in the global zone to %s a zone."), 1386 cmd_to_str(cmd_num)); 1387 return (Z_ERR); 1388 } 1389 1390 if ((privset = priv_allocset()) == NULL) { 1391 zerror(gettext("%s failed"), "priv_allocset"); 1392 return (Z_ERR); 1393 } 1394 1395 if (getppriv(PRIV_EFFECTIVE, privset) != 0) { 1396 zerror(gettext("%s failed"), "getppriv"); 1397 priv_freeset(privset); 1398 return (Z_ERR); 1399 } 1400 1401 if (priv_isfullset(privset) == B_FALSE) { 1402 zerror(gettext("only a privileged user may %s a zone."), 1403 cmd_to_str(cmd_num)); 1404 priv_freeset(privset); 1405 return (Z_ERR); 1406 } 1407 priv_freeset(privset); 1408 1409 if (zone == NULL) { 1410 zerror(gettext("no zone specified")); 1411 return (Z_ERR); 1412 } 1413 1414 zent = lookup_running_zone(zone); 1415 1416 if (strcmp(zone, GLOBAL_ZONENAME) == 0) { 1417 assert((zent != NULL) && (zent->zid == GLOBAL_ZONEID)); 1418 zerror(gettext("%s operation is invalid for the global zone."), 1419 cmd_to_str(cmd_num)); 1420 return (Z_ERR); 1421 } 1422 1423 if (strncmp(zone, "SUNW", 4) == 0) { 1424 zerror(gettext("%s operation is invalid for zones starting " 1425 "with SUNW."), cmd_to_str(cmd_num)); 1426 return (Z_ERR); 1427 } 1428 1429 /* 1430 * Look up from the kernel for 'running' zones. 1431 */ 1432 if (running) { 1433 if (zent == NULL) { 1434 zerror(gettext("not running")); 1435 return (Z_ERR); 1436 } 1437 } else { 1438 int err; 1439 1440 if (unsafe_when_running && zent != NULL) { 1441 /* check whether the zone is ready or running */ 1442 if ((err = zone_get_state(zent->zname, 1443 &zent->zstate_num)) != Z_OK) { 1444 errno = err; 1445 zperror2(zent->zname, 1446 gettext("could not get state")); 1447 /* can't tell, so hedge */ 1448 zent->zstate_str = "ready/running"; 1449 } else { 1450 zent->zstate_str = 1451 zone_state_str(zent->zstate_num); 1452 } 1453 zerror(gettext("%s operation is invalid for %s zones."), 1454 cmd_to_str(cmd_num), zent->zstate_str); 1455 return (Z_ERR); 1456 } 1457 if ((err = zone_get_state(zone, &state)) != Z_OK) { 1458 errno = err; 1459 zperror2(zone, gettext("could not get state")); 1460 return (Z_ERR); 1461 } 1462 switch (cmd_num) { 1463 case CMD_UNINSTALL: 1464 if (state == ZONE_STATE_CONFIGURED) { 1465 zerror(gettext("is already in state '%s'."), 1466 zone_state_str(ZONE_STATE_CONFIGURED)); 1467 return (Z_ERR); 1468 } 1469 break; 1470 case CMD_INSTALL: 1471 if (state == ZONE_STATE_INSTALLED) { 1472 zerror(gettext("is already %s."), 1473 zone_state_str(ZONE_STATE_INSTALLED)); 1474 return (Z_ERR); 1475 } else if (state == ZONE_STATE_INCOMPLETE) { 1476 zerror(gettext("zone is %s; %s required."), 1477 zone_state_str(ZONE_STATE_INCOMPLETE), 1478 cmd_to_str(CMD_UNINSTALL)); 1479 return (Z_ERR); 1480 } 1481 break; 1482 case CMD_READY: 1483 case CMD_BOOT: 1484 if (state < ZONE_STATE_INSTALLED) { 1485 zerror(gettext("must be %s before %s."), 1486 zone_state_str(ZONE_STATE_INSTALLED), 1487 cmd_to_str(cmd_num)); 1488 return (Z_ERR); 1489 } 1490 break; 1491 case CMD_VERIFY: 1492 if (state == ZONE_STATE_INCOMPLETE) { 1493 zerror(gettext("zone is %s; %s required."), 1494 zone_state_str(ZONE_STATE_INCOMPLETE), 1495 cmd_to_str(CMD_UNINSTALL)); 1496 return (Z_ERR); 1497 } 1498 break; 1499 } 1500 } 1501 return (Z_OK); 1502 } 1503 1504 static int 1505 halt_func(int argc, char *argv[]) 1506 { 1507 zone_cmd_arg_t zarg; 1508 int arg; 1509 1510 optind = 0; 1511 if ((arg = getopt(argc, argv, "?")) != EOF) { 1512 switch (arg) { 1513 case '?': 1514 sub_usage(SHELP_HALT, CMD_HALT); 1515 return (optopt == '?' ? Z_OK : Z_USAGE); 1516 default: 1517 sub_usage(SHELP_HALT, CMD_HALT); 1518 return (Z_USAGE); 1519 } 1520 } 1521 if (argc > optind) { 1522 sub_usage(SHELP_HALT, CMD_HALT); 1523 return (Z_USAGE); 1524 } 1525 /* 1526 * zoneadmd should be the one to decide whether or not to proceed, 1527 * so even though it seems that the fourth parameter below should 1528 * perhaps be B_TRUE, it really shouldn't be. 1529 */ 1530 if (sanity_check(target_zone, CMD_HALT, B_FALSE, B_FALSE) != Z_OK) 1531 return (Z_ERR); 1532 1533 zarg.cmd = Z_HALT; 1534 return ((call_zoneadmd(target_zone, &zarg) == 0) ? Z_OK : Z_ERR); 1535 } 1536 1537 static int 1538 reboot_func(int argc, char *argv[]) 1539 { 1540 zone_cmd_arg_t zarg; 1541 int arg; 1542 1543 optind = 0; 1544 if ((arg = getopt(argc, argv, "?")) != EOF) { 1545 switch (arg) { 1546 case '?': 1547 sub_usage(SHELP_REBOOT, CMD_REBOOT); 1548 return (optopt == '?' ? Z_OK : Z_USAGE); 1549 default: 1550 sub_usage(SHELP_REBOOT, CMD_REBOOT); 1551 return (Z_USAGE); 1552 } 1553 } 1554 if (argc > 0) { 1555 sub_usage(SHELP_REBOOT, CMD_REBOOT); 1556 return (Z_USAGE); 1557 } 1558 /* 1559 * zoneadmd should be the one to decide whether or not to proceed, 1560 * so even though it seems that the fourth parameter below should 1561 * perhaps be B_TRUE, it really shouldn't be. 1562 */ 1563 if (sanity_check(target_zone, CMD_REBOOT, B_TRUE, B_FALSE) != Z_OK) 1564 return (Z_ERR); 1565 1566 zarg.cmd = Z_REBOOT; 1567 return ((call_zoneadmd(target_zone, &zarg) == 0) ? Z_OK : Z_ERR); 1568 } 1569 1570 static int 1571 verify_rctls(zone_dochandle_t handle) 1572 { 1573 struct zone_rctltab rctltab; 1574 size_t rbs = rctlblk_size(); 1575 rctlblk_t *rctlblk; 1576 int error = Z_INVAL; 1577 1578 if ((rctlblk = malloc(rbs)) == NULL) { 1579 zerror(gettext("failed to allocate %lu bytes: %s"), rbs, 1580 strerror(errno)); 1581 return (Z_NOMEM); 1582 } 1583 1584 if (zonecfg_setrctlent(handle) != Z_OK) { 1585 zerror(gettext("zonecfg_setrctlent failed")); 1586 free(rctlblk); 1587 return (error); 1588 } 1589 1590 rctltab.zone_rctl_valptr = NULL; 1591 while (zonecfg_getrctlent(handle, &rctltab) == Z_OK) { 1592 struct zone_rctlvaltab *rctlval; 1593 const char *name = rctltab.zone_rctl_name; 1594 1595 if (!zonecfg_is_rctl(name)) { 1596 zerror(gettext("WARNING: Ignoring unrecognized rctl " 1597 "'%s'."), name); 1598 zonecfg_free_rctl_value_list(rctltab.zone_rctl_valptr); 1599 rctltab.zone_rctl_valptr = NULL; 1600 continue; 1601 } 1602 1603 for (rctlval = rctltab.zone_rctl_valptr; rctlval != NULL; 1604 rctlval = rctlval->zone_rctlval_next) { 1605 if (zonecfg_construct_rctlblk(rctlval, rctlblk) 1606 != Z_OK) { 1607 zerror(gettext("invalid rctl value: " 1608 "(priv=%s,limit=%s,action%s)"), 1609 rctlval->zone_rctlval_priv, 1610 rctlval->zone_rctlval_limit, 1611 rctlval->zone_rctlval_action); 1612 goto out; 1613 } 1614 if (!zonecfg_valid_rctl(name, rctlblk)) { 1615 zerror(gettext("(priv=%s,limit=%s,action=%s) " 1616 "is not a valid value for rctl '%s'"), 1617 rctlval->zone_rctlval_priv, 1618 rctlval->zone_rctlval_limit, 1619 rctlval->zone_rctlval_action, 1620 name); 1621 goto out; 1622 } 1623 } 1624 zonecfg_free_rctl_value_list(rctltab.zone_rctl_valptr); 1625 } 1626 rctltab.zone_rctl_valptr = NULL; 1627 error = Z_OK; 1628 out: 1629 zonecfg_free_rctl_value_list(rctltab.zone_rctl_valptr); 1630 (void) zonecfg_endrctlent(handle); 1631 free(rctlblk); 1632 return (error); 1633 } 1634 1635 static int 1636 verify_pool(zone_dochandle_t handle) 1637 { 1638 char poolname[MAXPATHLEN]; 1639 pool_conf_t *poolconf; 1640 pool_t *pool; 1641 int status; 1642 int error; 1643 1644 /* 1645 * This ends up being very similar to the check done in zoneadmd. 1646 */ 1647 error = zonecfg_get_pool(handle, poolname, sizeof (poolname)); 1648 if (error == Z_NO_ENTRY || (error == Z_OK && strlen(poolname) == 0)) { 1649 /* 1650 * No pool specified. 1651 */ 1652 return (0); 1653 } 1654 if (error != Z_OK) { 1655 zperror(gettext("Unable to retrieve pool name from " 1656 "configuration"), B_TRUE); 1657 return (error); 1658 } 1659 /* 1660 * Don't do anything if pools aren't enabled. 1661 */ 1662 if (pool_get_status(&status) != PO_SUCCESS || status != POOL_ENABLED) { 1663 zerror(gettext("WARNING: pools facility not active; " 1664 "zone will not be bound to pool '%s'."), poolname); 1665 return (Z_OK); 1666 } 1667 /* 1668 * Try to provide a sane error message if the requested pool doesn't 1669 * exist. It isn't clear that pools-related failures should 1670 * necessarily translate to a failure to verify the zone configuration, 1671 * hence they are not considered errors. 1672 */ 1673 if ((poolconf = pool_conf_alloc()) == NULL) { 1674 zerror(gettext("WARNING: pool_conf_alloc failed; " 1675 "using default pool")); 1676 return (Z_OK); 1677 } 1678 if (pool_conf_open(poolconf, pool_dynamic_location(), PO_RDONLY) != 1679 PO_SUCCESS) { 1680 zerror(gettext("WARNING: pool_conf_open failed; " 1681 "using default pool")); 1682 pool_conf_free(poolconf); 1683 return (Z_OK); 1684 } 1685 pool = pool_get_pool(poolconf, poolname); 1686 (void) pool_conf_close(poolconf); 1687 pool_conf_free(poolconf); 1688 if (pool == NULL) { 1689 zerror(gettext("WARNING: pool '%s' not found. " 1690 "using default pool"), poolname); 1691 } 1692 1693 return (Z_OK); 1694 } 1695 1696 static int 1697 verify_filesystems(zone_dochandle_t handle) 1698 { 1699 int return_code = Z_OK; 1700 struct zone_fstab fstab; 1701 char cmdbuf[MAXPATHLEN]; 1702 struct stat st; 1703 1704 /* 1705 * No need to verify inherit-pkg-dir fs types, as their type is 1706 * implicitly lofs, which is known. Therefore, the types are only 1707 * verified for regular filesystems below. 1708 * 1709 * Since the actual mount point is not known until the dependent mounts 1710 * are performed, we don't attempt any path validation here: that will 1711 * happen later when zoneadmd actually does the mounts. 1712 */ 1713 if (zonecfg_setfsent(handle) != Z_OK) { 1714 (void) fprintf(stderr, gettext("cannot verify file-systems: " 1715 "unable to enumerate mounts\n")); 1716 return (Z_ERR); 1717 } 1718 while (zonecfg_getfsent(handle, &fstab) == Z_OK) { 1719 if (!zonecfg_valid_fs_type(fstab.zone_fs_type)) { 1720 (void) fprintf(stderr, gettext("cannot verify fs %s: " 1721 "type %s is not allowed.\n"), fstab.zone_fs_dir, 1722 fstab.zone_fs_type); 1723 return_code = Z_ERR; 1724 goto next_fs; 1725 } 1726 /* 1727 * Verify /usr/lib/fs/<fstype>/mount exists. 1728 */ 1729 if (snprintf(cmdbuf, sizeof (cmdbuf), "/usr/lib/fs/%s/mount", 1730 fstab.zone_fs_type) > sizeof (cmdbuf)) { 1731 (void) fprintf(stderr, gettext("cannot verify fs %s: " 1732 "type %s is too long.\n"), fstab.zone_fs_dir, 1733 fstab.zone_fs_type); 1734 return_code = Z_ERR; 1735 goto next_fs; 1736 } 1737 if (stat(cmdbuf, &st) != 0) { 1738 (void) fprintf(stderr, gettext("cannot verify fs %s: " 1739 "can't access %s: %s\n"), fstab.zone_fs_dir, 1740 cmdbuf, strerror(errno)); 1741 return_code = Z_ERR; 1742 goto next_fs; 1743 } 1744 if (!S_ISREG(st.st_mode)) { 1745 (void) fprintf(stderr, gettext("cannot verify fs %s: " 1746 "%s is not a regular file\n"), fstab.zone_fs_dir, 1747 cmdbuf); 1748 return_code = Z_ERR; 1749 goto next_fs; 1750 } 1751 /* 1752 * Verify /usr/lib/fs/<fstype>/fsck exists iff zone_fs_raw is 1753 * set. 1754 */ 1755 if (snprintf(cmdbuf, sizeof (cmdbuf), "/usr/lib/fs/%s/fsck", 1756 fstab.zone_fs_type) > sizeof (cmdbuf)) { 1757 (void) fprintf(stderr, gettext("cannot verify fs %s: " 1758 "type %s is too long.\n"), fstab.zone_fs_dir, 1759 fstab.zone_fs_type); 1760 return_code = Z_ERR; 1761 goto next_fs; 1762 } 1763 if (fstab.zone_fs_raw[0] == '\0' && stat(cmdbuf, &st) == 0) { 1764 (void) fprintf(stderr, gettext("cannot verify fs %s: " 1765 "must specify 'raw' device for %s file-systems\n"), 1766 fstab.zone_fs_dir, fstab.zone_fs_type); 1767 return_code = Z_ERR; 1768 goto next_fs; 1769 } 1770 if (fstab.zone_fs_raw[0] != '\0' && 1771 (stat(cmdbuf, &st) != 0 || !S_ISREG(st.st_mode))) { 1772 (void) fprintf(stderr, gettext("cannot verify fs %s: " 1773 "'raw' device specified but " 1774 "no fsck executable exists for %s\n"), 1775 fstab.zone_fs_dir, fstab.zone_fs_type); 1776 return_code = Z_ERR; 1777 goto next_fs; 1778 } 1779 next_fs: 1780 zonecfg_free_fs_option_list(fstab.zone_fs_options); 1781 } 1782 (void) zonecfg_endfsent(handle); 1783 1784 return (return_code); 1785 } 1786 1787 static int 1788 verify_details(int cmd_num) 1789 { 1790 zone_dochandle_t handle; 1791 struct zone_nwiftab nwiftab; 1792 char zonepath[MAXPATHLEN], checkpath[MAXPATHLEN]; 1793 int return_code = Z_OK; 1794 int err; 1795 1796 if ((handle = zonecfg_init_handle()) == NULL) { 1797 zperror(cmd_to_str(cmd_num), B_TRUE); 1798 return (Z_ERR); 1799 } 1800 if ((err = zonecfg_get_handle(target_zone, handle)) != Z_OK) { 1801 errno = err; 1802 zperror(cmd_to_str(cmd_num), B_TRUE); 1803 zonecfg_fini_handle(handle); 1804 return (Z_ERR); 1805 } 1806 if ((err = zonecfg_get_zonepath(handle, zonepath, sizeof (zonepath))) != 1807 Z_OK) { 1808 errno = err; 1809 zperror(cmd_to_str(cmd_num), B_TRUE); 1810 zonecfg_fini_handle(handle); 1811 return (Z_ERR); 1812 } 1813 /* 1814 * zonecfg_get_zonepath() gets its data from the XML repository. 1815 * Verify this against the index file, which is checked first by 1816 * zone_get_zonepath(). If they don't match, bail out. 1817 */ 1818 if ((err = zone_get_zonepath(target_zone, checkpath, 1819 sizeof (checkpath))) != Z_OK) { 1820 errno = err; 1821 zperror2(target_zone, gettext("could not get zone path")); 1822 return (Z_ERR); 1823 } 1824 if (strcmp(zonepath, checkpath) != 0) { 1825 (void) fprintf(stderr, gettext("The XML repository has " 1826 "zonepath '%s',\nbut the index file has zonepath '%s'.\n" 1827 "These must match, so fix the incorrect entry.\n"), 1828 zonepath, checkpath); 1829 return (Z_ERR); 1830 } 1831 if (validate_zonepath(zonepath, cmd_num) != Z_OK) { 1832 (void) fprintf(stderr, gettext("could not verify zonepath %s " 1833 "because of the above errors.\n"), zonepath); 1834 return_code = Z_ERR; 1835 } 1836 1837 if ((err = zonecfg_setnwifent(handle)) != Z_OK) { 1838 errno = err; 1839 zperror(cmd_to_str(cmd_num), B_TRUE); 1840 zonecfg_fini_handle(handle); 1841 return (Z_ERR); 1842 } 1843 while (zonecfg_getnwifent(handle, &nwiftab) == Z_OK) { 1844 struct lifreq lifr; 1845 sa_family_t af; 1846 int so, res; 1847 1848 /* skip any loopback interfaces */ 1849 if (strcmp(nwiftab.zone_nwif_physical, "lo0") == 0) 1850 continue; 1851 if ((res = zonecfg_valid_net_address(nwiftab.zone_nwif_address, 1852 &lifr)) != Z_OK) { 1853 (void) fprintf(stderr, gettext("could not verify %s " 1854 "%s=%s %s=%s: %s\n"), "net", "address", 1855 nwiftab.zone_nwif_address, "physical", 1856 nwiftab.zone_nwif_physical, zonecfg_strerror(res)); 1857 return_code = Z_ERR; 1858 continue; 1859 } 1860 af = lifr.lifr_addr.ss_family; 1861 (void) memset(&lifr, 0, sizeof (lifr)); 1862 (void) strlcpy(lifr.lifr_name, nwiftab.zone_nwif_physical, 1863 sizeof (lifr.lifr_name)); 1864 lifr.lifr_addr.ss_family = af; 1865 if ((so = socket(af, SOCK_DGRAM, 0)) < 0) { 1866 (void) fprintf(stderr, gettext("could not verify %s " 1867 "%s=%s %s=%s: could not get socket: %s\n"), "net", 1868 "address", nwiftab.zone_nwif_address, "physical", 1869 nwiftab.zone_nwif_physical, strerror(errno)); 1870 return_code = Z_ERR; 1871 continue; 1872 } 1873 if (ioctl(so, SIOCGLIFFLAGS, (caddr_t)&lifr) < 0) { 1874 (void) fprintf(stderr, 1875 gettext("could not verify %s %s=%s %s=%s: %s\n"), 1876 "net", "address", nwiftab.zone_nwif_address, 1877 "physical", nwiftab.zone_nwif_physical, 1878 strerror(errno)); 1879 return_code = Z_ERR; 1880 } 1881 (void) close(so); 1882 } 1883 (void) zonecfg_endnwifent(handle); 1884 1885 if (verify_filesystems(handle) != Z_OK) 1886 return_code = Z_ERR; 1887 if (verify_rctls(handle) != Z_OK) 1888 return_code = Z_ERR; 1889 if (verify_pool(handle) != Z_OK) 1890 return_code = Z_ERR; 1891 zonecfg_fini_handle(handle); 1892 if (return_code == Z_ERR) 1893 (void) fprintf(stderr, 1894 gettext("%s: zone %s failed to verify\n"), 1895 execname, target_zone); 1896 return (return_code); 1897 } 1898 1899 static int 1900 verify_func(int argc, char *argv[]) 1901 { 1902 int arg; 1903 1904 optind = 0; 1905 if ((arg = getopt(argc, argv, "?")) != EOF) { 1906 switch (arg) { 1907 case '?': 1908 sub_usage(SHELP_VERIFY, CMD_VERIFY); 1909 return (optopt == '?' ? Z_OK : Z_USAGE); 1910 default: 1911 sub_usage(SHELP_VERIFY, CMD_VERIFY); 1912 return (Z_USAGE); 1913 } 1914 } 1915 if (argc > optind) { 1916 sub_usage(SHELP_VERIFY, CMD_VERIFY); 1917 return (Z_USAGE); 1918 } 1919 if (sanity_check(target_zone, CMD_VERIFY, B_FALSE, B_FALSE) != Z_OK) 1920 return (Z_ERR); 1921 return (verify_details(CMD_VERIFY)); 1922 } 1923 1924 #define LUCREATEZONE "/usr/lib/lu/lucreatezone" 1925 1926 static int 1927 install_func(int argc, char *argv[]) 1928 { 1929 /* 9: "exec " and " -z " */ 1930 char cmdbuf[sizeof (LUCREATEZONE) + ZONENAME_MAX + 9]; 1931 int lockfd; 1932 int err, arg; 1933 char zonepath[MAXPATHLEN]; 1934 int status; 1935 1936 optind = 0; 1937 if ((arg = getopt(argc, argv, "?")) != EOF) { 1938 switch (arg) { 1939 case '?': 1940 sub_usage(SHELP_INSTALL, CMD_INSTALL); 1941 return (optopt == '?' ? Z_OK : Z_USAGE); 1942 default: 1943 sub_usage(SHELP_INSTALL, CMD_INSTALL); 1944 return (Z_USAGE); 1945 } 1946 } 1947 if (argc > optind) { 1948 sub_usage(SHELP_INSTALL, CMD_INSTALL); 1949 return (Z_USAGE); 1950 } 1951 if (sanity_check(target_zone, CMD_INSTALL, B_FALSE, B_TRUE) != Z_OK) 1952 return (Z_ERR); 1953 if (verify_details(CMD_INSTALL) != Z_OK) 1954 return (Z_ERR); 1955 1956 if (grab_lock_file(target_zone, &lockfd) != Z_OK) { 1957 zerror(gettext("another %s may have an operation in progress."), 1958 "zoneadmd"); 1959 return (Z_ERR); 1960 } 1961 err = zone_set_state(target_zone, ZONE_STATE_INCOMPLETE); 1962 if (err != Z_OK) { 1963 errno = err; 1964 zperror2(target_zone, gettext("could not set state")); 1965 goto done; 1966 } 1967 1968 /* 1969 * According to the Application Packaging Developer's Guide, a 1970 * "checkinstall" script when included in a package is executed as 1971 * the user "install", if such a user exists, or by the user 1972 * "nobody". In order to support this dubious behavior, the path 1973 * to the zone being constructed is opened up during the life of 1974 * the command laying down the zone's root file system. Once this 1975 * has completed, regardless of whether it was successful, the 1976 * path to the zone is again restricted. 1977 */ 1978 if ((err = zone_get_zonepath(target_zone, zonepath, 1979 sizeof (zonepath))) != Z_OK) { 1980 errno = err; 1981 zperror2(target_zone, gettext("could not get zone path")); 1982 goto done; 1983 } 1984 if (chmod(zonepath, DEFAULT_DIR_MODE) != 0) { 1985 zperror(zonepath, B_FALSE); 1986 err = Z_ERR; 1987 goto done; 1988 } 1989 1990 /* 1991 * "exec" the command so that the returned status is that of 1992 * LUCREATEZONE and not the shell. 1993 */ 1994 (void) snprintf(cmdbuf, sizeof (cmdbuf), "exec " LUCREATEZONE " -z %s", 1995 target_zone); 1996 status = do_subproc(cmdbuf); 1997 if (chmod(zonepath, S_IRWXU) != 0) { 1998 zperror(zonepath, B_FALSE); 1999 err = Z_ERR; 2000 goto done; 2001 } 2002 if ((err = subproc_status(LUCREATEZONE, status)) != Z_OK) 2003 goto done; 2004 2005 if ((err = zone_set_state(target_zone, ZONE_STATE_INSTALLED)) != Z_OK) { 2006 errno = err; 2007 zperror2(target_zone, gettext("could not set state")); 2008 goto done; 2009 } 2010 2011 done: 2012 release_lock_file(lockfd); 2013 return ((err == Z_OK) ? Z_OK : Z_ERR); 2014 } 2015 2016 /* 2017 * On input, TRUE => yes, FALSE => no. 2018 * On return, TRUE => 1, FALSE => 0, could not ask => -1. 2019 */ 2020 2021 static int 2022 ask_yesno(boolean_t default_answer, const char *question) 2023 { 2024 char line[64]; /* should be large enough to answer yes or no */ 2025 2026 if (!isatty(STDIN_FILENO)) 2027 return (-1); 2028 for (;;) { 2029 (void) printf("%s (%s)? ", question, 2030 default_answer ? "[y]/n" : "y/[n]"); 2031 if (fgets(line, sizeof (line), stdin) == NULL || 2032 line[0] == '\n') 2033 return (default_answer ? 1 : 0); 2034 if (tolower(line[0]) == 'y') 2035 return (1); 2036 if (tolower(line[0]) == 'n') 2037 return (0); 2038 } 2039 } 2040 2041 #define RMCOMMAND "/usr/bin/rm -rf" 2042 2043 /* ARGSUSED */ 2044 int 2045 zfm_print(const char *p, void *r) { 2046 zerror(" %s\n", p); 2047 return (0); 2048 } 2049 2050 static int 2051 uninstall_func(int argc, char *argv[]) 2052 { 2053 /* 6: "exec " and " " */ 2054 char cmdbuf[sizeof (RMCOMMAND) + MAXPATHLEN + 6]; 2055 char line[ZONENAME_MAX + 128]; /* Enough for "Are you sure ..." */ 2056 char rootpath[MAXPATHLEN], devpath[MAXPATHLEN]; 2057 boolean_t force = B_FALSE; 2058 int lockfd, answer; 2059 int err, arg; 2060 int status; 2061 2062 optind = 0; 2063 while ((arg = getopt(argc, argv, "?F")) != EOF) { 2064 switch (arg) { 2065 case '?': 2066 sub_usage(SHELP_UNINSTALL, CMD_UNINSTALL); 2067 return (optopt == '?' ? Z_OK : Z_USAGE); 2068 case 'F': 2069 force = B_TRUE; 2070 break; 2071 default: 2072 sub_usage(SHELP_UNINSTALL, CMD_UNINSTALL); 2073 return (Z_USAGE); 2074 } 2075 } 2076 if (argc > optind) { 2077 sub_usage(SHELP_UNINSTALL, CMD_UNINSTALL); 2078 return (Z_USAGE); 2079 } 2080 2081 if (sanity_check(target_zone, CMD_UNINSTALL, B_FALSE, B_TRUE) != Z_OK) 2082 return (Z_ERR); 2083 2084 if (!force) { 2085 (void) snprintf(line, sizeof (line), 2086 gettext("Are you sure you want to %s zone %s"), 2087 cmd_to_str(CMD_UNINSTALL), target_zone); 2088 if ((answer = ask_yesno(B_FALSE, line)) == 0) { 2089 return (Z_OK); 2090 } else if (answer == -1) { 2091 zerror(gettext("Input not from terminal and -F " 2092 "not specified: %s not done."), 2093 cmd_to_str(CMD_UNINSTALL)); 2094 return (Z_ERR); 2095 } 2096 } 2097 2098 if ((err = zone_get_zonepath(target_zone, devpath, 2099 sizeof (devpath))) != Z_OK) { 2100 errno = err; 2101 zperror2(target_zone, gettext("could not get zone path")); 2102 return (Z_ERR); 2103 } 2104 (void) strlcat(devpath, "/dev", sizeof (devpath)); 2105 if ((err = zone_get_rootpath(target_zone, rootpath, 2106 sizeof (rootpath))) != Z_OK) { 2107 errno = err; 2108 zperror2(target_zone, gettext("could not get root path")); 2109 return (Z_ERR); 2110 } 2111 2112 /* 2113 * If there seems to be a zoneadmd running for this zone, call it 2114 * to tell it that an uninstall is happening; if all goes well it 2115 * will then shut itself down. 2116 */ 2117 if (ping_zoneadmd(target_zone) == Z_OK) { 2118 zone_cmd_arg_t zarg; 2119 zarg.cmd = Z_NOTE_UNINSTALLING; 2120 /* we don't care too much if this fails... just plow on */ 2121 (void) call_zoneadmd(target_zone, &zarg); 2122 } 2123 2124 if (grab_lock_file(target_zone, &lockfd) != Z_OK) { 2125 zerror(gettext("another %s may have an operation in progress."), 2126 "zoneadmd"); 2127 return (Z_ERR); 2128 } 2129 2130 /* Don't uninstall the zone if anything is mounted there */ 2131 err = zonecfg_find_mounts(rootpath, NULL, NULL); 2132 if (err) { 2133 zerror(gettext("These file-systems are mounted on " 2134 "subdirectories of %s.\n"), rootpath); 2135 (void) zonecfg_find_mounts(rootpath, zfm_print, NULL); 2136 return (Z_ERR); 2137 } 2138 2139 err = zone_set_state(target_zone, ZONE_STATE_INCOMPLETE); 2140 if (err != Z_OK) { 2141 errno = err; 2142 zperror2(target_zone, gettext("could not set state")); 2143 goto bad; 2144 } 2145 2146 /* 2147 * "exec" the command so that the returned status is that of 2148 * RMCOMMAND and not the shell. 2149 */ 2150 (void) snprintf(cmdbuf, sizeof (cmdbuf), "exec " RMCOMMAND " %s", 2151 devpath); 2152 status = do_subproc(cmdbuf); 2153 if ((err = subproc_status(RMCOMMAND, status)) != Z_OK) 2154 goto bad; 2155 (void) snprintf(cmdbuf, sizeof (cmdbuf), "exec " RMCOMMAND " %s", 2156 rootpath); 2157 status = do_subproc(cmdbuf); 2158 if ((err = subproc_status(RMCOMMAND, status)) != Z_OK) 2159 goto bad; 2160 err = zone_set_state(target_zone, ZONE_STATE_CONFIGURED); 2161 if (err != Z_OK) { 2162 errno = err; 2163 zperror2(target_zone, gettext("could not reset state")); 2164 } 2165 bad: 2166 release_lock_file(lockfd); 2167 return (err); 2168 } 2169 2170 static int 2171 help_func(int argc, char *argv[]) 2172 { 2173 int arg, cmd_num; 2174 2175 if (argc == 0) { 2176 (void) usage(B_TRUE); 2177 return (Z_OK); 2178 } 2179 optind = 0; 2180 if ((arg = getopt(argc, argv, "?")) != EOF) { 2181 switch (arg) { 2182 case '?': 2183 sub_usage(SHELP_HELP, CMD_HELP); 2184 return (optopt == '?' ? Z_OK : Z_USAGE); 2185 default: 2186 sub_usage(SHELP_HELP, CMD_HELP); 2187 return (Z_USAGE); 2188 } 2189 } 2190 while (optind < argc) { 2191 if ((cmd_num = cmd_match(argv[optind])) < 0) { 2192 sub_usage(SHELP_HELP, CMD_HELP); 2193 return (Z_USAGE); 2194 } 2195 sub_usage(cmdtab[cmd_num].short_usage, cmd_num); 2196 optind++; 2197 } 2198 return (Z_OK); 2199 } 2200 2201 /* 2202 * Returns: CMD_MIN thru CMD_MAX on success, -1 on error 2203 */ 2204 2205 static int 2206 cmd_match(char *cmd) 2207 { 2208 int i; 2209 2210 for (i = CMD_MIN; i <= CMD_MAX; i++) { 2211 /* return only if there is an exact match */ 2212 if (strcmp(cmd, cmdtab[i].cmd_name) == 0) 2213 return (cmdtab[i].cmd_num); 2214 } 2215 return (-1); 2216 } 2217 2218 static int 2219 parse_and_run(int argc, char *argv[]) 2220 { 2221 int i = cmd_match(argv[0]); 2222 2223 if (i < 0) 2224 return (usage(B_FALSE)); 2225 return (cmdtab[i].handler(argc - 1, &(argv[1]))); 2226 } 2227 2228 static char * 2229 get_execbasename(char *execfullname) 2230 { 2231 char *last_slash, *execbasename; 2232 2233 /* guard against '/' at end of command invocation */ 2234 for (;;) { 2235 last_slash = strrchr(execfullname, '/'); 2236 if (last_slash == NULL) { 2237 execbasename = execfullname; 2238 break; 2239 } else { 2240 execbasename = last_slash + 1; 2241 if (*execbasename == '\0') { 2242 *last_slash = '\0'; 2243 continue; 2244 } 2245 break; 2246 } 2247 } 2248 return (execbasename); 2249 } 2250 2251 int 2252 main(int argc, char **argv) 2253 { 2254 int arg; 2255 zoneid_t zid; 2256 2257 if ((locale = setlocale(LC_ALL, "")) == NULL) 2258 locale = "C"; 2259 (void) textdomain(TEXT_DOMAIN); 2260 setbuf(stdout, NULL); 2261 (void) sigset(SIGHUP, SIG_IGN); 2262 execname = get_execbasename(argv[0]); 2263 target_zone = NULL; 2264 if (chdir("/") != 0) { 2265 zerror(gettext("could not change directory to /.")); 2266 exit(Z_ERR); 2267 } 2268 2269 while ((arg = getopt(argc, argv, "?z:")) != EOF) { 2270 switch (arg) { 2271 case '?': 2272 return (usage(B_TRUE)); 2273 case 'z': 2274 target_zone = optarg; 2275 break; 2276 default: 2277 return (usage(B_FALSE)); 2278 } 2279 } 2280 2281 if (optind >= argc) 2282 return (usage(B_FALSE)); 2283 if (target_zone != NULL && zone_get_id(target_zone, &zid) != 0) { 2284 errno = Z_NO_ZONE; 2285 zperror(target_zone, B_TRUE); 2286 exit(Z_ERR); 2287 } 2288 return (parse_and_run(argc - optind, &argv[optind])); 2289 } 2290