Print this page
    
Fixes to allow compilation on OmniOS and OI
OS-3342+co
OS-1572
OS-327
    
      
        | Split | 
	Close | 
      
      | Expand all | 
      | Collapse all | 
    
    
          --- old/usr/src/cmd/zoneadmd/zoneadmd.c
          +++ new/usr/src/cmd/zoneadmd/zoneadmd.c
   1    1  /*
   2    2   * CDDL HEADER START
   3    3   *
   4    4   * The contents of this file are subject to the terms of the
   5    5   * Common Development and Distribution License (the "License").
   6    6   * You may not use this file except in compliance with the License.
   7    7   *
   8    8   * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
   9    9   * or http://www.opensolaris.org/os/licensing.
  10   10   * See the License for the specific language governing permissions
  11   11   * and limitations under the License.
  12   12   *
  13   13   * When distributing Covered Code, include this CDDL HEADER in each
  14   14   * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
  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   25   */
  26   26  
  27   27  /*
  28   28   * zoneadmd manages zones; one zoneadmd process is launched for each
  29   29   * non-global zone on the system.  This daemon juggles four jobs:
  30   30   *
  31   31   * - Implement setup and teardown of the zone "virtual platform": mount and
  32   32   *   unmount filesystems; create and destroy network interfaces; communicate
  33   33   *   with devfsadmd to lay out devices for the zone; instantiate the zone
  34   34   *   console device; configure process runtime attributes such as resource
  35   35   *   controls, pool bindings, fine-grained privileges.
  36   36   *
  37   37   * - Launch the zone's init(1M) process.
  38   38   *
  39   39   * - Implement a door server; clients (like zoneadm) connect to the door
  40   40   *   server and request zone state changes.  The kernel is also a client of
  41   41   *   this door server.  A request to halt or reboot the zone which originates
  42   42   *   *inside* the zone results in a door upcall from the kernel into zoneadmd.
  43   43   *
  44   44   *   One minor problem is that messages emitted by zoneadmd need to be passed
  45   45   *   back to the zoneadm process making the request.  These messages need to
  46   46   *   be rendered in the client's locale; so, this is passed in as part of the
  47   47   *   request.  The exception is the kernel upcall to zoneadmd, in which case
  48   48   *   messages are syslog'd.
  49   49   *
  50   50   *   To make all of this work, the Makefile adds -a to xgettext to extract *all*
  51   51   *   strings, and an exclusion file (zoneadmd.xcl) is used to exclude those
  52   52   *   strings which do not need to be translated.
  53   53   *
  54   54   * - Act as a console server for zlogin -C processes; see comments in zcons.c
  55   55   *   for more information about the zone console architecture.
  56   56   *
  57   57   * DESIGN NOTES
  58   58   *
  59   59   * Restart:
  60   60   *   A chief design constraint of zoneadmd is that it should be restartable in
  61   61   *   the case that the administrator kills it off, or it suffers a fatal error,
  62   62   *   without the running zone being impacted; this is akin to being able to
  63   63   *   reboot the service processor of a server without affecting the OS instance.
  64   64   */
  65   65  
  66   66  #include <sys/param.h>
  67   67  #include <sys/mman.h>
  68   68  #include <sys/types.h>
  69   69  #include <sys/stat.h>
  70   70  #include <sys/sysmacros.h>
  71   71  
  72   72  #include <bsm/adt.h>
  73   73  #include <bsm/adt_event.h>
  74   74  
  75   75  #include <alloca.h>
  76   76  #include <assert.h>
  77   77  #include <errno.h>
  78   78  #include <door.h>
  79   79  #include <fcntl.h>
  80   80  #include <locale.h>
  81   81  #include <signal.h>
  82   82  #include <stdarg.h>
  83   83  #include <stdio.h>
  84   84  #include <stdlib.h>
  85   85  #include <string.h>
  86   86  #include <strings.h>
  87   87  #include <synch.h>
  88   88  #include <syslog.h>
  89   89  #include <thread.h>
  90   90  #include <unistd.h>
  91   91  #include <wait.h>
  92   92  #include <limits.h>
  93   93  #include <zone.h>
  94   94  #include <libbrand.h>
  95   95  #include <sys/brand.h>
  96   96  #include <libcontract.h>
  97   97  #include <libcontract_priv.h>
  98   98  #include <sys/brand.h>
  99   99  #include <sys/contract/process.h>
 100  100  #include <sys/ctfs.h>
 101  101  #include <libdladm.h>
 102  102  #include <sys/dls_mgmt.h>
 103  103  #include <libscf.h>
 104  104  
 105  105  #include <libzonecfg.h>
 106  106  #include <zonestat_impl.h>
 107  107  #include "zoneadmd.h"
 108  108  
 109  109  static char *progname;
 110  110  char *zone_name;        /* zone which we are managing */
 111  111  char pool_name[MAXNAMELEN];
 112  112  char default_brand[MAXNAMELEN];
 113  113  char brand_name[MAXNAMELEN];
 114  114  boolean_t zone_isnative;
 115  115  boolean_t zone_iscluster;
 116  116  boolean_t zone_islabeled;
 117  117  boolean_t shutdown_in_progress;
 118  118  static zoneid_t zone_id;
 119  119  dladm_handle_t dld_handle = NULL;
 120  120  
 121  121  static char pre_statechg_hook[2 * MAXPATHLEN];
 122  122  static char post_statechg_hook[2 * MAXPATHLEN];
 123  123  char query_hook[2 * MAXPATHLEN];
 124  124  
 125  125  zlog_t logsys;
 126  126  
 127  127  mutex_t lock = DEFAULTMUTEX;    /* to serialize stuff */
 128  128  mutex_t msglock = DEFAULTMUTEX; /* for calling setlocale() */
 129  129  
 130  130  static sema_t scratch_sem;      /* for scratch zones */
 131  131  
 132  132  static char     zone_door_path[MAXPATHLEN];
 133  133  static int      zone_door = -1;
 134  134  
 135  135  boolean_t in_death_throes = B_FALSE;    /* daemon is dying */
 136  136  boolean_t bringup_failure_recovery = B_FALSE; /* ignore certain failures */
 137  137  
 138  138  #if !defined(TEXT_DOMAIN)               /* should be defined by cc -D */
 139  139  #define TEXT_DOMAIN     "SYS_TEST"      /* Use this only if it wasn't */
 140  140  #endif
 141  141  
 142  142  #define DEFAULT_LOCALE  "C"
 143  143  
 144  144  static const char *
 145  145  z_cmd_name(zone_cmd_t zcmd)
 146  146  {
 147  147          /* This list needs to match the enum in sys/zone.h */
 148  148          static const char *zcmdstr[] = {
 149  149                  "ready", "boot", "forceboot", "reboot", "halt",
 150  150                  "note_uninstalling", "mount", "forcemount", "unmount",
 151  151                  "shutdown"
 152  152          };
 153  153  
 154  154          if (zcmd >= sizeof (zcmdstr) / sizeof (*zcmdstr))
 155  155                  return ("unknown");
 156  156          else
 157  157                  return (zcmdstr[(int)zcmd]);
 158  158  }
 159  159  
 160  160  static char *
 161  161  get_execbasename(char *execfullname)
 162  162  {
 163  163          char *last_slash, *execbasename;
 164  164  
 165  165          /* guard against '/' at end of command invocation */
 166  166          for (;;) {
 167  167                  last_slash = strrchr(execfullname, '/');
 168  168                  if (last_slash == NULL) {
 169  169                          execbasename = execfullname;
 170  170                          break;
 171  171                  } else {
 172  172                          execbasename = last_slash + 1;
 173  173                          if (*execbasename == '\0') {
 174  174                                  *last_slash = '\0';
 175  175                                  continue;
 176  176                          }
 177  177                          break;
 178  178                  }
 179  179          }
 180  180          return (execbasename);
 181  181  }
 182  182  
 183  183  static void
 184  184  usage(void)
 185  185  {
 186  186          (void) fprintf(stderr, gettext("Usage: %s -z zonename\n"), progname);
 187  187          (void) fprintf(stderr,
 188  188              gettext("\tNote: %s should not be run directly.\n"), progname);
 189  189          exit(2);
 190  190  }
 191  191  
 192  192  /* ARGSUSED */
 193  193  static void
 194  194  sigchld(int sig)
 195  195  {
 196  196  }
 197  197  
 198  198  char *
 199  199  localize_msg(char *locale, const char *msg)
 200  200  {
 201  201          char *out;
 202  202  
 203  203          (void) mutex_lock(&msglock);
 204  204          (void) setlocale(LC_MESSAGES, locale);
 205  205          out = gettext(msg);
 206  206          (void) setlocale(LC_MESSAGES, DEFAULT_LOCALE);
 207  207          (void) mutex_unlock(&msglock);
 208  208          return (out);
 209  209  }
 210  210  
 211  211  /* PRINTFLIKE3 */
 212  212  void
 213  213  zerror(zlog_t *zlogp, boolean_t use_strerror, const char *fmt, ...)
 214  214  {
 215  215          va_list alist;
 216  216          char buf[MAXPATHLEN * 2]; /* enough space for err msg with a path */
 217  217          char *bp;
 218  218          int saved_errno = errno;
 219  219  
 220  220          if (zlogp == NULL)
 221  221                  return;
 222  222          if (zlogp == &logsys)
 223  223                  (void) snprintf(buf, sizeof (buf), "[zone '%s'] ",
 224  224                      zone_name);
 225  225          else
 226  226                  buf[0] = '\0';
 227  227          bp = &(buf[strlen(buf)]);
 228  228  
 229  229          /*
 230  230           * In theory, the locale pointer should be set to either "C" or a
 231  231           * char array, so it should never be NULL
 232  232           */
 233  233          assert(zlogp->locale != NULL);
 234  234          /* Locale is per process, but we are multi-threaded... */
 235  235          fmt = localize_msg(zlogp->locale, fmt);
 236  236  
 237  237          va_start(alist, fmt);
 238  238          (void) vsnprintf(bp, sizeof (buf) - (bp - buf), fmt, alist);
 239  239          va_end(alist);
 240  240          bp = &(buf[strlen(buf)]);
 241  241          if (use_strerror)
 242  242                  (void) snprintf(bp, sizeof (buf) - (bp - buf), ": %s",
 243  243                      strerror(saved_errno));
 244  244          if (zlogp == &logsys) {
 245  245                  (void) syslog(LOG_ERR, "%s", buf);
 246  246          } else if (zlogp->logfile != NULL) {
 247  247                  (void) fprintf(zlogp->logfile, "%s\n", buf);
 248  248          } else {
 249  249                  size_t buflen;
 250  250                  size_t copylen;
 251  251  
 252  252                  buflen = snprintf(zlogp->log, zlogp->loglen, "%s\n", buf);
 253  253                  copylen = MIN(buflen, zlogp->loglen);
 254  254                  zlogp->log += copylen;
 255  255                  zlogp->loglen -= copylen;
 256  256          }
 257  257  }
 258  258  
 259  259  /*
 260  260   * Emit a warning for any boot arguments which are unrecognized.  Since
 261  261   * Solaris boot arguments are getopt(3c) compatible (see kernel(1m)), we
 262  262   * put the arguments into an argv style array, use getopt to process them,
 263  263   * and put the resultant argument string back into outargs.
 264  264   *
 265  265   * During the filtering, we pull out any arguments which are truly "boot"
 266  266   * arguments, leaving only those which are to be passed intact to the
 267  267   * progenitor process.  The one we support at the moment is -i, which
 268  268   * indicates to the kernel which program should be launched as 'init'.
 269  269   *
 270  270   * A return of Z_INVAL indicates specifically that the arguments are
 271  271   * not valid; this is a non-fatal error.  Except for Z_OK, all other return
 272  272   * values are treated as fatal.
 273  273   */
 274  274  static int
 275  275  filter_bootargs(zlog_t *zlogp, const char *inargs, char *outargs,
 276  276      char *init_file, char *badarg)
 277  277  {
 278  278          int argc = 0, argc_save;
 279  279          int i;
 280  280          int err;
 281  281          char *arg, *lasts, **argv = NULL, **argv_save;
 282  282          char zonecfg_args[BOOTARGS_MAX];
 283  283          char scratchargs[BOOTARGS_MAX], *sargs;
 284  284          char c;
 285  285  
 286  286          bzero(outargs, BOOTARGS_MAX);
 287  287          bzero(badarg, BOOTARGS_MAX);
 288  288  
 289  289          /*
 290  290           * If the user didn't specify transient boot arguments, check
 291  291           * to see if there were any specified in the zone configuration,
 292  292           * and use them if applicable.
 293  293           */
 294  294          if (inargs == NULL || inargs[0] == '\0')  {
 295  295                  zone_dochandle_t handle;
 296  296                  if ((handle = zonecfg_init_handle()) == NULL) {
 297  297                          zerror(zlogp, B_TRUE,
 298  298                              "getting zone configuration handle");
 299  299                          return (Z_BAD_HANDLE);
 300  300                  }
 301  301                  err = zonecfg_get_snapshot_handle(zone_name, handle);
 302  302                  if (err != Z_OK) {
 303  303                          zerror(zlogp, B_FALSE,
 304  304                              "invalid configuration snapshot");
 305  305                          zonecfg_fini_handle(handle);
 306  306                          return (Z_BAD_HANDLE);
 307  307                  }
 308  308  
 309  309                  bzero(zonecfg_args, sizeof (zonecfg_args));
 310  310                  (void) zonecfg_get_bootargs(handle, zonecfg_args,
 311  311                      sizeof (zonecfg_args));
 312  312                  inargs = zonecfg_args;
 313  313                  zonecfg_fini_handle(handle);
 314  314          }
 315  315  
 316  316          if (strlen(inargs) >= BOOTARGS_MAX) {
 317  317                  zerror(zlogp, B_FALSE, "boot argument string too long");
 318  318                  return (Z_INVAL);
 319  319          }
 320  320  
 321  321          (void) strlcpy(scratchargs, inargs, sizeof (scratchargs));
 322  322          sargs = scratchargs;
 323  323          while ((arg = strtok_r(sargs, " \t", &lasts)) != NULL) {
 324  324                  sargs = NULL;
 325  325                  argc++;
 326  326          }
 327  327  
 328  328          if ((argv = calloc(argc + 1, sizeof (char *))) == NULL) {
 329  329                  zerror(zlogp, B_FALSE, "memory allocation failed");
 330  330                  return (Z_NOMEM);
 331  331          }
 332  332  
 333  333          argv_save = argv;
 334  334          argc_save = argc;
 335  335  
 336  336          (void) strlcpy(scratchargs, inargs, sizeof (scratchargs));
 337  337          sargs = scratchargs;
 338  338          i = 0;
 339  339          while ((arg = strtok_r(sargs, " \t", &lasts)) != NULL) {
 340  340                  sargs = NULL;
 341  341                  if ((argv[i] = strdup(arg)) == NULL) {
 342  342                          err = Z_NOMEM;
 343  343                          zerror(zlogp, B_FALSE, "memory allocation failed");
 344  344                          goto done;
 345  345                  }
 346  346                  i++;
 347  347          }
 348  348  
 349  349          /*
 350  350           * We preserve compatibility with the Solaris system boot behavior,
 351  351           * which allows:
 352  352           *
 353  353           *      # reboot kernel/unix -s -m verbose
 354  354           *
 355  355           * In this example, kernel/unix tells the booter what file to
 356  356           * boot.  We don't want reboot in a zone to be gratuitously different,
 357  357           * so we silently ignore the boot file, if necessary.
 358  358           */
 359  359          if (argv[0] == NULL)
 360  360                  goto done;
 361  361  
 362  362          assert(argv[0][0] != ' ');
 363  363          assert(argv[0][0] != '\t');
 364  364  
 365  365          if (argv[0][0] != '-' && argv[0][0] != '\0') {
 366  366                  argv = &argv[1];
 367  367                  argc--;
 368  368          }
 369  369  
 370  370          optind = 0;
 371  371          opterr = 0;
 372  372          err = Z_OK;
 373  373          while ((c = getopt(argc, argv, "fi:m:s")) != -1) {
 374  374                  switch (c) {
 375  375                  case 'i':
 376  376                          /*
 377  377                           * -i is handled by the runtime and is not passed
 378  378                           * along to userland
 379  379                           */
 380  380                          (void) strlcpy(init_file, optarg, MAXPATHLEN);
 381  381                          break;
 382  382                  case 'f':
 383  383                          /* This has already been processed by zoneadm */
 384  384                          break;
 385  385                  case 'm':
 386  386                  case 's':
 387  387                          /* These pass through unmolested */
 388  388                          (void) snprintf(outargs, BOOTARGS_MAX,
 389  389                              "%s -%c %s ", outargs, c, optarg ? optarg : "");
 390  390                          break;
 391  391                  case '?':
 392  392                          /*
 393  393                           * We warn about unknown arguments but pass them
 394  394                           * along anyway-- if someone wants to develop their
 395  395                           * own init replacement, they can pass it whatever
 396  396                           * args they want.
 397  397                           */
 398  398                          err = Z_INVAL;
 399  399                          (void) snprintf(outargs, BOOTARGS_MAX,
 400  400                              "%s -%c", outargs, optopt);
 401  401                          (void) snprintf(badarg, BOOTARGS_MAX,
 402  402                              "%s -%c", badarg, optopt);
 403  403                          break;
 404  404                  }
 405  405          }
 406  406  
 407  407          /*
 408  408           * For Solaris Zones we warn about and discard non-option arguments.
 409  409           * Hence 'boot foo bar baz gub' --> 'boot'.  However, to be similar
 410  410           * to the kernel, we concat up all the other remaining boot args.
 411  411           * and warn on them as a group.
 412  412           */
 413  413          if (optind < argc) {
 414  414                  err = Z_INVAL;
 415  415                  while (optind < argc) {
 416  416                          (void) snprintf(badarg, BOOTARGS_MAX, "%s%s%s",
 417  417                              badarg, strlen(badarg) > 0 ? " " : "",
 418  418                              argv[optind]);
 419  419                          optind++;
 420  420                  }
 421  421                  zerror(zlogp, B_FALSE, "WARNING: Unused or invalid boot "
 422  422                      "arguments `%s'.", badarg);
 423  423          }
 424  424  
 425  425  done:
 426  426          for (i = 0; i < argc_save; i++) {
 427  427                  if (argv_save[i] != NULL)
 428  428                          free(argv_save[i]);
 429  429          }
 430  430          free(argv_save);
 431  431          return (err);
 432  432  }
 433  433  
 434  434  
 435  435  static int
 436  436  mkzonedir(zlog_t *zlogp)
 437  437  {
 438  438          struct stat st;
 439  439          /*
 440  440           * We must create and lock everyone but root out of ZONES_TMPDIR
 441  441           * since anyone can open any UNIX domain socket, regardless of
 442  442           * its file system permissions.  Sigh...
 443  443           */
 444  444          if (mkdir(ZONES_TMPDIR, S_IRWXU) < 0 && errno != EEXIST) {
 445  445                  zerror(zlogp, B_TRUE, "could not mkdir '%s'", ZONES_TMPDIR);
 446  446                  return (-1);
 447  447          }
 448  448          /* paranoia */
 449  449          if ((stat(ZONES_TMPDIR, &st) < 0) || !S_ISDIR(st.st_mode)) {
 450  450                  zerror(zlogp, B_TRUE, "'%s' is not a directory", ZONES_TMPDIR);
 451  451                  return (-1);
 452  452          }
 453  453          (void) chmod(ZONES_TMPDIR, S_IRWXU);
 454  454          return (0);
 455  455  }
 456  456  
 457  457  /*
 458  458   * Run the brand's pre-state change callback, if it exists.
 459  459   */
 460  460  static int
 461  461  brand_prestatechg(zlog_t *zlogp, int state, int cmd)
 462  462  {
 463  463          char cmdbuf[2 * MAXPATHLEN];
 464  464          const char *altroot;
 465  465  
 466  466          if (pre_statechg_hook[0] == '\0')
 467  467                  return (0);
 468  468  
 469  469          altroot = zonecfg_get_root();
 470  470          if (snprintf(cmdbuf, sizeof (cmdbuf), "%s %d %d %s", pre_statechg_hook,
 471  471              state, cmd, altroot) > sizeof (cmdbuf))
 472  472                  return (-1);
 473  473  
 474  474          if (do_subproc(zlogp, cmdbuf, NULL) != 0)
 475  475                  return (-1);
 476  476  
 477  477          return (0);
 478  478  }
 479  479  
 480  480  /*
 481  481   * Run the brand's post-state change callback, if it exists.
 482  482   */
 483  483  static int
 484  484  brand_poststatechg(zlog_t *zlogp, int state, int cmd)
 485  485  {
 486  486          char cmdbuf[2 * MAXPATHLEN];
 487  487          const char *altroot;
 488  488  
 489  489          if (post_statechg_hook[0] == '\0')
 490  490                  return (0);
 491  491  
 492  492          altroot = zonecfg_get_root();
 493  493          if (snprintf(cmdbuf, sizeof (cmdbuf), "%s %d %d %s", post_statechg_hook,
 494  494              state, cmd, altroot) > sizeof (cmdbuf))
 495  495                  return (-1);
 496  496  
 497  497          if (do_subproc(zlogp, cmdbuf, NULL) != 0)
 498  498                  return (-1);
 499  499  
 500  500          return (0);
 501  501  }
 502  502  
 503  503  /*
 504  504   * Notify zonestatd of the new zone.  If zonestatd is not running, this
 505  505   * will do nothing.
 506  506   */
 507  507  static void
 508  508  notify_zonestatd(zoneid_t zoneid)
 509  509  {
 510  510          int cmd[2];
 511  511          int fd;
 512  512          door_arg_t params;
 513  513  
 514  514          fd = open(ZS_DOOR_PATH, O_RDONLY);
 515  515          if (fd < 0)
 516  516                  return;
 517  517  
 518  518          cmd[0] = ZSD_CMD_NEW_ZONE;
 519  519          cmd[1] = zoneid;
 520  520          params.data_ptr = (char *)&cmd;
 521  521          params.data_size = sizeof (cmd);
 522  522          params.desc_ptr = NULL;
 523  523          params.desc_num = 0;
 524  524          params.rbuf = NULL;
 525  525          params.rsize = NULL;
 526  526          (void) door_call(fd, ¶ms);
 527  527          (void) close(fd);
 528  528  }
 529  529  
 530  530  /*
 531  531   * Bring a zone up to the pre-boot "ready" stage.  The mount_cmd argument is
 532  532   * 'true' if this is being invoked as part of the processing for the "mount"
 533  533   * subcommand.
 534  534   */
 535  535  static int
 536  536  zone_ready(zlog_t *zlogp, zone_mnt_t mount_cmd, int zstate)
 537  537  {
 538  538          int err;
 539  539  
 540  540          if (brand_prestatechg(zlogp, zstate, Z_READY) != 0)
 541  541                  return (-1);
 542  542  
 543  543          if ((err = zonecfg_create_snapshot(zone_name)) != Z_OK) {
 544  544                  zerror(zlogp, B_FALSE, "unable to create snapshot: %s",
 545  545                      zonecfg_strerror(err));
 546  546                  goto bad;
 547  547          }
 548  548  
 549  549          if ((zone_id = vplat_create(zlogp, mount_cmd)) == -1) {
 550  550                  if ((err = zonecfg_destroy_snapshot(zone_name)) != Z_OK)
 551  551                          zerror(zlogp, B_FALSE, "destroying snapshot: %s",
 552  552                              zonecfg_strerror(err));
 553  553                  goto bad;
 554  554          }
 555  555          if (vplat_bringup(zlogp, mount_cmd, zone_id) != 0) {
 556  556                  bringup_failure_recovery = B_TRUE;
 557  557                  (void) vplat_teardown(NULL, (mount_cmd != Z_MNT_BOOT), B_FALSE);
 558  558                  if ((err = zonecfg_destroy_snapshot(zone_name)) != Z_OK)
 559  559                          zerror(zlogp, B_FALSE, "destroying snapshot: %s",
 560  560                              zonecfg_strerror(err));
 561  561                  goto bad;
 562  562          }
 563  563  
 564  564          if (brand_poststatechg(zlogp, zstate, Z_READY) != 0)
 565  565                  goto bad;
 566  566  
 567  567          return (0);
 568  568  
 569  569  bad:
 570  570          /*
 571  571           * If something goes wrong, we up the zones's state to the target
 572  572           * state, READY, and then invoke the hook as if we're halting.
 573  573           */
 574  574          (void) brand_poststatechg(zlogp, ZONE_STATE_READY, Z_HALT);
 575  575          return (-1);
 576  576  }
 577  577  
 578  578  int
 579  579  init_template(void)
 580  580  {
 581  581          int fd;
 582  582          int err = 0;
 583  583  
 584  584          fd = open64(CTFS_ROOT "/process/template", O_RDWR);
 585  585          if (fd == -1)
 586  586                  return (-1);
 587  587  
 588  588          /*
 589  589           * For now, zoneadmd doesn't do anything with the contract.
 590  590           * Deliver no events, don't inherit, and allow it to be orphaned.
 591  591           */
 592  592          err |= ct_tmpl_set_critical(fd, 0);
 593  593          err |= ct_tmpl_set_informative(fd, 0);
 594  594          err |= ct_pr_tmpl_set_fatal(fd, CT_PR_EV_HWERR);
 595  595          err |= ct_pr_tmpl_set_param(fd, CT_PR_PGRPONLY | CT_PR_REGENT);
 596  596          if (err || ct_tmpl_activate(fd)) {
 597  597                  (void) close(fd);
 598  598                  return (-1);
 599  599          }
 600  600  
 601  601          return (fd);
 602  602  }
 603  603  
 604  604  typedef struct fs_callback {
 605  605          zlog_t          *zlogp;
 606  606          zoneid_t        zoneid;
 607  607          boolean_t       mount_cmd;
 608  608  } fs_callback_t;
 609  609  
 610  610  static int
 611  611  mount_early_fs(void *data, const char *spec, const char *dir,
 612  612      const char *fstype, const char *opt)
 613  613  {
 614  614          zlog_t *zlogp = ((fs_callback_t *)data)->zlogp;
 615  615          zoneid_t zoneid = ((fs_callback_t *)data)->zoneid;
 616  616          boolean_t mount_cmd = ((fs_callback_t *)data)->mount_cmd;
 617  617          char rootpath[MAXPATHLEN];
 618  618          pid_t child;
 619  619          int child_status;
 620  620          int tmpl_fd;
 621  621          int rv;
 622  622          ctid_t ct;
 623  623  
 624  624          /* determine the zone rootpath */
 625  625          if (mount_cmd) {
 626  626                  char zonepath[MAXPATHLEN];
 627  627                  char luroot[MAXPATHLEN];
 628  628  
 629  629                  if (zone_get_zonepath(zone_name,
 630  630                      zonepath, sizeof (zonepath)) != Z_OK) {
 631  631                          zerror(zlogp, B_FALSE, "unable to determine zone path");
 632  632                          return (-1);
 633  633                  }
 634  634  
 635  635                  (void) snprintf(luroot, sizeof (luroot), "%s/lu", zonepath);
 636  636                  resolve_lofs(zlogp, luroot, sizeof (luroot));
 637  637                  (void) strlcpy(rootpath, luroot, sizeof (rootpath));
 638  638          } else {
 639  639                  if (zone_get_rootpath(zone_name,
 640  640                      rootpath, sizeof (rootpath)) != Z_OK) {
 641  641                          zerror(zlogp, B_FALSE, "unable to determine zone root");
 642  642                          return (-1);
 643  643                  }
 644  644          }
 645  645  
 646  646          if ((rv = valid_mount_path(zlogp, rootpath, spec, dir, fstype)) < 0) {
 647  647                  zerror(zlogp, B_FALSE, "%s%s is not a valid mount point",
 648  648                      rootpath, dir);
 649  649                  return (-1);
 650  650          } else if (rv > 0) {
 651  651                  /* The mount point path doesn't exist, create it now. */
 652  652                  if (make_one_dir(zlogp, rootpath, dir,
 653  653                      DEFAULT_DIR_MODE, DEFAULT_DIR_USER,
 654  654                      DEFAULT_DIR_GROUP) != 0) {
 655  655                          zerror(zlogp, B_FALSE, "failed to create mount point");
 656  656                          return (-1);
 657  657                  }
 658  658  
 659  659                  /*
 660  660                   * Now this might seem weird, but we need to invoke
 661  661                   * valid_mount_path() again.  Why?  Because it checks
 662  662                   * to make sure that the mount point path is canonical,
 663  663                   * which it can only do if the path exists, so now that
 664  664                   * we've created the path we have to verify it again.
 665  665                   */
 666  666                  if ((rv = valid_mount_path(zlogp, rootpath, spec, dir,
 667  667                      fstype)) < 0) {
 668  668                          zerror(zlogp, B_FALSE,
 669  669                              "%s%s is not a valid mount point", rootpath, dir);
 670  670                          return (-1);
 671  671                  }
 672  672          }
 673  673  
 674  674          if ((tmpl_fd = init_template()) == -1) {
 675  675                  zerror(zlogp, B_TRUE, "failed to create contract");
 676  676                  return (-1);
 677  677          }
 678  678  
 679  679          if ((child = fork()) == -1) {
 680  680                  (void) ct_tmpl_clear(tmpl_fd);
 681  681                  (void) close(tmpl_fd);
 682  682                  zerror(zlogp, B_TRUE, "failed to fork");
 683  683                  return (-1);
 684  684  
 685  685          } else if (child == 0) {        /* child */
 686  686                  char opt_buf[MAX_MNTOPT_STR];
 687  687                  int optlen = 0;
 688  688                  int mflag = MS_DATA;
 689  689  
 690  690                  (void) ct_tmpl_clear(tmpl_fd);
 691  691                  /*
 692  692                   * Even though there are no procs running in the zone, we
 693  693                   * do this for paranoia's sake.
 694  694                   */
 695  695                  (void) closefrom(0);
 696  696  
 697  697                  if (zone_enter(zoneid) == -1) {
 698  698                          _exit(errno);
 699  699                  }
 700  700                  if (opt != NULL) {
 701  701                          /*
 702  702                           * The mount() system call is incredibly annoying.
 703  703                           * If options are specified, we need to copy them
 704  704                           * into a temporary buffer since the mount() system
 705  705                           * call will overwrite the options string.  It will
 706  706                           * also fail if the new option string it wants to
 707  707                           * write is bigger than the one we passed in, so
 708  708                           * you must pass in a buffer of the maximum possible
 709  709                           * option string length.  sigh.
 710  710                           */
 711  711                          (void) strlcpy(opt_buf, opt, sizeof (opt_buf));
 712  712                          opt = opt_buf;
 713  713                          optlen = MAX_MNTOPT_STR;
 714  714                          mflag = MS_OPTIONSTR;
 715  715                  }
 716  716                  if (mount(spec, dir, mflag, fstype, NULL, 0, opt, optlen) != 0)
 717  717                          _exit(errno);
 718  718                  _exit(0);
 719  719          }
 720  720  
 721  721          /* parent */
 722  722          if (contract_latest(&ct) == -1)
 723  723                  ct = -1;
 724  724          (void) ct_tmpl_clear(tmpl_fd);
 725  725          (void) close(tmpl_fd);
 726  726          if (waitpid(child, &child_status, 0) != child) {
 727  727                  /* unexpected: we must have been signalled */
 728  728                  (void) contract_abandon_id(ct);
 729  729                  return (-1);
 730  730          }
 731  731          (void) contract_abandon_id(ct);
 732  732          if (WEXITSTATUS(child_status) != 0) {
 733  733                  errno = WEXITSTATUS(child_status);
 734  734                  zerror(zlogp, B_TRUE, "mount of %s failed", dir);
 735  735                  return (-1);
 736  736          }
 737  737  
 738  738          return (0);
 739  739  }
 740  740  
 741  741  /*
 742  742   * If retstr is not NULL, the output of the subproc is returned in the str,
 743  743   * otherwise it is output using zerror().  Any memory allocated for retstr
 744  744   * should be freed by the caller.
 745  745   */
 746  746  int
 747  747  do_subproc(zlog_t *zlogp, char *cmdbuf, char **retstr)
 748  748  {
 749  749          char buf[1024];         /* arbitrary large amount */
 750  750          char *inbuf;
 751  751          FILE *file;
 752  752          int status;
 753  753          int rd_cnt;
 754  754  
 755  755          if (retstr != NULL) {
 756  756                  if ((*retstr = malloc(1024)) == NULL) {
 757  757                          zerror(zlogp, B_FALSE, "out of memory");
 758  758                          return (-1);
 759  759                  }
 760  760                  inbuf = *retstr;
 761  761                  rd_cnt = 0;
 762  762          } else {
 763  763                  inbuf = buf;
  
    | 
      ↓ open down ↓ | 
    763 lines elided | 
    
      ↑ open up ↑ | 
  
 764  764          }
 765  765  
 766  766          file = popen(cmdbuf, "r");
 767  767          if (file == NULL) {
 768  768                  zerror(zlogp, B_TRUE, "could not launch: %s", cmdbuf);
 769  769                  return (-1);
 770  770          }
 771  771  
 772  772          while (fgets(inbuf, 1024, file) != NULL) {
 773  773                  if (retstr == NULL) {
 774      -                        if (zlogp != &logsys)
      774 +                        if (zlogp != &logsys) {
      775 +                                int last = strlen(inbuf) - 1;
      776 +
      777 +                                if (inbuf[last] == '\n')
      778 +                                        inbuf[last] = '\0';
 775  779                                  zerror(zlogp, B_FALSE, "%s", inbuf);
      780 +                        }
 776  781                  } else {
 777  782                          char *p;
 778  783  
 779  784                          rd_cnt += 1024 - 1;
 780  785                          if ((p = realloc(*retstr, rd_cnt + 1024)) == NULL) {
 781  786                                  zerror(zlogp, B_FALSE, "out of memory");
 782  787                                  (void) pclose(file);
 783  788                                  return (-1);
 784  789                          }
 785  790  
 786  791                          *retstr = p;
 787  792                          inbuf = *retstr + rd_cnt;
 788  793                  }
 789  794          }
 790  795          status = pclose(file);
 791  796  
 792  797          if (WIFSIGNALED(status)) {
 793  798                  zerror(zlogp, B_FALSE, "%s unexpectedly terminated due to "
 794  799                      "signal %d", cmdbuf, WTERMSIG(status));
 795  800                  return (-1);
 796  801          }
 797  802          assert(WIFEXITED(status));
 798  803          if (WEXITSTATUS(status) == ZEXIT_EXEC) {
 799  804                  zerror(zlogp, B_FALSE, "failed to exec %s", cmdbuf);
 800  805                  return (-1);
 801  806          }
 802  807          return (WEXITSTATUS(status));
 803  808  }
 804  809  
 805  810  static int
 806  811  zone_bootup(zlog_t *zlogp, const char *bootargs, int zstate)
 807  812  {
 808  813          zoneid_t zoneid;
 809  814          struct stat st;
 810  815          char zpath[MAXPATHLEN], initpath[MAXPATHLEN], init_file[MAXPATHLEN];
 811  816          char nbootargs[BOOTARGS_MAX];
 812  817          char cmdbuf[MAXPATHLEN];
 813  818          fs_callback_t cb;
 814  819          brand_handle_t bh;
 815  820          zone_iptype_t iptype;
 816  821          boolean_t links_loaded = B_FALSE;
 817  822          dladm_status_t status;
 818  823          char errmsg[DLADM_STRSIZE];
 819  824          int err;
 820  825          boolean_t restart_init;
 821  826  
 822  827          if (brand_prestatechg(zlogp, zstate, Z_BOOT) != 0)
 823  828                  return (-1);
 824  829  
 825  830          if ((zoneid = getzoneidbyname(zone_name)) == -1) {
 826  831                  zerror(zlogp, B_TRUE, "unable to get zoneid");
 827  832                  goto bad;
 828  833          }
 829  834  
 830  835          cb.zlogp = zlogp;
 831  836          cb.zoneid = zoneid;
 832  837          cb.mount_cmd = B_FALSE;
 833  838  
 834  839          /* Get a handle to the brand info for this zone */
 835  840          if ((bh = brand_open(brand_name)) == NULL) {
 836  841                  zerror(zlogp, B_FALSE, "unable to determine zone brand");
 837  842                  goto bad;
 838  843          }
 839  844  
 840  845          /*
 841  846           * Get the list of filesystems to mount from the brand
 842  847           * configuration.  These mounts are done via a thread that will
 843  848           * enter the zone, so they are done from within the context of the
 844  849           * zone.
 845  850           */
 846  851          if (brand_platform_iter_mounts(bh, mount_early_fs, &cb) != 0) {
 847  852                  zerror(zlogp, B_FALSE, "unable to mount filesystems");
 848  853                  brand_close(bh);
 849  854                  goto bad;
 850  855          }
 851  856  
 852  857          /*
 853  858           * Get the brand's boot callback if it exists.
 854  859           */
 855  860          if (zone_get_zonepath(zone_name, zpath, sizeof (zpath)) != Z_OK) {
 856  861                  zerror(zlogp, B_FALSE, "unable to determine zone path");
 857  862                  brand_close(bh);
 858  863                  goto bad;
 859  864          }
 860  865          (void) strcpy(cmdbuf, EXEC_PREFIX);
 861  866          if (brand_get_boot(bh, zone_name, zpath, cmdbuf + EXEC_LEN,
 862  867              sizeof (cmdbuf) - EXEC_LEN) != 0) {
 863  868                  zerror(zlogp, B_FALSE,
 864  869                      "unable to determine branded zone's boot callback");
 865  870                  brand_close(bh);
 866  871                  goto bad;
 867  872          }
 868  873  
 869  874          /* Get the path for this zone's init(1M) (or equivalent) process.  */
 870  875          if (brand_get_initname(bh, init_file, MAXPATHLEN) != 0) {
 871  876                  zerror(zlogp, B_FALSE,
 872  877                      "unable to determine zone's init(1M) location");
 873  878                  brand_close(bh);
 874  879                  goto bad;
 875  880          }
 876  881  
 877  882          /* See if this zone's brand should restart init if it dies. */
 878  883          restart_init = brand_restartinit(bh);
 879  884  
 880  885          brand_close(bh);
 881  886  
 882  887          err = filter_bootargs(zlogp, bootargs, nbootargs, init_file,
 883  888              bad_boot_arg);
 884  889          if (err == Z_INVAL)
 885  890                  eventstream_write(Z_EVT_ZONE_BADARGS);
 886  891          else if (err != Z_OK)
 887  892                  goto bad;
 888  893  
 889  894          assert(init_file[0] != '\0');
 890  895  
 891  896          /* Try to anticipate possible problems: Make sure init is executable. */
 892  897          if (zone_get_rootpath(zone_name, zpath, sizeof (zpath)) != Z_OK) {
 893  898                  zerror(zlogp, B_FALSE, "unable to determine zone root");
 894  899                  goto bad;
 895  900          }
 896  901  
 897  902          (void) snprintf(initpath, sizeof (initpath), "%s%s", zpath, init_file);
 898  903  
 899  904          if (stat(initpath, &st) == -1) {
 900  905                  zerror(zlogp, B_TRUE, "could not stat %s", initpath);
 901  906                  goto bad;
 902  907          }
 903  908  
 904  909          if ((st.st_mode & S_IXUSR) == 0) {
 905  910                  zerror(zlogp, B_FALSE, "%s is not executable", initpath);
 906  911                  goto bad;
 907  912          }
 908  913  
 909  914          /*
 910  915           * Exclusive stack zones interact with the dlmgmtd running in the
 911  916           * global zone.  dladm_zone_boot() tells dlmgmtd that this zone is
 912  917           * booting, and loads its datalinks from the zone's datalink
 913  918           * configuration file.
 914  919           */
 915  920          if (vplat_get_iptype(zlogp, &iptype) == 0 && iptype == ZS_EXCLUSIVE) {
 916  921                  status = dladm_zone_boot(dld_handle, zoneid);
 917  922                  if (status != DLADM_STATUS_OK) {
 918  923                          zerror(zlogp, B_FALSE, "unable to load zone datalinks: "
 919  924                              " %s", dladm_status2str(status, errmsg));
 920  925                          goto bad;
 921  926                  }
 922  927                  links_loaded = B_TRUE;
 923  928          }
 924  929  
 925  930          /*
 926  931           * If there is a brand 'boot' callback, execute it now to give the
 927  932           * brand one last chance to do any additional setup before the zone
 928  933           * is booted.
 929  934           */
 930  935          if ((strlen(cmdbuf) > EXEC_LEN) &&
 931  936              (do_subproc(zlogp, cmdbuf, NULL) != Z_OK)) {
 932  937                  zerror(zlogp, B_FALSE, "%s failed", cmdbuf);
 933  938                  goto bad;
 934  939          }
 935  940  
 936  941          if (zone_setattr(zoneid, ZONE_ATTR_INITNAME, init_file, 0) == -1) {
 937  942                  zerror(zlogp, B_TRUE, "could not set zone boot file");
 938  943                  goto bad;
 939  944          }
 940  945  
 941  946          if (zone_setattr(zoneid, ZONE_ATTR_BOOTARGS, nbootargs, 0) == -1) {
 942  947                  zerror(zlogp, B_TRUE, "could not set zone boot arguments");
 943  948                  goto bad;
 944  949          }
 945  950  
 946  951          if (!restart_init && zone_setattr(zoneid, ZONE_ATTR_INITNORESTART,
 947  952              NULL, 0) == -1) {
 948  953                  zerror(zlogp, B_TRUE, "could not set zone init-no-restart");
 949  954                  goto bad;
 950  955          }
 951  956  
 952  957          /*
 953  958           * Inform zonestatd of a new zone so that it can install a door for
 954  959           * the zone to contact it.
 955  960           */
 956  961          notify_zonestatd(zone_id);
 957  962  
 958  963          if (zone_boot(zoneid) == -1) {
 959  964                  zerror(zlogp, B_TRUE, "unable to boot zone");
 960  965                  goto bad;
 961  966          }
 962  967  
 963  968          if (brand_poststatechg(zlogp, zstate, Z_BOOT) != 0)
 964  969                  goto bad;
 965  970  
 966  971          return (0);
 967  972  
 968  973  bad:
 969  974          /*
 970  975           * If something goes wrong, we up the zones's state to the target
 971  976           * state, RUNNING, and then invoke the hook as if we're halting.
 972  977           */
 973  978          (void) brand_poststatechg(zlogp, ZONE_STATE_RUNNING, Z_HALT);
 974  979          if (links_loaded)
 975  980                  (void) dladm_zone_halt(dld_handle, zoneid);
 976  981          return (-1);
 977  982  }
 978  983  
 979  984  static int
 980  985  zone_halt(zlog_t *zlogp, boolean_t unmount_cmd, boolean_t rebooting, int zstate)
 981  986  {
 982  987          int err;
 983  988  
 984  989          if (brand_prestatechg(zlogp, zstate, Z_HALT) != 0)
 985  990                  return (-1);
 986  991  
 987  992          if (vplat_teardown(zlogp, unmount_cmd, rebooting) != 0) {
 988  993                  if (!bringup_failure_recovery)
 989  994                          zerror(zlogp, B_FALSE, "unable to destroy zone");
 990  995                  return (-1);
 991  996          }
 992  997  
 993  998          if ((err = zonecfg_destroy_snapshot(zone_name)) != Z_OK)
 994  999                  zerror(zlogp, B_FALSE, "destroying snapshot: %s",
 995 1000                      zonecfg_strerror(err));
 996 1001  
 997 1002          if (brand_poststatechg(zlogp, zstate, Z_HALT) != 0)
 998 1003                  return (-1);
 999 1004  
1000 1005          return (0);
1001 1006  }
1002 1007  
1003 1008  static int
1004 1009  zone_graceful_shutdown(zlog_t *zlogp)
1005 1010  {
1006 1011          zoneid_t zoneid;
1007 1012          pid_t child;
1008 1013          char cmdbuf[MAXPATHLEN];
1009 1014          brand_handle_t bh = NULL;
1010 1015          char zpath[MAXPATHLEN];
1011 1016          ctid_t ct;
1012 1017          int tmpl_fd;
1013 1018          int child_status;
1014 1019  
1015 1020          if (shutdown_in_progress) {
1016 1021                  zerror(zlogp, B_FALSE, "shutdown already in progress");
1017 1022                  return (-1);
1018 1023          }
1019 1024  
1020 1025          if ((zoneid = getzoneidbyname(zone_name)) == -1) {
1021 1026                  zerror(zlogp, B_TRUE, "unable to get zoneid");
1022 1027                  return (-1);
1023 1028          }
1024 1029  
1025 1030          /* Get a handle to the brand info for this zone */
1026 1031          if ((bh = brand_open(brand_name)) == NULL) {
1027 1032                  zerror(zlogp, B_FALSE, "unable to determine zone brand");
1028 1033                  return (-1);
1029 1034          }
1030 1035  
1031 1036          if (zone_get_zonepath(zone_name, zpath, sizeof (zpath)) != Z_OK) {
1032 1037                  zerror(zlogp, B_FALSE, "unable to determine zone path");
1033 1038                  brand_close(bh);
1034 1039                  return (-1);
1035 1040          }
1036 1041  
1037 1042          /*
1038 1043           * If there is a brand 'shutdown' callback, execute it now to give the
1039 1044           * brand a chance to cleanup any custom configuration.
1040 1045           */
1041 1046          (void) strcpy(cmdbuf, EXEC_PREFIX);
1042 1047          if (brand_get_shutdown(bh, zone_name, zpath, cmdbuf + EXEC_LEN,
1043 1048              sizeof (cmdbuf) - EXEC_LEN) != 0 || strlen(cmdbuf) <= EXEC_LEN) {
1044 1049                  (void) strcat(cmdbuf, SHUTDOWN_DEFAULT);
1045 1050          }
1046 1051          brand_close(bh);
1047 1052  
1048 1053          if ((tmpl_fd = init_template()) == -1) {
1049 1054                  zerror(zlogp, B_TRUE, "failed to create contract");
1050 1055                  return (-1);
1051 1056          }
1052 1057  
1053 1058          if ((child = fork()) == -1) {
1054 1059                  (void) ct_tmpl_clear(tmpl_fd);
1055 1060                  (void) close(tmpl_fd);
1056 1061                  zerror(zlogp, B_TRUE, "failed to fork");
1057 1062                  return (-1);
1058 1063          } else if (child == 0) {
1059 1064                  (void) ct_tmpl_clear(tmpl_fd);
1060 1065                  if (zone_enter(zoneid) == -1) {
1061 1066                          _exit(errno);
1062 1067                  }
1063 1068                  _exit(execl("/bin/sh", "sh", "-c", cmdbuf, (char *)NULL));
1064 1069          }
1065 1070  
1066 1071          if (contract_latest(&ct) == -1)
1067 1072                  ct = -1;
1068 1073          (void) ct_tmpl_clear(tmpl_fd);
1069 1074          (void) close(tmpl_fd);
1070 1075  
1071 1076          if (waitpid(child, &child_status, 0) != child) {
1072 1077                  /* unexpected: we must have been signalled */
1073 1078                  (void) contract_abandon_id(ct);
1074 1079                  return (-1);
1075 1080          }
1076 1081  
1077 1082          (void) contract_abandon_id(ct);
1078 1083          if (WEXITSTATUS(child_status) != 0) {
1079 1084                  errno = WEXITSTATUS(child_status);
1080 1085                  zerror(zlogp, B_FALSE, "unable to shutdown zone");
1081 1086                  return (-1);
1082 1087          }
1083 1088  
1084 1089          shutdown_in_progress = B_TRUE;
1085 1090  
1086 1091          return (0);
1087 1092  }
1088 1093  
1089 1094  static int
1090 1095  zone_wait_shutdown(zlog_t *zlogp)
1091 1096  {
1092 1097          zone_state_t zstate;
1093 1098          uint64_t *tm = NULL;
1094 1099          scf_simple_prop_t *prop = NULL;
1095 1100          int timeout;
1096 1101          int tries;
1097 1102          int rc = -1;
1098 1103  
1099 1104          /* Get default stop timeout from SMF framework */
1100 1105          timeout = SHUTDOWN_WAIT;
1101 1106          if ((prop = scf_simple_prop_get(NULL, SHUTDOWN_FMRI, "stop",
1102 1107              SCF_PROPERTY_TIMEOUT)) != NULL) {
1103 1108                  if ((tm = scf_simple_prop_next_count(prop)) != NULL) {
1104 1109                          if (tm != 0)
1105 1110                                  timeout = *tm;
1106 1111                  }
1107 1112                  scf_simple_prop_free(prop);
1108 1113          }
1109 1114  
1110 1115          /* allow time for zone to shutdown cleanly */
1111 1116          for (tries = 0; tries < timeout; tries ++) {
1112 1117                  (void) sleep(1);
1113 1118                  if (zone_get_state(zone_name, &zstate) == Z_OK &&
1114 1119                      zstate == ZONE_STATE_INSTALLED) {
1115 1120                          rc = 0;
1116 1121                          break;
1117 1122                  }
1118 1123          }
1119 1124  
1120 1125          if (rc != 0)
1121 1126                  zerror(zlogp, B_FALSE, "unable to shutdown zone");
1122 1127  
1123 1128          shutdown_in_progress = B_FALSE;
1124 1129  
1125 1130          return (rc);
1126 1131  }
1127 1132  
1128 1133  
1129 1134  
1130 1135  /*
1131 1136   * Generate AUE_zone_state for a command that boots a zone.
1132 1137   */
1133 1138  static void
1134 1139  audit_put_record(zlog_t *zlogp, ucred_t *uc, int return_val,
1135 1140      char *new_state)
1136 1141  {
1137 1142          adt_session_data_t      *ah;
1138 1143          adt_event_data_t        *event;
1139 1144          int                     pass_fail, fail_reason;
1140 1145  
1141 1146          if (!adt_audit_enabled())
1142 1147                  return;
1143 1148  
1144 1149          if (return_val == 0) {
1145 1150                  pass_fail = ADT_SUCCESS;
1146 1151                  fail_reason = ADT_SUCCESS;
1147 1152          } else {
1148 1153                  pass_fail = ADT_FAILURE;
1149 1154                  fail_reason = ADT_FAIL_VALUE_PROGRAM;
1150 1155          }
1151 1156  
1152 1157          if (adt_start_session(&ah, NULL, 0)) {
1153 1158                  zerror(zlogp, B_TRUE, gettext("audit failure."));
1154 1159                  return;
1155 1160          }
1156 1161          if (adt_set_from_ucred(ah, uc, ADT_NEW)) {
1157 1162                  zerror(zlogp, B_TRUE, gettext("audit failure."));
1158 1163                  (void) adt_end_session(ah);
1159 1164                  return;
1160 1165          }
1161 1166  
1162 1167          event = adt_alloc_event(ah, ADT_zone_state);
1163 1168          if (event == NULL) {
1164 1169                  zerror(zlogp, B_TRUE, gettext("audit failure."));
1165 1170                  (void) adt_end_session(ah);
1166 1171                  return;
1167 1172          }
1168 1173          event->adt_zone_state.zonename = zone_name;
1169 1174          event->adt_zone_state.new_state = new_state;
1170 1175  
1171 1176          if (adt_put_event(event, pass_fail, fail_reason))
1172 1177                  zerror(zlogp, B_TRUE, gettext("audit failure."));
1173 1178  
1174 1179          adt_free_event(event);
1175 1180  
1176 1181          (void) adt_end_session(ah);
1177 1182  }
1178 1183  
1179 1184  /*
1180 1185   * The main routine for the door server that deals with zone state transitions.
1181 1186   */
1182 1187  /* ARGSUSED */
1183 1188  static void
1184 1189  server(void *cookie, char *args, size_t alen, door_desc_t *dp,
1185 1190      uint_t n_desc)
1186 1191  {
1187 1192          ucred_t *uc = NULL;
1188 1193          const priv_set_t *eset;
1189 1194  
1190 1195          zone_state_t zstate;
1191 1196          zone_cmd_t cmd;
1192 1197          zone_cmd_arg_t *zargp;
1193 1198  
1194 1199          boolean_t kernelcall;
1195 1200  
1196 1201          int rval = -1;
1197 1202          uint64_t uniqid;
1198 1203          zoneid_t zoneid = -1;
1199 1204          zlog_t zlog;
1200 1205          zlog_t *zlogp;
1201 1206          zone_cmd_rval_t *rvalp;
1202 1207          size_t rlen = getpagesize(); /* conservative */
1203 1208          fs_callback_t cb;
1204 1209          brand_handle_t bh;
1205 1210          boolean_t wait_shut = B_FALSE;
1206 1211  
1207 1212          /* LINTED E_BAD_PTR_CAST_ALIGN */
1208 1213          zargp = (zone_cmd_arg_t *)args;
1209 1214  
1210 1215          /*
1211 1216           * When we get the door unref message, we've fdetach'd the door, and
1212 1217           * it is time for us to shut down zoneadmd.
1213 1218           */
1214 1219          if (zargp == DOOR_UNREF_DATA) {
1215 1220                  /*
1216 1221                   * See comment at end of main() for info on the last rites.
1217 1222                   */
1218 1223                  exit(0);
1219 1224          }
1220 1225  
1221 1226          if (zargp == NULL) {
1222 1227                  (void) door_return(NULL, 0, 0, 0);
1223 1228          }
1224 1229  
1225 1230          rvalp = alloca(rlen);
1226 1231          bzero(rvalp, rlen);
1227 1232          zlog.logfile = NULL;
1228 1233          zlog.buflen = zlog.loglen = rlen - sizeof (zone_cmd_rval_t) + 1;
1229 1234          zlog.buf = rvalp->errbuf;
1230 1235          zlog.log = zlog.buf;
1231 1236          /* defer initialization of zlog.locale until after credential check */
1232 1237          zlogp = &zlog;
1233 1238  
1234 1239          if (alen != sizeof (zone_cmd_arg_t)) {
1235 1240                  /*
1236 1241                   * This really shouldn't be happening.
1237 1242                   */
1238 1243                  zerror(&logsys, B_FALSE, "argument size (%d bytes) "
1239 1244                      "unexpected (expected %d bytes)", alen,
1240 1245                      sizeof (zone_cmd_arg_t));
1241 1246                  goto out;
1242 1247          }
1243 1248          cmd = zargp->cmd;
1244 1249  
1245 1250          if (door_ucred(&uc) != 0) {
1246 1251                  zerror(&logsys, B_TRUE, "door_ucred");
1247 1252                  goto out;
1248 1253          }
1249 1254          eset = ucred_getprivset(uc, PRIV_EFFECTIVE);
1250 1255          if (ucred_getzoneid(uc) != GLOBAL_ZONEID ||
1251 1256              (eset != NULL ? !priv_ismember(eset, PRIV_SYS_CONFIG) :
1252 1257              ucred_geteuid(uc) != 0)) {
1253 1258                  zerror(&logsys, B_FALSE, "insufficient privileges");
1254 1259                  goto out;
1255 1260          }
1256 1261  
1257 1262          kernelcall = ucred_getpid(uc) == 0;
1258 1263  
1259 1264          /*
1260 1265           * This is safe because we only use a zlog_t throughout the
1261 1266           * duration of a door call; i.e., by the time the pointer
1262 1267           * might become invalid, the door call would be over.
1263 1268           */
1264 1269          zlog.locale = kernelcall ? DEFAULT_LOCALE : zargp->locale;
1265 1270  
1266 1271          (void) mutex_lock(&lock);
1267 1272  
1268 1273          /*
1269 1274           * Once we start to really die off, we don't want more connections.
1270 1275           */
1271 1276          if (in_death_throes) {
1272 1277                  (void) mutex_unlock(&lock);
1273 1278                  ucred_free(uc);
1274 1279                  (void) door_return(NULL, 0, 0, 0);
1275 1280                  thr_exit(NULL);
1276 1281          }
1277 1282  
1278 1283          /*
1279 1284           * Check for validity of command.
1280 1285           */
1281 1286          if (cmd != Z_READY && cmd != Z_BOOT && cmd != Z_FORCEBOOT &&
1282 1287              cmd != Z_REBOOT && cmd != Z_SHUTDOWN && cmd != Z_HALT &&
1283 1288              cmd != Z_NOTE_UNINSTALLING && cmd != Z_MOUNT &&
1284 1289              cmd != Z_FORCEMOUNT && cmd != Z_UNMOUNT) {
1285 1290                  zerror(&logsys, B_FALSE, "invalid command %d", (int)cmd);
1286 1291                  goto out;
1287 1292          }
1288 1293  
1289 1294          if (kernelcall && (cmd != Z_HALT && cmd != Z_REBOOT)) {
1290 1295                  /*
1291 1296                   * Can't happen
1292 1297                   */
1293 1298                  zerror(&logsys, B_FALSE, "received unexpected kernel upcall %d",
1294 1299                      cmd);
1295 1300                  goto out;
1296 1301          }
1297 1302          /*
1298 1303           * We ignore the possibility of someone calling zone_create(2)
1299 1304           * explicitly; all requests must come through zoneadmd.
1300 1305           */
1301 1306          if (zone_get_state(zone_name, &zstate) != Z_OK) {
1302 1307                  /*
1303 1308                   * Something terribly wrong happened
1304 1309                   */
1305 1310                  zerror(&logsys, B_FALSE, "unable to determine state of zone");
1306 1311                  goto out;
1307 1312          }
1308 1313  
1309 1314          if (kernelcall) {
1310 1315                  /*
1311 1316                   * Kernel-initiated requests may lose their validity if the
1312 1317                   * zone_t the kernel was referring to has gone away.
1313 1318                   */
1314 1319                  if ((zoneid = getzoneidbyname(zone_name)) == -1 ||
1315 1320                      zone_getattr(zoneid, ZONE_ATTR_UNIQID, &uniqid,
1316 1321                      sizeof (uniqid)) == -1 || uniqid != zargp->uniqid) {
1317 1322                          /*
1318 1323                           * We're not talking about the same zone. The request
1319 1324                           * must have arrived too late.  Return error.
1320 1325                           */
1321 1326                          rval = -1;
1322 1327                          goto out;
1323 1328                  }
1324 1329                  zlogp = &logsys;        /* Log errors to syslog */
1325 1330          }
1326 1331  
1327 1332          /*
1328 1333           * If we are being asked to forcibly mount or boot a zone, we
1329 1334           * pretend that an INCOMPLETE zone is actually INSTALLED.
1330 1335           */
1331 1336          if (zstate == ZONE_STATE_INCOMPLETE &&
1332 1337              (cmd == Z_FORCEBOOT || cmd == Z_FORCEMOUNT))
1333 1338                  zstate = ZONE_STATE_INSTALLED;
1334 1339  
1335 1340          switch (zstate) {
1336 1341          case ZONE_STATE_CONFIGURED:
1337 1342          case ZONE_STATE_INCOMPLETE:
1338 1343                  /*
1339 1344                   * Not our area of expertise; we just print a nice message
1340 1345                   * and die off.
1341 1346                   */
1342 1347                  zerror(zlogp, B_FALSE,
1343 1348                      "%s operation is invalid for zones in state '%s'",
1344 1349                      z_cmd_name(cmd), zone_state_str(zstate));
1345 1350                  break;
1346 1351  
1347 1352          case ZONE_STATE_INSTALLED:
1348 1353                  switch (cmd) {
1349 1354                  case Z_READY:
1350 1355                          rval = zone_ready(zlogp, Z_MNT_BOOT, zstate);
1351 1356                          if (rval == 0)
1352 1357                                  eventstream_write(Z_EVT_ZONE_READIED);
1353 1358                          break;
1354 1359                  case Z_BOOT:
1355 1360                  case Z_FORCEBOOT:
1356 1361                          eventstream_write(Z_EVT_ZONE_BOOTING);
1357 1362                          if ((rval = zone_ready(zlogp, Z_MNT_BOOT, zstate))
1358 1363                              == 0) {
1359 1364                                  rval = zone_bootup(zlogp, zargp->bootbuf,
1360 1365                                      zstate);
1361 1366                          }
1362 1367                          audit_put_record(zlogp, uc, rval, "boot");
1363 1368                          if (rval != 0) {
1364 1369                                  bringup_failure_recovery = B_TRUE;
1365 1370                                  (void) zone_halt(zlogp, B_FALSE, B_FALSE,
1366 1371                                      zstate);
1367 1372                                  eventstream_write(Z_EVT_ZONE_BOOTFAILED);
1368 1373                          }
1369 1374                          break;
1370 1375                  case Z_SHUTDOWN:
1371 1376                  case Z_HALT:
1372 1377                          if (kernelcall) /* Invalid; can't happen */
1373 1378                                  abort();
1374 1379                          /*
1375 1380                           * We could have two clients racing to halt this
1376 1381                           * zone; the second client loses, but his request
1377 1382                           * doesn't fail, since the zone is now in the desired
1378 1383                           * state.
1379 1384                           */
1380 1385                          zerror(zlogp, B_FALSE, "zone is already halted");
1381 1386                          rval = 0;
1382 1387                          break;
1383 1388                  case Z_REBOOT:
1384 1389                          if (kernelcall) /* Invalid; can't happen */
1385 1390                                  abort();
1386 1391                          zerror(zlogp, B_FALSE, "%s operation is invalid "
1387 1392                              "for zones in state '%s'", z_cmd_name(cmd),
1388 1393                              zone_state_str(zstate));
1389 1394                          rval = -1;
1390 1395                          break;
1391 1396                  case Z_NOTE_UNINSTALLING:
1392 1397                          if (kernelcall) /* Invalid; can't happen */
1393 1398                                  abort();
1394 1399                          /*
1395 1400                           * Tell the console to print out a message about this.
1396 1401                           * Once it does, we will be in_death_throes.
1397 1402                           */
1398 1403                          eventstream_write(Z_EVT_ZONE_UNINSTALLING);
1399 1404                          break;
1400 1405                  case Z_MOUNT:
1401 1406                  case Z_FORCEMOUNT:
1402 1407                          if (kernelcall) /* Invalid; can't happen */
1403 1408                                  abort();
1404 1409                          if (!zone_isnative && !zone_iscluster &&
1405 1410                              !zone_islabeled) {
1406 1411                                  /*
1407 1412                                   * -U mounts the zone without lofs mounting
1408 1413                                   * zone file systems back into the scratch
1409 1414                                   * zone.  This is required when mounting
1410 1415                                   * non-native branded zones.
1411 1416                                   */
1412 1417                                  (void) strlcpy(zargp->bootbuf, "-U",
1413 1418                                      BOOTARGS_MAX);
1414 1419                          }
1415 1420  
1416 1421                          rval = zone_ready(zlogp,
1417 1422                              strcmp(zargp->bootbuf, "-U") == 0 ?
1418 1423                              Z_MNT_UPDATE : Z_MNT_SCRATCH, zstate);
1419 1424                          if (rval != 0)
1420 1425                                  break;
1421 1426  
1422 1427                          eventstream_write(Z_EVT_ZONE_READIED);
1423 1428  
1424 1429                          /*
1425 1430                           * Get a handle to the default brand info.
1426 1431                           * We must always use the default brand file system
1427 1432                           * list when mounting the zone.
1428 1433                           */
1429 1434                          if ((bh = brand_open(default_brand)) == NULL) {
1430 1435                                  rval = -1;
1431 1436                                  break;
1432 1437                          }
1433 1438  
1434 1439                          /*
1435 1440                           * Get the list of filesystems to mount from
1436 1441                           * the brand configuration.  These mounts are done
1437 1442                           * via a thread that will enter the zone, so they
1438 1443                           * are done from within the context of the zone.
1439 1444                           */
1440 1445                          cb.zlogp = zlogp;
1441 1446                          cb.zoneid = zone_id;
1442 1447                          cb.mount_cmd = B_TRUE;
1443 1448                          rval = brand_platform_iter_mounts(bh,
1444 1449                              mount_early_fs, &cb);
1445 1450  
1446 1451                          brand_close(bh);
1447 1452  
1448 1453                          /*
1449 1454                           * Ordinarily, /dev/fd would be mounted inside the zone
1450 1455                           * by svc:/system/filesystem/usr:default, but since
1451 1456                           * we're not booting the zone, we need to do this
1452 1457                           * manually.
1453 1458                           */
1454 1459                          if (rval == 0)
1455 1460                                  rval = mount_early_fs(&cb,
1456 1461                                      "fd", "/dev/fd", "fd", NULL);
1457 1462                          break;
1458 1463                  case Z_UNMOUNT:
1459 1464                          if (kernelcall) /* Invalid; can't happen */
1460 1465                                  abort();
1461 1466                          zerror(zlogp, B_FALSE, "zone is already unmounted");
1462 1467                          rval = 0;
1463 1468                          break;
1464 1469                  }
1465 1470                  break;
1466 1471  
1467 1472          case ZONE_STATE_READY:
1468 1473                  switch (cmd) {
1469 1474                  case Z_READY:
  
    | 
      ↓ open down ↓ | 
    684 lines elided | 
    
      ↑ open up ↑ | 
  
1470 1475                          /*
1471 1476                           * We could have two clients racing to ready this
1472 1477                           * zone; the second client loses, but his request
1473 1478                           * doesn't fail, since the zone is now in the desired
1474 1479                           * state.
1475 1480                           */
1476 1481                          zerror(zlogp, B_FALSE, "zone is already ready");
1477 1482                          rval = 0;
1478 1483                          break;
1479 1484                  case Z_BOOT:
     1485 +                case Z_FORCEBOOT:
1480 1486                          (void) strlcpy(boot_args, zargp->bootbuf,
1481 1487                              sizeof (boot_args));
1482 1488                          eventstream_write(Z_EVT_ZONE_BOOTING);
1483 1489                          rval = zone_bootup(zlogp, zargp->bootbuf, zstate);
1484 1490                          audit_put_record(zlogp, uc, rval, "boot");
1485 1491                          if (rval != 0) {
1486 1492                                  bringup_failure_recovery = B_TRUE;
1487 1493                                  (void) zone_halt(zlogp, B_FALSE, B_TRUE,
1488 1494                                      zstate);
1489 1495                                  eventstream_write(Z_EVT_ZONE_BOOTFAILED);
1490 1496                          }
1491 1497                          boot_args[0] = '\0';
1492 1498                          break;
1493 1499                  case Z_HALT:
1494 1500                          if (kernelcall) /* Invalid; can't happen */
  
    | 
      ↓ open down ↓ | 
    5 lines elided | 
    
      ↑ open up ↑ | 
  
1495 1501                                  abort();
1496 1502                          if ((rval = zone_halt(zlogp, B_FALSE, B_FALSE, zstate))
1497 1503                              != 0)
1498 1504                                  break;
1499 1505                          eventstream_write(Z_EVT_ZONE_HALTED);
1500 1506                          break;
1501 1507                  case Z_SHUTDOWN:
1502 1508                  case Z_REBOOT:
1503 1509                  case Z_NOTE_UNINSTALLING:
1504 1510                  case Z_MOUNT:
     1511 +                case Z_FORCEMOUNT:
1505 1512                  case Z_UNMOUNT:
1506 1513                          if (kernelcall) /* Invalid; can't happen */
1507 1514                                  abort();
1508 1515                          zerror(zlogp, B_FALSE, "%s operation is invalid "
1509 1516                              "for zones in state '%s'", z_cmd_name(cmd),
1510 1517                              zone_state_str(zstate));
1511 1518                          rval = -1;
1512 1519                          break;
1513 1520                  }
1514 1521                  break;
1515 1522  
1516 1523          case ZONE_STATE_MOUNTED:
1517 1524                  switch (cmd) {
1518 1525                  case Z_UNMOUNT:
1519 1526                          if (kernelcall) /* Invalid; can't happen */
1520 1527                                  abort();
1521 1528                          rval = zone_halt(zlogp, B_TRUE, B_FALSE, zstate);
1522 1529                          if (rval == 0) {
1523 1530                                  eventstream_write(Z_EVT_ZONE_HALTED);
1524 1531                                  (void) sema_post(&scratch_sem);
1525 1532                          }
1526 1533                          break;
1527 1534                  default:
1528 1535                          if (kernelcall) /* Invalid; can't happen */
1529 1536                                  abort();
1530 1537                          zerror(zlogp, B_FALSE, "%s operation is invalid "
1531 1538                              "for zones in state '%s'", z_cmd_name(cmd),
1532 1539                              zone_state_str(zstate));
1533 1540                          rval = -1;
1534 1541                          break;
1535 1542                  }
1536 1543                  break;
1537 1544  
1538 1545          case ZONE_STATE_RUNNING:
1539 1546          case ZONE_STATE_SHUTTING_DOWN:
1540 1547          case ZONE_STATE_DOWN:
1541 1548                  switch (cmd) {
  
    | 
      ↓ open down ↓ | 
    27 lines elided | 
    
      ↑ open up ↑ | 
  
1542 1549                  case Z_READY:
1543 1550                          if ((rval = zone_halt(zlogp, B_FALSE, B_TRUE, zstate))
1544 1551                              != 0)
1545 1552                                  break;
1546 1553                          if ((rval = zone_ready(zlogp, Z_MNT_BOOT, zstate)) == 0)
1547 1554                                  eventstream_write(Z_EVT_ZONE_READIED);
1548 1555                          else
1549 1556                                  eventstream_write(Z_EVT_ZONE_HALTED);
1550 1557                          break;
1551 1558                  case Z_BOOT:
     1559 +                case Z_FORCEBOOT:
1552 1560                          /*
1553 1561                           * We could have two clients racing to boot this
1554 1562                           * zone; the second client loses, but his request
1555 1563                           * doesn't fail, since the zone is now in the desired
1556 1564                           * state.
1557 1565                           */
1558 1566                          zerror(zlogp, B_FALSE, "zone is already booted");
1559 1567                          rval = 0;
1560 1568                          break;
1561 1569                  case Z_HALT:
1562 1570                          if ((rval = zone_halt(zlogp, B_FALSE, B_FALSE, zstate))
1563 1571                              != 0)
1564 1572                                  break;
1565 1573                          eventstream_write(Z_EVT_ZONE_HALTED);
1566 1574                          break;
1567 1575                  case Z_REBOOT:
1568 1576                          (void) strlcpy(boot_args, zargp->bootbuf,
1569 1577                              sizeof (boot_args));
1570 1578                          eventstream_write(Z_EVT_ZONE_REBOOTING);
1571 1579                          if ((rval = zone_halt(zlogp, B_FALSE, B_TRUE, zstate))
1572 1580                              != 0) {
1573 1581                                  eventstream_write(Z_EVT_ZONE_BOOTFAILED);
1574 1582                                  boot_args[0] = '\0';
1575 1583                                  break;
1576 1584                          }
1577 1585                          if ((rval = zone_ready(zlogp, Z_MNT_BOOT, zstate))
1578 1586                              != 0) {
1579 1587                                  eventstream_write(Z_EVT_ZONE_BOOTFAILED);
1580 1588                                  boot_args[0] = '\0';
1581 1589                                  break;
1582 1590                          }
1583 1591                          rval = zone_bootup(zlogp, zargp->bootbuf, zstate);
1584 1592                          audit_put_record(zlogp, uc, rval, "reboot");
1585 1593                          if (rval != 0) {
1586 1594                                  (void) zone_halt(zlogp, B_FALSE, B_TRUE,
1587 1595                                      zstate);
1588 1596                                  eventstream_write(Z_EVT_ZONE_BOOTFAILED);
  
    | 
      ↓ open down ↓ | 
    27 lines elided | 
    
      ↑ open up ↑ | 
  
1589 1597                          }
1590 1598                          boot_args[0] = '\0';
1591 1599                          break;
1592 1600                  case Z_SHUTDOWN:
1593 1601                          if ((rval = zone_graceful_shutdown(zlogp)) == 0) {
1594 1602                                  wait_shut = B_TRUE;
1595 1603                          }
1596 1604                          break;
1597 1605                  case Z_NOTE_UNINSTALLING:
1598 1606                  case Z_MOUNT:
     1607 +                case Z_FORCEMOUNT:
1599 1608                  case Z_UNMOUNT:
1600 1609                          zerror(zlogp, B_FALSE, "%s operation is invalid "
1601 1610                              "for zones in state '%s'", z_cmd_name(cmd),
1602 1611                              zone_state_str(zstate));
1603 1612                          rval = -1;
1604 1613                          break;
1605 1614                  }
1606 1615                  break;
1607 1616          default:
1608 1617                  abort();
1609 1618          }
1610 1619  
1611 1620          /*
1612 1621           * Because the state of the zone may have changed, we make sure
1613 1622           * to wake the console poller, which is in charge of initiating
1614 1623           * the shutdown procedure as necessary.
1615 1624           */
1616 1625          eventstream_write(Z_EVT_NULL);
1617 1626  
1618 1627  out:
1619 1628          (void) mutex_unlock(&lock);
1620 1629  
1621 1630          /* Wait for the Z_SHUTDOWN commands to complete */
1622 1631          if (wait_shut)
1623 1632                  rval = zone_wait_shutdown(zlogp);
1624 1633  
1625 1634          if (kernelcall) {
1626 1635                  rvalp = NULL;
1627 1636                  rlen = 0;
1628 1637          } else {
1629 1638                  rvalp->rval = rval;
1630 1639          }
1631 1640          if (uc != NULL)
1632 1641                  ucred_free(uc);
1633 1642          (void) door_return((char *)rvalp, rlen, NULL, 0);
1634 1643          thr_exit(NULL);
1635 1644  }
1636 1645  
1637 1646  static int
1638 1647  setup_door(zlog_t *zlogp)
1639 1648  {
1640 1649          if ((zone_door = door_create(server, NULL,
1641 1650              DOOR_UNREF | DOOR_REFUSE_DESC | DOOR_NO_CANCEL)) < 0) {
1642 1651                  zerror(zlogp, B_TRUE, "%s failed", "door_create");
1643 1652                  return (-1);
1644 1653          }
1645 1654          (void) fdetach(zone_door_path);
1646 1655  
1647 1656          if (fattach(zone_door, zone_door_path) != 0) {
1648 1657                  zerror(zlogp, B_TRUE, "fattach to %s failed", zone_door_path);
1649 1658                  (void) door_revoke(zone_door);
1650 1659                  (void) fdetach(zone_door_path);
1651 1660                  zone_door = -1;
1652 1661                  return (-1);
1653 1662          }
1654 1663          return (0);
1655 1664  }
1656 1665  
1657 1666  /*
1658 1667   * zoneadm(1m) will start zoneadmd if it thinks it isn't running; this
1659 1668   * is where zoneadmd itself will check to see that another instance of
1660 1669   * zoneadmd isn't already controlling this zone.
1661 1670   *
1662 1671   * The idea here is that we want to open the path to which we will
1663 1672   * attach our door, lock it, and then make sure that no-one has beat us
1664 1673   * to fattach(3c)ing onto it.
1665 1674   *
1666 1675   * fattach(3c) is really a mount, so there are actually two possible
1667 1676   * vnodes we could be dealing with.  Our strategy is as follows:
1668 1677   *
1669 1678   * - If the file we opened is a regular file (common case):
1670 1679   *      There is no fattach(3c)ed door, so we have a chance of becoming
1671 1680   *      the managing zoneadmd. We attempt to lock the file: if it is
1672 1681   *      already locked, that means someone else raced us here, so we
1673 1682   *      lose and give up.  zoneadm(1m) will try to contact the zoneadmd
1674 1683   *      that beat us to it.
1675 1684   *
1676 1685   * - If the file we opened is a namefs file:
1677 1686   *      This means there is already an established door fattach(3c)'ed
1678 1687   *      to the rendezvous path.  We've lost the race, so we give up.
1679 1688   *      Note that in this case we also try to grab the file lock, and
1680 1689   *      will succeed in acquiring it since the vnode locked by the
1681 1690   *      "winning" zoneadmd was a regular one, and the one we locked was
1682 1691   *      the fattach(3c)'ed door node.  At any rate, no harm is done, and
1683 1692   *      we just return to zoneadm(1m) which knows to retry.
1684 1693   */
1685 1694  static int
1686 1695  make_daemon_exclusive(zlog_t *zlogp)
1687 1696  {
1688 1697          int doorfd = -1;
1689 1698          int err, ret = -1;
1690 1699          struct stat st;
1691 1700          struct flock flock;
1692 1701          zone_state_t zstate;
1693 1702  
1694 1703  top:
1695 1704          if ((err = zone_get_state(zone_name, &zstate)) != Z_OK) {
1696 1705                  zerror(zlogp, B_FALSE, "failed to get zone state: %s",
1697 1706                      zonecfg_strerror(err));
1698 1707                  goto out;
1699 1708          }
1700 1709          if ((doorfd = open(zone_door_path, O_CREAT|O_RDWR,
1701 1710              S_IREAD|S_IWRITE)) < 0) {
1702 1711                  zerror(zlogp, B_TRUE, "failed to open %s", zone_door_path);
1703 1712                  goto out;
1704 1713          }
1705 1714          if (fstat(doorfd, &st) < 0) {
1706 1715                  zerror(zlogp, B_TRUE, "failed to stat %s", zone_door_path);
1707 1716                  goto out;
1708 1717          }
1709 1718          /*
1710 1719           * Lock the file to synchronize with other zoneadmd
1711 1720           */
1712 1721          flock.l_type = F_WRLCK;
1713 1722          flock.l_whence = SEEK_SET;
1714 1723          flock.l_start = (off_t)0;
1715 1724          flock.l_len = (off_t)0;
1716 1725          if (fcntl(doorfd, F_SETLK, &flock) < 0) {
1717 1726                  /*
1718 1727                   * Someone else raced us here and grabbed the lock file
1719 1728                   * first.  A warning here is inappropriate since nothing
1720 1729                   * went wrong.
1721 1730                   */
1722 1731                  goto out;
1723 1732          }
1724 1733  
1725 1734          if (strcmp(st.st_fstype, "namefs") == 0) {
1726 1735                  struct door_info info;
1727 1736  
1728 1737                  /*
1729 1738                   * There is already something fattach()'ed to this file.
1730 1739                   * Lets see what the door is up to.
1731 1740                   */
1732 1741                  if (door_info(doorfd, &info) == 0 && info.di_target != -1) {
1733 1742                          /*
1734 1743                           * Another zoneadmd process seems to be in
1735 1744                           * control of the situation and we don't need to
1736 1745                           * be here.  A warning here is inappropriate
1737 1746                           * since nothing went wrong.
1738 1747                           *
1739 1748                           * If the door has been revoked, the zoneadmd
1740 1749                           * process currently managing the zone is going
1741 1750                           * away.  We'll return control to zoneadm(1m)
1742 1751                           * which will try again (by which time zoneadmd
1743 1752                           * will hopefully have exited).
1744 1753                           */
1745 1754                          goto out;
1746 1755                  }
1747 1756  
1748 1757                  /*
1749 1758                   * If we got this far, there's a fattach(3c)'ed door
1750 1759                   * that belongs to a process that has exited, which can
1751 1760                   * happen if the previous zoneadmd died unexpectedly.
1752 1761                   *
1753 1762                   * Let user know that something is amiss, but that we can
1754 1763                   * recover; if the zone is in the installed state, then don't
1755 1764                   * message, since having a running zoneadmd isn't really
1756 1765                   * expected/needed.  We want to keep occurences of this message
1757 1766                   * limited to times when zoneadmd is picking back up from a
1758 1767                   * zoneadmd that died while the zone was in some non-trivial
1759 1768                   * state.
1760 1769                   */
1761 1770                  if (zstate > ZONE_STATE_INSTALLED) {
1762 1771                          zerror(zlogp, B_FALSE,
1763 1772                              "zone '%s': WARNING: zone is in state '%s', but "
1764 1773                              "zoneadmd does not appear to be available; "
1765 1774                              "restarted zoneadmd to recover.",
1766 1775                              zone_name, zone_state_str(zstate));
1767 1776                  }
1768 1777  
1769 1778                  (void) fdetach(zone_door_path);
1770 1779                  (void) close(doorfd);
1771 1780                  goto top;
1772 1781          }
1773 1782          ret = 0;
1774 1783  out:
1775 1784          (void) close(doorfd);
1776 1785          return (ret);
1777 1786  }
1778 1787  
1779 1788  /*
1780 1789   * Setup the brand's pre and post state change callbacks, as well as the
1781 1790   * query callback, if any of these exist.
1782 1791   */
1783 1792  static int
1784 1793  brand_callback_init(brand_handle_t bh, char *zone_name)
1785 1794  {
1786 1795          char zpath[MAXPATHLEN];
1787 1796  
1788 1797          if (zone_get_zonepath(zone_name, zpath, sizeof (zpath)) != Z_OK)
1789 1798                  return (-1);
1790 1799  
1791 1800          (void) strlcpy(pre_statechg_hook, EXEC_PREFIX,
1792 1801              sizeof (pre_statechg_hook));
1793 1802  
1794 1803          if (brand_get_prestatechange(bh, zone_name, zpath,
1795 1804              pre_statechg_hook + EXEC_LEN,
1796 1805              sizeof (pre_statechg_hook) - EXEC_LEN) != 0)
1797 1806                  return (-1);
1798 1807  
1799 1808          if (strlen(pre_statechg_hook) <= EXEC_LEN)
1800 1809                  pre_statechg_hook[0] = '\0';
1801 1810  
1802 1811          (void) strlcpy(post_statechg_hook, EXEC_PREFIX,
1803 1812              sizeof (post_statechg_hook));
1804 1813  
1805 1814          if (brand_get_poststatechange(bh, zone_name, zpath,
1806 1815              post_statechg_hook + EXEC_LEN,
1807 1816              sizeof (post_statechg_hook) - EXEC_LEN) != 0)
1808 1817                  return (-1);
1809 1818  
1810 1819          if (strlen(post_statechg_hook) <= EXEC_LEN)
1811 1820                  post_statechg_hook[0] = '\0';
1812 1821  
1813 1822          (void) strlcpy(query_hook, EXEC_PREFIX,
1814 1823              sizeof (query_hook));
1815 1824  
1816 1825          if (brand_get_query(bh, zone_name, zpath, query_hook + EXEC_LEN,
1817 1826              sizeof (query_hook) - EXEC_LEN) != 0)
1818 1827                  return (-1);
1819 1828  
1820 1829          if (strlen(query_hook) <= EXEC_LEN)
1821 1830                  query_hook[0] = '\0';
1822 1831  
1823 1832          return (0);
1824 1833  }
1825 1834  
1826 1835  int
1827 1836  main(int argc, char *argv[])
1828 1837  {
1829 1838          int opt;
1830 1839          zoneid_t zid;
1831 1840          priv_set_t *privset;
1832 1841          zone_state_t zstate;
1833 1842          char parents_locale[MAXPATHLEN];
1834 1843          brand_handle_t bh;
1835 1844          int err;
1836 1845  
1837 1846          pid_t pid;
1838 1847          sigset_t blockset;
1839 1848          sigset_t block_cld;
1840 1849  
1841 1850          struct {
1842 1851                  sema_t sem;
1843 1852                  int status;
1844 1853                  zlog_t log;
1845 1854          } *shstate;
1846 1855          size_t shstatelen = getpagesize();
1847 1856  
1848 1857          zlog_t errlog;
1849 1858          zlog_t *zlogp;
1850 1859  
1851 1860          int ctfd;
1852 1861  
1853 1862          progname = get_execbasename(argv[0]);
1854 1863  
1855 1864          /*
1856 1865           * Make sure stderr is unbuffered
1857 1866           */
1858 1867          (void) setbuffer(stderr, NULL, 0);
1859 1868  
1860 1869          /*
1861 1870           * Get out of the way of mounted filesystems, since we will daemonize
1862 1871           * soon.
1863 1872           */
1864 1873          (void) chdir("/");
1865 1874  
1866 1875          /*
1867 1876           * Use the default system umask per PSARC 1998/110 rather than
1868 1877           * anything that may have been set by the caller.
1869 1878           */
1870 1879          (void) umask(CMASK);
1871 1880  
1872 1881          /*
1873 1882           * Initially we want to use our parent's locale.
1874 1883           */
1875 1884          (void) setlocale(LC_ALL, "");
1876 1885          (void) textdomain(TEXT_DOMAIN);
1877 1886          (void) strlcpy(parents_locale, setlocale(LC_MESSAGES, NULL),
1878 1887              sizeof (parents_locale));
1879 1888  
1880 1889          /*
1881 1890           * This zlog_t is used for writing to stderr
1882 1891           */
1883 1892          errlog.logfile = stderr;
1884 1893          errlog.buflen = errlog.loglen = 0;
1885 1894          errlog.buf = errlog.log = NULL;
1886 1895          errlog.locale = parents_locale;
1887 1896  
1888 1897          /*
1889 1898           * We start off writing to stderr until we're ready to daemonize.
1890 1899           */
1891 1900          zlogp = &errlog;
1892 1901  
1893 1902          /*
1894 1903           * Process options.
1895 1904           */
1896 1905          while ((opt = getopt(argc, argv, "R:z:")) != EOF) {
1897 1906                  switch (opt) {
1898 1907                  case 'R':
1899 1908                          zonecfg_set_root(optarg);
1900 1909                          break;
1901 1910                  case 'z':
1902 1911                          zone_name = optarg;
1903 1912                          break;
1904 1913                  default:
1905 1914                          usage();
1906 1915                  }
1907 1916          }
1908 1917  
1909 1918          if (zone_name == NULL)
1910 1919                  usage();
1911 1920  
1912 1921          /*
1913 1922           * Because usage() prints directly to stderr, it has gettext()
1914 1923           * wrapping, which depends on the locale.  But since zerror() calls
1915 1924           * localize() which tweaks the locale, it is not safe to call zerror()
1916 1925           * until after the last call to usage().  Fortunately, the last call
1917 1926           * to usage() is just above and the first call to zerror() is just
1918 1927           * below.  Don't mess this up.
1919 1928           */
1920 1929          if (strcmp(zone_name, GLOBAL_ZONENAME) == 0) {
1921 1930                  zerror(zlogp, B_FALSE, "cannot manage the %s zone",
1922 1931                      GLOBAL_ZONENAME);
1923 1932                  return (1);
1924 1933          }
1925 1934  
1926 1935          if (zone_get_id(zone_name, &zid) != 0) {
1927 1936                  zerror(zlogp, B_FALSE, "could not manage %s: %s", zone_name,
1928 1937                      zonecfg_strerror(Z_NO_ZONE));
1929 1938                  return (1);
1930 1939          }
1931 1940  
1932 1941          if ((err = zone_get_state(zone_name, &zstate)) != Z_OK) {
1933 1942                  zerror(zlogp, B_FALSE, "failed to get zone state: %s",
1934 1943                      zonecfg_strerror(err));
1935 1944                  return (1);
1936 1945          }
1937 1946          if (zstate < ZONE_STATE_INCOMPLETE) {
1938 1947                  zerror(zlogp, B_FALSE,
1939 1948                      "cannot manage a zone which is in state '%s'",
1940 1949                      zone_state_str(zstate));
1941 1950                  return (1);
1942 1951          }
1943 1952  
1944 1953          if (zonecfg_default_brand(default_brand,
1945 1954              sizeof (default_brand)) != Z_OK) {
1946 1955                  zerror(zlogp, B_FALSE, "unable to determine default brand");
1947 1956                  return (1);
1948 1957          }
1949 1958  
1950 1959          /* Get a handle to the brand info for this zone */
1951 1960          if (zone_get_brand(zone_name, brand_name, sizeof (brand_name))
1952 1961              != Z_OK) {
1953 1962                  zerror(zlogp, B_FALSE, "unable to determine zone brand");
1954 1963                  return (1);
1955 1964          }
1956 1965          zone_isnative = (strcmp(brand_name, NATIVE_BRAND_NAME) == 0);
1957 1966          zone_islabeled = (strcmp(brand_name, LABELED_BRAND_NAME) == 0);
1958 1967  
1959 1968          /*
1960 1969           * In the alternate root environment, the only supported
1961 1970           * operations are mount and unmount.  In this case, just treat
1962 1971           * the zone as native if it is cluster.  Cluster zones can be
1963 1972           * native for the purpose of LU or upgrade, and the cluster
1964 1973           * brand may not exist in the miniroot (such as in net install
1965 1974           * upgrade).
1966 1975           */
1967 1976          if (strcmp(brand_name, CLUSTER_BRAND_NAME) == 0) {
1968 1977                  zone_iscluster = B_TRUE;
1969 1978                  if (zonecfg_in_alt_root()) {
1970 1979                          (void) strlcpy(brand_name, default_brand,
1971 1980                              sizeof (brand_name));
1972 1981                  }
1973 1982          } else {
1974 1983                  zone_iscluster = B_FALSE;
1975 1984          }
1976 1985  
1977 1986          if ((bh = brand_open(brand_name)) == NULL) {
1978 1987                  zerror(zlogp, B_FALSE, "unable to open zone brand");
1979 1988                  return (1);
1980 1989          }
1981 1990  
1982 1991          /* Get state change brand hooks. */
1983 1992          if (brand_callback_init(bh, zone_name) == -1) {
1984 1993                  zerror(zlogp, B_TRUE,
1985 1994                      "failed to initialize brand state change hooks");
1986 1995                  brand_close(bh);
1987 1996                  return (1);
1988 1997          }
1989 1998  
1990 1999          brand_close(bh);
1991 2000  
1992 2001          /*
1993 2002           * Check that we have all privileges.  It would be nice to pare
1994 2003           * this down, but this is at least a first cut.
1995 2004           */
1996 2005          if ((privset = priv_allocset()) == NULL) {
1997 2006                  zerror(zlogp, B_TRUE, "%s failed", "priv_allocset");
1998 2007                  return (1);
1999 2008          }
2000 2009  
2001 2010          if (getppriv(PRIV_EFFECTIVE, privset) != 0) {
2002 2011                  zerror(zlogp, B_TRUE, "%s failed", "getppriv");
2003 2012                  priv_freeset(privset);
2004 2013                  return (1);
2005 2014          }
2006 2015  
2007 2016          if (priv_isfullset(privset) == B_FALSE) {
2008 2017                  zerror(zlogp, B_FALSE, "You lack sufficient privilege to "
2009 2018                      "run this command (all privs required)");
2010 2019                  priv_freeset(privset);
2011 2020                  return (1);
2012 2021          }
2013 2022          priv_freeset(privset);
2014 2023  
2015 2024          if (mkzonedir(zlogp) != 0)
2016 2025                  return (1);
2017 2026  
2018 2027          /*
2019 2028           * Pre-fork: setup shared state
2020 2029           */
2021 2030          if ((shstate = (void *)mmap(NULL, shstatelen,
2022 2031              PROT_READ|PROT_WRITE, MAP_SHARED|MAP_ANON, -1, (off_t)0)) ==
2023 2032              MAP_FAILED) {
2024 2033                  zerror(zlogp, B_TRUE, "%s failed", "mmap");
2025 2034                  return (1);
2026 2035          }
2027 2036          if (sema_init(&shstate->sem, 0, USYNC_PROCESS, NULL) != 0) {
2028 2037                  zerror(zlogp, B_TRUE, "%s failed", "sema_init()");
2029 2038                  (void) munmap((char *)shstate, shstatelen);
2030 2039                  return (1);
2031 2040          }
2032 2041          shstate->log.logfile = NULL;
2033 2042          shstate->log.buflen = shstatelen - sizeof (*shstate);
2034 2043          shstate->log.loglen = shstate->log.buflen;
2035 2044          shstate->log.buf = (char *)shstate + sizeof (*shstate);
2036 2045          shstate->log.log = shstate->log.buf;
2037 2046          shstate->log.locale = parents_locale;
2038 2047          shstate->status = -1;
2039 2048  
2040 2049          /*
2041 2050           * We need a SIGCHLD handler so the sema_wait() below will wake
2042 2051           * up if the child dies without doing a sema_post().
2043 2052           */
2044 2053          (void) sigset(SIGCHLD, sigchld);
2045 2054          /*
2046 2055           * We must mask SIGCHLD until after we've coped with the fork
2047 2056           * sufficiently to deal with it; otherwise we can race and
2048 2057           * receive the signal before pid has been initialized
2049 2058           * (yes, this really happens).
2050 2059           */
2051 2060          (void) sigemptyset(&block_cld);
2052 2061          (void) sigaddset(&block_cld, SIGCHLD);
2053 2062          (void) sigprocmask(SIG_BLOCK, &block_cld, NULL);
2054 2063  
2055 2064          if ((ctfd = init_template()) == -1) {
2056 2065                  zerror(zlogp, B_TRUE, "failed to create contract");
2057 2066                  return (1);
2058 2067          }
2059 2068  
2060 2069          /*
2061 2070           * Do not let another thread localize a message while we are forking.
2062 2071           */
2063 2072          (void) mutex_lock(&msglock);
2064 2073          pid = fork();
2065 2074          (void) mutex_unlock(&msglock);
2066 2075  
2067 2076          /*
2068 2077           * In all cases (parent, child, and in the event of an error) we
2069 2078           * don't want to cause creation of contracts on subsequent fork()s.
2070 2079           */
2071 2080          (void) ct_tmpl_clear(ctfd);
2072 2081          (void) close(ctfd);
2073 2082  
2074 2083          if (pid == -1) {
2075 2084                  zerror(zlogp, B_TRUE, "could not fork");
2076 2085                  return (1);
2077 2086  
2078 2087          } else if (pid > 0) { /* parent */
2079 2088                  (void) sigprocmask(SIG_UNBLOCK, &block_cld, NULL);
2080 2089                  /*
2081 2090                   * This marks a window of vulnerability in which we receive
2082 2091                   * the SIGCLD before falling into sema_wait (normally we would
2083 2092                   * get woken up from sema_wait with EINTR upon receipt of
2084 2093                   * SIGCLD).  So we may need to use some other scheme like
2085 2094                   * sema_posting in the sigcld handler.
2086 2095                   * blech
2087 2096                   */
2088 2097                  (void) sema_wait(&shstate->sem);
2089 2098                  (void) sema_destroy(&shstate->sem);
2090 2099                  if (shstate->status != 0)
2091 2100                          (void) waitpid(pid, NULL, WNOHANG);
2092 2101                  /*
2093 2102                   * It's ok if we die with SIGPIPE.  It's not like we could have
2094 2103                   * done anything about it.
2095 2104                   */
2096 2105                  (void) fprintf(stderr, "%s", shstate->log.buf);
2097 2106                  _exit(shstate->status == 0 ? 0 : 1);
2098 2107          }
2099 2108  
2100 2109          /*
2101 2110           * The child charges on.
2102 2111           */
2103 2112          (void) sigset(SIGCHLD, SIG_DFL);
2104 2113          (void) sigprocmask(SIG_UNBLOCK, &block_cld, NULL);
2105 2114  
2106 2115          /*
2107 2116           * SIGPIPE can be delivered if we write to a socket for which the
2108 2117           * peer endpoint is gone.  That can lead to too-early termination
2109 2118           * of zoneadmd, and that's not good eats.
2110 2119           */
2111 2120          (void) sigset(SIGPIPE, SIG_IGN);
2112 2121          /*
2113 2122           * Stop using stderr
2114 2123           */
2115 2124          zlogp = &shstate->log;
2116 2125  
2117 2126          /*
2118 2127           * We don't need stdout/stderr from now on.
2119 2128           */
2120 2129          closefrom(0);
2121 2130  
2122 2131          /*
2123 2132           * Initialize the syslog zlog_t.  This needs to be done after
2124 2133           * the call to closefrom().
2125 2134           */
2126 2135          logsys.buf = logsys.log = NULL;
2127 2136          logsys.buflen = logsys.loglen = 0;
2128 2137          logsys.logfile = NULL;
2129 2138          logsys.locale = DEFAULT_LOCALE;
2130 2139  
2131 2140          openlog("zoneadmd", LOG_PID, LOG_DAEMON);
2132 2141  
2133 2142          /*
2134 2143           * The eventstream is used to publish state changes in the zone
2135 2144           * from the door threads to the console I/O poller.
2136 2145           */
2137 2146          if (eventstream_init() == -1) {
2138 2147                  zerror(zlogp, B_TRUE, "unable to create eventstream");
2139 2148                  goto child_out;
2140 2149          }
2141 2150  
2142 2151          (void) snprintf(zone_door_path, sizeof (zone_door_path),
2143 2152              "%s" ZONE_DOOR_PATH, zonecfg_get_root(), zone_name);
2144 2153  
2145 2154          /*
2146 2155           * See if another zoneadmd is running for this zone.  If not, then we
2147 2156           * can now modify system state.
2148 2157           */
2149 2158          if (make_daemon_exclusive(zlogp) == -1)
2150 2159                  goto child_out;
2151 2160  
2152 2161  
2153 2162          /*
2154 2163           * Create/join a new session; we need to be careful of what we do with
2155 2164           * the console from now on so we don't end up being the session leader
2156 2165           * for the terminal we're going to be handing out.
2157 2166           */
2158 2167          (void) setsid();
2159 2168  
2160 2169          /*
2161 2170           * This thread shouldn't be receiving any signals; in particular,
2162 2171           * SIGCHLD should be received by the thread doing the fork().
2163 2172           */
2164 2173          (void) sigfillset(&blockset);
2165 2174          (void) thr_sigsetmask(SIG_BLOCK, &blockset, NULL);
2166 2175  
2167 2176          /*
2168 2177           * Setup the console device and get ready to serve the console;
2169 2178           * once this has completed, we're ready to let console clients
2170 2179           * make an attempt to connect (they will block until
2171 2180           * serve_console_sock() below gets called, and any pending
2172 2181           * connection is accept()ed).
2173 2182           */
2174 2183          if (!zonecfg_in_alt_root() && init_console(zlogp) < 0)
2175 2184                  goto child_out;
2176 2185  
2177 2186          /*
2178 2187           * Take the lock now, so that when the door server gets going, we
2179 2188           * are guaranteed that it won't take a request until we are sure
2180 2189           * that everything is completely set up.  See the child_out: label
2181 2190           * below to see why this matters.
2182 2191           */
2183 2192          (void) mutex_lock(&lock);
2184 2193  
2185 2194          /* Init semaphore for scratch zones. */
2186 2195          if (sema_init(&scratch_sem, 0, USYNC_THREAD, NULL) == -1) {
2187 2196                  zerror(zlogp, B_TRUE,
2188 2197                      "failed to initialize semaphore for scratch zone");
2189 2198                  goto child_out;
2190 2199          }
2191 2200  
2192 2201          /* open the dladm handle */
2193 2202          if (dladm_open(&dld_handle) != DLADM_STATUS_OK) {
2194 2203                  zerror(zlogp, B_FALSE, "failed to open dladm handle");
2195 2204                  goto child_out;
2196 2205          }
2197 2206  
2198 2207          /*
2199 2208           * Note: door setup must occur *after* the console is setup.
2200 2209           * This is so that as zlogin tests the door to see if zoneadmd
2201 2210           * is ready yet, we know that the console will get serviced
2202 2211           * once door_info() indicates that the door is "up".
2203 2212           */
2204 2213          if (setup_door(zlogp) == -1)
2205 2214                  goto child_out;
2206 2215  
2207 2216          /*
2208 2217           * Things seem OK so far; tell the parent process that we're done
2209 2218           * with setup tasks.  This will cause the parent to exit, signalling
2210 2219           * to zoneadm, zlogin, or whatever forked it that we are ready to
2211 2220           * service requests.
2212 2221           */
2213 2222          shstate->status = 0;
2214 2223          (void) sema_post(&shstate->sem);
2215 2224          (void) munmap((char *)shstate, shstatelen);
2216 2225          shstate = NULL;
2217 2226  
2218 2227          (void) mutex_unlock(&lock);
2219 2228  
2220 2229          /*
2221 2230           * zlogp is now invalid, so reset it to the syslog logger.
2222 2231           */
2223 2232          zlogp = &logsys;
2224 2233  
2225 2234          /*
2226 2235           * Now that we are free of any parents, switch to the default locale.
2227 2236           */
2228 2237          (void) setlocale(LC_ALL, DEFAULT_LOCALE);
2229 2238  
2230 2239          /*
2231 2240           * At this point the setup portion of main() is basically done, so
2232 2241           * we reuse this thread to manage the zone console.  When
2233 2242           * serve_console() has returned, we are past the point of no return
2234 2243           * in the life of this zoneadmd.
2235 2244           */
2236 2245          if (zonecfg_in_alt_root()) {
2237 2246                  /*
2238 2247                   * This is just awful, but mounted scratch zones don't (and
2239 2248                   * can't) have consoles.  We just wait for unmount instead.
2240 2249                   */
2241 2250                  while (sema_wait(&scratch_sem) == EINTR)
2242 2251                          ;
2243 2252          } else {
2244 2253                  serve_console(zlogp);
2245 2254                  assert(in_death_throes);
2246 2255          }
2247 2256  
2248 2257          /*
2249 2258           * This is the next-to-last part of the exit interlock.  Upon calling
2250 2259           * fdetach(), the door will go unreferenced; once any
2251 2260           * outstanding requests (like the door thread doing Z_HALT) are
2252 2261           * done, the door will get an UNREF notification; when it handles
2253 2262           * the UNREF, the door server will cause the exit.  It's possible
2254 2263           * that fdetach() can fail because the file is in use, in which
2255 2264           * case we'll retry the operation.
2256 2265           */
2257 2266          assert(!MUTEX_HELD(&lock));
2258 2267          for (;;) {
2259 2268                  if ((fdetach(zone_door_path) == 0) || (errno != EBUSY))
2260 2269                          break;
2261 2270                  yield();
2262 2271          }
2263 2272  
2264 2273          for (;;)
2265 2274                  (void) pause();
2266 2275  
2267 2276  child_out:
2268 2277          assert(pid == 0);
2269 2278          if (shstate != NULL) {
2270 2279                  shstate->status = -1;
2271 2280                  (void) sema_post(&shstate->sem);
2272 2281                  (void) munmap((char *)shstate, shstatelen);
2273 2282          }
2274 2283  
2275 2284          /*
2276 2285           * This might trigger an unref notification, but if so,
2277 2286           * we are still holding the lock, so our call to exit will
2278 2287           * ultimately win the race and will publish the right exit
2279 2288           * code.
2280 2289           */
2281 2290          if (zone_door != -1) {
2282 2291                  assert(MUTEX_HELD(&lock));
2283 2292                  (void) door_revoke(zone_door);
2284 2293                  (void) fdetach(zone_door_path);
2285 2294          }
2286 2295  
2287 2296          if (dld_handle != NULL)
2288 2297                  dladm_close(dld_handle);
2289 2298  
2290 2299          return (1); /* return from main() forcibly exits an MT process */
2291 2300  }
  
    | 
      ↓ open down ↓ | 
    683 lines elided | 
    
      ↑ open up ↑ | 
  
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX