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