Print this page
OS-5330 zoneadm mounting an lx or joyent branded zone fails
Reviewed by: Jerry Jelinek <jerry.jelinek@joyent.com>
Approved by: Jerry Jelinek <jerry.jelinek@joyent.com>
(NOTE: Manual port, because of divergence from SmartOS.)
OS-3831 lxbrand /proc/cmdline should reflect zone boot arguments
Reviewed by: Jerry Jelinek <jerry.jelinek@joyent.com>
Reviewed by: Patrick Mooney <patrick.mooney@joyent.com>
Approved by: Jerry Jelinek <jerry.jelinek@joyent.com>
Remove most KEBE comments and accompanying unused code or variables/fields.
Merge cleanup from previous six commits
OS-200 need a better mechanism for storing persistent zone_did
OS-2564 zone boot failed: could not start zoneadmd
OS-1763 mount of /etc/svc/volatile failed: Device busy
OS-511 make zonecfg device resource extensible, like the net resource
OS-224 add more zonecfg net properties
Reduce lint
Add zfd.c to zoneadmd's Makefile, a bit more not-yet ifdef-out.
zoneadmd mismerge (we don't support debug yet)
OS-4932 zoneadm boot args not passed to lx init
Reviewed by: Patrick Mooney <patrick.mooney@joyent.com>
OS-4781 would like to be able to add CT_PR_EV_EXIT to fatal event set of current contract
OS-4253 lxbrand ubuntu 15.04 won't boot because /sbin/init is a symlink
OS-3524 in order to support interaction with docker containers, need to be able to connect to stdio for init from GZ
OS-3525 in order to support 'docker logs' need to be able to get stdio from zone to log file
OS-3429 Expose zone's init exit status
OS-3342 dlmgmtd needs to be mindful of lock ordering
OS-2608 dlmgmtd needs to record zone identifiers
OS-3492 zone_free asserts to its destruction when dlmgmtd has fallen
OS-3494 zoneadmd tears down networking too soon when boot fails
Reviewed by: Jerry Jelinek <jerry.jelinek@joyent.com>
OS-3077 restarted zoneadmd uses invalid zlogp
OS-3075 zone long boot args aren't passed through
OS-11 rcapd behaves poorly when under extreme load

Split Close
Expand all
Collapse all
          --- old/usr/src/cmd/zoneadmd/zoneadmd.c
          +++ new/usr/src/cmd/zoneadmd/zoneadmd.c
↓ open down ↓ 14 lines elided ↑ open up ↑
  15   15   * If applicable, add the following below this CDDL HEADER, with the
  16   16   * fields enclosed by brackets "[]" replaced with your own identifying
  17   17   * information: Portions Copyright [yyyy] [name of copyright owner]
  18   18   *
  19   19   * CDDL HEADER END
  20   20   */
  21   21  
  22   22  /*
  23   23   * Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved.
  24   24   * Copyright 2014 Nexenta Systems, Inc. All rights reserved.
       25 + * Copyright 2016 Joyent, Inc.
  25   26   */
  26   27  
  27   28  /*
  28   29   * zoneadmd manages zones; one zoneadmd process is launched for each
  29   30   * non-global zone on the system.  This daemon juggles four jobs:
  30   31   *
  31   32   * - Implement setup and teardown of the zone "virtual platform": mount and
  32   33   *   unmount filesystems; create and destroy network interfaces; communicate
  33   34   *   with devfsadmd to lay out devices for the zone; instantiate the zone
  34   35   *   console device; configure process runtime attributes such as resource
↓ open down ↓ 26 lines elided ↑ open up ↑
  61   62   *   the case that the administrator kills it off, or it suffers a fatal error,
  62   63   *   without the running zone being impacted; this is akin to being able to
  63   64   *   reboot the service processor of a server without affecting the OS instance.
  64   65   */
  65   66  
  66   67  #include <sys/param.h>
  67   68  #include <sys/mman.h>
  68   69  #include <sys/types.h>
  69   70  #include <sys/stat.h>
  70   71  #include <sys/sysmacros.h>
       72 +#include <sys/time.h>
  71   73  
  72   74  #include <bsm/adt.h>
  73   75  #include <bsm/adt_event.h>
  74   76  
  75   77  #include <alloca.h>
  76   78  #include <assert.h>
  77   79  #include <errno.h>
  78   80  #include <door.h>
  79   81  #include <fcntl.h>
  80   82  #include <locale.h>
↓ open down ↓ 20 lines elided ↑ open up ↑
 101  103  #include <libdladm.h>
 102  104  #include <sys/dls_mgmt.h>
 103  105  #include <libscf.h>
 104  106  
 105  107  #include <libzonecfg.h>
 106  108  #include <zonestat_impl.h>
 107  109  #include "zoneadmd.h"
 108  110  
 109  111  static char *progname;
 110  112  char *zone_name;        /* zone which we are managing */
      113 +zone_dochandle_t snap_hndl;     /* handle for snapshot created when ready */
      114 +char zonepath[MAXNAMELEN];
 111  115  char pool_name[MAXNAMELEN];
 112  116  char default_brand[MAXNAMELEN];
 113  117  char brand_name[MAXNAMELEN];
 114  118  boolean_t zone_isnative;
 115  119  boolean_t zone_iscluster;
 116  120  boolean_t zone_islabeled;
 117  121  boolean_t shutdown_in_progress;
 118  122  static zoneid_t zone_id;
 119  123  dladm_handle_t dld_handle = NULL;
 120  124  
↓ open down ↓ 13 lines elided ↑ open up ↑
 134  138  
 135  139  boolean_t in_death_throes = B_FALSE;    /* daemon is dying */
 136  140  boolean_t bringup_failure_recovery = B_FALSE; /* ignore certain failures */
 137  141  
 138  142  #if !defined(TEXT_DOMAIN)               /* should be defined by cc -D */
 139  143  #define TEXT_DOMAIN     "SYS_TEST"      /* Use this only if it wasn't */
 140  144  #endif
 141  145  
 142  146  #define DEFAULT_LOCALE  "C"
 143  147  
      148 +#define RSRC_NET        "net"
      149 +#define RSRC_DEV        "device"
      150 +
 144  151  static const char *
 145  152  z_cmd_name(zone_cmd_t zcmd)
 146  153  {
 147  154          /* This list needs to match the enum in sys/zone.h */
 148  155          static const char *zcmdstr[] = {
 149  156                  "ready", "boot", "forceboot", "reboot", "halt",
 150  157                  "note_uninstalling", "mount", "forcemount", "unmount",
 151  158                  "shutdown"
 152  159          };
 153  160  
↓ open down ↓ 96 lines elided ↑ open up ↑
 250  257                  size_t copylen;
 251  258  
 252  259                  buflen = snprintf(zlogp->log, zlogp->loglen, "%s\n", buf);
 253  260                  copylen = MIN(buflen, zlogp->loglen);
 254  261                  zlogp->log += copylen;
 255  262                  zlogp->loglen -= copylen;
 256  263          }
 257  264  }
 258  265  
 259  266  /*
 260      - * Emit a warning for any boot arguments which are unrecognized.  Since
 261      - * Solaris boot arguments are getopt(3c) compatible (see kernel(1m)), we
      267 + * Append src to dest, modifying dest in the process. Prefix src with
      268 + * a space character if dest is a non-empty string.
      269 + */
      270 +static void
      271 +strnappend(char *dest, size_t n, const char *src)
      272 +{
      273 +        (void) snprintf(dest, n, "%s%s%s", dest,
      274 +            dest[0] == '\0' ? "" : " ", src);
      275 +}
      276 +
      277 +/*
      278 + * Since illumos boot arguments are getopt(3c) compatible (see kernel(1m)), we
 262  279   * put the arguments into an argv style array, use getopt to process them,
 263      - * and put the resultant argument string back into outargs.
      280 + * and put the resultant argument string back into outargs. Non-native brands
      281 + * may support alternate forms of boot arguments so we must handle that as well.
 264  282   *
 265  283   * During the filtering, we pull out any arguments which are truly "boot"
 266  284   * arguments, leaving only those which are to be passed intact to the
 267  285   * progenitor process.  The one we support at the moment is -i, which
 268  286   * indicates to the kernel which program should be launched as 'init'.
 269  287   *
 270      - * A return of Z_INVAL indicates specifically that the arguments are
 271      - * not valid; this is a non-fatal error.  Except for Z_OK, all other return
 272      - * values are treated as fatal.
      288 + * Except for Z_OK, all other return values are treated as fatal.
 273  289   */
 274  290  static int
 275  291  filter_bootargs(zlog_t *zlogp, const char *inargs, char *outargs,
 276      -    char *init_file, char *badarg)
      292 +    char *init_file)
 277  293  {
 278  294          int argc = 0, argc_save;
 279  295          int i;
 280  296          int err;
 281  297          char *arg, *lasts, **argv = NULL, **argv_save;
 282  298          char zonecfg_args[BOOTARGS_MAX];
 283  299          char scratchargs[BOOTARGS_MAX], *sargs;
      300 +        char scratchopt[3];
 284  301          char c;
 285  302  
 286  303          bzero(outargs, BOOTARGS_MAX);
 287      -        bzero(badarg, BOOTARGS_MAX);
 288  304  
 289  305          /*
 290  306           * If the user didn't specify transient boot arguments, check
 291  307           * to see if there were any specified in the zone configuration,
 292  308           * and use them if applicable.
 293  309           */
 294  310          if (inargs == NULL || inargs[0] == '\0')  {
 295  311                  zone_dochandle_t handle;
 296  312                  if ((handle = zonecfg_init_handle()) == NULL) {
 297  313                          zerror(zlogp, B_TRUE,
↓ open down ↓ 42 lines elided ↑ open up ↑
 340  356                  sargs = NULL;
 341  357                  if ((argv[i] = strdup(arg)) == NULL) {
 342  358                          err = Z_NOMEM;
 343  359                          zerror(zlogp, B_FALSE, "memory allocation failed");
 344  360                          goto done;
 345  361                  }
 346  362                  i++;
 347  363          }
 348  364  
 349  365          /*
 350      -         * We preserve compatibility with the Solaris system boot behavior,
      366 +         * We preserve compatibility with the illumos system boot behavior,
 351  367           * which allows:
 352  368           *
 353  369           *      # reboot kernel/unix -s -m verbose
 354  370           *
 355      -         * In this example, kernel/unix tells the booter what file to
 356      -         * boot.  We don't want reboot in a zone to be gratuitously different,
 357      -         * so we silently ignore the boot file, if necessary.
      371 +         * In this example, kernel/unix tells the booter what file to boot. The
      372 +         * original intent of this was that we didn't want reboot in a zone to
      373 +         * be gratuitously different, so we would silently ignore the boot
      374 +         * file, if necessary. However, this usage is archaic and has never
      375 +         * been common, since it is impossible to boot a zone onto a different
      376 +         * kernel. Ignoring the first argument breaks for non-native brands
      377 +         * which pass boot arguments in a different style. e.g.
      378 +         *      systemd.log_level=debug
      379 +         * Thus, for backward compatibility we only ignore the first argument
      380 +         * if it appears to be in the illumos form and attempting to specify a
      381 +         * kernel.
 358  382           */
 359  383          if (argv[0] == NULL)
 360  384                  goto done;
 361  385  
 362  386          assert(argv[0][0] != ' ');
 363  387          assert(argv[0][0] != '\t');
 364  388  
 365      -        if (argv[0][0] != '-' && argv[0][0] != '\0') {
      389 +        if (strncmp(argv[0], "kernel/", 7) == 0) {
 366  390                  argv = &argv[1];
 367  391                  argc--;
 368  392          }
 369  393  
 370  394          optind = 0;
 371  395          opterr = 0;
 372  396          err = Z_OK;
 373  397          while ((c = getopt(argc, argv, "fi:m:s")) != -1) {
 374  398                  switch (c) {
 375  399                  case 'i':
↓ open down ↓ 2 lines elided ↑ open up ↑
 378  402                           * along to userland
 379  403                           */
 380  404                          (void) strlcpy(init_file, optarg, MAXPATHLEN);
 381  405                          break;
 382  406                  case 'f':
 383  407                          /* This has already been processed by zoneadm */
 384  408                          break;
 385  409                  case 'm':
 386  410                  case 's':
 387  411                          /* These pass through unmolested */
 388      -                        (void) snprintf(outargs, BOOTARGS_MAX,
 389      -                            "%s -%c %s ", outargs, c, optarg ? optarg : "");
      412 +                        (void) snprintf(scratchopt, sizeof (scratchopt),
      413 +                            "-%c", c);
      414 +                        strnappend(outargs, BOOTARGS_MAX, scratchopt);
      415 +                        if (optarg != NULL)
      416 +                                strnappend(outargs, BOOTARGS_MAX, optarg);
 390  417                          break;
 391  418                  case '?':
 392  419                          /*
 393      -                         * We warn about unknown arguments but pass them
 394      -                         * along anyway-- if someone wants to develop their
 395      -                         * own init replacement, they can pass it whatever
 396      -                         * args they want.
      420 +                         * If a brand has its own init, we need to pass along
      421 +                         * whatever the user provides. We use the entire
      422 +                         * unknown string here so that we correctly handle
      423 +                         * unknown long options (e.g. --debug).
 397  424                           */
 398      -                        err = Z_INVAL;
 399      -                        (void) snprintf(outargs, BOOTARGS_MAX,
 400      -                            "%s -%c", outargs, optopt);
 401      -                        (void) snprintf(badarg, BOOTARGS_MAX,
 402      -                            "%s -%c", badarg, optopt);
      425 +                        strnappend(outargs, BOOTARGS_MAX, argv[optind - 1]);
 403  426                          break;
 404  427                  }
 405  428          }
 406  429  
 407  430          /*
 408      -         * For Solaris Zones we warn about and discard non-option arguments.
 409      -         * Hence 'boot foo bar baz gub' --> 'boot'.  However, to be similar
 410      -         * to the kernel, we concat up all the other remaining boot args.
 411      -         * and warn on them as a group.
      431 +         * We need to pass along everything else since we don't know what
      432 +         * the brand's init is expecting. For example, an argument list like:
      433 +         *   --confdir /foo --debug
      434 +         * will cause the getopt parsing to stop at '/foo' but we need to pass
      435 +         * that on, along with the '--debug'. This does mean that we require
      436 +         * any of our known options (-ifms) to preceed the brand-specific ones.
 412  437           */
 413      -        if (optind < argc) {
 414      -                err = Z_INVAL;
 415      -                while (optind < argc) {
 416      -                        (void) snprintf(badarg, BOOTARGS_MAX, "%s%s%s",
 417      -                            badarg, strlen(badarg) > 0 ? " " : "",
 418      -                            argv[optind]);
 419      -                        optind++;
 420      -                }
 421      -                zerror(zlogp, B_FALSE, "WARNING: Unused or invalid boot "
 422      -                    "arguments `%s'.", badarg);
      438 +        while (optind < argc) {
      439 +                strnappend(outargs, BOOTARGS_MAX, argv[optind]);
      440 +                optind++;
 423  441          }
 424  442  
 425  443  done:
 426  444          for (i = 0; i < argc_save; i++) {
 427  445                  if (argv_save[i] != NULL)
 428  446                          free(argv_save[i]);
 429  447          }
 430  448          free(argv_save);
 431  449          return (err);
 432  450  }
↓ open down ↓ 97 lines elided ↑ open up ↑
 530  548  /*
 531  549   * Bring a zone up to the pre-boot "ready" stage.  The mount_cmd argument is
 532  550   * 'true' if this is being invoked as part of the processing for the "mount"
 533  551   * subcommand.
 534  552   */
 535  553  static int
 536  554  zone_ready(zlog_t *zlogp, zone_mnt_t mount_cmd, int zstate)
 537  555  {
 538  556          int err;
 539  557  
 540      -        if (brand_prestatechg(zlogp, zstate, Z_READY) != 0)
      558 +        if (!ALT_MOUNT(mount_cmd) &&
      559 +            brand_prestatechg(zlogp, zstate, Z_READY) != 0)
 541  560                  return (-1);
 542  561  
 543  562          if ((err = zonecfg_create_snapshot(zone_name)) != Z_OK) {
 544  563                  zerror(zlogp, B_FALSE, "unable to create snapshot: %s",
 545  564                      zonecfg_strerror(err));
 546  565                  goto bad;
 547  566          }
 548  567  
 549  568          if ((zone_id = vplat_create(zlogp, mount_cmd)) == -1) {
 550  569                  if ((err = zonecfg_destroy_snapshot(zone_name)) != Z_OK)
↓ open down ↓ 3 lines elided ↑ open up ↑
 554  573          }
 555  574          if (vplat_bringup(zlogp, mount_cmd, zone_id) != 0) {
 556  575                  bringup_failure_recovery = B_TRUE;
 557  576                  (void) vplat_teardown(NULL, (mount_cmd != Z_MNT_BOOT), B_FALSE);
 558  577                  if ((err = zonecfg_destroy_snapshot(zone_name)) != Z_OK)
 559  578                          zerror(zlogp, B_FALSE, "destroying snapshot: %s",
 560  579                              zonecfg_strerror(err));
 561  580                  goto bad;
 562  581          }
 563  582  
 564      -        if (brand_poststatechg(zlogp, zstate, Z_READY) != 0)
      583 +        if (!ALT_MOUNT(mount_cmd) &&
      584 +            brand_poststatechg(zlogp, zstate, Z_READY) != 0)
 565  585                  goto bad;
 566  586  
 567  587          return (0);
 568  588  
 569  589  bad:
 570  590          /*
 571  591           * If something goes wrong, we up the zones's state to the target
 572  592           * state, READY, and then invoke the hook as if we're halting.
 573  593           */
 574      -        (void) brand_poststatechg(zlogp, ZONE_STATE_READY, Z_HALT);
      594 +        if (!ALT_MOUNT(mount_cmd))
      595 +                (void) brand_poststatechg(zlogp, ZONE_STATE_READY, Z_HALT);
 575  596          return (-1);
 576  597  }
 577  598  
 578  599  int
 579  600  init_template(void)
 580  601  {
 581  602          int fd;
 582  603          int err = 0;
 583  604  
 584  605          fd = open64(CTFS_ROOT "/process/template", O_RDWR);
↓ open down ↓ 31 lines elided ↑ open up ↑
 616  637          boolean_t mount_cmd = ((fs_callback_t *)data)->mount_cmd;
 617  638          char rootpath[MAXPATHLEN];
 618  639          pid_t child;
 619  640          int child_status;
 620  641          int tmpl_fd;
 621  642          int rv;
 622  643          ctid_t ct;
 623  644  
 624  645          /* determine the zone rootpath */
 625  646          if (mount_cmd) {
 626      -                char zonepath[MAXPATHLEN];
 627  647                  char luroot[MAXPATHLEN];
 628  648  
 629      -                if (zone_get_zonepath(zone_name,
 630      -                    zonepath, sizeof (zonepath)) != Z_OK) {
 631      -                        zerror(zlogp, B_FALSE, "unable to determine zone path");
 632      -                        return (-1);
 633      -                }
 634      -
 635  649                  (void) snprintf(luroot, sizeof (luroot), "%s/lu", zonepath);
 636  650                  resolve_lofs(zlogp, luroot, sizeof (luroot));
 637  651                  (void) strlcpy(rootpath, luroot, sizeof (rootpath));
 638  652          } else {
 639  653                  if (zone_get_rootpath(zone_name,
 640  654                      rootpath, sizeof (rootpath)) != Z_OK) {
 641  655                          zerror(zlogp, B_FALSE, "unable to determine zone root");
 642  656                          return (-1);
 643  657                  }
 644  658          }
↓ open down ↓ 34 lines elided ↑ open up ↑
 679  693          if ((child = fork()) == -1) {
 680  694                  (void) ct_tmpl_clear(tmpl_fd);
 681  695                  (void) close(tmpl_fd);
 682  696                  zerror(zlogp, B_TRUE, "failed to fork");
 683  697                  return (-1);
 684  698  
 685  699          } else if (child == 0) {        /* child */
 686  700                  char opt_buf[MAX_MNTOPT_STR];
 687  701                  int optlen = 0;
 688  702                  int mflag = MS_DATA;
      703 +                int i;
      704 +                int ret;
 689  705  
 690  706                  (void) ct_tmpl_clear(tmpl_fd);
 691  707                  /*
 692  708                   * Even though there are no procs running in the zone, we
 693  709                   * do this for paranoia's sake.
 694  710                   */
 695  711                  (void) closefrom(0);
 696  712  
 697  713                  if (zone_enter(zoneid) == -1) {
 698  714                          _exit(errno);
↓ open down ↓ 7 lines elided ↑ open up ↑
 706  722                           * also fail if the new option string it wants to
 707  723                           * write is bigger than the one we passed in, so
 708  724                           * you must pass in a buffer of the maximum possible
 709  725                           * option string length.  sigh.
 710  726                           */
 711  727                          (void) strlcpy(opt_buf, opt, sizeof (opt_buf));
 712  728                          opt = opt_buf;
 713  729                          optlen = MAX_MNTOPT_STR;
 714  730                          mflag = MS_OPTIONSTR;
 715  731                  }
 716      -                if (mount(spec, dir, mflag, fstype, NULL, 0, opt, optlen) != 0)
 717      -                        _exit(errno);
 718      -                _exit(0);
      732 +
      733 +                /*
      734 +                 * There is an obscure race condition which can cause mount
      735 +                 * to return EBUSY. This happens for example on the mount
      736 +                 * of the zone's /etc/svc/volatile file system if there is
      737 +                 * a GZ process running svcs -Z, which will touch the
      738 +                 * mountpoint, just as we're trying to do the mount. To cope
      739 +                 * with this, we retry up to 3 times to let this transient
      740 +                 * process get out of the way.
      741 +                 */
      742 +                for (i = 0; i < 3; i++) {
      743 +                        ret = 0;
      744 +                        if (mount(spec, dir, mflag, fstype, NULL, 0, opt,
      745 +                            optlen) != 0)
      746 +                                ret = errno;
      747 +                        if (ret != EBUSY)
      748 +                                break;
      749 +                        (void) sleep(1);
      750 +                }
      751 +                _exit(ret);
 719  752          }
 720  753  
 721  754          /* parent */
 722  755          if (contract_latest(&ct) == -1)
 723  756                  ct = -1;
 724  757          (void) ct_tmpl_clear(tmpl_fd);
 725  758          (void) close(tmpl_fd);
 726  759          if (waitpid(child, &child_status, 0) != child) {
 727  760                  /* unexpected: we must have been signalled */
 728  761                  (void) contract_abandon_id(ct);
↓ open down ↓ 3 lines elided ↑ open up ↑
 732  765          if (WEXITSTATUS(child_status) != 0) {
 733  766                  errno = WEXITSTATUS(child_status);
 734  767                  zerror(zlogp, B_TRUE, "mount of %s failed", dir);
 735  768                  return (-1);
 736  769          }
 737  770  
 738  771          return (0);
 739  772  }
 740  773  
 741  774  /*
      775 + * env variable name format
      776 + *      _ZONECFG;{resource name};{identifying attr. name};{property name}
      777 + */
      778 +static void
      779 +set_zonecfg_env(char *rsrc, char *attr, char *name, char *val)
      780 +{
      781 +        char *p;
      782 +        /* Enough for maximal name, rsrc + attr, & slop for ZONECFG & _'s */
      783 +        char nm[2 * MAXNAMELEN + 32];
      784 +
      785 +        if (attr == NULL)
      786 +                (void) snprintf(nm, sizeof (nm), "_ZONECFG_%s_%s", rsrc,
      787 +                    name);
      788 +        else
      789 +                (void) snprintf(nm, sizeof (nm), "_ZONECFG_%s_%s_%s", rsrc,
      790 +                    attr, name);
      791 +
      792 +        p = nm;
      793 +        while ((p = strchr(p, '-')) != NULL)
      794 +                *p++ = '_';
      795 +
      796 +        (void) setenv(nm, val, 1);
      797 +}
      798 +
      799 +/*
      800 + * Export zonecfg network and device properties into environment for the boot
      801 + * and state change hooks.
      802 + * If debug is true, export the brand hook debug env. variable as well.
      803 + *
      804 + * We could export more of the config in the future, as necessary.
      805 + */
      806 +static int
      807 +setup_subproc_env()
      808 +{
      809 +        int res;
      810 +        zone_dochandle_t handle;
      811 +        struct zone_nwiftab ntab;
      812 +        struct zone_devtab dtab;
      813 +        char net_resources[MAXNAMELEN * 2];
      814 +        char dev_resources[MAXNAMELEN * 2];
      815 +
      816 +        if ((handle = zonecfg_init_handle()) == NULL)
      817 +                exit(Z_NOMEM);
      818 +
      819 +        if ((res = zonecfg_get_handle(zone_name, handle)) != Z_OK)
      820 +                goto done;
      821 +
      822 +        if ((res = zonecfg_setnwifent(handle)) != Z_OK)
      823 +                goto done;
      824 +
      825 +        while (zonecfg_getnwifent(handle, &ntab) == Z_OK) {
      826 +                struct zone_res_attrtab *rap;
      827 +                char *phys;
      828 +
      829 +                phys = ntab.zone_nwif_physical;
      830 +
      831 +                (void) strlcat(net_resources, phys, sizeof (net_resources));
      832 +                (void) strlcat(net_resources, " ", sizeof (net_resources));
      833 +
      834 +                set_zonecfg_env(RSRC_NET, phys, "physical", phys);
      835 +
      836 +                set_zonecfg_env(RSRC_NET, phys, "address",
      837 +                    ntab.zone_nwif_address);
      838 +                set_zonecfg_env(RSRC_NET, phys, "allowed-address",
      839 +                    ntab.zone_nwif_allowed_address);
      840 +                set_zonecfg_env(RSRC_NET, phys, "defrouter",
      841 +                    ntab.zone_nwif_defrouter);
      842 +                set_zonecfg_env(RSRC_NET, phys, "global-nic",
      843 +                    ntab.zone_nwif_gnic);
      844 +                set_zonecfg_env(RSRC_NET, phys, "mac-addr", ntab.zone_nwif_mac);
      845 +                set_zonecfg_env(RSRC_NET, phys, "vlan-id",
      846 +                    ntab.zone_nwif_vlan_id);
      847 +
      848 +                for (rap = ntab.zone_nwif_attrp; rap != NULL;
      849 +                    rap = rap->zone_res_attr_next)
      850 +                        set_zonecfg_env(RSRC_NET, phys, rap->zone_res_attr_name,
      851 +                            rap->zone_res_attr_value);
      852 +        }
      853 +
      854 +        (void) zonecfg_endnwifent(handle);
      855 +
      856 +        if ((res = zonecfg_setdevent(handle)) != Z_OK)
      857 +                goto done;
      858 +
      859 +        while (zonecfg_getdevent(handle, &dtab) == Z_OK) {
      860 +                struct zone_res_attrtab *rap;
      861 +                char *match;
      862 +
      863 +                match = dtab.zone_dev_match;
      864 +
      865 +                (void) strlcat(dev_resources, match, sizeof (dev_resources));
      866 +                (void) strlcat(dev_resources, " ", sizeof (dev_resources));
      867 +
      868 +                for (rap = dtab.zone_dev_attrp; rap != NULL;
      869 +                    rap = rap->zone_res_attr_next)
      870 +                        set_zonecfg_env(RSRC_DEV, match,
      871 +                            rap->zone_res_attr_name, rap->zone_res_attr_value);
      872 +        }
      873 +
      874 +        (void) zonecfg_enddevent(handle);
      875 +
      876 +        res = Z_OK;
      877 +
      878 +done:
      879 +        zonecfg_fini_handle(handle);
      880 +        return (res);
      881 +}
      882 +
      883 +/*
 742  884   * If retstr is not NULL, the output of the subproc is returned in the str,
 743  885   * otherwise it is output using zerror().  Any memory allocated for retstr
 744  886   * should be freed by the caller.
 745  887   */
 746  888  int
 747  889  do_subproc(zlog_t *zlogp, char *cmdbuf, char **retstr)
 748  890  {
 749  891          char buf[1024];         /* arbitrary large amount */
 750  892          char *inbuf;
 751  893          FILE *file;
↓ open down ↓ 4 lines elided ↑ open up ↑
 756  898                  if ((*retstr = malloc(1024)) == NULL) {
 757  899                          zerror(zlogp, B_FALSE, "out of memory");
 758  900                          return (-1);
 759  901                  }
 760  902                  inbuf = *retstr;
 761  903                  rd_cnt = 0;
 762  904          } else {
 763  905                  inbuf = buf;
 764  906          }
 765  907  
      908 +        if (setup_subproc_env() != Z_OK) {
      909 +                zerror(zlogp, B_FALSE, "failed to setup environment");
      910 +                return (-1);
      911 +        }
      912 +
 766  913          file = popen(cmdbuf, "r");
 767  914          if (file == NULL) {
 768  915                  zerror(zlogp, B_TRUE, "could not launch: %s", cmdbuf);
 769  916                  return (-1);
 770  917          }
 771  918  
 772  919          while (fgets(inbuf, 1024, file) != NULL) {
 773  920                  if (retstr == NULL) {
 774  921                          if (zlogp != &logsys)
 775  922                                  zerror(zlogp, B_FALSE, "%s", inbuf);
↓ open down ↓ 19 lines elided ↑ open up ↑
 795  942                  return (-1);
 796  943          }
 797  944          assert(WIFEXITED(status));
 798  945          if (WEXITSTATUS(status) == ZEXIT_EXEC) {
 799  946                  zerror(zlogp, B_FALSE, "failed to exec %s", cmdbuf);
 800  947                  return (-1);
 801  948          }
 802  949          return (WEXITSTATUS(status));
 803  950  }
 804  951  
      952 +/*
      953 + * Get the app-svc-dependent flag for this zone's init process. This is a
      954 + * zone-specific attr which controls the type of contract we create for the
      955 + * zone's init. When true, the contract will include CT_PR_EV_EXIT in the fatal
      956 + * set, so that when any service which is in the same contract exits, the init
      957 + * application will be terminated.
      958 + *
      959 + * We use the global "snap_hndl", so no parameters get passed here.
      960 + */
      961 +static boolean_t
      962 +is_app_svc_dep(void)
      963 +{
      964 +        struct zone_attrtab a;
      965 +
      966 +        bzero(&a, sizeof (a));
      967 +        (void) strlcpy(a.zone_attr_name, "app-svc-dependent",
      968 +            sizeof (a.zone_attr_name));
      969 +
      970 +        if (zonecfg_lookup_attr(snap_hndl, &a) == Z_OK &&
      971 +            strcmp(a.zone_attr_value, "true") == 0) {
      972 +                return (B_TRUE);
      973 +        }
      974 +
      975 +        return (B_FALSE);
      976 +}
      977 +
 805  978  static int
 806  979  zone_bootup(zlog_t *zlogp, const char *bootargs, int zstate)
 807  980  {
 808  981          zoneid_t zoneid;
 809  982          struct stat st;
 810      -        char zpath[MAXPATHLEN], initpath[MAXPATHLEN], init_file[MAXPATHLEN];
      983 +        char rpath[MAXPATHLEN], initpath[MAXPATHLEN], init_file[MAXPATHLEN];
 811  984          char nbootargs[BOOTARGS_MAX];
 812  985          char cmdbuf[MAXPATHLEN];
 813  986          fs_callback_t cb;
 814  987          brand_handle_t bh;
 815  988          zone_iptype_t iptype;
 816      -        boolean_t links_loaded = B_FALSE;
 817  989          dladm_status_t status;
 818  990          char errmsg[DLADM_STRSIZE];
 819  991          int err;
 820  992          boolean_t restart_init;
      993 +        boolean_t app_svc_dep;
 821  994  
 822  995          if (brand_prestatechg(zlogp, zstate, Z_BOOT) != 0)
 823  996                  return (-1);
 824  997  
 825  998          if ((zoneid = getzoneidbyname(zone_name)) == -1) {
 826  999                  zerror(zlogp, B_TRUE, "unable to get zoneid");
 827 1000                  goto bad;
 828 1001          }
 829 1002  
 830 1003          cb.zlogp = zlogp;
↓ open down ↓ 14 lines elided ↑ open up ↑
 845 1018           */
 846 1019          if (brand_platform_iter_mounts(bh, mount_early_fs, &cb) != 0) {
 847 1020                  zerror(zlogp, B_FALSE, "unable to mount filesystems");
 848 1021                  brand_close(bh);
 849 1022                  goto bad;
 850 1023          }
 851 1024  
 852 1025          /*
 853 1026           * Get the brand's boot callback if it exists.
 854 1027           */
 855      -        if (zone_get_zonepath(zone_name, zpath, sizeof (zpath)) != Z_OK) {
 856      -                zerror(zlogp, B_FALSE, "unable to determine zone path");
 857      -                brand_close(bh);
 858      -                goto bad;
 859      -        }
 860 1028          (void) strcpy(cmdbuf, EXEC_PREFIX);
 861      -        if (brand_get_boot(bh, zone_name, zpath, cmdbuf + EXEC_LEN,
     1029 +        if (brand_get_boot(bh, zone_name, zonepath, cmdbuf + EXEC_LEN,
 862 1030              sizeof (cmdbuf) - EXEC_LEN) != 0) {
 863 1031                  zerror(zlogp, B_FALSE,
 864 1032                      "unable to determine branded zone's boot callback");
 865 1033                  brand_close(bh);
 866 1034                  goto bad;
 867 1035          }
 868 1036  
 869 1037          /* Get the path for this zone's init(1M) (or equivalent) process.  */
 870 1038          if (brand_get_initname(bh, init_file, MAXPATHLEN) != 0) {
 871 1039                  zerror(zlogp, B_FALSE,
 872 1040                      "unable to determine zone's init(1M) location");
 873 1041                  brand_close(bh);
 874 1042                  goto bad;
 875 1043          }
 876 1044  
 877 1045          /* See if this zone's brand should restart init if it dies. */
 878 1046          restart_init = brand_restartinit(bh);
 879 1047  
     1048 +        /*
     1049 +         * See if we need to setup contract dependencies between the zone's
     1050 +         * primary application and any of its services.
     1051 +         */
     1052 +        app_svc_dep = is_app_svc_dep();
     1053 +
 880 1054          brand_close(bh);
 881 1055  
 882      -        err = filter_bootargs(zlogp, bootargs, nbootargs, init_file,
 883      -            bad_boot_arg);
 884      -        if (err == Z_INVAL)
 885      -                eventstream_write(Z_EVT_ZONE_BADARGS);
 886      -        else if (err != Z_OK)
     1056 +        err = filter_bootargs(zlogp, bootargs, nbootargs, init_file);
     1057 +        if (err != Z_OK)
 887 1058                  goto bad;
 888 1059  
 889 1060          assert(init_file[0] != '\0');
 890 1061  
 891      -        /* Try to anticipate possible problems: Make sure init is executable. */
 892      -        if (zone_get_rootpath(zone_name, zpath, sizeof (zpath)) != Z_OK) {
     1062 +        /*
     1063 +         * Try to anticipate possible problems: If possible, make sure init is
     1064 +         * executable.
     1065 +         */
     1066 +        if (zone_get_rootpath(zone_name, rpath, sizeof (rpath)) != Z_OK) {
 893 1067                  zerror(zlogp, B_FALSE, "unable to determine zone root");
 894 1068                  goto bad;
 895 1069          }
 896 1070  
 897      -        (void) snprintf(initpath, sizeof (initpath), "%s%s", zpath, init_file);
     1071 +        (void) snprintf(initpath, sizeof (initpath), "%s%s", rpath, init_file);
 898 1072  
 899      -        if (stat(initpath, &st) == -1) {
     1073 +        if (lstat(initpath, &st) == -1) {
 900 1074                  zerror(zlogp, B_TRUE, "could not stat %s", initpath);
 901 1075                  goto bad;
 902 1076          }
 903 1077  
 904      -        if ((st.st_mode & S_IXUSR) == 0) {
     1078 +        /*
     1079 +         * If a symlink, we'll have to wait and resolve when we boot,
     1080 +         * otherwise check the executable bits now.
     1081 +         */
     1082 +        if ((st.st_mode & S_IFMT) != S_IFLNK && (st.st_mode & S_IXUSR) == 0) {
 905 1083                  zerror(zlogp, B_FALSE, "%s is not executable", initpath);
 906 1084                  goto bad;
 907 1085          }
 908 1086  
 909 1087          /*
 910 1088           * Exclusive stack zones interact with the dlmgmtd running in the
 911 1089           * global zone.  dladm_zone_boot() tells dlmgmtd that this zone is
 912 1090           * booting, and loads its datalinks from the zone's datalink
 913 1091           * configuration file.
 914 1092           */
 915 1093          if (vplat_get_iptype(zlogp, &iptype) == 0 && iptype == ZS_EXCLUSIVE) {
 916 1094                  status = dladm_zone_boot(dld_handle, zoneid);
 917 1095                  if (status != DLADM_STATUS_OK) {
 918 1096                          zerror(zlogp, B_FALSE, "unable to load zone datalinks: "
 919 1097                              " %s", dladm_status2str(status, errmsg));
 920 1098                          goto bad;
 921 1099                  }
 922      -                links_loaded = B_TRUE;
 923 1100          }
 924 1101  
 925 1102          /*
 926 1103           * If there is a brand 'boot' callback, execute it now to give the
 927 1104           * brand one last chance to do any additional setup before the zone
 928 1105           * is booted.
 929 1106           */
 930 1107          if ((strlen(cmdbuf) > EXEC_LEN) &&
 931 1108              (do_subproc(zlogp, cmdbuf, NULL) != Z_OK)) {
 932 1109                  zerror(zlogp, B_FALSE, "%s failed", cmdbuf);
↓ open down ↓ 9 lines elided ↑ open up ↑
 942 1119                  zerror(zlogp, B_TRUE, "could not set zone boot arguments");
 943 1120                  goto bad;
 944 1121          }
 945 1122  
 946 1123          if (!restart_init && zone_setattr(zoneid, ZONE_ATTR_INITNORESTART,
 947 1124              NULL, 0) == -1) {
 948 1125                  zerror(zlogp, B_TRUE, "could not set zone init-no-restart");
 949 1126                  goto bad;
 950 1127          }
 951 1128  
     1129 +        if (app_svc_dep && zone_setattr(zoneid, ZONE_ATTR_APP_SVC_CT,
     1130 +            (void *)B_TRUE, sizeof (boolean_t)) == -1) {
     1131 +                zerror(zlogp, B_TRUE, "could not set zone app-die");
     1132 +                goto bad;
     1133 +        }
     1134 +
 952 1135          /*
 953 1136           * Inform zonestatd of a new zone so that it can install a door for
 954 1137           * the zone to contact it.
 955 1138           */
 956 1139          notify_zonestatd(zone_id);
 957 1140  
 958 1141          if (zone_boot(zoneid) == -1) {
 959 1142                  zerror(zlogp, B_TRUE, "unable to boot zone");
 960 1143                  goto bad;
 961 1144          }
 962 1145  
 963 1146          if (brand_poststatechg(zlogp, zstate, Z_BOOT) != 0)
 964 1147                  goto bad;
 965 1148  
     1149 +        /* Startup a thread to perform zfd logging/tty svc for the zone. */
     1150 +        create_log_thread(zlogp, zone_id);
     1151 +
     1152 +        /* Startup a thread to perform memory capping for the zone. */
     1153 +        create_mcap_thread(zlogp, zone_id);
     1154 +
 966 1155          return (0);
 967 1156  
 968 1157  bad:
 969 1158          /*
 970 1159           * If something goes wrong, we up the zones's state to the target
 971 1160           * state, RUNNING, and then invoke the hook as if we're halting.
 972 1161           */
 973 1162          (void) brand_poststatechg(zlogp, ZONE_STATE_RUNNING, Z_HALT);
 974      -        if (links_loaded)
 975      -                (void) dladm_zone_halt(dld_handle, zoneid);
     1163 +
 976 1164          return (-1);
 977 1165  }
 978 1166  
 979 1167  static int
 980 1168  zone_halt(zlog_t *zlogp, boolean_t unmount_cmd, boolean_t rebooting, int zstate)
 981 1169  {
 982 1170          int err;
 983 1171  
 984      -        if (brand_prestatechg(zlogp, zstate, Z_HALT) != 0)
     1172 +        if (unmount_cmd == B_FALSE &&
     1173 +            brand_prestatechg(zlogp, zstate, Z_HALT) != 0)
 985 1174                  return (-1);
 986 1175  
     1176 +        /* Shutting down, stop the memcap thread */
     1177 +        destroy_mcap_thread();
     1178 +
 987 1179          if (vplat_teardown(zlogp, unmount_cmd, rebooting) != 0) {
 988 1180                  if (!bringup_failure_recovery)
 989 1181                          zerror(zlogp, B_FALSE, "unable to destroy zone");
     1182 +                destroy_log_thread();
 990 1183                  return (-1);
 991 1184          }
 992 1185  
     1186 +        /* Shut down is done, stop the log thread */
     1187 +        destroy_log_thread();
     1188 +
     1189 +        if (unmount_cmd == B_FALSE &&
     1190 +            brand_poststatechg(zlogp, zstate, Z_HALT) != 0)
     1191 +                return (-1);
     1192 +
 993 1193          if ((err = zonecfg_destroy_snapshot(zone_name)) != Z_OK)
 994 1194                  zerror(zlogp, B_FALSE, "destroying snapshot: %s",
 995 1195                      zonecfg_strerror(err));
 996 1196  
 997      -        if (brand_poststatechg(zlogp, zstate, Z_HALT) != 0)
 998      -                return (-1);
 999      -
1000 1197          return (0);
1001 1198  }
1002 1199  
1003 1200  static int
1004 1201  zone_graceful_shutdown(zlog_t *zlogp)
1005 1202  {
1006 1203          zoneid_t zoneid;
1007 1204          pid_t child;
1008 1205          char cmdbuf[MAXPATHLEN];
1009 1206          brand_handle_t bh = NULL;
1010      -        char zpath[MAXPATHLEN];
1011 1207          ctid_t ct;
1012 1208          int tmpl_fd;
1013 1209          int child_status;
1014 1210  
1015 1211          if (shutdown_in_progress) {
1016 1212                  zerror(zlogp, B_FALSE, "shutdown already in progress");
1017 1213                  return (-1);
1018 1214          }
1019 1215  
1020 1216          if ((zoneid = getzoneidbyname(zone_name)) == -1) {
1021 1217                  zerror(zlogp, B_TRUE, "unable to get zoneid");
1022 1218                  return (-1);
1023 1219          }
1024 1220  
1025 1221          /* Get a handle to the brand info for this zone */
1026 1222          if ((bh = brand_open(brand_name)) == NULL) {
1027 1223                  zerror(zlogp, B_FALSE, "unable to determine zone brand");
1028 1224                  return (-1);
1029 1225          }
1030 1226  
1031      -        if (zone_get_zonepath(zone_name, zpath, sizeof (zpath)) != Z_OK) {
1032      -                zerror(zlogp, B_FALSE, "unable to determine zone path");
1033      -                brand_close(bh);
1034      -                return (-1);
1035      -        }
1036      -
1037 1227          /*
1038 1228           * If there is a brand 'shutdown' callback, execute it now to give the
1039 1229           * brand a chance to cleanup any custom configuration.
1040 1230           */
1041 1231          (void) strcpy(cmdbuf, EXEC_PREFIX);
1042      -        if (brand_get_shutdown(bh, zone_name, zpath, cmdbuf + EXEC_LEN,
     1232 +        if (brand_get_shutdown(bh, zone_name, zonepath, cmdbuf + EXEC_LEN,
1043 1233              sizeof (cmdbuf) - EXEC_LEN) != 0 || strlen(cmdbuf) <= EXEC_LEN) {
1044 1234                  (void) strcat(cmdbuf, SHUTDOWN_DEFAULT);
1045 1235          }
1046 1236          brand_close(bh);
1047 1237  
1048 1238          if ((tmpl_fd = init_template()) == -1) {
1049 1239                  zerror(zlogp, B_TRUE, "failed to create contract");
1050 1240                  return (-1);
1051 1241          }
1052 1242  
↓ open down ↓ 117 lines elided ↑ open up ↑
1170 1360  
1171 1361          if (adt_put_event(event, pass_fail, fail_reason))
1172 1362                  zerror(zlogp, B_TRUE, gettext("audit failure."));
1173 1363  
1174 1364          adt_free_event(event);
1175 1365  
1176 1366          (void) adt_end_session(ah);
1177 1367  }
1178 1368  
1179 1369  /*
     1370 + * Log the exit time and status of the zone's init process into
     1371 + * {zonepath}/lastexited. If the zone shutdown normally, the exit status will
     1372 + * be -1, otherwise it will be the exit status as described in wait.3c.
     1373 + * If the zone is configured to restart init, then nothing will be logged if
     1374 + * init exits unexpectedly (the kernel will never upcall in this case).
     1375 + */
     1376 +static void
     1377 +log_init_exit(int status)
     1378 +{
     1379 +        char p[MAXPATHLEN];
     1380 +        char buf[128];
     1381 +        struct timeval t;
     1382 +        int fd;
     1383 +
     1384 +        if (snprintf(p, sizeof (p), "%s/lastexited", zonepath) > sizeof (p))
     1385 +                return;
     1386 +        if (gettimeofday(&t, NULL) != 0)
     1387 +                return;
     1388 +        if (snprintf(buf, sizeof (buf), "%ld.%ld %d\n", t.tv_sec, t.tv_usec,
     1389 +            status) > sizeof (buf))
     1390 +                return;
     1391 +        if ((fd = open(p, O_WRONLY | O_CREAT | O_TRUNC, 0644)) < 0)
     1392 +                return;
     1393 +
     1394 +        (void) write(fd, buf, strlen(buf));
     1395 +
     1396 +        (void) close(fd);
     1397 +}
     1398 +
     1399 +/*
1180 1400   * The main routine for the door server that deals with zone state transitions.
1181 1401   */
1182 1402  /* ARGSUSED */
1183 1403  static void
1184 1404  server(void *cookie, char *args, size_t alen, door_desc_t *dp,
1185 1405      uint_t n_desc)
1186 1406  {
1187 1407          ucred_t *uc = NULL;
1188 1408          const priv_set_t *eset;
1189 1409  
1190 1410          zone_state_t zstate;
1191 1411          zone_cmd_t cmd;
     1412 +        int init_status;
1192 1413          zone_cmd_arg_t *zargp;
1193 1414  
1194 1415          boolean_t kernelcall;
1195 1416  
1196 1417          int rval = -1;
1197 1418          uint64_t uniqid;
1198 1419          zoneid_t zoneid = -1;
1199 1420          zlog_t zlog;
1200 1421          zlog_t *zlogp;
1201 1422          zone_cmd_rval_t *rvalp;
↓ open down ↓ 32 lines elided ↑ open up ↑
1234 1455          if (alen != sizeof (zone_cmd_arg_t)) {
1235 1456                  /*
1236 1457                   * This really shouldn't be happening.
1237 1458                   */
1238 1459                  zerror(&logsys, B_FALSE, "argument size (%d bytes) "
1239 1460                      "unexpected (expected %d bytes)", alen,
1240 1461                      sizeof (zone_cmd_arg_t));
1241 1462                  goto out;
1242 1463          }
1243 1464          cmd = zargp->cmd;
     1465 +        init_status = zargp->status;
1244 1466  
1245 1467          if (door_ucred(&uc) != 0) {
1246 1468                  zerror(&logsys, B_TRUE, "door_ucred");
1247 1469                  goto out;
1248 1470          }
1249 1471          eset = ucred_getprivset(uc, PRIV_EFFECTIVE);
1250 1472          if (ucred_getzoneid(uc) != GLOBAL_ZONEID ||
1251 1473              (eset != NULL ? !priv_ismember(eset, PRIV_SYS_CONFIG) :
1252 1474              ucred_geteuid(uc) != 0)) {
1253 1475                  zerror(&logsys, B_FALSE, "insufficient privileges");
↓ open down ↓ 89 lines elided ↑ open up ↑
1343 1565                      "%s operation is invalid for zones in state '%s'",
1344 1566                      z_cmd_name(cmd), zone_state_str(zstate));
1345 1567                  break;
1346 1568  
1347 1569          case ZONE_STATE_INSTALLED:
1348 1570                  switch (cmd) {
1349 1571                  case Z_READY:
1350 1572                          rval = zone_ready(zlogp, Z_MNT_BOOT, zstate);
1351 1573                          if (rval == 0)
1352 1574                                  eventstream_write(Z_EVT_ZONE_READIED);
     1575 +                        zcons_statechanged();
1353 1576                          break;
1354 1577                  case Z_BOOT:
1355 1578                  case Z_FORCEBOOT:
1356 1579                          eventstream_write(Z_EVT_ZONE_BOOTING);
1357 1580                          if ((rval = zone_ready(zlogp, Z_MNT_BOOT, zstate))
1358 1581                              == 0) {
1359 1582                                  rval = zone_bootup(zlogp, zargp->bootbuf,
1360 1583                                      zstate);
1361 1584                          }
1362 1585                          audit_put_record(zlogp, uc, rval, "boot");
     1586 +                        zcons_statechanged();
1363 1587                          if (rval != 0) {
1364 1588                                  bringup_failure_recovery = B_TRUE;
1365 1589                                  (void) zone_halt(zlogp, B_FALSE, B_FALSE,
1366 1590                                      zstate);
1367 1591                                  eventstream_write(Z_EVT_ZONE_BOOTFAILED);
1368 1592                          }
1369 1593                          break;
1370 1594                  case Z_SHUTDOWN:
1371 1595                  case Z_HALT:
1372 1596                          if (kernelcall) /* Invalid; can't happen */
↓ open down ↓ 102 lines elided ↑ open up ↑
1475 1699                           */
1476 1700                          zerror(zlogp, B_FALSE, "zone is already ready");
1477 1701                          rval = 0;
1478 1702                          break;
1479 1703                  case Z_BOOT:
1480 1704                          (void) strlcpy(boot_args, zargp->bootbuf,
1481 1705                              sizeof (boot_args));
1482 1706                          eventstream_write(Z_EVT_ZONE_BOOTING);
1483 1707                          rval = zone_bootup(zlogp, zargp->bootbuf, zstate);
1484 1708                          audit_put_record(zlogp, uc, rval, "boot");
     1709 +                        zcons_statechanged();
1485 1710                          if (rval != 0) {
1486 1711                                  bringup_failure_recovery = B_TRUE;
1487 1712                                  (void) zone_halt(zlogp, B_FALSE, B_TRUE,
1488 1713                                      zstate);
1489 1714                                  eventstream_write(Z_EVT_ZONE_BOOTFAILED);
1490 1715                          }
1491 1716                          boot_args[0] = '\0';
1492 1717                          break;
1493 1718                  case Z_HALT:
1494 1719                          if (kernelcall) /* Invalid; can't happen */
1495 1720                                  abort();
1496 1721                          if ((rval = zone_halt(zlogp, B_FALSE, B_FALSE, zstate))
1497 1722                              != 0)
1498 1723                                  break;
     1724 +                        zcons_statechanged();
1499 1725                          eventstream_write(Z_EVT_ZONE_HALTED);
1500 1726                          break;
1501 1727                  case Z_SHUTDOWN:
1502 1728                  case Z_REBOOT:
1503 1729                  case Z_NOTE_UNINSTALLING:
1504 1730                  case Z_MOUNT:
1505 1731                  case Z_UNMOUNT:
1506 1732                          if (kernelcall) /* Invalid; can't happen */
1507 1733                                  abort();
1508 1734                          zerror(zlogp, B_FALSE, "%s operation is invalid "
↓ open down ↓ 27 lines elided ↑ open up ↑
1536 1762                  break;
1537 1763  
1538 1764          case ZONE_STATE_RUNNING:
1539 1765          case ZONE_STATE_SHUTTING_DOWN:
1540 1766          case ZONE_STATE_DOWN:
1541 1767                  switch (cmd) {
1542 1768                  case Z_READY:
1543 1769                          if ((rval = zone_halt(zlogp, B_FALSE, B_TRUE, zstate))
1544 1770                              != 0)
1545 1771                                  break;
     1772 +                        zcons_statechanged();
1546 1773                          if ((rval = zone_ready(zlogp, Z_MNT_BOOT, zstate)) == 0)
1547 1774                                  eventstream_write(Z_EVT_ZONE_READIED);
1548 1775                          else
1549 1776                                  eventstream_write(Z_EVT_ZONE_HALTED);
1550 1777                          break;
1551 1778                  case Z_BOOT:
1552 1779                          /*
1553 1780                           * We could have two clients racing to boot this
1554 1781                           * zone; the second client loses, but his request
1555 1782                           * doesn't fail, since the zone is now in the desired
1556 1783                           * state.
1557 1784                           */
1558 1785                          zerror(zlogp, B_FALSE, "zone is already booted");
1559 1786                          rval = 0;
1560 1787                          break;
1561 1788                  case Z_HALT:
     1789 +                        if (kernelcall) {
     1790 +                                log_init_exit(init_status);
     1791 +                        } else {
     1792 +                                log_init_exit(-1);
     1793 +                        }
1562 1794                          if ((rval = zone_halt(zlogp, B_FALSE, B_FALSE, zstate))
1563 1795                              != 0)
1564 1796                                  break;
1565 1797                          eventstream_write(Z_EVT_ZONE_HALTED);
     1798 +                        zcons_statechanged();
1566 1799                          break;
1567 1800                  case Z_REBOOT:
1568 1801                          (void) strlcpy(boot_args, zargp->bootbuf,
1569 1802                              sizeof (boot_args));
1570 1803                          eventstream_write(Z_EVT_ZONE_REBOOTING);
1571 1804                          if ((rval = zone_halt(zlogp, B_FALSE, B_TRUE, zstate))
1572 1805                              != 0) {
1573 1806                                  eventstream_write(Z_EVT_ZONE_BOOTFAILED);
1574 1807                                  boot_args[0] = '\0';
1575 1808                                  break;
1576 1809                          }
1577      -                        if ((rval = zone_ready(zlogp, Z_MNT_BOOT, zstate))
1578      -                            != 0) {
     1810 +                        zcons_statechanged();
     1811 +                        if ((rval = zone_ready(zlogp, Z_MNT_BOOT, zstate)) !=
     1812 +                            0) {
1579 1813                                  eventstream_write(Z_EVT_ZONE_BOOTFAILED);
1580 1814                                  boot_args[0] = '\0';
1581 1815                                  break;
1582 1816                          }
1583 1817                          rval = zone_bootup(zlogp, zargp->bootbuf, zstate);
1584 1818                          audit_put_record(zlogp, uc, rval, "reboot");
1585 1819                          if (rval != 0) {
1586 1820                                  (void) zone_halt(zlogp, B_FALSE, B_TRUE,
1587 1821                                      zstate);
1588 1822                                  eventstream_write(Z_EVT_ZONE_BOOTFAILED);
↓ open down ↓ 163 lines elided ↑ open up ↑
1752 1986                   *
1753 1987                   * Let user know that something is amiss, but that we can
1754 1988                   * recover; if the zone is in the installed state, then don't
1755 1989                   * message, since having a running zoneadmd isn't really
1756 1990                   * expected/needed.  We want to keep occurences of this message
1757 1991                   * limited to times when zoneadmd is picking back up from a
1758 1992                   * zoneadmd that died while the zone was in some non-trivial
1759 1993                   * state.
1760 1994                   */
1761 1995                  if (zstate > ZONE_STATE_INSTALLED) {
     1996 +                        static zoneid_t zid;
     1997 +
1762 1998                          zerror(zlogp, B_FALSE,
1763 1999                              "zone '%s': WARNING: zone is in state '%s', but "
1764 2000                              "zoneadmd does not appear to be available; "
1765 2001                              "restarted zoneadmd to recover.",
1766 2002                              zone_name, zone_state_str(zstate));
     2003 +
     2004 +                        /*
     2005 +                         * Startup a thread to perform the zfd logging/tty svc
     2006 +                         * and a thread to perform memory capping for the
     2007 +                         * zone. zlogp won't be valid for much longer so use
     2008 +                         * logsys.
     2009 +                         */
     2010 +                        if ((zid = getzoneidbyname(zone_name)) != -1) {
     2011 +                                create_log_thread(&logsys, zid);
     2012 +                                create_mcap_thread(&logsys, zid);
     2013 +                        }
     2014 +
     2015 +                        /* recover the global configuration snapshot */
     2016 +                        if (snap_hndl == NULL) {
     2017 +                                if ((snap_hndl = zonecfg_init_handle())
     2018 +                                    == NULL ||
     2019 +                                    zonecfg_create_snapshot(zone_name)
     2020 +                                    != Z_OK ||
     2021 +                                    zonecfg_get_snapshot_handle(zone_name,
     2022 +                                    snap_hndl) != Z_OK) {
     2023 +                                        zerror(zlogp, B_FALSE, "recovering "
     2024 +                                            "zone configuration handle");
     2025 +                                        goto out;
     2026 +                                }
     2027 +                        }
1767 2028                  }
1768 2029  
1769 2030                  (void) fdetach(zone_door_path);
1770 2031                  (void) close(doorfd);
1771 2032                  goto top;
1772 2033          }
1773 2034          ret = 0;
1774 2035  out:
1775 2036          (void) close(doorfd);
1776 2037          return (ret);
1777 2038  }
1778 2039  
1779 2040  /*
1780 2041   * Setup the brand's pre and post state change callbacks, as well as the
1781 2042   * query callback, if any of these exist.
1782 2043   */
1783 2044  static int
1784 2045  brand_callback_init(brand_handle_t bh, char *zone_name)
1785 2046  {
1786      -        char zpath[MAXPATHLEN];
1787      -
1788      -        if (zone_get_zonepath(zone_name, zpath, sizeof (zpath)) != Z_OK)
1789      -                return (-1);
1790      -
1791 2047          (void) strlcpy(pre_statechg_hook, EXEC_PREFIX,
1792 2048              sizeof (pre_statechg_hook));
1793 2049  
1794      -        if (brand_get_prestatechange(bh, zone_name, zpath,
     2050 +        if (brand_get_prestatechange(bh, zone_name, zonepath,
1795 2051              pre_statechg_hook + EXEC_LEN,
1796 2052              sizeof (pre_statechg_hook) - EXEC_LEN) != 0)
1797 2053                  return (-1);
1798 2054  
1799 2055          if (strlen(pre_statechg_hook) <= EXEC_LEN)
1800 2056                  pre_statechg_hook[0] = '\0';
1801 2057  
1802 2058          (void) strlcpy(post_statechg_hook, EXEC_PREFIX,
1803 2059              sizeof (post_statechg_hook));
1804 2060  
1805      -        if (brand_get_poststatechange(bh, zone_name, zpath,
     2061 +        if (brand_get_poststatechange(bh, zone_name, zonepath,
1806 2062              post_statechg_hook + EXEC_LEN,
1807 2063              sizeof (post_statechg_hook) - EXEC_LEN) != 0)
1808 2064                  return (-1);
1809 2065  
1810 2066          if (strlen(post_statechg_hook) <= EXEC_LEN)
1811 2067                  post_statechg_hook[0] = '\0';
1812 2068  
1813 2069          (void) strlcpy(query_hook, EXEC_PREFIX,
1814 2070              sizeof (query_hook));
1815 2071  
1816      -        if (brand_get_query(bh, zone_name, zpath, query_hook + EXEC_LEN,
     2072 +        if (brand_get_query(bh, zone_name, zonepath, query_hook + EXEC_LEN,
1817 2073              sizeof (query_hook) - EXEC_LEN) != 0)
1818 2074                  return (-1);
1819 2075  
1820 2076          if (strlen(query_hook) <= EXEC_LEN)
1821 2077                  query_hook[0] = '\0';
1822 2078  
1823 2079          return (0);
1824 2080  }
1825 2081  
1826 2082  int
↓ open down ↓ 107 lines elided ↑ open up ↑
1934 2190                      zonecfg_strerror(err));
1935 2191                  return (1);
1936 2192          }
1937 2193          if (zstate < ZONE_STATE_INCOMPLETE) {
1938 2194                  zerror(zlogp, B_FALSE,
1939 2195                      "cannot manage a zone which is in state '%s'",
1940 2196                      zone_state_str(zstate));
1941 2197                  return (1);
1942 2198          }
1943 2199  
     2200 +        if (zone_get_zonepath(zone_name, zonepath, sizeof (zonepath)) != Z_OK) {
     2201 +                zerror(zlogp, B_FALSE, "unable to determine zone path");
     2202 +                return (-1);
     2203 +        }
     2204 +
1944 2205          if (zonecfg_default_brand(default_brand,
1945 2206              sizeof (default_brand)) != Z_OK) {
1946 2207                  zerror(zlogp, B_FALSE, "unable to determine default brand");
1947 2208                  return (1);
1948 2209          }
1949 2210  
1950 2211          /* Get a handle to the brand info for this zone */
1951 2212          if (zone_get_brand(zone_name, brand_name, sizeof (brand_name))
1952 2213              != Z_OK) {
1953 2214                  zerror(zlogp, B_FALSE, "unable to determine zone brand");
↓ open down ↓ 345 lines elided ↑ open up ↑
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX