1 /*
   2  * CDDL HEADER START
   3  *
   4  * The contents of this file are subject to the terms of the
   5  * Common Development and Distribution License (the "License").
   6  * You may not use this file except in compliance with the License.
   7  *
   8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
   9  * or http://www.opensolaris.org/os/licensing.
  10  * See the License for the specific language governing permissions
  11  * and limitations under the License.
  12  *
  13  * When distributing Covered Code, include this CDDL HEADER in each
  14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
  15  * If applicable, add the following below this CDDL HEADER, with the
  16  * fields enclosed by brackets "[]" replaced with your own identifying
  17  * information: Portions Copyright [yyyy] [name of copyright owner]
  18  *
  19  * CDDL HEADER END
  20  */
  21 
  22 /*
  23  * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
  24  * Use is subject to license terms.
  25  */
  26 
  27 #pragma ident   "@(#)zoneadm.c  1.65    08/05/07 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/brand.h>
  59 #include <sys/param.h>
  60 #include <sys/types.h>
  61 #include <sys/stat.h>
  62 #include <sys/statvfs.h>
  63 #include <assert.h>
  64 #include <sys/sockio.h>
  65 #include <sys/mntent.h>
  66 #include <limits.h>
  67 #include <dirent.h>
  68 #include <uuid/uuid.h>
  69 #include <libdlpi.h>
  70 
  71 #include <fcntl.h>
  72 #include <door.h>
  73 #include <macros.h>
  74 #include <libgen.h>
  75 #include <fnmatch.h>
  76 #include <sys/modctl.h>
  77 #include <libbrand.h>
  78 #include <libscf.h>
  79 #include <procfs.h>
  80 #include <strings.h>
  81 
  82 #include <pool.h>
  83 #include <sys/pool.h>
  84 #include <sys/priocntl.h>
  85 #include <sys/fsspriocntl.h>
  86 
  87 #include "zoneadm.h"
  88 
  89 #define MAXARGS 8
  90 
  91 /* Reflects kernel zone entries */
  92 typedef struct zone_entry {
  93         zoneid_t        zid;
  94         char            zname[ZONENAME_MAX];
  95         char            *zstate_str;
  96         zone_state_t    zstate_num;
  97         char            zbrand[MAXNAMELEN];
  98         char            zroot[MAXPATHLEN];
  99         char            zuuid[UUID_PRINTABLE_STRING_LENGTH];
 100         zone_iptype_t   ziptype;
 101 } zone_entry_t;
 102 
 103 #define CLUSTER_BRAND_NAME      "cluster"
 104 
 105 static zone_entry_t *zents;
 106 static size_t nzents;
 107 static boolean_t is_native_zone = B_TRUE;
 108 static boolean_t is_cluster_zone = B_FALSE;
 109 
 110 #define LOOPBACK_IF     "lo0"
 111 #define SOCKET_AF(af)   (((af) == AF_UNSPEC) ? AF_INET : (af))
 112 
 113 struct net_if {
 114         char    *name;
 115         int     af;
 116 };
 117 
 118 /* 0755 is the default directory mode. */
 119 #define DEFAULT_DIR_MODE \
 120         (S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH)
 121 
 122 struct cmd {
 123         uint_t  cmd_num;                                /* command number */
 124         char    *cmd_name;                              /* command name */
 125         char    *short_usage;                           /* short form help */
 126         int     (*handler)(int argc, char *argv[]);     /* function to call */
 127 
 128 };
 129 
 130 #define SHELP_HELP      "help"
 131 #define SHELP_BOOT      "boot [-- boot_arguments]"
 132 #define SHELP_HALT      "halt"
 133 #define SHELP_READY     "ready"
 134 #define SHELP_REBOOT    "reboot [-- boot_arguments]"
 135 #define SHELP_LIST      "list [-cipv]"
 136 #define SHELP_VERIFY    "verify"
 137 #define SHELP_INSTALL   "install [-x nodataset] [brand-specific args]"
 138 #define SHELP_UNINSTALL "uninstall [-F]"
 139 #define SHELP_CLONE     "clone [-m method] [-s <ZFS snapshot>] zonename"
 140 #define SHELP_MOVE      "move zonepath"
 141 #define SHELP_DETACH    "detach [-n]"
 142 #define SHELP_ATTACH    "attach [-F] [-n <path>] [-u]"
 143 #define SHELP_MARK      "mark incomplete"
 144 
 145 #define EXEC_PREFIX     "exec "
 146 #define EXEC_LEN        (strlen(EXEC_PREFIX))
 147 #define RMCOMMAND       "/usr/bin/rm -rf"
 148 
 149 static int cleanup_zonepath(char *, boolean_t);
 150 
 151 
 152 static int help_func(int argc, char *argv[]);
 153 static int ready_func(int argc, char *argv[]);
 154 static int boot_func(int argc, char *argv[]);
 155 static int halt_func(int argc, char *argv[]);
 156 static int reboot_func(int argc, char *argv[]);
 157 static int list_func(int argc, char *argv[]);
 158 static int verify_func(int argc, char *argv[]);
 159 static int install_func(int argc, char *argv[]);
 160 static int uninstall_func(int argc, char *argv[]);
 161 static int mount_func(int argc, char *argv[]);
 162 static int unmount_func(int argc, char *argv[]);
 163 static int clone_func(int argc, char *argv[]);
 164 static int move_func(int argc, char *argv[]);
 165 static int detach_func(int argc, char *argv[]);
 166 static int attach_func(int argc, char *argv[]);
 167 static int mark_func(int argc, char *argv[]);
 168 static int apply_func(int argc, char *argv[]);
 169 static int sanity_check(char *zone, int cmd_num, boolean_t running,
 170     boolean_t unsafe_when_running, boolean_t force);
 171 static int cmd_match(char *cmd);
 172 static int verify_details(int, char *argv[]);
 173 static int verify_brand(zone_dochandle_t, int, char *argv[]);
 174 static int invoke_brand_handler(int, char *argv[]);
 175 
 176 static struct cmd cmdtab[] = {
 177         { CMD_HELP,             "help",         SHELP_HELP,     help_func },
 178         { CMD_BOOT,             "boot",         SHELP_BOOT,     boot_func },
 179         { CMD_HALT,             "halt",         SHELP_HALT,     halt_func },
 180         { CMD_READY,            "ready",        SHELP_READY,    ready_func },
 181         { CMD_REBOOT,           "reboot",       SHELP_REBOOT,   reboot_func },
 182         { CMD_LIST,             "list",         SHELP_LIST,     list_func },
 183         { CMD_VERIFY,           "verify",       SHELP_VERIFY,   verify_func },
 184         { CMD_INSTALL,          "install",      SHELP_INSTALL,  install_func },
 185         { CMD_UNINSTALL,        "uninstall",    SHELP_UNINSTALL,
 186             uninstall_func },
 187         /* mount and unmount are private commands for admin/install */
 188         { CMD_MOUNT,            "mount",        NULL,           mount_func },
 189         { CMD_UNMOUNT,          "unmount",      NULL,           unmount_func },
 190         { CMD_CLONE,            "clone",        SHELP_CLONE,    clone_func },
 191         { CMD_MOVE,             "move",         SHELP_MOVE,     move_func },
 192         { CMD_DETACH,           "detach",       SHELP_DETACH,   detach_func },
 193         { CMD_ATTACH,           "attach",       SHELP_ATTACH,   attach_func },
 194         { CMD_MARK,             "mark",         SHELP_MARK,     mark_func },
 195         { CMD_APPLY,            "apply",        NULL,           apply_func }
 196 };
 197 
 198 /* global variables */
 199 
 200 /* set early in main(), never modified thereafter, used all over the place */
 201 static char *execname;
 202 static char target_brand[MAXNAMELEN];
 203 static char *locale;
 204 char *target_zone;
 205 static char *target_uuid;
 206 
 207 /* used in do_subproc() and signal handler */
 208 static volatile boolean_t child_killed;
 209 /* used in attach_func() and signal handler */
 210 static volatile boolean_t attach_interupted;
 211 static int do_subproc_cnt = 0;
 212 
 213 /*
 214  * Used to indicate whether this zoneadm instance has another zoneadm
 215  * instance in its ancestry.
 216  */
 217 static boolean_t zoneadm_is_nested = B_FALSE;
 218 
 219 /* used to track nested zone-lock operations */
 220 static int zone_lock_cnt = 0;
 221 
 222 /* used to communicate lock status to children */
 223 #define LOCK_ENV_VAR    "_ZONEADM_LOCK_HELD"
 224 static char zoneadm_lock_held[] = LOCK_ENV_VAR"=1";
 225 static char zoneadm_lock_not_held[] = LOCK_ENV_VAR"=0";
 226 
 227 char *
 228 cmd_to_str(int cmd_num)
 229 {
 230         assert(cmd_num >= CMD_MIN && cmd_num <= CMD_MAX);
 231         return (cmdtab[cmd_num].cmd_name);
 232 }
 233 
 234 /* This is a separate function because of gettext() wrapping. */
 235 static char *
 236 long_help(int cmd_num)
 237 {
 238         assert(cmd_num >= CMD_MIN && cmd_num <= CMD_MAX);
 239         switch (cmd_num) {
 240         case CMD_HELP:
 241                 return (gettext("Print usage message."));
 242         case CMD_BOOT:
 243                 return (gettext("Activates (boots) specified zone.  See "
 244                     "zoneadm(1m) for valid boot\n\targuments."));
 245         case CMD_HALT:
 246                 return (gettext("Halts specified zone, bypassing shutdown "
 247                     "scripts and removing runtime\n\tresources of the zone."));
 248         case CMD_READY:
 249                 return (gettext("Prepares a zone for running applications but "
 250                     "does not start any user\n\tprocesses in the zone."));
 251         case CMD_REBOOT:
 252                 return (gettext("Restarts the zone (equivalent to a halt / "
 253                     "boot sequence).\n\tFails if the zone is not active.  "
 254                     "See zoneadm(1m) for valid boot\n\targuments."));
 255         case CMD_LIST:
 256                 return (gettext("Lists the current zones, or a "
 257                     "specific zone if indicated.  By default,\n\tall "
 258                     "running zones are listed, though this can be "
 259                     "expanded to all\n\tinstalled zones with the -i "
 260                     "option or all configured zones with the\n\t-c "
 261                     "option.  When used with the general -z <zone> and/or -u "
 262                     "<uuid-match>\n\toptions, lists only the specified "
 263                     "matching zone, but lists it\n\tregardless of its state, "
 264                     "and the -i and -c options are disallowed.  The\n\t-v "
 265                     "option can be used to display verbose information: zone "
 266                     "name, id,\n\tcurrent state, root directory and options.  "
 267                     "The -p option can be used\n\tto request machine-parsable "
 268                     "output.  The -v and -p options are mutually\n\texclusive."
 269                     "  If neither -v nor -p is used, just the zone name is "
 270                     "listed."));
 271         case CMD_VERIFY:
 272                 return (gettext("Check to make sure the configuration "
 273                     "can safely be instantiated\n\ton the machine: "
 274                     "physical network interfaces exist, etc."));
 275         case CMD_INSTALL:
 276                 return (gettext("Install the configuration on to the system.  "
 277                     "The -x nodataset option\n\tcan be used to prevent the "
 278                     "creation of a new ZFS file system for the\n\tzone "
 279                     "(assuming the zonepath is within a ZFS file system).\n\t"
 280                     "All other arguments are passed to the brand installation "
 281                     "function;\n\tsee brand(4) for more information."));
 282         case CMD_UNINSTALL:
 283                 return (gettext("Uninstall the configuration from the system.  "
 284                     "The -F flag can be used\n\tto force the action."));
 285         case CMD_CLONE:
 286                 return (gettext("Clone the installation of another zone.  "
 287                     "The -m option can be used to\n\tspecify 'copy' which "
 288                     "forces a copy of the source zone.  The -s option\n\t"
 289                     "can be used to specify the name of a ZFS snapshot "
 290                     "that was taken from\n\ta previous clone command.  The "
 291                     "snapshot will be used as the source\n\tinstead of "
 292                     "creating a new ZFS snapshot."));
 293         case CMD_MOVE:
 294                 return (gettext("Move the zone to a new zonepath."));
 295         case CMD_DETACH:
 296                 return (gettext("Detach the zone from the system. The zone "
 297                     "state is changed to\n\t'configured' (but the files under "
 298                     "the zonepath are untouched).\n\tThe zone can subsequently "
 299                     "be attached, or can be moved to another\n\tsystem and "
 300                     "attached there.  The -n option can be used to specify\n\t"
 301                     "'no-execute' mode.  When -n is used, the information "
 302                     "needed to attach\n\tthe zone is sent to standard output "
 303                     "but the zone is not actually\n\tdetached."));
 304         case CMD_ATTACH:
 305                 return (gettext("Attach the zone to the system.  The zone "
 306                     "state must be 'configured'\n\tprior to attach; upon "
 307                     "successful completion, the zone state will be\n\t"
 308                     "'installed'.  The system software on the current "
 309                     "system must be\n\tcompatible with the software on the "
 310                     "zone's original system or use\n\tthe -u option to update "
 311                     "the zone to the current system software.\n\tSpecify -F "
 312                     "to force the attach and skip software compatibility "
 313                     "tests.\n\tThe -n option can be used to specify "
 314                     "'no-execute' mode.  When -n is\n\tused, the information "
 315                     "needed to attach the zone is read from the\n\tspecified "
 316                     "path and the configuration is only validated.  The path "
 317                     "can\n\tbe '-' to specify standard input.  The -F, -n and "
 318                     "-u options are\n\tmutually exclusive."));
 319         case CMD_MARK:
 320                 return (gettext("Set the state of the zone.  This can be used "
 321                     "to force the zone\n\tstate to 'incomplete' "
 322                     "administratively if some activity has rendered\n\tthe "
 323                     "zone permanently unusable.  The only valid state that "
 324                     "may be\n\tspecified is 'incomplete'."));
 325         default:
 326                 return ("");
 327         }
 328         /* NOTREACHED */
 329         return (NULL);
 330 }
 331 
 332 /*
 333  * Called with explicit B_TRUE when help is explicitly requested, B_FALSE for
 334  * unexpected errors.
 335  */
 336 
 337 static int
 338 usage(boolean_t explicit)
 339 {
 340         int i;
 341         FILE *fd = explicit ? stdout : stderr;
 342 
 343         (void) fprintf(fd, "%s:\t%s help\n", gettext("usage"), execname);
 344         (void) fprintf(fd, "\t%s [-z <zone>] [-u <uuid-match>] list\n",
 345             execname);
 346         (void) fprintf(fd, "\t%s {-z <zone>|-u <uuid-match>} <%s>\n", execname,
 347             gettext("subcommand"));
 348         (void) fprintf(fd, "\n%s:\n\n", gettext("Subcommands"));
 349         for (i = CMD_MIN; i <= CMD_MAX; i++) {
 350                 if (cmdtab[i].short_usage == NULL)
 351                         continue;
 352                 (void) fprintf(fd, "%s\n", cmdtab[i].short_usage);
 353                 if (explicit)
 354                         (void) fprintf(fd, "\t%s\n\n", long_help(i));
 355         }
 356         if (!explicit)
 357                 (void) fputs("\n", fd);
 358         return (Z_USAGE);
 359 }
 360 
 361 static void
 362 sub_usage(char *short_usage, int cmd_num)
 363 {
 364         (void) fprintf(stderr, "%s:\t%s\n", gettext("usage"), short_usage);
 365         (void) fprintf(stderr, "\t%s\n", long_help(cmd_num));
 366 }
 367 
 368 /*
 369  * zperror() is like perror(3c) except that this also prints the executable
 370  * name at the start of the message, and takes a boolean indicating whether
 371  * to call libc'c strerror() or that from libzonecfg.
 372  */
 373 
 374 void
 375 zperror(const char *str, boolean_t zonecfg_error)
 376 {
 377         (void) fprintf(stderr, "%s: %s: %s\n", execname, str,
 378             zonecfg_error ? zonecfg_strerror(errno) : strerror(errno));
 379 }
 380 
 381 /*
 382  * zperror2() is very similar to zperror() above, except it also prints a
 383  * supplied zone name after the executable.
 384  *
 385  * All current consumers of this function want libzonecfg's strerror() rather
 386  * than libc's; if this ever changes, this function can be made more generic
 387  * like zperror() above.
 388  */
 389 
 390 void
 391 zperror2(const char *zone, const char *str)
 392 {
 393         (void) fprintf(stderr, "%s: %s: %s: %s\n", execname, zone, str,
 394             zonecfg_strerror(errno));
 395 }
 396 
 397 /* PRINTFLIKE1 */
 398 void
 399 zerror(const char *fmt, ...)
 400 {
 401         va_list alist;
 402 
 403         va_start(alist, fmt);
 404         (void) fprintf(stderr, "%s: ", execname);
 405         if (target_zone != NULL)
 406                 (void) fprintf(stderr, "zone '%s': ", target_zone);
 407         (void) vfprintf(stderr, fmt, alist);
 408         (void) fprintf(stderr, "\n");
 409         va_end(alist);
 410 }
 411 
 412 static void *
 413 safe_calloc(size_t nelem, size_t elsize)
 414 {
 415         void *r = calloc(nelem, elsize);
 416 
 417         if (r == NULL) {
 418                 zerror(gettext("failed to allocate %lu bytes: %s"),
 419                     (ulong_t)nelem * elsize, strerror(errno));
 420                 exit(Z_ERR);
 421         }
 422         return (r);
 423 }
 424 
 425 static void
 426 zone_print(zone_entry_t *zent, boolean_t verbose, boolean_t parsable)
 427 {
 428         static boolean_t firsttime = B_TRUE;
 429         char *ip_type_str;
 430 
 431         if (zent->ziptype == ZS_EXCLUSIVE)
 432                 ip_type_str = "excl";
 433         else
 434                 ip_type_str = "shared";
 435 
 436         assert(!(verbose && parsable));
 437         if (firsttime && verbose) {
 438                 firsttime = B_FALSE;
 439                 (void) printf("%*s %-16s %-10s %-30s %-8s %-6s\n",
 440                     ZONEID_WIDTH, "ID", "NAME", "STATUS", "PATH", "BRAND",
 441                     "IP");
 442         }
 443         if (!verbose) {
 444                 char *cp, *clim;
 445 
 446                 if (!parsable) {
 447                         (void) printf("%s\n", zent->zname);
 448                         return;
 449                 }
 450                 if (zent->zid == ZONE_ID_UNDEFINED)
 451                         (void) printf("-");
 452                 else
 453                         (void) printf("%lu", zent->zid);
 454                 (void) printf(":%s:%s:", zent->zname, zent->zstate_str);
 455                 cp = zent->zroot;
 456                 while ((clim = strchr(cp, ':')) != NULL) {
 457                         (void) printf("%.*s\\:", clim - cp, cp);
 458                         cp = clim + 1;
 459                 }
 460                 (void) printf("%s:%s:%s:%s\n", cp, zent->zuuid, zent->zbrand,
 461                     ip_type_str);
 462                 return;
 463         }
 464         if (zent->zstate_str != NULL) {
 465                 if (zent->zid == ZONE_ID_UNDEFINED)
 466                         (void) printf("%*s", ZONEID_WIDTH, "-");
 467                 else
 468                         (void) printf("%*lu", ZONEID_WIDTH, zent->zid);
 469                 (void) printf(" %-16s %-10s %-30s %-8s %-6s\n", zent->zname,
 470                     zent->zstate_str, zent->zroot, zent->zbrand, ip_type_str);
 471         }
 472 }
 473 
 474 static int
 475 lookup_zone_info(const char *zone_name, zoneid_t zid, zone_entry_t *zent)
 476 {
 477         char root[MAXPATHLEN], *cp;
 478         int err;
 479         uuid_t uuid;
 480 
 481         (void) strlcpy(zent->zname, zone_name, sizeof (zent->zname));
 482         (void) strlcpy(zent->zroot, "???", sizeof (zent->zroot));
 483         (void) strlcpy(zent->zbrand, "???", sizeof (zent->zbrand));
 484         zent->zstate_str = "???";
 485 
 486         zent->zid = zid;
 487 
 488         if (zonecfg_get_uuid(zone_name, uuid) == Z_OK &&
 489             !uuid_is_null(uuid))
 490                 uuid_unparse(uuid, zent->zuuid);
 491         else
 492                 zent->zuuid[0] = '\0';
 493 
 494         /*
 495          * For labeled zones which query the zone path of lower-level
 496          * zones, the path needs to be adjusted to drop the final
 497          * "/root" component. This adjusted path is then useful
 498          * for reading down any exported directories from the
 499          * lower-level zone.
 500          */
 501         if (is_system_labeled() && zent->zid != ZONE_ID_UNDEFINED) {
 502                 if (zone_getattr(zent->zid, ZONE_ATTR_ROOT, zent->zroot,
 503                     sizeof (zent->zroot)) == -1) {
 504                         zperror2(zent->zname,
 505                             gettext("could not get zone path."));
 506                         return (Z_ERR);
 507                 }
 508                 cp = zent->zroot + strlen(zent->zroot) - 5;
 509                 if (cp > zent->zroot && strcmp(cp, "/root") == 0)
 510                         *cp = 0;
 511         } else {
 512                 if ((err = zone_get_zonepath(zent->zname, root,
 513                     sizeof (root))) != Z_OK) {
 514                         errno = err;
 515                         zperror2(zent->zname,
 516                             gettext("could not get zone path."));
 517                         return (Z_ERR);
 518                 }
 519                 (void) strlcpy(zent->zroot, root, sizeof (zent->zroot));
 520         }
 521 
 522         if ((err = zone_get_state(zent->zname, &zent->zstate_num)) != Z_OK) {
 523                 errno = err;
 524                 zperror2(zent->zname, gettext("could not get state"));
 525                 return (Z_ERR);
 526         }
 527         zent->zstate_str = zone_state_str(zent->zstate_num);
 528 
 529         /*
 530          * A zone's brand is only available in the .xml file describing it,
 531          * which is only visible to the global zone.  This causes
 532          * zone_get_brand() to fail when called from within a non-global
 533          * zone.  Fortunately we only do this on labeled systems, where we
 534          * know all zones are native.
 535          */
 536         if (getzoneid() != GLOBAL_ZONEID) {
 537                 assert(is_system_labeled() != 0);
 538                 (void) strlcpy(zent->zbrand, NATIVE_BRAND_NAME,
 539                     sizeof (zent->zbrand));
 540         } else if (zone_get_brand(zent->zname, zent->zbrand,
 541             sizeof (zent->zbrand)) != Z_OK) {
 542                 zperror2(zent->zname, gettext("could not get brand name"));
 543                 return (Z_ERR);
 544         }
 545 
 546         /*
 547          * Get ip type of the zone.
 548          * Note for global zone, ZS_SHARED is set always.
 549          */
 550         if (zid == GLOBAL_ZONEID) {
 551                 zent->ziptype = ZS_SHARED;
 552         } else {
 553 
 554                 if (zent->zstate_num == ZONE_STATE_RUNNING) {
 555                         ushort_t flags;
 556 
 557                         if (zone_getattr(zid, ZONE_ATTR_FLAGS, &flags,
 558                             sizeof (flags)) < 0) {
 559                                 zperror2(zent->zname,
 560                                     gettext("could not get zone flags"));
 561                                 return (Z_ERR);
 562                         }
 563                         if (flags & ZF_NET_EXCL)
 564                                 zent->ziptype = ZS_EXCLUSIVE;
 565                         else
 566                                 zent->ziptype = ZS_SHARED;
 567                 } else {
 568                         zone_dochandle_t handle;
 569 
 570                         if ((handle = zonecfg_init_handle()) == NULL) {
 571                                 zperror2(zent->zname,
 572                                     gettext("could not init handle"));
 573                                 return (Z_ERR);
 574                         }
 575                         if ((err = zonecfg_get_handle(zent->zname, handle))
 576                             != Z_OK) {
 577                                 zperror2(zent->zname,
 578                                     gettext("could not get handle"));
 579                                 zonecfg_fini_handle(handle);
 580                                 return (Z_ERR);
 581                         }
 582 
 583                         if ((err = zonecfg_get_iptype(handle, &zent->ziptype))
 584                             != Z_OK) {
 585                                 zperror2(zent->zname,
 586                                     gettext("could not get ip-type"));
 587                                 zonecfg_fini_handle(handle);
 588                                 return (Z_ERR);
 589                         }
 590                         zonecfg_fini_handle(handle);
 591                 }
 592         }
 593 
 594         return (Z_OK);
 595 }
 596 
 597 /*
 598  * fetch_zents() calls zone_list(2) to find out how many zones are running
 599  * (which is stored in the global nzents), then calls zone_list(2) again
 600  * to fetch the list of running zones (stored in the global zents).  This
 601  * function may be called multiple times, so if zents is already set, we
 602  * return immediately to save work.
 603  */
 604 
 605 static int
 606 fetch_zents(void)
 607 {
 608         zoneid_t *zids = NULL;
 609         uint_t nzents_saved;
 610         int i, retv;
 611         FILE *fp;
 612         boolean_t inaltroot;
 613         zone_entry_t *zentp;
 614 
 615         if (nzents > 0)
 616                 return (Z_OK);
 617 
 618         if (zone_list(NULL, &nzents) != 0) {
 619                 zperror(gettext("failed to get zoneid list"), B_FALSE);
 620                 return (Z_ERR);
 621         }
 622 
 623 again:
 624         if (nzents == 0)
 625                 return (Z_OK);
 626 
 627         zids = safe_calloc(nzents, sizeof (zoneid_t));
 628         nzents_saved = nzents;
 629 
 630         if (zone_list(zids, &nzents) != 0) {
 631                 zperror(gettext("failed to get zone list"), B_FALSE);
 632                 free(zids);
 633                 return (Z_ERR);
 634         }
 635         if (nzents != nzents_saved) {
 636                 /* list changed, try again */
 637                 free(zids);
 638                 goto again;
 639         }
 640 
 641         zents = safe_calloc(nzents, sizeof (zone_entry_t));
 642 
 643         inaltroot = zonecfg_in_alt_root();
 644         if (inaltroot)
 645                 fp = zonecfg_open_scratch("", B_FALSE);
 646         else
 647                 fp = NULL;
 648         zentp = zents;
 649         retv = Z_OK;
 650         for (i = 0; i < nzents; i++) {
 651                 char name[ZONENAME_MAX];
 652                 char altname[ZONENAME_MAX];
 653 
 654                 if (getzonenamebyid(zids[i], name, sizeof (name)) < 0) {
 655                         zperror(gettext("failed to get zone name"), B_FALSE);
 656                         retv = Z_ERR;
 657                         continue;
 658                 }
 659                 if (zonecfg_is_scratch(name)) {
 660                         /* Ignore scratch zones by default */
 661                         if (!inaltroot)
 662                                 continue;
 663                         if (fp == NULL ||
 664                             zonecfg_reverse_scratch(fp, name, altname,
 665                             sizeof (altname), NULL, 0) == -1) {
 666                                 zerror(gettext("could not resolve scratch "
 667                                     "zone %s"), name);
 668                                 retv = Z_ERR;
 669                                 continue;
 670                         }
 671                         (void) strcpy(name, altname);
 672                 } else {
 673                         /* Ignore non-scratch when in an alternate root */
 674                         if (inaltroot && strcmp(name, GLOBAL_ZONENAME) != 0)
 675                                 continue;
 676                 }
 677                 if (lookup_zone_info(name, zids[i], zentp) != Z_OK) {
 678                         zerror(gettext("failed to get zone data"));
 679                         retv = Z_ERR;
 680                         continue;
 681                 }
 682                 zentp++;
 683         }
 684         nzents = zentp - zents;
 685         if (fp != NULL)
 686                 zonecfg_close_scratch(fp);
 687 
 688         free(zids);
 689         return (retv);
 690 }
 691 
 692 static int
 693 zone_print_list(zone_state_t min_state, boolean_t verbose, boolean_t parsable)
 694 {
 695         int i;
 696         zone_entry_t zent;
 697         FILE *cookie;
 698         char *name;
 699 
 700         /*
 701          * First get the list of running zones from the kernel and print them.
 702          * If that is all we need, then return.
 703          */
 704         if ((i = fetch_zents()) != Z_OK) {
 705                 /*
 706                  * No need for error messages; fetch_zents() has already taken
 707                  * care of this.
 708                  */
 709                 return (i);
 710         }
 711         for (i = 0; i < nzents; i++)
 712                 zone_print(&zents[i], verbose, parsable);
 713         if (min_state >= ZONE_STATE_RUNNING)
 714                 return (Z_OK);
 715         /*
 716          * Next, get the full list of zones from the configuration, skipping
 717          * any we have already printed.
 718          */
 719         cookie = setzoneent();
 720         while ((name = getzoneent(cookie)) != NULL) {
 721                 for (i = 0; i < nzents; i++) {
 722                         if (strcmp(zents[i].zname, name) == 0)
 723                                 break;
 724                 }
 725                 if (i < nzents) {
 726                         free(name);
 727                         continue;
 728                 }
 729                 if (lookup_zone_info(name, ZONE_ID_UNDEFINED, &zent) != Z_OK) {
 730                         free(name);
 731                         continue;
 732                 }
 733                 free(name);
 734                 if (zent.zstate_num >= min_state)
 735                         zone_print(&zent, verbose, parsable);
 736         }
 737         endzoneent(cookie);
 738         return (Z_OK);
 739 }
 740 
 741 static zone_entry_t *
 742 lookup_running_zone(char *str)
 743 {
 744         zoneid_t zoneid;
 745         char *cp;
 746         int i;
 747 
 748         if (fetch_zents() != Z_OK)
 749                 return (NULL);
 750 
 751         for (i = 0; i < nzents; i++) {
 752                 if (strcmp(str, zents[i].zname) == 0)
 753                         return (&zents[i]);
 754         }
 755         errno = 0;
 756         zoneid = strtol(str, &cp, 0);
 757         if (zoneid < MIN_ZONEID || zoneid > MAX_ZONEID ||
 758             errno != 0 || *cp != '\0')
 759                 return (NULL);
 760         for (i = 0; i < nzents; i++) {
 761                 if (zoneid == zents[i].zid)
 762                         return (&zents[i]);
 763         }
 764         return (NULL);
 765 }
 766 
 767 /*
 768  * Check a bit in a mode_t: if on is B_TRUE, that bit should be on; if
 769  * B_FALSE, it should be off.  Return B_TRUE if the mode is bad (incorrect).
 770  */
 771 static boolean_t
 772 bad_mode_bit(mode_t mode, mode_t bit, boolean_t on, char *file)
 773 {
 774         char *str;
 775 
 776         assert(bit == S_IRUSR || bit == S_IWUSR || bit == S_IXUSR ||
 777             bit == S_IRGRP || bit == S_IWGRP || bit == S_IXGRP ||
 778             bit == S_IROTH || bit == S_IWOTH || bit == S_IXOTH);
 779         /*
 780          * TRANSLATION_NOTE
 781          * The strings below will be used as part of a larger message,
 782          * either:
 783          * (file name) must be (owner|group|world) (read|writ|execut)able
 784          * or
 785          * (file name) must not be (owner|group|world) (read|writ|execut)able
 786          */
 787         switch (bit) {
 788         case S_IRUSR:
 789                 str = gettext("owner readable");
 790                 break;
 791         case S_IWUSR:
 792                 str = gettext("owner writable");
 793                 break;
 794         case S_IXUSR:
 795                 str = gettext("owner executable");
 796                 break;
 797         case S_IRGRP:
 798                 str = gettext("group readable");
 799                 break;
 800         case S_IWGRP:
 801                 str = gettext("group writable");
 802                 break;
 803         case S_IXGRP:
 804                 str = gettext("group executable");
 805                 break;
 806         case S_IROTH:
 807                 str = gettext("world readable");
 808                 break;
 809         case S_IWOTH:
 810                 str = gettext("world writable");
 811                 break;
 812         case S_IXOTH:
 813                 str = gettext("world executable");
 814                 break;
 815         }
 816         if ((mode & bit) == (on ? 0 : bit)) {
 817                 /*
 818                  * TRANSLATION_NOTE
 819                  * The first parameter below is a file name; the second
 820                  * is one of the "(owner|group|world) (read|writ|execut)able"
 821                  * strings from above.
 822                  */
 823                 /*
 824                  * The code below could be simplified but not in a way
 825                  * that would easily translate to non-English locales.
 826                  */
 827                 if (on) {
 828                         (void) fprintf(stderr, gettext("%s must be %s.\n"),
 829                             file, str);
 830                 } else {
 831                         (void) fprintf(stderr, gettext("%s must not be %s.\n"),
 832                             file, str);
 833                 }
 834                 return (B_TRUE);
 835         }
 836         return (B_FALSE);
 837 }
 838 
 839 /*
 840  * We want to make sure that no zone has its zone path as a child node
 841  * (in the directory sense) of any other.  We do that by comparing this
 842  * zone's path to the path of all other (non-global) zones.  The comparison
 843  * in each case is simple: add '/' to the end of the path, then do a
 844  * strncmp() of the two paths, using the length of the shorter one.
 845  */
 846 
 847 static int
 848 crosscheck_zonepaths(char *path)
 849 {
 850         char rpath[MAXPATHLEN];         /* resolved path */
 851         char path_copy[MAXPATHLEN];     /* copy of original path */
 852         char rpath_copy[MAXPATHLEN];    /* copy of original rpath */
 853         struct zoneent *ze;
 854         int res, err;
 855         FILE *cookie;
 856 
 857         cookie = setzoneent();
 858         while ((ze = getzoneent_private(cookie)) != NULL) {
 859                 /* Skip zones which are not installed. */
 860                 if (ze->zone_state < ZONE_STATE_INSTALLED) {
 861                         free(ze);
 862                         continue;
 863                 }
 864                 /* Skip the global zone and the current target zone. */
 865                 if (strcmp(ze->zone_name, GLOBAL_ZONENAME) == 0 ||
 866                     strcmp(ze->zone_name, target_zone) == 0) {
 867                         free(ze);
 868                         continue;
 869                 }
 870                 if (strlen(ze->zone_path) == 0) {
 871                         /* old index file without path, fall back */
 872                         if ((err = zone_get_zonepath(ze->zone_name,
 873                             ze->zone_path, sizeof (ze->zone_path))) != Z_OK) {
 874                                 errno = err;
 875                                 zperror2(ze->zone_name,
 876                                     gettext("could not get zone path"));
 877                                 free(ze);
 878                                 continue;
 879                         }
 880                 }
 881                 (void) snprintf(path_copy, sizeof (path_copy), "%s%s",
 882                     zonecfg_get_root(), ze->zone_path);
 883                 res = resolvepath(path_copy, rpath, sizeof (rpath));
 884                 if (res == -1) {
 885                         if (errno != ENOENT) {
 886                                 zperror(path_copy, B_FALSE);
 887                                 free(ze);
 888                                 return (Z_ERR);
 889                         }
 890                         (void) printf(gettext("WARNING: zone %s is installed, "
 891                             "but its %s %s does not exist.\n"), ze->zone_name,
 892                             "zonepath", path_copy);
 893                         free(ze);
 894                         continue;
 895                 }
 896                 rpath[res] = '\0';
 897                 (void) snprintf(path_copy, sizeof (path_copy), "%s/", path);
 898                 (void) snprintf(rpath_copy, sizeof (rpath_copy), "%s/", rpath);
 899                 if (strncmp(path_copy, rpath_copy,
 900                     min(strlen(path_copy), strlen(rpath_copy))) == 0) {
 901                         /*
 902                          * TRANSLATION_NOTE
 903                          * zonepath is a literal that should not be translated.
 904                          */
 905                         (void) fprintf(stderr, gettext("%s zonepath (%s) and "
 906                             "%s zonepath (%s) overlap.\n"),
 907                             target_zone, path, ze->zone_name, rpath);
 908                         free(ze);
 909                         return (Z_ERR);
 910                 }
 911                 free(ze);
 912         }
 913         endzoneent(cookie);
 914         return (Z_OK);
 915 }
 916 
 917 static int
 918 validate_zonepath(char *path, int cmd_num)
 919 {
 920         int res;                        /* result of last library/system call */
 921         boolean_t err = B_FALSE;        /* have we run into an error? */
 922         struct stat stbuf;
 923         struct statvfs64 vfsbuf;
 924         char rpath[MAXPATHLEN];         /* resolved path */
 925         char ppath[MAXPATHLEN];         /* parent path */
 926         char rppath[MAXPATHLEN];        /* resolved parent path */
 927         char rootpath[MAXPATHLEN];      /* root path */
 928         zone_state_t state;
 929 
 930         if (path[0] != '/') {
 931                 (void) fprintf(stderr,
 932                     gettext("%s is not an absolute path.\n"), path);
 933                 return (Z_ERR);
 934         }
 935         if ((res = resolvepath(path, rpath, sizeof (rpath))) == -1) {
 936                 if ((errno != ENOENT) ||
 937                     (cmd_num != CMD_VERIFY && cmd_num != CMD_INSTALL &&
 938                     cmd_num != CMD_CLONE && cmd_num != CMD_MOVE)) {
 939                         zperror(path, B_FALSE);
 940                         return (Z_ERR);
 941                 }
 942                 if (cmd_num == CMD_VERIFY) {
 943                         /*
 944                          * TRANSLATION_NOTE
 945                          * zoneadm is a literal that should not be translated.
 946                          */
 947                         (void) fprintf(stderr, gettext("WARNING: %s does not "
 948                             "exist, so it could not be verified.\nWhen "
 949                             "'zoneadm %s' is run, '%s' will try to create\n%s, "
 950                             "and '%s' will be tried again,\nbut the '%s' may "
 951                             "fail if:\nthe parent directory of %s is group- or "
 952                             "other-writable\nor\n%s overlaps with any other "
 953                             "installed zones.\n"), path,
 954                             cmd_to_str(CMD_INSTALL), cmd_to_str(CMD_INSTALL),
 955                             path, cmd_to_str(CMD_VERIFY),
 956                             cmd_to_str(CMD_VERIFY), path, path);
 957                         return (Z_OK);
 958                 }
 959                 /*
 960                  * The zonepath is supposed to be mode 700 but its
 961                  * parent(s) 755.  So use 755 on the mkdirp() then
 962                  * chmod() the zonepath itself to 700.
 963                  */
 964                 if (mkdirp(path, DEFAULT_DIR_MODE) < 0) {
 965                         zperror(path, B_FALSE);
 966                         return (Z_ERR);
 967                 }
 968                 /*
 969                  * If the chmod() fails, report the error, but might
 970                  * as well continue the verify procedure.
 971                  */
 972                 if (chmod(path, S_IRWXU) != 0)
 973                         zperror(path, B_FALSE);
 974                 /*
 975                  * Since the mkdir() succeeded, we should not have to
 976                  * worry about a subsequent ENOENT, thus this should
 977                  * only recurse once.
 978                  */
 979                 return (validate_zonepath(path, cmd_num));
 980         }
 981         rpath[res] = '\0';
 982         if (strcmp(path, rpath) != 0) {
 983                 errno = Z_RESOLVED_PATH;
 984                 zperror(path, B_TRUE);
 985                 return (Z_ERR);
 986         }
 987         if ((res = stat(rpath, &stbuf)) != 0) {
 988                 zperror(rpath, B_FALSE);
 989                 return (Z_ERR);
 990         }
 991         if (!S_ISDIR(stbuf.st_mode)) {
 992                 (void) fprintf(stderr, gettext("%s is not a directory.\n"),
 993                     rpath);
 994                 return (Z_ERR);
 995         }
 996         if (strcmp(stbuf.st_fstype, MNTTYPE_TMPFS) == 0) {
 997                 (void) printf(gettext("WARNING: %s is on a temporary "
 998                     "file system.\n"), rpath);
 999         }
1000         if (crosscheck_zonepaths(rpath) != Z_OK)
1001                 return (Z_ERR);
1002         /*
1003          * Try to collect and report as many minor errors as possible
1004          * before returning, so the user can learn everything that needs
1005          * to be fixed up front.
1006          */
1007         if (stbuf.st_uid != 0) {
1008                 (void) fprintf(stderr, gettext("%s is not owned by root.\n"),
1009                     rpath);
1010                 err = B_TRUE;
1011         }
1012         err |= bad_mode_bit(stbuf.st_mode, S_IRUSR, B_TRUE, rpath);
1013         err |= bad_mode_bit(stbuf.st_mode, S_IWUSR, B_TRUE, rpath);
1014         err |= bad_mode_bit(stbuf.st_mode, S_IXUSR, B_TRUE, rpath);
1015         err |= bad_mode_bit(stbuf.st_mode, S_IRGRP, B_FALSE, rpath);
1016         err |= bad_mode_bit(stbuf.st_mode, S_IWGRP, B_FALSE, rpath);
1017         err |= bad_mode_bit(stbuf.st_mode, S_IXGRP, B_FALSE, rpath);
1018         err |= bad_mode_bit(stbuf.st_mode, S_IROTH, B_FALSE, rpath);
1019         err |= bad_mode_bit(stbuf.st_mode, S_IWOTH, B_FALSE, rpath);
1020         err |= bad_mode_bit(stbuf.st_mode, S_IXOTH, B_FALSE, rpath);
1021 
1022         (void) snprintf(ppath, sizeof (ppath), "%s/..", path);
1023         if ((res = resolvepath(ppath, rppath, sizeof (rppath))) == -1) {
1024                 zperror(ppath, B_FALSE);
1025                 return (Z_ERR);
1026         }
1027         rppath[res] = '\0';
1028         if ((res = stat(rppath, &stbuf)) != 0) {
1029                 zperror(rppath, B_FALSE);
1030                 return (Z_ERR);
1031         }
1032         /* theoretically impossible */
1033         if (!S_ISDIR(stbuf.st_mode)) {
1034                 (void) fprintf(stderr, gettext("%s is not a directory.\n"),
1035                     rppath);
1036                 return (Z_ERR);
1037         }
1038         if (stbuf.st_uid != 0) {
1039                 (void) fprintf(stderr, gettext("%s is not owned by root.\n"),
1040                     rppath);
1041                 err = B_TRUE;
1042         }
1043         err |= bad_mode_bit(stbuf.st_mode, S_IRUSR, B_TRUE, rppath);
1044         err |= bad_mode_bit(stbuf.st_mode, S_IWUSR, B_TRUE, rppath);
1045         err |= bad_mode_bit(stbuf.st_mode, S_IXUSR, B_TRUE, rppath);
1046         err |= bad_mode_bit(stbuf.st_mode, S_IWGRP, B_FALSE, rppath);
1047         err |= bad_mode_bit(stbuf.st_mode, S_IWOTH, B_FALSE, rppath);
1048         if (strcmp(rpath, rppath) == 0) {
1049                 (void) fprintf(stderr, gettext("%s is its own parent.\n"),
1050                     rppath);
1051                 err = B_TRUE;
1052         }
1053 
1054         if (statvfs64(rpath, &vfsbuf) != 0) {
1055                 zperror(rpath, B_FALSE);
1056                 return (Z_ERR);
1057         }
1058         if (strcmp(vfsbuf.f_basetype, MNTTYPE_NFS) == 0) {
1059                 /*
1060                  * TRANSLATION_NOTE
1061                  * Zonepath and NFS are literals that should not be translated.
1062                  */
1063                 (void) fprintf(stderr, gettext("Zonepath %s is on an NFS "
1064                     "mounted file system.\n"
1065                     "\tA local file system must be used.\n"), rpath);
1066                 return (Z_ERR);
1067         }
1068         if (vfsbuf.f_flag & ST_NOSUID) {
1069                 /*
1070                  * TRANSLATION_NOTE
1071                  * Zonepath and nosuid are literals that should not be
1072                  * translated.
1073                  */
1074                 (void) fprintf(stderr, gettext("Zonepath %s is on a nosuid "
1075                     "file system.\n"), rpath);
1076                 return (Z_ERR);
1077         }
1078 
1079         if ((res = zone_get_state(target_zone, &state)) != Z_OK) {
1080                 errno = res;
1081                 zperror2(target_zone, gettext("could not get state"));
1082                 return (Z_ERR);
1083         }
1084         /*
1085          * The existence of the root path is only bad in the configured state,
1086          * as it is *supposed* to be there at the installed and later states.
1087          * However, the root path is expected to be there if the zone is
1088          * detached.
1089          * State/command mismatches are caught earlier in verify_details().
1090          */
1091         if (state == ZONE_STATE_CONFIGURED && cmd_num != CMD_ATTACH) {
1092                 if (snprintf(rootpath, sizeof (rootpath), "%s/root", rpath) >=
1093                     sizeof (rootpath)) {
1094                         /*
1095                          * TRANSLATION_NOTE
1096                          * Zonepath is a literal that should not be translated.
1097                          */
1098                         (void) fprintf(stderr,
1099                             gettext("Zonepath %s is too long.\n"), rpath);
1100                         return (Z_ERR);
1101                 }
1102                 if ((res = stat(rootpath, &stbuf)) == 0) {
1103                         if (zonecfg_detached(rpath))
1104                                 (void) fprintf(stderr,
1105                                     gettext("Cannot %s detached "
1106                                     "zone.\nUse attach or remove %s "
1107                                     "directory.\n"), cmd_to_str(cmd_num),
1108                                     rpath);
1109                         else
1110                                 (void) fprintf(stderr,
1111                                     gettext("Rootpath %s exists; "
1112                                     "remove or move aside prior to %s.\n"),
1113                                     rootpath, cmd_to_str(cmd_num));
1114                         return (Z_ERR);
1115                 }
1116         }
1117 
1118         return (err ? Z_ERR : Z_OK);
1119 }
1120 
1121 /*
1122  * The following two routines implement a simple locking mechanism to
1123  * ensure that only one instance of zoneadm at a time is able to manipulate
1124  * a given zone.  The lock is built on top of an fcntl(2) lock of
1125  * [<altroot>]/var/run/zones/<zonename>.zoneadm.lock.  If a zoneadm instance
1126  * can grab that lock, it is allowed to manipulate the zone.
1127  *
1128  * Since zoneadm may call external applications which in turn invoke
1129  * zoneadm again, we introduce the notion of "lock inheritance".  Any
1130  * instance of zoneadm that has another instance in its ancestry is assumed
1131  * to be acting on behalf of the original zoneadm, and is thus allowed to
1132  * manipulate its zone.
1133  *
1134  * This inheritance is implemented via the _ZONEADM_LOCK_HELD environment
1135  * variable.  When zoneadm is granted a lock on its zone, this environment
1136  * variable is set to 1.  When it releases the lock, the variable is set to
1137  * 0.  Since a child process inherits its parent's environment, checking
1138  * the state of this variable indicates whether or not any ancestor owns
1139  * the lock.
1140  */
1141 static void
1142 release_lock_file(int lockfd)
1143 {
1144         /*
1145          * If we are cleaning up from a failed attempt to lock the zone for
1146          * the first time, we might have a zone_lock_cnt of 0.  In that
1147          * error case, we don't want to do anything but close the lock
1148          * file.
1149          */
1150         assert(zone_lock_cnt >= 0);
1151         if (zone_lock_cnt > 0) {
1152                 assert(getenv(LOCK_ENV_VAR) != NULL);
1153                 assert(atoi(getenv(LOCK_ENV_VAR)) == 1);
1154                 if (--zone_lock_cnt > 0) {
1155                         assert(lockfd == -1);
1156                         return;
1157                 }
1158                 if (putenv(zoneadm_lock_not_held) != 0) {
1159                         zperror(target_zone, B_TRUE);
1160                         exit(Z_ERR);
1161                 }
1162         }
1163         assert(lockfd >= 0);
1164         (void) close(lockfd);
1165 }
1166 
1167 static int
1168 grab_lock_file(const char *zone_name, int *lockfd)
1169 {
1170         char pathbuf[PATH_MAX];
1171         struct flock flock;
1172 
1173         /*
1174          * If we already have the lock, we can skip this expensive song
1175          * and dance.
1176          */
1177         if (zone_lock_cnt > 0) {
1178                 zone_lock_cnt++;
1179                 *lockfd = -1;
1180                 return (Z_OK);
1181         }
1182         assert(getenv(LOCK_ENV_VAR) != NULL);
1183         assert(atoi(getenv(LOCK_ENV_VAR)) == 0);
1184 
1185         if (snprintf(pathbuf, sizeof (pathbuf), "%s%s", zonecfg_get_root(),
1186             ZONES_TMPDIR) >= sizeof (pathbuf)) {
1187                 zerror(gettext("alternate root path is too long"));
1188                 return (Z_ERR);
1189         }
1190         if (mkdir(pathbuf, S_IRWXU) < 0 && errno != EEXIST) {
1191                 zerror(gettext("could not mkdir %s: %s"), pathbuf,
1192                     strerror(errno));
1193                 return (Z_ERR);
1194         }
1195         (void) chmod(pathbuf, S_IRWXU);
1196 
1197         /*
1198          * One of these lock files is created for each zone (when needed).
1199          * The lock files are not cleaned up (except on system reboot),
1200          * but since there is only one per zone, there is no resource
1201          * starvation issue.
1202          */
1203         if (snprintf(pathbuf, sizeof (pathbuf), "%s%s/%s.zoneadm.lock",
1204             zonecfg_get_root(), ZONES_TMPDIR, zone_name) >= sizeof (pathbuf)) {
1205                 zerror(gettext("alternate root path is too long"));
1206                 return (Z_ERR);
1207         }
1208         if ((*lockfd = open(pathbuf, O_RDWR|O_CREAT, S_IRUSR|S_IWUSR)) < 0) {
1209                 zerror(gettext("could not open %s: %s"), pathbuf,
1210                     strerror(errno));
1211                 return (Z_ERR);
1212         }
1213         /*
1214          * Lock the file to synchronize with other zoneadmds
1215          */
1216         flock.l_type = F_WRLCK;
1217         flock.l_whence = SEEK_SET;
1218         flock.l_start = (off_t)0;
1219         flock.l_len = (off_t)0;
1220         if ((fcntl(*lockfd, F_SETLKW, &flock) < 0) ||
1221             (putenv(zoneadm_lock_held) != 0)) {
1222                 zerror(gettext("unable to lock %s: %s"), pathbuf,
1223                     strerror(errno));
1224                 release_lock_file(*lockfd);
1225                 return (Z_ERR);
1226         }
1227         zone_lock_cnt = 1;
1228         return (Z_OK);
1229 }
1230 
1231 static boolean_t
1232 get_doorname(const char *zone_name, char *buffer)
1233 {
1234         return (snprintf(buffer, PATH_MAX, "%s" ZONE_DOOR_PATH,
1235             zonecfg_get_root(), zone_name) < PATH_MAX);
1236 }
1237 
1238 /*
1239  * system daemons are not audited.  For the global zone, this occurs
1240  * "naturally" since init is started with the default audit
1241  * characteristics.  Since zoneadmd is a system daemon and it starts
1242  * init for a zone, it is necessary to clear out the audit
1243  * characteristics inherited from whomever started zoneadmd.  This is
1244  * indicated by the audit id, which is set from the ruid parameter of
1245  * adt_set_user(), below.
1246  */
1247 
1248 static void
1249 prepare_audit_context()
1250 {
1251         adt_session_data_t      *ah;
1252         char                    *failure = gettext("audit failure: %s");
1253 
1254         if (adt_start_session(&ah, NULL, 0)) {
1255                 zerror(failure, strerror(errno));
1256                 return;
1257         }
1258         if (adt_set_user(ah, ADT_NO_AUDIT, ADT_NO_AUDIT,
1259             ADT_NO_AUDIT, ADT_NO_AUDIT, NULL, ADT_NEW)) {
1260                 zerror(failure, strerror(errno));
1261                 (void) adt_end_session(ah);
1262                 return;
1263         }
1264         if (adt_set_proc(ah))
1265                 zerror(failure, strerror(errno));
1266 
1267         (void) adt_end_session(ah);
1268 }
1269 
1270 static int
1271 start_zoneadmd(const char *zone_name)
1272 {
1273         char doorpath[PATH_MAX];
1274         pid_t child_pid;
1275         int error = Z_ERR;
1276         int doorfd, lockfd;
1277         struct door_info info;
1278 
1279         if (!get_doorname(zone_name, doorpath))
1280                 return (Z_ERR);
1281 
1282         if (grab_lock_file(zone_name, &lockfd) != Z_OK)
1283                 return (Z_ERR);
1284 
1285         /*
1286          * Now that we have the lock, re-confirm that the daemon is
1287          * *not* up and working fine.  If it is still down, we have a green
1288          * light to start it.
1289          */
1290         if ((doorfd = open(doorpath, O_RDONLY)) < 0) {
1291                 if (errno != ENOENT) {
1292                         zperror(doorpath, B_FALSE);
1293                         goto out;
1294                 }
1295         } else {
1296                 if (door_info(doorfd, &info) == 0 &&
1297                     ((info.di_attributes & DOOR_REVOKED) == 0)) {
1298                         error = Z_OK;
1299                         (void) close(doorfd);
1300                         goto out;
1301                 }
1302                 (void) close(doorfd);
1303         }
1304 
1305         if ((child_pid = fork()) == -1) {
1306                 zperror(gettext("could not fork"), B_FALSE);
1307                 goto out;
1308         } else if (child_pid == 0) {
1309                 const char *argv[6], **ap;
1310 
1311                 /* child process */
1312                 prepare_audit_context();
1313 
1314                 ap = argv;
1315                 *ap++ = "zoneadmd";
1316                 *ap++ = "-z";
1317                 *ap++ = zone_name;
1318                 if (zonecfg_in_alt_root()) {
1319                         *ap++ = "-R";
1320                         *ap++ = zonecfg_get_root();
1321                 }
1322                 *ap = NULL;
1323 
1324                 (void) execv("/usr/lib/zones/zoneadmd", (char * const *)argv);
1325                 /*
1326                  * TRANSLATION_NOTE
1327                  * zoneadmd is a literal that should not be translated.
1328                  */
1329                 zperror(gettext("could not exec zoneadmd"), B_FALSE);
1330                 _exit(Z_ERR);
1331         } else {
1332                 /* parent process */
1333                 pid_t retval;
1334                 int pstatus = 0;
1335 
1336                 do {
1337                         retval = waitpid(child_pid, &pstatus, 0);
1338                 } while (retval != child_pid);
1339                 if (WIFSIGNALED(pstatus) || (WIFEXITED(pstatus) &&
1340                     WEXITSTATUS(pstatus) != 0)) {
1341                         zerror(gettext("could not start %s"), "zoneadmd");
1342                         goto out;
1343                 }
1344         }
1345         error = Z_OK;
1346 out:
1347         release_lock_file(lockfd);
1348         return (error);
1349 }
1350 
1351 static int
1352 ping_zoneadmd(const char *zone_name)
1353 {
1354         char doorpath[PATH_MAX];
1355         int doorfd;
1356         struct door_info info;
1357 
1358         if (!get_doorname(zone_name, doorpath))
1359                 return (Z_ERR);
1360 
1361         if ((doorfd = open(doorpath, O_RDONLY)) < 0) {
1362                 return (Z_ERR);
1363         }
1364         if (door_info(doorfd, &info) == 0 &&
1365             ((info.di_attributes & DOOR_REVOKED) == 0)) {
1366                 (void) close(doorfd);
1367                 return (Z_OK);
1368         }
1369         (void) close(doorfd);
1370         return (Z_ERR);
1371 }
1372 
1373 static int
1374 call_zoneadmd(const char *zone_name, zone_cmd_arg_t *arg)
1375 {
1376         char doorpath[PATH_MAX];
1377         int doorfd, result;
1378         door_arg_t darg;
1379 
1380         zoneid_t zoneid;
1381         uint64_t uniqid = 0;
1382 
1383         zone_cmd_rval_t *rvalp;
1384         size_t rlen;
1385         char *cp, *errbuf;
1386 
1387         rlen = getpagesize();
1388         if ((rvalp = malloc(rlen)) == NULL) {
1389                 zerror(gettext("failed to allocate %lu bytes: %s"), rlen,
1390                     strerror(errno));
1391                 return (-1);
1392         }
1393 
1394         if ((zoneid = getzoneidbyname(zone_name)) != ZONE_ID_UNDEFINED) {
1395                 (void) zone_getattr(zoneid, ZONE_ATTR_UNIQID, &uniqid,
1396                     sizeof (uniqid));
1397         }
1398         arg->uniqid = uniqid;
1399         (void) strlcpy(arg->locale, locale, sizeof (arg->locale));
1400         if (!get_doorname(zone_name, doorpath)) {
1401                 zerror(gettext("alternate root path is too long"));
1402                 free(rvalp);
1403                 return (-1);
1404         }
1405 
1406         /*
1407          * Loop trying to start zoneadmd; if something goes seriously
1408          * wrong we break out and fail.
1409          */
1410         for (;;) {
1411                 if (start_zoneadmd(zone_name) != Z_OK)
1412                         break;
1413 
1414                 if ((doorfd = open(doorpath, O_RDONLY)) < 0) {
1415                         zperror(gettext("failed to open zone door"), B_FALSE);
1416                         break;
1417                 }
1418 
1419                 darg.data_ptr = (char *)arg;
1420                 darg.data_size = sizeof (*arg);
1421                 darg.desc_ptr = NULL;
1422                 darg.desc_num = 0;
1423                 darg.rbuf = (char *)rvalp;
1424                 darg.rsize = rlen;
1425                 if (door_call(doorfd, &darg) != 0) {
1426                         (void) close(doorfd);
1427                         /*
1428                          * We'll get EBADF if the door has been revoked.
1429                          */
1430                         if (errno != EBADF) {
1431                                 zperror(gettext("door_call failed"), B_FALSE);
1432                                 break;
1433                         }
1434                         continue;       /* take another lap */
1435                 }
1436                 (void) close(doorfd);
1437 
1438                 if (darg.data_size == 0) {
1439                         /* Door server is going away; kick it again. */
1440                         continue;
1441                 }
1442 
1443                 errbuf = rvalp->errbuf;
1444                 while (*errbuf != '\0') {
1445                         /*
1446                          * Remove any newlines since zerror()
1447                          * will append one automatically.
1448                          */
1449                         cp = strchr(errbuf, '\n');
1450                         if (cp != NULL)
1451                                 *cp = '\0';
1452                         zerror("%s", errbuf);
1453                         if (cp == NULL)
1454                                 break;
1455                         errbuf = cp + 1;
1456                 }
1457                 result = rvalp->rval == 0 ? 0 : -1;
1458                 free(rvalp);
1459                 return (result);
1460         }
1461 
1462         free(rvalp);
1463         return (-1);
1464 }
1465 
1466 static int
1467 invoke_brand_handler(int cmd_num, char *argv[])
1468 {
1469         zone_dochandle_t handle;
1470         int err;
1471 
1472         if ((handle = zonecfg_init_handle()) == NULL) {
1473                 zperror(cmd_to_str(cmd_num), B_TRUE);
1474                 return (Z_ERR);
1475         }
1476         if ((err = zonecfg_get_handle(target_zone, handle)) != Z_OK) {
1477                 errno = err;
1478                 zperror(cmd_to_str(cmd_num), B_TRUE);
1479                 zonecfg_fini_handle(handle);
1480                 return (Z_ERR);
1481         }
1482         if (verify_brand(handle, cmd_num, argv) != Z_OK) {
1483                 zonecfg_fini_handle(handle);
1484                 return (Z_ERR);
1485         }
1486         zonecfg_fini_handle(handle);
1487         return (Z_OK);
1488 }
1489 
1490 static int
1491 ready_func(int argc, char *argv[])
1492 {
1493         zone_cmd_arg_t zarg;
1494         int arg;
1495 
1496         if (zonecfg_in_alt_root()) {
1497                 zerror(gettext("cannot ready zone in alternate root"));
1498                 return (Z_ERR);
1499         }
1500 
1501         optind = 0;
1502         if ((arg = getopt(argc, argv, "?")) != EOF) {
1503                 switch (arg) {
1504                 case '?':
1505                         sub_usage(SHELP_READY, CMD_READY);
1506                         return (optopt == '?' ? Z_OK : Z_USAGE);
1507                 default:
1508                         sub_usage(SHELP_READY, CMD_READY);
1509                         return (Z_USAGE);
1510                 }
1511         }
1512         if (argc > optind) {
1513                 sub_usage(SHELP_READY, CMD_READY);
1514                 return (Z_USAGE);
1515         }
1516         if (sanity_check(target_zone, CMD_READY, B_FALSE, B_FALSE, B_FALSE)
1517             != Z_OK)
1518                 return (Z_ERR);
1519         if (verify_details(CMD_READY, argv) != Z_OK)
1520                 return (Z_ERR);
1521 
1522         zarg.cmd = Z_READY;
1523         if (call_zoneadmd(target_zone, &zarg) != 0) {
1524                 zerror(gettext("call to %s failed"), "zoneadmd");
1525                 return (Z_ERR);
1526         }
1527         return (Z_OK);
1528 }
1529 
1530 static int
1531 boot_func(int argc, char *argv[])
1532 {
1533         zone_cmd_arg_t zarg;
1534         boolean_t force = B_FALSE;
1535         int arg;
1536 
1537         if (zonecfg_in_alt_root()) {
1538                 zerror(gettext("cannot boot zone in alternate root"));
1539                 return (Z_ERR);
1540         }
1541 
1542         zarg.bootbuf[0] = '\0';
1543 
1544         /*
1545          * The following getopt processes arguments to zone boot; that
1546          * is to say, the [here] portion of the argument string:
1547          *
1548          *      zoneadm -z myzone boot [here] -- -v -m verbose
1549          *
1550          * Where [here] can either be nothing, -? (in which case we bail
1551          * and print usage), -f (a private option to indicate that the
1552          * boot operation should be 'forced'), or -s.  Support for -s is
1553          * vestigal and obsolete, but is retained because it was a
1554          * documented interface and there are known consumers including
1555          * admin/install; the proper way to specify boot arguments like -s
1556          * is:
1557          *
1558          *      zoneadm -z myzone boot -- -s -v -m verbose.
1559          */
1560         optind = 0;
1561         while ((arg = getopt(argc, argv, "?fs")) != EOF) {
1562                 switch (arg) {
1563                 case '?':
1564                         sub_usage(SHELP_BOOT, CMD_BOOT);
1565                         return (optopt == '?' ? Z_OK : Z_USAGE);
1566                 case 's':
1567                         (void) strlcpy(zarg.bootbuf, "-s",
1568                             sizeof (zarg.bootbuf));
1569                         break;
1570                 case 'f':
1571                         force = B_TRUE;
1572                         break;
1573                 default:
1574                         sub_usage(SHELP_BOOT, CMD_BOOT);
1575                         return (Z_USAGE);
1576                 }
1577         }
1578 
1579         for (; optind < argc; optind++) {
1580                 if (strlcat(zarg.bootbuf, argv[optind],
1581                     sizeof (zarg.bootbuf)) >= sizeof (zarg.bootbuf)) {
1582                         zerror(gettext("Boot argument list too long"));
1583                         return (Z_ERR);
1584                 }
1585                 if (optind < argc - 1)
1586                         if (strlcat(zarg.bootbuf, " ", sizeof (zarg.bootbuf)) >=
1587                             sizeof (zarg.bootbuf)) {
1588                                 zerror(gettext("Boot argument list too long"));
1589                                 return (Z_ERR);
1590                         }
1591         }
1592         if (sanity_check(target_zone, CMD_BOOT, B_FALSE, B_FALSE, force)
1593             != Z_OK)
1594                 return (Z_ERR);
1595         if (verify_details(CMD_BOOT, argv) != Z_OK)
1596                 return (Z_ERR);
1597         zarg.cmd = force ? Z_FORCEBOOT : Z_BOOT;
1598         if (call_zoneadmd(target_zone, &zarg) != 0) {
1599                 zerror(gettext("call to %s failed"), "zoneadmd");
1600                 return (Z_ERR);
1601         }
1602 
1603         return (Z_OK);
1604 }
1605 
1606 static void
1607 fake_up_local_zone(zoneid_t zid, zone_entry_t *zeptr)
1608 {
1609         ssize_t result;
1610         uuid_t uuid;
1611         FILE *fp;
1612         ushort_t flags;
1613 
1614         (void) memset(zeptr, 0, sizeof (*zeptr));
1615 
1616         zeptr->zid = zid;
1617 
1618         /*
1619          * Since we're looking up our own (non-global) zone name,
1620          * we can be assured that it will succeed.
1621          */
1622         result = getzonenamebyid(zid, zeptr->zname, sizeof (zeptr->zname));
1623         assert(result >= 0);
1624         if (zonecfg_is_scratch(zeptr->zname) &&
1625             (fp = zonecfg_open_scratch("", B_FALSE)) != NULL) {
1626                 (void) zonecfg_reverse_scratch(fp, zeptr->zname, zeptr->zname,
1627                     sizeof (zeptr->zname), NULL, 0);
1628                 zonecfg_close_scratch(fp);
1629         }
1630 
1631         if (is_system_labeled()) {
1632                 (void) zone_getattr(zid, ZONE_ATTR_ROOT, zeptr->zroot,
1633                     sizeof (zeptr->zroot));
1634                 (void) strlcpy(zeptr->zbrand, NATIVE_BRAND_NAME,
1635                     sizeof (zeptr->zbrand));
1636         } else {
1637                 (void) strlcpy(zeptr->zroot, "/", sizeof (zeptr->zroot));
1638                 (void) zone_getattr(zid, ZONE_ATTR_BRAND, zeptr->zbrand,
1639                     sizeof (zeptr->zbrand));
1640         }
1641 
1642         zeptr->zstate_str = "running";
1643         if (zonecfg_get_uuid(zeptr->zname, uuid) == Z_OK &&
1644             !uuid_is_null(uuid))
1645                 uuid_unparse(uuid, zeptr->zuuid);
1646 
1647         if (zone_getattr(zid, ZONE_ATTR_FLAGS, &flags, sizeof (flags)) < 0) {
1648                 zperror2(zeptr->zname, gettext("could not get zone flags"));
1649                 exit(Z_ERR);
1650         }
1651         if (flags & ZF_NET_EXCL)
1652                 zeptr->ziptype = ZS_EXCLUSIVE;
1653         else
1654                 zeptr->ziptype = ZS_SHARED;
1655 }
1656 
1657 static int
1658 list_func(int argc, char *argv[])
1659 {
1660         zone_entry_t *zentp, zent;
1661         int arg, retv;
1662         boolean_t output = B_FALSE, verbose = B_FALSE, parsable = B_FALSE;
1663         zone_state_t min_state = ZONE_STATE_RUNNING;
1664         zoneid_t zone_id = getzoneid();
1665 
1666         if (target_zone == NULL) {
1667                 /* all zones: default view to running but allow override */
1668                 optind = 0;
1669                 while ((arg = getopt(argc, argv, "?cipv")) != EOF) {
1670                         switch (arg) {
1671                         case '?':
1672                                 sub_usage(SHELP_LIST, CMD_LIST);
1673                                 return (optopt == '?' ? Z_OK : Z_USAGE);
1674                                 /*
1675                                  * The 'i' and 'c' options are not mutually
1676                                  * exclusive so if 'c' is given, then min_state
1677                                  * is set to 0 (ZONE_STATE_CONFIGURED) which is
1678                                  * the lowest possible state.  If 'i' is given,
1679                                  * then min_state is set to be the lowest state
1680                                  * so far.
1681                                  */
1682                         case 'c':
1683                                 min_state = ZONE_STATE_CONFIGURED;
1684                                 break;
1685                         case 'i':
1686                                 min_state = min(ZONE_STATE_INSTALLED,
1687                                     min_state);
1688 
1689                                 break;
1690                         case 'p':
1691                                 parsable = B_TRUE;
1692                                 break;
1693                         case 'v':
1694                                 verbose = B_TRUE;
1695                                 break;
1696                         default:
1697                                 sub_usage(SHELP_LIST, CMD_LIST);
1698                                 return (Z_USAGE);
1699                         }
1700                 }
1701                 if (parsable && verbose) {
1702                         zerror(gettext("%s -p and -v are mutually exclusive."),
1703                             cmd_to_str(CMD_LIST));
1704                         return (Z_ERR);
1705                 }
1706                 if (zone_id == GLOBAL_ZONEID || is_system_labeled()) {
1707                         retv = zone_print_list(min_state, verbose, parsable);
1708                 } else {
1709                         fake_up_local_zone(zone_id, &zent);
1710                         retv = Z_OK;
1711                         zone_print(&zent, verbose, parsable);
1712                 }
1713                 return (retv);
1714         }
1715 
1716         /*
1717          * Specific target zone: disallow -i/-c suboptions.
1718          */
1719         optind = 0;
1720         while ((arg = getopt(argc, argv, "?pv")) != EOF) {
1721                 switch (arg) {
1722                 case '?':
1723                         sub_usage(SHELP_LIST, CMD_LIST);
1724                         return (optopt == '?' ? Z_OK : Z_USAGE);
1725                 case 'p':
1726                         parsable = B_TRUE;
1727                         break;
1728                 case 'v':
1729                         verbose = B_TRUE;
1730                         break;
1731                 default:
1732                         sub_usage(SHELP_LIST, CMD_LIST);
1733                         return (Z_USAGE);
1734                 }
1735         }
1736         if (parsable && verbose) {
1737                 zerror(gettext("%s -p and -v are mutually exclusive."),
1738                     cmd_to_str(CMD_LIST));
1739                 return (Z_ERR);
1740         }
1741         if (argc > optind) {
1742                 sub_usage(SHELP_LIST, CMD_LIST);
1743                 return (Z_USAGE);
1744         }
1745         if (zone_id != GLOBAL_ZONEID && !is_system_labeled()) {
1746                 fake_up_local_zone(zone_id, &zent);
1747                 /*
1748                  * main() will issue a Z_NO_ZONE error if it cannot get an
1749                  * id for target_zone, which in a non-global zone should
1750                  * happen for any zone name except `zonename`.  Thus we
1751                  * assert() that here but don't otherwise check.
1752                  */
1753                 assert(strcmp(zent.zname, target_zone) == 0);
1754                 zone_print(&zent, verbose, parsable);
1755                 output = B_TRUE;
1756         } else if ((zentp = lookup_running_zone(target_zone)) != NULL) {
1757                 zone_print(zentp, verbose, parsable);
1758                 output = B_TRUE;
1759         } else if (lookup_zone_info(target_zone, ZONE_ID_UNDEFINED,
1760             &zent) == Z_OK) {
1761                 zone_print(&zent, verbose, parsable);
1762                 output = B_TRUE;
1763         }
1764 
1765         /*
1766          * Invoke brand-specific handler. Note that we do this
1767          * only if we're in the global zone, and target_zone is specified
1768          * and it is not the global zone.
1769          */
1770         if (zone_id == GLOBAL_ZONEID && target_zone != NULL &&
1771             strcmp(target_zone, GLOBAL_ZONENAME) != 0)
1772                 if (invoke_brand_handler(CMD_LIST, argv) != Z_OK)
1773                         return (Z_ERR);
1774 
1775         return (output ? Z_OK : Z_ERR);
1776 }
1777 
1778 static void
1779 sigterm(int sig)
1780 {
1781         /*
1782          * Ignore SIG{INT,TERM}, so we don't end up in an infinite loop,
1783          * then propagate the signal to our process group.
1784          */
1785         assert(sig == SIGINT || sig == SIGTERM);
1786         (void) sigset(SIGINT, SIG_IGN);
1787         (void) sigset(SIGTERM, SIG_IGN);
1788         (void) kill(0, sig);
1789         child_killed = B_TRUE;
1790 }
1791 
1792 static int
1793 do_subproc(char *cmdbuf)
1794 {
1795         char inbuf[1024];       /* arbitrary large amount */
1796         FILE *file;
1797 
1798         do_subproc_cnt++;
1799         child_killed = B_FALSE;
1800         /*
1801          * We use popen(3c) to launch child processes for [un]install;
1802          * this library call does not return a PID, so we have to kill
1803          * the whole process group.  To avoid killing our parent, we
1804          * become a process group leader here.  But doing so can wreak
1805          * havoc with reading from stdin when launched by a non-job-control
1806          * shell, so we close stdin and reopen it as /dev/null first.
1807          */
1808         (void) close(STDIN_FILENO);
1809         (void) openat(STDIN_FILENO, "/dev/null", O_RDONLY);
1810         if (!zoneadm_is_nested)
1811                 (void) setpgid(0, 0);
1812         (void) sigset(SIGINT, sigterm);
1813         (void) sigset(SIGTERM, sigterm);
1814         file = popen(cmdbuf, "r");
1815         for (;;) {
1816                 if (child_killed || fgets(inbuf, sizeof (inbuf), file) == NULL)
1817                         break;
1818                 (void) fputs(inbuf, stdout);
1819         }
1820         (void) sigset(SIGINT, SIG_DFL);
1821         (void) sigset(SIGTERM, SIG_DFL);
1822         return (pclose(file));
1823 }
1824 
1825 static int
1826 do_subproc_interactive(char *cmdbuf)
1827 {
1828         void (*saveint)(int);
1829         void (*saveterm)(int);
1830         void (*savequit)(int);
1831         void (*savehup)(int);
1832         int pid, child, status;
1833 
1834         /*
1835          * do_subproc() links stdin to /dev/null, which would break any
1836          * interactive subprocess we try to launch here.  Similarly, we
1837          * can't have been launched as a subprocess ourselves.
1838          */
1839         assert(do_subproc_cnt == 0 && !zoneadm_is_nested);
1840 
1841         if ((child = vfork()) == 0) {
1842                 (void) execl("/bin/sh", "sh", "-c", cmdbuf, (char *)NULL);
1843         }
1844 
1845         if (child == -1)
1846                 return (-1);
1847 
1848         saveint = sigset(SIGINT, SIG_IGN);
1849         saveterm = sigset(SIGTERM, SIG_IGN);
1850         savequit = sigset(SIGQUIT, SIG_IGN);
1851         savehup = sigset(SIGHUP, SIG_IGN);
1852 
1853         while ((pid = waitpid(child, &status, 0)) != child && pid != -1)
1854                 ;
1855 
1856         (void) sigset(SIGINT, saveint);
1857         (void) sigset(SIGTERM, saveterm);
1858         (void) sigset(SIGQUIT, savequit);
1859         (void) sigset(SIGHUP, savehup);
1860 
1861         return (pid == -1 ? -1 : status);
1862 }
1863 
1864 static int
1865 subproc_status(const char *cmd, int status, boolean_t verbose_failure)
1866 {
1867         if (WIFEXITED(status)) {
1868                 int exit_code = WEXITSTATUS(status);
1869 
1870                 if ((verbose_failure) && (exit_code != ZONE_SUBPROC_OK))
1871                         zerror(gettext("'%s' failed with exit code %d."), cmd,
1872                             exit_code);
1873 
1874                 return (exit_code);
1875         } else if (WIFSIGNALED(status)) {
1876                 int signal = WTERMSIG(status);
1877                 char sigstr[SIG2STR_MAX];
1878 
1879                 if (sig2str(signal, sigstr) == 0) {
1880                         zerror(gettext("'%s' terminated by signal SIG%s."), cmd,
1881                             sigstr);
1882                 } else {
1883                         zerror(gettext("'%s' terminated by an unknown signal."),
1884                             cmd);
1885                 }
1886         } else {
1887                 zerror(gettext("'%s' failed for unknown reasons."), cmd);
1888         }
1889 
1890         /*
1891          * Assume a subprocess that died due to a signal or an unknown error
1892          * should be considered an exit code of ZONE_SUBPROC_FATAL, as the
1893          * user will likely need to do some manual cleanup.
1894          */
1895         return (ZONE_SUBPROC_FATAL);
1896 }
1897 
1898 /*
1899  * Various sanity checks; make sure:
1900  * 1. We're in the global zone.
1901  * 2. The calling user has sufficient privilege.
1902  * 3. The target zone is neither the global zone nor anything starting with
1903  *    "SUNW".
1904  * 4a. If we're looking for a 'not running' (i.e., configured or installed)
1905  *     zone, the name service knows about it.
1906  * 4b. For some operations which expect a zone not to be running, that it is
1907  *     not already running (or ready).
1908  */
1909 static int
1910 sanity_check(char *zone, int cmd_num, boolean_t running,
1911     boolean_t unsafe_when_running, boolean_t force)
1912 {
1913         zone_entry_t *zent;
1914         priv_set_t *privset;
1915         zone_state_t state, min_state;
1916         char kernzone[ZONENAME_MAX];
1917         FILE *fp;
1918 
1919         if (getzoneid() != GLOBAL_ZONEID) {
1920                 switch (cmd_num) {
1921                 case CMD_HALT:
1922                         zerror(gettext("use %s to %s this zone."), "halt(1M)",
1923                             cmd_to_str(cmd_num));
1924                         break;
1925                 case CMD_REBOOT:
1926                         zerror(gettext("use %s to %s this zone."),
1927                             "reboot(1M)", cmd_to_str(cmd_num));
1928                         break;
1929                 default:
1930                         zerror(gettext("must be in the global zone to %s a "
1931                             "zone."), cmd_to_str(cmd_num));
1932                         break;
1933                 }
1934                 return (Z_ERR);
1935         }
1936 
1937         if ((privset = priv_allocset()) == NULL) {
1938                 zerror(gettext("%s failed"), "priv_allocset");
1939                 return (Z_ERR);
1940         }
1941 
1942         if (getppriv(PRIV_EFFECTIVE, privset) != 0) {
1943                 zerror(gettext("%s failed"), "getppriv");
1944                 priv_freeset(privset);
1945                 return (Z_ERR);
1946         }
1947 
1948         if (priv_isfullset(privset) == B_FALSE) {
1949                 zerror(gettext("only a privileged user may %s a zone."),
1950                     cmd_to_str(cmd_num));
1951                 priv_freeset(privset);
1952                 return (Z_ERR);
1953         }
1954         priv_freeset(privset);
1955 
1956         if (zone == NULL) {
1957                 zerror(gettext("no zone specified"));
1958                 return (Z_ERR);
1959         }
1960 
1961         if (strcmp(zone, GLOBAL_ZONENAME) == 0) {
1962                 zerror(gettext("%s operation is invalid for the global zone."),
1963                     cmd_to_str(cmd_num));
1964                 return (Z_ERR);
1965         }
1966 
1967         if (strncmp(zone, "SUNW", 4) == 0) {
1968                 zerror(gettext("%s operation is invalid for zones starting "
1969                     "with SUNW."), cmd_to_str(cmd_num));
1970                 return (Z_ERR);
1971         }
1972 
1973         if (!is_native_zone && !is_cluster_zone && cmd_num == CMD_MOUNT) {
1974                 zerror(gettext("%s operation is invalid for branded zones."),
1975                     cmd_to_str(cmd_num));
1976                         return (Z_ERR);
1977         }
1978 
1979         if (!zonecfg_in_alt_root()) {
1980                 zent = lookup_running_zone(zone);
1981         } else if ((fp = zonecfg_open_scratch("", B_FALSE)) == NULL) {
1982                 zent = NULL;
1983         } else {
1984                 if (zonecfg_find_scratch(fp, zone, zonecfg_get_root(),
1985                     kernzone, sizeof (kernzone)) == 0)
1986                         zent = lookup_running_zone(kernzone);
1987                 else
1988                         zent = NULL;
1989                 zonecfg_close_scratch(fp);
1990         }
1991 
1992         /*
1993          * Look up from the kernel for 'running' zones.
1994          */
1995         if (running && !force) {
1996                 if (zent == NULL) {
1997                         zerror(gettext("not running"));
1998                         return (Z_ERR);
1999                 }
2000         } else {
2001                 int err;
2002 
2003                 if (unsafe_when_running && zent != NULL) {
2004                         /* check whether the zone is ready or running */
2005                         if ((err = zone_get_state(zent->zname,
2006                             &zent->zstate_num)) != Z_OK) {
2007                                 errno = err;
2008                                 zperror2(zent->zname,
2009                                     gettext("could not get state"));
2010                                 /* can't tell, so hedge */
2011                                 zent->zstate_str = "ready/running";
2012                         } else {
2013                                 zent->zstate_str =
2014                                     zone_state_str(zent->zstate_num);
2015                         }
2016                         zerror(gettext("%s operation is invalid for %s zones."),
2017                             cmd_to_str(cmd_num), zent->zstate_str);
2018                         return (Z_ERR);
2019                 }
2020                 if ((err = zone_get_state(zone, &state)) != Z_OK) {
2021                         errno = err;
2022                         zperror2(zone, gettext("could not get state"));
2023                         return (Z_ERR);
2024                 }
2025                 switch (cmd_num) {
2026                 case CMD_UNINSTALL:
2027                         if (state == ZONE_STATE_CONFIGURED) {
2028                                 zerror(gettext("is already in state '%s'."),
2029                                     zone_state_str(ZONE_STATE_CONFIGURED));
2030                                 return (Z_ERR);
2031                         }
2032                         break;
2033                 case CMD_ATTACH:
2034                 case CMD_CLONE:
2035                 case CMD_INSTALL:
2036                         if (state == ZONE_STATE_INSTALLED) {
2037                                 zerror(gettext("is already %s."),
2038                                     zone_state_str(ZONE_STATE_INSTALLED));
2039                                 return (Z_ERR);
2040                         } else if (state == ZONE_STATE_INCOMPLETE) {
2041                                 zerror(gettext("zone is %s; %s required."),
2042                                     zone_state_str(ZONE_STATE_INCOMPLETE),
2043                                     cmd_to_str(CMD_UNINSTALL));
2044                                 return (Z_ERR);
2045                         }
2046                         break;
2047                 case CMD_DETACH:
2048                 case CMD_MOVE:
2049                 case CMD_READY:
2050                 case CMD_BOOT:
2051                 case CMD_MOUNT:
2052                 case CMD_MARK:
2053                         if ((cmd_num == CMD_BOOT || cmd_num == CMD_MOUNT) &&
2054                             force)
2055                                 min_state = ZONE_STATE_INCOMPLETE;
2056                         else
2057                                 min_state = ZONE_STATE_INSTALLED;
2058 
2059                         if (force && cmd_num == CMD_BOOT && is_native_zone) {
2060                                 zerror(gettext("Only branded zones may be "
2061                                     "force-booted."));
2062                                 return (Z_ERR);
2063                         }
2064 
2065                         if (state < min_state) {
2066                                 zerror(gettext("must be %s before %s."),
2067                                     zone_state_str(min_state),
2068                                     cmd_to_str(cmd_num));
2069                                 return (Z_ERR);
2070                         }
2071                         break;
2072                 case CMD_VERIFY:
2073                         if (state == ZONE_STATE_INCOMPLETE) {
2074                                 zerror(gettext("zone is %s; %s required."),
2075                                     zone_state_str(ZONE_STATE_INCOMPLETE),
2076                                     cmd_to_str(CMD_UNINSTALL));
2077                                 return (Z_ERR);
2078                         }
2079                         break;
2080                 case CMD_UNMOUNT:
2081                         if (state != ZONE_STATE_MOUNTED) {
2082                                 zerror(gettext("must be %s before %s."),
2083                                     zone_state_str(ZONE_STATE_MOUNTED),
2084                                     cmd_to_str(cmd_num));
2085                                 return (Z_ERR);
2086                         }
2087                         break;
2088                 }
2089         }
2090         return (Z_OK);
2091 }
2092 
2093 static int
2094 halt_func(int argc, char *argv[])
2095 {
2096         zone_cmd_arg_t zarg;
2097         int arg;
2098 
2099         if (zonecfg_in_alt_root()) {
2100                 zerror(gettext("cannot halt zone in alternate root"));
2101                 return (Z_ERR);
2102         }
2103 
2104         optind = 0;
2105         if ((arg = getopt(argc, argv, "?")) != EOF) {
2106                 switch (arg) {
2107                 case '?':
2108                         sub_usage(SHELP_HALT, CMD_HALT);
2109                         return (optopt == '?' ? Z_OK : Z_USAGE);
2110                 default:
2111                         sub_usage(SHELP_HALT, CMD_HALT);
2112                         return (Z_USAGE);
2113                 }
2114         }
2115         if (argc > optind) {
2116                 sub_usage(SHELP_HALT, CMD_HALT);
2117                 return (Z_USAGE);
2118         }
2119         /*
2120          * zoneadmd should be the one to decide whether or not to proceed,
2121          * so even though it seems that the fourth parameter below should
2122          * perhaps be B_TRUE, it really shouldn't be.
2123          */
2124         if (sanity_check(target_zone, CMD_HALT, B_FALSE, B_FALSE, B_FALSE)
2125             != Z_OK)
2126                 return (Z_ERR);
2127 
2128         /*
2129          * Invoke brand-specific handler.
2130          */
2131         if (invoke_brand_handler(CMD_HALT, argv) != Z_OK)
2132                 return (Z_ERR);
2133 
2134         zarg.cmd = Z_HALT;
2135         return ((call_zoneadmd(target_zone, &zarg) == 0) ? Z_OK : Z_ERR);
2136 }
2137 
2138 static int
2139 reboot_func(int argc, char *argv[])
2140 {
2141         zone_cmd_arg_t zarg;
2142         int arg;
2143 
2144         if (zonecfg_in_alt_root()) {
2145                 zerror(gettext("cannot reboot zone in alternate root"));
2146                 return (Z_ERR);
2147         }
2148 
2149         optind = 0;
2150         if ((arg = getopt(argc, argv, "?")) != EOF) {
2151                 switch (arg) {
2152                 case '?':
2153                         sub_usage(SHELP_REBOOT, CMD_REBOOT);
2154                         return (optopt == '?' ? Z_OK : Z_USAGE);
2155                 default:
2156                         sub_usage(SHELP_REBOOT, CMD_REBOOT);
2157                         return (Z_USAGE);
2158                 }
2159         }
2160 
2161         zarg.bootbuf[0] = '\0';
2162         for (; optind < argc; optind++) {
2163                 if (strlcat(zarg.bootbuf, argv[optind],
2164                     sizeof (zarg.bootbuf)) >= sizeof (zarg.bootbuf)) {
2165                         zerror(gettext("Boot argument list too long"));
2166                         return (Z_ERR);
2167                 }
2168                 if (optind < argc - 1)
2169                         if (strlcat(zarg.bootbuf, " ", sizeof (zarg.bootbuf)) >=
2170                             sizeof (zarg.bootbuf)) {
2171                                 zerror(gettext("Boot argument list too long"));
2172                                 return (Z_ERR);
2173                         }
2174         }
2175 
2176 
2177         /*
2178          * zoneadmd should be the one to decide whether or not to proceed,
2179          * so even though it seems that the fourth parameter below should
2180          * perhaps be B_TRUE, it really shouldn't be.
2181          */
2182         if (sanity_check(target_zone, CMD_REBOOT, B_TRUE, B_FALSE, B_FALSE)
2183             != Z_OK)
2184                 return (Z_ERR);
2185         if (verify_details(CMD_REBOOT, argv) != Z_OK)
2186                 return (Z_ERR);
2187 
2188         zarg.cmd = Z_REBOOT;
2189         return ((call_zoneadmd(target_zone, &zarg) == 0) ? Z_OK : Z_ERR);
2190 }
2191 
2192 static int
2193 verify_brand(zone_dochandle_t handle, int cmd_num, char *argv[])
2194 {
2195         char cmdbuf[MAXPATHLEN];
2196         int err;
2197         char zonepath[MAXPATHLEN];
2198         brand_handle_t bh = NULL;
2199         int status, i;
2200 
2201         /*
2202          * Fetch the verify command from the brand configuration.
2203          * "exec" the command so that the returned status is that of
2204          * the command and not the shell.
2205          */
2206         if ((err = zonecfg_get_zonepath(handle, zonepath, sizeof (zonepath))) !=
2207             Z_OK) {
2208                 errno = err;
2209                 zperror(cmd_to_str(cmd_num), B_TRUE);
2210                 return (Z_ERR);
2211         }
2212         if ((bh = brand_open(target_brand)) == NULL) {
2213                 zerror(gettext("missing or invalid brand"));
2214                 return (Z_ERR);
2215         }
2216 
2217         /*
2218          * If the brand has its own verification routine, execute it now.
2219          * The verification routine validates the intended zoneadm
2220          * operation for the specific brand. The zoneadm subcommand and
2221          * all its arguments are passed to the routine.
2222          */
2223         (void) strcpy(cmdbuf, EXEC_PREFIX);
2224         err = brand_get_verify_adm(bh, target_zone, zonepath,
2225             cmdbuf + EXEC_LEN, sizeof (cmdbuf) - EXEC_LEN, 0, NULL);
2226         brand_close(bh);
2227         if (err != 0)
2228                 return (Z_BRAND_ERROR);
2229         if (strlen(cmdbuf) <= EXEC_LEN)
2230                 return (Z_OK);
2231 
2232         if (strlcat(cmdbuf, cmd_to_str(cmd_num),
2233             sizeof (cmdbuf)) >= sizeof (cmdbuf))
2234                 return (Z_ERR);
2235 
2236         /* Build the argv string */
2237         i = 0;
2238         while (argv[i] != NULL) {
2239                 if ((strlcat(cmdbuf, " ",
2240                     sizeof (cmdbuf)) >= sizeof (cmdbuf)) ||
2241                     (strlcat(cmdbuf, argv[i++],
2242                     sizeof (cmdbuf)) >= sizeof (cmdbuf)))
2243                         return (Z_ERR);
2244         }
2245 
2246         if (zoneadm_is_nested)
2247                 status = do_subproc(cmdbuf);
2248         else
2249                 status = do_subproc_interactive(cmdbuf);
2250         err = subproc_status(gettext("brand-specific verification"),
2251             status, B_FALSE);
2252 
2253         return ((err == ZONE_SUBPROC_OK) ? Z_OK : Z_BRAND_ERROR);
2254 }
2255 
2256 static int
2257 verify_rctls(zone_dochandle_t handle)
2258 {
2259         struct zone_rctltab rctltab;
2260         size_t rbs = rctlblk_size();
2261         rctlblk_t *rctlblk;
2262         int error = Z_INVAL;
2263 
2264         if ((rctlblk = malloc(rbs)) == NULL) {
2265                 zerror(gettext("failed to allocate %lu bytes: %s"), rbs,
2266                     strerror(errno));
2267                 return (Z_NOMEM);
2268         }
2269 
2270         if (zonecfg_setrctlent(handle) != Z_OK) {
2271                 zerror(gettext("zonecfg_setrctlent failed"));
2272                 free(rctlblk);
2273                 return (error);
2274         }
2275 
2276         rctltab.zone_rctl_valptr = NULL;
2277         while (zonecfg_getrctlent(handle, &rctltab) == Z_OK) {
2278                 struct zone_rctlvaltab *rctlval;
2279                 const char *name = rctltab.zone_rctl_name;
2280 
2281                 if (!zonecfg_is_rctl(name)) {
2282                         zerror(gettext("WARNING: Ignoring unrecognized rctl "
2283                             "'%s'."),  name);
2284                         zonecfg_free_rctl_value_list(rctltab.zone_rctl_valptr);
2285                         rctltab.zone_rctl_valptr = NULL;
2286                         continue;
2287                 }
2288 
2289                 for (rctlval = rctltab.zone_rctl_valptr; rctlval != NULL;
2290                     rctlval = rctlval->zone_rctlval_next) {
2291                         if (zonecfg_construct_rctlblk(rctlval, rctlblk)
2292                             != Z_OK) {
2293                                 zerror(gettext("invalid rctl value: "
2294                                     "(priv=%s,limit=%s,action%s)"),
2295                                     rctlval->zone_rctlval_priv,
2296                                     rctlval->zone_rctlval_limit,
2297                                     rctlval->zone_rctlval_action);
2298                                 goto out;
2299                         }
2300                         if (!zonecfg_valid_rctl(name, rctlblk)) {
2301                                 zerror(gettext("(priv=%s,limit=%s,action=%s) "
2302                                     "is not a valid value for rctl '%s'"),
2303                                     rctlval->zone_rctlval_priv,
2304                                     rctlval->zone_rctlval_limit,
2305                                     rctlval->zone_rctlval_action,
2306                                     name);
2307                                 goto out;
2308                         }
2309                 }
2310                 zonecfg_free_rctl_value_list(rctltab.zone_rctl_valptr);
2311         }
2312         rctltab.zone_rctl_valptr = NULL;
2313         error = Z_OK;
2314 out:
2315         zonecfg_free_rctl_value_list(rctltab.zone_rctl_valptr);
2316         (void) zonecfg_endrctlent(handle);
2317         free(rctlblk);
2318         return (error);
2319 }
2320 
2321 static int
2322 verify_pool(zone_dochandle_t handle)
2323 {
2324         char poolname[MAXPATHLEN];
2325         pool_conf_t *poolconf;
2326         pool_t *pool;
2327         int status;
2328         int error;
2329 
2330         /*
2331          * This ends up being very similar to the check done in zoneadmd.
2332          */
2333         error = zonecfg_get_pool(handle, poolname, sizeof (poolname));
2334         if (error == Z_NO_ENTRY || (error == Z_OK && strlen(poolname) == 0)) {
2335                 /*
2336                  * No pool specified.
2337                  */
2338                 return (0);
2339         }
2340         if (error != Z_OK) {
2341                 zperror(gettext("Unable to retrieve pool name from "
2342                     "configuration"), B_TRUE);
2343                 return (error);
2344         }
2345         /*
2346          * Don't do anything if pools aren't enabled.
2347          */
2348         if (pool_get_status(&status) != PO_SUCCESS || status != POOL_ENABLED) {
2349                 zerror(gettext("WARNING: pools facility not active; "
2350                     "zone will not be bound to pool '%s'."), poolname);
2351                 return (Z_OK);
2352         }
2353         /*
2354          * Try to provide a sane error message if the requested pool doesn't
2355          * exist.  It isn't clear that pools-related failures should
2356          * necessarily translate to a failure to verify the zone configuration,
2357          * hence they are not considered errors.
2358          */
2359         if ((poolconf = pool_conf_alloc()) == NULL) {
2360                 zerror(gettext("WARNING: pool_conf_alloc failed; "
2361                     "using default pool"));
2362                 return (Z_OK);
2363         }
2364         if (pool_conf_open(poolconf, pool_dynamic_location(), PO_RDONLY) !=
2365             PO_SUCCESS) {
2366                 zerror(gettext("WARNING: pool_conf_open failed; "
2367                     "using default pool"));
2368                 pool_conf_free(poolconf);
2369                 return (Z_OK);
2370         }
2371         pool = pool_get_pool(poolconf, poolname);
2372         (void) pool_conf_close(poolconf);
2373         pool_conf_free(poolconf);
2374         if (pool == NULL) {
2375                 zerror(gettext("WARNING: pool '%s' not found. "
2376                     "using default pool"), poolname);
2377         }
2378 
2379         return (Z_OK);
2380 }
2381 
2382 static int
2383 verify_ipd(zone_dochandle_t handle)
2384 {
2385         int return_code = Z_OK;
2386         struct zone_fstab fstab;
2387         struct stat st;
2388         char specdir[MAXPATHLEN];
2389 
2390         if (zonecfg_setipdent(handle) != Z_OK) {
2391                 /*
2392                  * TRANSLATION_NOTE
2393                  * inherit-pkg-dirs is a literal that should not be translated.
2394                  */
2395                 (void) fprintf(stderr, gettext("could not verify "
2396                     "inherit-pkg-dirs: unable to enumerate mounts\n"));
2397                 return (Z_ERR);
2398         }
2399         while (zonecfg_getipdent(handle, &fstab) == Z_OK) {
2400                 /*
2401                  * Verify fs_dir exists.
2402                  */
2403                 (void) snprintf(specdir, sizeof (specdir), "%s%s",
2404                     zonecfg_get_root(), fstab.zone_fs_dir);
2405                 if (stat(specdir, &st) != 0) {
2406                         /*
2407                          * TRANSLATION_NOTE
2408                          * inherit-pkg-dir is a literal that should not be
2409                          * translated.
2410                          */
2411                         (void) fprintf(stderr, gettext("could not verify "
2412                             "inherit-pkg-dir %s: %s\n"),
2413                             fstab.zone_fs_dir, strerror(errno));
2414                         return_code = Z_ERR;
2415                 }
2416                 if (strcmp(st.st_fstype, MNTTYPE_NFS) == 0) {
2417                         /*
2418                          * TRANSLATION_NOTE
2419                          * inherit-pkg-dir and NFS are literals that should
2420                          * not be translated.
2421                          */
2422                         (void) fprintf(stderr, gettext("cannot verify "
2423                             "inherit-pkg-dir %s: NFS mounted file system.\n"
2424                             "\tA local file system must be used.\n"),
2425                             fstab.zone_fs_dir);
2426                         return_code = Z_ERR;
2427                 }
2428         }
2429         (void) zonecfg_endipdent(handle);
2430 
2431         return (return_code);
2432 }
2433 
2434 /*
2435  * Verify that the special device/file system exists and is valid.
2436  */
2437 static int
2438 verify_fs_special(struct zone_fstab *fstab)
2439 {
2440         struct stat64 st;
2441 
2442         /*
2443          * This validation is really intended for standard zone administration.
2444          * If we are in a mini-root or some other upgrade situation where
2445          * we are using the scratch zone, just by-pass this.
2446          */
2447         if (zonecfg_in_alt_root())
2448                 return (Z_OK);
2449 
2450         if (strcmp(fstab->zone_fs_type, MNTTYPE_ZFS) == 0)
2451                 return (verify_fs_zfs(fstab));
2452 
2453         if (stat64(fstab->zone_fs_special, &st) != 0) {
2454                 (void) fprintf(stderr, gettext("could not verify fs "
2455                     "%s: could not access %s: %s\n"), fstab->zone_fs_dir,
2456                     fstab->zone_fs_special, strerror(errno));
2457                 return (Z_ERR);
2458         }
2459 
2460         if (strcmp(st.st_fstype, MNTTYPE_NFS) == 0) {
2461                 /*
2462                  * TRANSLATION_NOTE
2463                  * fs and NFS are literals that should
2464                  * not be translated.
2465                  */
2466                 (void) fprintf(stderr, gettext("cannot verify "
2467                     "fs %s: NFS mounted file system.\n"
2468                     "\tA local file system must be used.\n"),
2469                     fstab->zone_fs_special);
2470                 return (Z_ERR);
2471         }
2472 
2473         return (Z_OK);
2474 }
2475 
2476 static int
2477 isregfile(const char *path)
2478 {
2479         struct stat64 st;
2480 
2481         if (stat64(path, &st) == -1)
2482                 return (-1);
2483 
2484         return (S_ISREG(st.st_mode));
2485 }
2486 
2487 static int
2488 verify_filesystems(zone_dochandle_t handle)
2489 {
2490         int return_code = Z_OK;
2491         struct zone_fstab fstab;
2492         char cmdbuf[MAXPATHLEN];
2493         struct stat st;
2494 
2495         /*
2496          * No need to verify inherit-pkg-dir fs types, as their type is
2497          * implicitly lofs, which is known.  Therefore, the types are only
2498          * verified for regular file systems below.
2499          *
2500          * Since the actual mount point is not known until the dependent mounts
2501          * are performed, we don't attempt any path validation here: that will
2502          * happen later when zoneadmd actually does the mounts.
2503          */
2504         if (zonecfg_setfsent(handle) != Z_OK) {
2505                 (void) fprintf(stderr, gettext("could not verify file systems: "
2506                     "unable to enumerate mounts\n"));
2507                 return (Z_ERR);
2508         }
2509         while (zonecfg_getfsent(handle, &fstab) == Z_OK) {
2510                 if (!zonecfg_valid_fs_type(fstab.zone_fs_type)) {
2511                         (void) fprintf(stderr, gettext("cannot verify fs %s: "
2512                             "type %s is not allowed.\n"), fstab.zone_fs_dir,
2513                             fstab.zone_fs_type);
2514                         return_code = Z_ERR;
2515                         goto next_fs;
2516                 }
2517                 /*
2518                  * Verify /usr/lib/fs/<fstype>/mount exists.
2519                  */
2520                 if (snprintf(cmdbuf, sizeof (cmdbuf), "/usr/lib/fs/%s/mount",
2521                     fstab.zone_fs_type) > sizeof (cmdbuf)) {
2522                         (void) fprintf(stderr, gettext("cannot verify fs %s: "
2523                             "type %s is too long.\n"), fstab.zone_fs_dir,
2524                             fstab.zone_fs_type);
2525                         return_code = Z_ERR;
2526                         goto next_fs;
2527                 }
2528                 if (stat(cmdbuf, &st) != 0) {
2529                         (void) fprintf(stderr, gettext("could not verify fs "
2530                             "%s: could not access %s: %s\n"), fstab.zone_fs_dir,
2531                             cmdbuf, strerror(errno));
2532                         return_code = Z_ERR;
2533                         goto next_fs;
2534                 }
2535                 if (!S_ISREG(st.st_mode)) {
2536                         (void) fprintf(stderr, gettext("could not verify fs "
2537                             "%s: %s is not a regular file\n"),
2538                             fstab.zone_fs_dir, cmdbuf);
2539                         return_code = Z_ERR;
2540                         goto next_fs;
2541                 }
2542                 /*
2543                  * If zone_fs_raw is set, verify that there's an fsck
2544                  * binary for it.  If zone_fs_raw is not set, and it's
2545                  * not a regular file (lofi mount), and there's an fsck
2546                  * binary for it, complain.
2547                  */
2548                 if (snprintf(cmdbuf, sizeof (cmdbuf), "/usr/lib/fs/%s/fsck",
2549                     fstab.zone_fs_type) > sizeof (cmdbuf)) {
2550                         (void) fprintf(stderr, gettext("cannot verify fs %s: "
2551                             "type %s is too long.\n"), fstab.zone_fs_dir,
2552                             fstab.zone_fs_type);
2553                         return_code = Z_ERR;
2554                         goto next_fs;
2555                 }
2556                 if (fstab.zone_fs_raw[0] != '\0' &&
2557                     (stat(cmdbuf, &st) != 0 || !S_ISREG(st.st_mode))) {
2558                         (void) fprintf(stderr, gettext("cannot verify fs %s: "
2559                             "'raw' device specified but "
2560                             "no fsck executable exists for %s\n"),
2561                             fstab.zone_fs_dir, fstab.zone_fs_type);
2562                         return_code = Z_ERR;
2563                         goto next_fs;
2564                 } else if (fstab.zone_fs_raw[0] == '\0' &&
2565                     stat(cmdbuf, &st) == 0 &&
2566                     isregfile(fstab.zone_fs_special) != 1) {
2567                         (void) fprintf(stderr, gettext("could not verify fs "
2568                             "%s: must specify 'raw' device for %s "
2569                             "file systems\n"),
2570                             fstab.zone_fs_dir, fstab.zone_fs_type);
2571                         return_code = Z_ERR;
2572                         goto next_fs;
2573                 }
2574 
2575                 /* Verify fs_special. */
2576                 if ((return_code = verify_fs_special(&fstab)) != Z_OK)
2577                         goto next_fs;
2578 
2579                 /* Verify fs_raw. */
2580                 if (fstab.zone_fs_raw[0] != '\0' &&
2581                     stat(fstab.zone_fs_raw, &st) != 0) {
2582                         /*
2583                          * TRANSLATION_NOTE
2584                          * fs is a literal that should not be translated.
2585                          */
2586                         (void) fprintf(stderr, gettext("could not verify fs "
2587                             "%s: could not access %s: %s\n"), fstab.zone_fs_dir,
2588                             fstab.zone_fs_raw, strerror(errno));
2589                         return_code = Z_ERR;
2590                         goto next_fs;
2591                 }
2592 next_fs:
2593                 zonecfg_free_fs_option_list(fstab.zone_fs_options);
2594         }
2595         (void) zonecfg_endfsent(handle);
2596 
2597         return (return_code);
2598 }
2599 
2600 static int
2601 verify_limitpriv(zone_dochandle_t handle)
2602 {
2603         char *privname = NULL;
2604         int err;
2605         priv_set_t *privs;
2606 
2607         if ((privs = priv_allocset()) == NULL) {
2608                 zperror(gettext("failed to allocate privilege set"), B_FALSE);
2609                 return (Z_NOMEM);
2610         }
2611         err = zonecfg_get_privset(handle, privs, &privname);
2612         switch (err) {
2613         case Z_OK:
2614                 break;
2615         case Z_PRIV_PROHIBITED:
2616                 (void) fprintf(stderr, gettext("privilege \"%s\" is not "
2617                     "permitted within the zone's privilege set\n"), privname);
2618                 break;
2619         case Z_PRIV_REQUIRED:
2620                 (void) fprintf(stderr, gettext("required privilege \"%s\" is "
2621                     "missing from the zone's privilege set\n"), privname);
2622                 break;
2623         case Z_PRIV_UNKNOWN:
2624                 (void) fprintf(stderr, gettext("unknown privilege \"%s\" "
2625                     "specified in the zone's privilege set\n"), privname);
2626                 break;
2627         default:
2628                 zperror(
2629                     gettext("failed to determine the zone's privilege set"),
2630                     B_TRUE);
2631                 break;
2632         }
2633         free(privname);
2634         priv_freeset(privs);
2635         return (err);
2636 }
2637 
2638 static void
2639 free_local_netifs(int if_cnt, struct net_if **if_list)
2640 {
2641         int             i;
2642 
2643         for (i = 0; i < if_cnt; i++) {
2644                 free(if_list[i]->name);
2645                 free(if_list[i]);
2646         }
2647         free(if_list);
2648 }
2649 
2650 /*
2651  * Get a list of the network interfaces, along with their address families,
2652  * that are plumbed in the global zone.  See if_tcp(7p) for a description
2653  * of the ioctls used here.
2654  */
2655 static int
2656 get_local_netifs(int *if_cnt, struct net_if ***if_list)
2657 {
2658         int             s;
2659         int             i;
2660         int             res = Z_OK;
2661         int             space_needed;
2662         int             cnt = 0;
2663         struct          lifnum if_num;
2664         struct          lifconf if_conf;
2665         struct          lifreq *if_reqp;
2666         char            *if_buf;
2667         struct net_if   **local_ifs = NULL;
2668 
2669         *if_cnt = 0;
2670         *if_list = NULL;
2671 
2672         if ((s = socket(SOCKET_AF(AF_INET), SOCK_DGRAM, 0)) < 0)
2673                 return (Z_ERR);
2674 
2675         /*
2676          * Come back here in the unlikely event that the number of interfaces
2677          * increases between the time we get the count and the time we do the
2678          * SIOCGLIFCONF ioctl.
2679          */
2680 retry:
2681         /* Get the number of interfaces. */
2682         if_num.lifn_family = AF_UNSPEC;
2683         if_num.lifn_flags = LIFC_NOXMIT;
2684         if (ioctl(s, SIOCGLIFNUM, &if_num) < 0) {
2685                 (void) close(s);
2686                 return (Z_ERR);
2687         }
2688 
2689         /* Get the interface configuration list. */
2690         space_needed = if_num.lifn_count * sizeof (struct lifreq);
2691         if ((if_buf = malloc(space_needed)) == NULL) {
2692                 (void) close(s);
2693                 return (Z_ERR);
2694         }
2695         if_conf.lifc_family = AF_UNSPEC;
2696         if_conf.lifc_flags = LIFC_NOXMIT;
2697         if_conf.lifc_len = space_needed;
2698         if_conf.lifc_buf = if_buf;
2699         if (ioctl(s, SIOCGLIFCONF, &if_conf) < 0) {
2700                 free(if_buf);
2701                 /*
2702                  * SIOCGLIFCONF returns EINVAL if the buffer we passed in is
2703                  * too small.  In this case go back and get the new if cnt.
2704                  */
2705                 if (errno == EINVAL)
2706                         goto retry;
2707 
2708                 (void) close(s);
2709                 return (Z_ERR);
2710         }
2711         (void) close(s);
2712 
2713         /* Get the name and address family for each interface. */
2714         if_reqp = if_conf.lifc_req;
2715         for (i = 0; i < (if_conf.lifc_len / sizeof (struct lifreq)); i++) {
2716                 struct net_if   **p;
2717                 struct lifreq   req;
2718 
2719                 if (strcmp(LOOPBACK_IF, if_reqp->lifr_name) == 0) {
2720                         if_reqp++;
2721                         continue;
2722                 }
2723 
2724                 if ((s = socket(SOCKET_AF(if_reqp->lifr_addr.ss_family),
2725                     SOCK_DGRAM, 0)) == -1) {
2726                         res = Z_ERR;
2727                         break;
2728                 }
2729 
2730                 (void) strncpy(req.lifr_name, if_reqp->lifr_name,
2731                     sizeof (req.lifr_name));
2732                 if (ioctl(s, SIOCGLIFADDR, &req) < 0) {
2733                         (void) close(s);
2734                         if_reqp++;
2735                         continue;
2736                 }
2737 
2738                 if ((p = (struct net_if **)realloc(local_ifs,
2739                     sizeof (struct net_if *) * (cnt + 1))) == NULL) {
2740                         res = Z_ERR;
2741                         break;
2742                 }
2743                 local_ifs = p;
2744 
2745                 if ((local_ifs[cnt] = malloc(sizeof (struct net_if))) == NULL) {
2746                         res = Z_ERR;
2747                         break;
2748                 }
2749 
2750                 if ((local_ifs[cnt]->name = strdup(if_reqp->lifr_name))
2751                     == NULL) {
2752                         free(local_ifs[cnt]);
2753                         res = Z_ERR;
2754                         break;
2755                 }
2756                 local_ifs[cnt]->af = req.lifr_addr.ss_family;
2757                 cnt++;
2758 
2759                 (void) close(s);
2760                 if_reqp++;
2761         }
2762 
2763         free(if_buf);
2764 
2765         if (res != Z_OK) {
2766                 free_local_netifs(cnt, local_ifs);
2767         } else {
2768                 *if_cnt = cnt;
2769                 *if_list = local_ifs;
2770         }
2771 
2772         return (res);
2773 }
2774 
2775 static char *
2776 af2str(int af)
2777 {
2778         switch (af) {
2779         case AF_INET:
2780                 return ("IPv4");
2781         case AF_INET6:
2782                 return ("IPv6");
2783         default:
2784                 return ("Unknown");
2785         }
2786 }
2787 
2788 /*
2789  * Cross check the network interface name and address family with the
2790  * interfaces that are set up in the global zone so that we can print the
2791  * appropriate error message.
2792  */
2793 static void
2794 print_net_err(char *phys, char *addr, int af, char *msg)
2795 {
2796         int             i;
2797         int             local_if_cnt = 0;
2798         struct net_if   **local_ifs = NULL;
2799         boolean_t       found_if = B_FALSE;
2800         boolean_t       found_af = B_FALSE;
2801 
2802         if (get_local_netifs(&local_if_cnt, &local_ifs) != Z_OK) {
2803                 (void) fprintf(stderr,
2804                     gettext("could not verify %s %s=%s %s=%s\n\t%s\n"),
2805                     "net", "address", addr, "physical", phys, msg);
2806                 return;
2807         }
2808 
2809         for (i = 0; i < local_if_cnt; i++) {
2810                 if (strcmp(phys, local_ifs[i]->name) == 0) {
2811                         found_if = B_TRUE;
2812                         if (af == local_ifs[i]->af) {
2813                                 found_af = B_TRUE;
2814                                 break;
2815                         }
2816                 }
2817         }
2818 
2819         free_local_netifs(local_if_cnt, local_ifs);
2820 
2821         if (!found_if) {
2822                 (void) fprintf(stderr,
2823                     gettext("could not verify %s %s=%s\n\t"
2824                     "network interface %s is not plumbed in the global zone\n"),
2825                     "net", "physical", phys, phys);
2826                 return;
2827         }
2828 
2829         /*
2830          * Print this error if we were unable to find the address family
2831          * for this interface.  If the af variable is not initialized to
2832          * to something meaningful by the caller (not AF_UNSPEC) then we
2833          * also skip this message since it wouldn't be informative.
2834          */
2835         if (!found_af && af != AF_UNSPEC) {
2836                 (void) fprintf(stderr,
2837                     gettext("could not verify %s %s=%s %s=%s\n\tthe %s address "
2838                     "family is not configured on this network interface in "
2839                     "the\n\tglobal zone\n"),
2840                     "net", "address", addr, "physical", phys, af2str(af));
2841                 return;
2842         }
2843 
2844         (void) fprintf(stderr,
2845             gettext("could not verify %s %s=%s %s=%s\n\t%s\n"),
2846             "net", "address", addr, "physical", phys, msg);
2847 }
2848 
2849 static int
2850 verify_handle(int cmd_num, zone_dochandle_t handle, char *argv[])
2851 {
2852         struct zone_nwiftab nwiftab;
2853         int return_code = Z_OK;
2854         int err;
2855         boolean_t in_alt_root;
2856         zone_iptype_t iptype;
2857         dlpi_handle_t dh;
2858 
2859         in_alt_root = zonecfg_in_alt_root();
2860         if (in_alt_root)
2861                 goto no_net;
2862 
2863         if ((err = zonecfg_get_iptype(handle, &iptype)) != Z_OK) {
2864                 errno = err;
2865                 zperror(cmd_to_str(cmd_num), B_TRUE);
2866                 zonecfg_fini_handle(handle);
2867                 return (Z_ERR);
2868         }
2869         if ((err = zonecfg_setnwifent(handle)) != Z_OK) {
2870                 errno = err;
2871                 zperror(cmd_to_str(cmd_num), B_TRUE);
2872                 zonecfg_fini_handle(handle);
2873                 return (Z_ERR);
2874         }
2875         while (zonecfg_getnwifent(handle, &nwiftab) == Z_OK) {
2876                 struct lifreq lifr;
2877                 sa_family_t af = AF_UNSPEC;
2878                 char dl_owner_zname[ZONENAME_MAX];
2879                 zoneid_t dl_owner_zid;
2880                 zoneid_t target_zid;
2881                 int res;
2882 
2883                 /* skip any loopback interfaces */
2884                 if (strcmp(nwiftab.zone_nwif_physical, "lo0") == 0)
2885                         continue;
2886                 switch (iptype) {
2887                 case ZS_SHARED:
2888                         if ((res = zonecfg_valid_net_address(
2889                             nwiftab.zone_nwif_address, &lifr)) != Z_OK) {
2890                                 print_net_err(nwiftab.zone_nwif_physical,
2891                                     nwiftab.zone_nwif_address, af,
2892                                     zonecfg_strerror(res));
2893                                 return_code = Z_ERR;
2894                                 continue;
2895                         }
2896                         af = lifr.lifr_addr.ss_family;
2897                         if (!zonecfg_ifname_exists(af,
2898                             nwiftab.zone_nwif_physical)) {
2899                                 /*
2900                                  * The interface failed to come up. We continue
2901                                  * on anyway for the sake of consistency: a
2902                                  * zone is not shut down if the interface fails
2903                                  * any time after boot, nor does the global zone
2904                                  * fail to boot if an interface fails.
2905                                  */
2906                                 (void) fprintf(stderr,
2907                                     gettext("WARNING: skipping network "
2908                                     "interface '%s' which may not be "
2909                                     "present/plumbed in the global "
2910                                     "zone.\n"),
2911                                     nwiftab.zone_nwif_physical);
2912                         }
2913                         break;
2914                 case ZS_EXCLUSIVE:
2915                         /* Warning if it exists for either IPv4 or IPv6 */
2916 
2917                         if (zonecfg_ifname_exists(AF_INET,
2918                             nwiftab.zone_nwif_physical) ||
2919                             zonecfg_ifname_exists(AF_INET6,
2920                             nwiftab.zone_nwif_physical)) {
2921                                 (void) fprintf(stderr,
2922                                     gettext("WARNING: skipping network "
2923                                     "interface '%s' which is used in the "
2924                                     "global zone.\n"),
2925                                     nwiftab.zone_nwif_physical);
2926                                 break;
2927                         }
2928 
2929                         /*
2930                          * Verify that the physical interface can be opened.
2931                          */
2932                         err = dlpi_open(nwiftab.zone_nwif_physical, &dh, 0);
2933                         if (err != DLPI_SUCCESS) {
2934                                 (void) fprintf(stderr,
2935                                     gettext("WARNING: skipping network "
2936                                     "interface '%s' which cannot be opened: "
2937                                     "dlpi error (%s).\n"),
2938                                     nwiftab.zone_nwif_physical,
2939                                     dlpi_strerror(err));
2940                                 break;
2941                         } else {
2942                                 dlpi_close(dh);
2943                         }
2944                         /*
2945                          * Verify whether the physical interface is already
2946                          * used by a zone.
2947                          */
2948                         dl_owner_zid = ALL_ZONES;
2949                         if (zone_check_datalink(&dl_owner_zid,
2950                             nwiftab.zone_nwif_physical) != 0)
2951                                 break;
2952 
2953                         /*
2954                          * If the zone being verified is
2955                          * running and owns the interface
2956                          */
2957                         target_zid = getzoneidbyname(target_zone);
2958                         if (target_zid == dl_owner_zid)
2959                                 break;
2960 
2961                         /* Zone id match failed, use name to check */
2962                         if (getzonenamebyid(dl_owner_zid, dl_owner_zname,
2963                             ZONENAME_MAX) < 0) {
2964                                 /* No name, show ID instead */
2965                                 (void) snprintf(dl_owner_zname, ZONENAME_MAX,
2966                                     "<%d>", dl_owner_zid);
2967                         } else if (strcmp(dl_owner_zname, target_zone) == 0)
2968                                 break;
2969 
2970                         /*
2971                          * Note here we only report a warning that
2972                          * the interface is already in use by another
2973                          * running zone, and the verify process just
2974