Print this page
    
    
      
        | Split | 
	Close | 
      
      | Expand all | 
      | Collapse all | 
    
    
          --- old/usr/src/cmd/zoneadmd/zfd.c
          +++ new/usr/src/cmd/zoneadmd/zfd.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 2009 Sun Microsystems, Inc.  All rights reserved.
  24   24   * Use is subject to license terms.
  25   25   * Copyright 2016 Joyent, Inc.  All rights reserved.
  26   26   */
  27   27  
  28   28  /*
  29   29   * Zone file descriptor support is used as a mechanism for a process inside the
  30   30   * zone to log messages to the GZ zoneadmd and also as a way to interact
  31   31   * directly with the process (via zlogin -I). The zfd thread is modeled on
  32   32   * the zcons thread so see the comment header in zcons.c for a general overview.
  33   33   * Unlike with zcons, which has a single endpoint within the zone and a single
  34   34   * endpoint used by zoneadmd, we setup multiple endpoints within the zone.
  35   35   *
  36   36   * The mode, which is controlled by the zone attribute "zlog-mode" is somewhat
  37   37   * of a misnomer since its purpose has evolved. The attribute currently
  38   38   * can have six values which are used to control:
  39   39   *    - how the zfd devices are used inside the zone
  40   40   *    - if the output on the device(s) is also teed into another stream within
  41   41   *      the zone
  42   42   *    - if we do logging in the GZ
  43   43   * See the comment on get_mode_logmax() in this file, and the comment in
  44   44   * uts/common/io/zfd.c for more details.
  45   45   *
  46   46   * Internally the zfd_mode_t struct holds the number of stdio devs (1 or 3),
  47   47   * the number of additional devs corresponding to the zone attr value and the
  48   48   * GZ logging flag.
  49   49   *
  50   50   * Note that although the mode indicates the number of devices needed, we always
  51   51   * create all possible zfd devices for simplicity.
  52   52   */
  53   53  
  54   54  #include <sys/types.h>
  55   55  #include <sys/socket.h>
  56   56  #include <sys/stat.h>
  57   57  #include <sys/termios.h>
  58   58  #include <sys/zfd.h>
  59   59  #include <sys/mkdev.h>
  60   60  
  61   61  #include <assert.h>
  62   62  #include <ctype.h>
  63   63  #include <errno.h>
  64   64  #include <fcntl.h>
  65   65  #include <stdarg.h>
  66   66  #include <stdio.h>
  67   67  #include <stdlib.h>
  68   68  #include <strings.h>
  69   69  #include <stropts.h>
  70   70  #include <thread.h>
  71   71  #include <ucred.h>
  72   72  #include <unistd.h>
  73   73  #include <zone.h>
  74   74  #include <signal.h>
  75   75  #include <wchar.h>
  76   76  
  77   77  #include <libdevinfo.h>
  78   78  #include <libdevice.h>
  79   79  #include <libzonecfg.h>
  80   80  
  81   81  #include <syslog.h>
  82   82  #include <sys/modctl.h>
  83   83  
  84   84  #include "zoneadmd.h"
  85   85  
  86   86  static zlog_t   *zlogp;
  87   87  static int      shutting_down = 0;
  88   88  static thread_t logger_tid;
  89   89  static int      logfd = -1;
  90   90  static size_t   log_sz = 0;
  91   91  static size_t   log_rot_sz = 0;
  92   92  
  93   93  static void rotate_log();
  94   94  
  95   95  /*
  96   96   * The eventstream is a simple one-directional flow of messages implemented
  97   97   * with a pipe. It is used to wake up the poller when it needs to shutdown.
  98   98   */
  99   99  static int eventstream[2] = {-1, -1};
 100  100  
 101  101  #define LOGNAME                 "stdio.log"
 102  102  #define ZLOG_MODE               "zlog-mode"
 103  103  #define LOG_MAXSZ               "zlog-max-size"
 104  104  #define ZFDNEX_DEVTREEPATH      "/pseudo/zfdnex@2"
 105  105  #define ZFDNEX_FILEPATH         "/devices/pseudo/zfdnex@2"
 106  106  #define SERVER_SOCKPATH         ZONES_TMPDIR "/%s.server_%s"
 107  107  #define ZTTY_RETRY              5
 108  108  
 109  109  #define NUM_ZFD_DEVS            5
 110  110  
 111  111  typedef struct zfd_mode {
 112  112          uint_t          zmode_n_stddevs;
 113  113          uint_t          zmode_n_addl_devs;
 114  114          boolean_t       zmode_gzlogging;
 115  115  } zfd_mode_t;
 116  116  static zfd_mode_t mode;
 117  117  
 118  118  /*
 119  119   * cb_data is only used by destroy_cb.
 120  120   */
 121  121  struct cb_data {
 122  122          zlog_t *zlogp;
 123  123          int killed;
 124  124  };
 125  125  
 126  126  /*
 127  127   * destroy_zfd_devs() and its helper destroy_cb() tears down any zfd instances
 128  128   * associated with this zone. If things went very wrong, we might have an
 129  129   * incorrect number of instances hanging around.  This routine hunts down and
 130  130   * tries to remove all of them. Of course, if the fd is open, the instance will
 131  131   * not detach, which is a potential issue.
 132  132   */
 133  133  static int
 134  134  destroy_cb(di_node_t node, void *arg)
 135  135  {
 136  136          struct cb_data *cb = (struct cb_data *)arg;
 137  137          char *prop_data;
 138  138          char *tmp;
 139  139          char devpath[MAXPATHLEN];
 140  140          devctl_hdl_t hdl;
 141  141  
 142  142          if (di_prop_lookup_strings(DDI_DEV_T_ANY, node, "zfd_zname",
 143  143              &prop_data) == -1)
 144  144                  return (DI_WALK_CONTINUE);
 145  145  
 146  146          assert(prop_data != NULL);
 147  147          if (strcmp(prop_data, zone_name) != 0) {
 148  148                  /* this is a zfd for a different zone */
 149  149                  return (DI_WALK_CONTINUE);
 150  150          }
 151  151  
 152  152          tmp = di_devfs_path(node);
 153  153          (void) snprintf(devpath, sizeof (devpath), "/devices/%s", tmp);
 154  154          di_devfs_path_free(tmp);
 155  155  
 156  156          if ((hdl = devctl_device_acquire(devpath, 0)) == NULL) {
 157  157                  zerror(cb->zlogp, B_TRUE, "WARNING: zfd %s found, "
 158  158                      "but it could not be controlled.", devpath);
 159  159                  return (DI_WALK_CONTINUE);
 160  160          }
 161  161          if (devctl_device_remove(hdl) == 0) {
 162  162                  cb->killed++;
 163  163          } else {
 164  164                  zerror(cb->zlogp, B_TRUE, "WARNING: zfd %s found, "
 165  165                      "but it could not be removed.", devpath);
 166  166          }
 167  167          devctl_release(hdl);
 168  168          return (DI_WALK_CONTINUE);
 169  169  }
 170  170  
 171  171  static int
 172  172  destroy_zfd_devs(zlog_t *zlogp)
 173  173  {
 174  174          di_node_t root;
 175  175          struct cb_data cb;
 176  176  
 177  177          bzero(&cb, sizeof (cb));
 178  178          cb.zlogp = zlogp;
 179  179  
 180  180          if ((root = di_init(ZFDNEX_DEVTREEPATH, DINFOCPYALL)) == DI_NODE_NIL) {
 181  181                  zerror(zlogp, B_TRUE, "di_init failed");
 182  182                  return (-1);
 183  183          }
 184  184  
 185  185          (void) di_walk_node(root, DI_WALK_CLDFIRST, (void *)&cb, destroy_cb);
 186  186  
 187  187          di_fini(root);
 188  188          return (0);
 189  189  }
 190  190  
 191  191  static void
 192  192  make_tty(zlog_t *zlogp, int id)
 193  193  {
 194  194          int i;
 195  195          int fd = -1;
 196  196          char stdpath[MAXPATHLEN];
 197  197  
 198  198          /*
 199  199           * Open the master side of the dev and issue the ZFD_MAKETTY ioctl,
 200  200           * which will cause the the various tty-related streams modules to be
 201  201           * pushed when the slave opens the device.
 202  202           *
 203  203           * In very rare cases the open returns ENOENT if devfs doesn't have
 204  204           * everything setup yet due to heavy zone startup load. Wait for
 205  205           * 1 sec. and retry a few times. Even if we can't setup tty mode
 206  206           * we still move on.
 207  207           */
 208  208          (void) snprintf(stdpath, sizeof (stdpath), "/dev/zfd/%s/master/%d",
 209  209              zone_name, id);
 210  210  
 211  211          for (i = 0; !shutting_down && i < ZTTY_RETRY; i++) {
 212  212                  fd = open(stdpath, O_RDWR | O_NOCTTY);
 213  213                  if (fd >= 0 || errno != ENOENT)
 214  214                          break;
 215  215                  (void) sleep(1);
 216  216          }
 217  217          if (fd == -1) {
 218  218                  zerror(zlogp, B_TRUE, "ERROR: could not open zfd %d for "
 219  219                      "zone %s to set tty mode", id, zone_name);
 220  220          } else {
 221  221                  /*
 222  222                   * This ioctl can occasionally return ENXIO if devfs doesn't
 223  223                   * have everything plumbed up yet due to heavy zone startup
 224  224                   * load. Wait for 1 sec. and retry a few times before we give
 225  225                   * up.
 226  226                   */
 227  227                  for (i = 0; !shutting_down && i < ZTTY_RETRY; i++) {
 228  228                          if (ioctl(fd, ZFD_MAKETTY) == 0) {
 229  229                                  break;
 230  230                          } else if (errno != ENXIO) {
 231  231                                  break;
 232  232                          }
 233  233                          (void) sleep(1);
 234  234                  }
 235  235          }
 236  236  
 237  237          if (fd != -1)
 238  238                  (void) close(fd);
 239  239  }
 240  240  
 241  241  /*
 242  242   * init_zfd_devs() drives the device-tree configuration of the zone fd devices.
 243  243   * The general strategy is to use the libdevice (devctl) interfaces to
 244  244   * instantiate all of new zone fd nodes.  We do a lot of sanity checking, and
 245  245   * are careful to reuse a dev if one exists.
 246  246   *
 247  247   * Once the devices are in the device tree, we kick devfsadm via
 248  248   * di_devlink_init() to ensure that the appropriate symlinks (to the master and
 249  249   * slave fd devices) are placed in /dev in the global zone.
 250  250   */
 251  251  static int
 252  252  init_zfd_dev(zlog_t *zlogp, devctl_hdl_t bus_hdl, int id)
 253  253  {
 254  254          int rv = -1;
 255  255          devctl_ddef_t ddef_hdl = NULL;
 256  256          devctl_hdl_t dev_hdl = NULL;
 257  257  
 258  258          if ((ddef_hdl = devctl_ddef_alloc("zfd", 0)) == NULL) {
 259  259                  zerror(zlogp, B_TRUE, "failed to allocate ddef handle");
 260  260                  goto error;
 261  261          }
 262  262  
 263  263          /*
 264  264           * Set four properties on this node; the name of the zone, the dev name
 265  265           * seen inside the zone, a flag which lets pseudo know that it is OK to
 266  266           * automatically allocate an instance # for this device, and the last
 267  267           * one tells the device framework not to auto-detach this node - we
 268  268           * need the node to still be there when we ask devfsadmd to make links,
 269  269           * and when we need to open it.
 270  270           */
 271  271          if (devctl_ddef_string(ddef_hdl, "zfd_zname", zone_name) == -1) {
 272  272                  zerror(zlogp, B_TRUE, "failed to create zfd_zname property");
 273  273                  goto error;
 274  274          }
 275  275          if (devctl_ddef_int(ddef_hdl, "zfd_id", id) == -1) {
 276  276                  zerror(zlogp, B_TRUE, "failed to create zfd_id property");
 277  277                  goto error;
 278  278          }
 279  279          if (devctl_ddef_int(ddef_hdl, "auto-assign-instance", 1) == -1) {
 280  280                  zerror(zlogp, B_TRUE, "failed to create auto-assign-instance "
 281  281                      "property");
 282  282                  goto error;
 283  283          }
 284  284          if (devctl_ddef_int(ddef_hdl, "ddi-no-autodetach", 1) == -1) {
 285  285                  zerror(zlogp, B_TRUE, "failed to create ddi-no-auto-detach "
 286  286                      "property");
 287  287                  goto error;
 288  288          }
 289  289          if (devctl_bus_dev_create(bus_hdl, ddef_hdl, 0, &dev_hdl) == -1) {
 290  290                  zerror(zlogp, B_TRUE, "failed to create zfd node");
 291  291                  goto error;
 292  292          }
 293  293          rv = 0;
 294  294  
 295  295  error:
 296  296          if (ddef_hdl)
 297  297                  devctl_ddef_free(ddef_hdl);
 298  298          if (dev_hdl)
 299  299                  devctl_release(dev_hdl);
 300  300          return (rv);
 301  301  }
 302  302  
 303  303  static int
 304  304  init_zfd_devs(zlog_t *zlogp, zfd_mode_t *mode)
 305  305  {
 306  306          devctl_hdl_t bus_hdl = NULL;
 307  307          di_devlink_handle_t dl = NULL;
 308  308          int rv = -1;
 309  309          int i;
 310  310  
 311  311          /*
 312  312           * Time to make the devices.
 313  313           */
 314  314          if ((bus_hdl = devctl_bus_acquire(ZFDNEX_FILEPATH, 0)) == NULL) {
 315  315                  zerror(zlogp, B_TRUE, "devctl_bus_acquire failed");
 316  316                  goto error;
 317  317          }
 318  318  
 319  319          for (i = 0; i < NUM_ZFD_DEVS; i++) {
 320  320                  if (init_zfd_dev(zlogp, bus_hdl, i) != 0)
 321  321                          goto error;
 322  322          }
 323  323  
 324  324          if ((dl = di_devlink_init("zfd", DI_MAKE_LINK)) == NULL) {
 325  325                  zerror(zlogp, B_TRUE, "failed to create devlinks");
 326  326                  goto error;
 327  327          }
 328  328  
 329  329          (void) di_devlink_fini(&dl);
 330  330          rv = 0;
 331  331  
 332  332          if (mode->zmode_n_stddevs == 1) {
 333  333                  /* We want the primary stream to look like a tty. */
 334  334                  make_tty(zlogp, 0);
 335  335          }
 336  336  
 337  337  error:
 338  338          if (bus_hdl)
 339  339                  devctl_release(bus_hdl);
 340  340          return (rv);
 341  341  }
 342  342  
 343  343  static int
 344  344  init_server_sock(zlog_t *zlogp, int *servfd, char *nm)
 345  345  {
 346  346          int resfd = -1;
 347  347          struct sockaddr_un servaddr;
 348  348  
 349  349          bzero(&servaddr, sizeof (servaddr));
 350  350          servaddr.sun_family = AF_UNIX;
 351  351          (void) snprintf(servaddr.sun_path, sizeof (servaddr.sun_path),
 352  352              SERVER_SOCKPATH, zone_name, nm);
 353  353  
 354  354          if ((resfd = socket(AF_UNIX, SOCK_STREAM, 0)) == -1) {
 355  355                  zerror(zlogp, B_TRUE, "server setup: could not create socket");
 356  356                  goto err;
 357  357          }
 358  358          (void) unlink(servaddr.sun_path);
 359  359  
 360  360          if (bind(resfd, (struct sockaddr *)&servaddr, sizeof (servaddr))
 361  361              == -1) {
 362  362                  zerror(zlogp, B_TRUE,
 363  363                      "server setup: could not bind to socket");
 364  364                  goto err;
 365  365          }
 366  366  
 367  367          if (listen(resfd, 4) == -1) {
 368  368                  zerror(zlogp, B_TRUE,
 369  369                      "server setup: could not listen on socket");
 370  370                  goto err;
 371  371          }
 372  372  
 373  373          *servfd = resfd;
 374  374          return (0);
 375  375  
 376  376  err:
 377  377          (void) unlink(servaddr.sun_path);
 378  378          if (resfd != -1)
 379  379                  (void) close(resfd);
 380  380          return (-1);
 381  381  }
 382  382  
 383  383  static void
 384  384  destroy_server_sock(int servfd, char *nm)
 385  385  {
 386  386          char path[MAXPATHLEN];
 387  387  
 388  388          (void) snprintf(path, sizeof (path), SERVER_SOCKPATH, zone_name, nm);
 389  389          (void) unlink(path);
 390  390          (void) shutdown(servfd, SHUT_RDWR);
 391  391          (void) close(servfd);
 392  392  }
 393  393  
 394  394  /*
 395  395   * Read the "ident" string from the client's descriptor; this routine also
 396  396   * tolerates being called with pid=NULL, for times when you want to "eat"
 397  397   * the ident string from a client without saving it.
 398  398   */
 399  399  static int
 400  400  get_client_ident(int clifd, pid_t *pid, char *locale, size_t locale_len,
 401  401      uint_t *flagsp)
 402  402  {
 403  403          char buf[BUFSIZ], *bufp;
 404  404          size_t buflen = sizeof (buf);
 405  405          char c = '\0';
 406  406          int i = 0, r;
 407  407          ucred_t *cred = NULL;
 408  408  
 409  409          /* "eat up the ident string" case, for simplicity */
 410  410          if (pid == NULL) {
 411  411                  assert(locale == NULL && locale_len == 0);
 412  412                  while (read(clifd, &c, 1) == 1) {
 413  413                          if (c == '\n')
 414  414                                  return (0);
 415  415                  }
 416  416          }
 417  417  
 418  418          bzero(buf, sizeof (buf));
 419  419          while ((buflen > 1) && (r = read(clifd, &c, 1)) == 1) {
 420  420                  buflen--;
 421  421                  if (c == '\n')
 422  422                          break;
 423  423  
 424  424                  buf[i] = c;
 425  425                  i++;
 426  426          }
 427  427          if (r == -1)
 428  428                  return (-1);
 429  429  
 430  430          /*
 431  431           * We've filled the buffer, but still haven't seen \n.  Keep eating
 432  432           * until we find it; we don't expect this to happen, but this is
 433  433           * defensive.
 434  434           */
 435  435          if (c != '\n') {
 436  436                  while ((r = read(clifd, &c, sizeof (c))) > 0)
 437  437                          if (c == '\n')
 438  438                                  break;
 439  439          }
 440  440  
 441  441          /*
 442  442           * Parse buffer for message of the form:
 443  443           * IDENT <locale> <flags>
 444  444           */
 445  445          bufp = buf;
 446  446          if (strncmp(bufp, "IDENT ", 6) != 0)
 447  447                  return (-1);
 448  448          bufp += 6;
 449  449  
 450  450          if (getpeerucred(clifd, &cred) == 0) {
 451  451                  *pid = ucred_getpid((const ucred_t *)cred);
 452  452                  ucred_free(cred);
 453  453          } else {
 454  454                  return (-1);
 455  455          }
 456  456  
 457  457          while (*bufp != '\0' && isspace(*bufp))
 458  458                  bufp++;
 459  459          buflen = strlen(bufp) - 1;
 460  460          bufp[buflen - 1] = '\0';
 461  461          (void) strlcpy(locale, bufp, locale_len);
 462  462  
 463  463          *flagsp = atoi(&bufp[buflen]);
 464  464  
 465  465          return (0);
 466  466  }
 467  467  
 468  468  static int
 469  469  accept_client(int servfd, pid_t *pid, char *locale, size_t locale_len,
 470  470      uint_t *flagsp)
 471  471  {
 472  472          int connfd;
 473  473          struct sockaddr_un cliaddr;
 474  474          socklen_t clilen;
 475  475          int flags;
 476  476  
 477  477          clilen = sizeof (cliaddr);
 478  478          connfd = accept(servfd, (struct sockaddr *)&cliaddr, &clilen);
 479  479          if (connfd == -1)
 480  480                  return (-1);
 481  481          if (pid != NULL) {
 482  482                  if (get_client_ident(connfd, pid, locale, locale_len, flagsp)
 483  483                      == -1) {
 484  484                          (void) shutdown(connfd, SHUT_RDWR);
 485  485                          (void) close(connfd);
 486  486                          return (-1);
 487  487                  }
 488  488                  (void) write(connfd, "OK\n", 3);
 489  489          }
 490  490  
 491  491          flags = fcntl(connfd, F_GETFL, 0);
 492  492          if (flags != -1)
 493  493                  (void) fcntl(connfd, F_SETFL, flags | O_NONBLOCK | FD_CLOEXEC);
 494  494  
 495  495          return (connfd);
 496  496  }
 497  497  
 498  498  static void
 499  499  reject_client(int servfd, pid_t clientpid)
 500  500  {
 501  501          int connfd;
 502  502          struct sockaddr_un cliaddr;
 503  503          socklen_t clilen;
 504  504          char nak[MAXPATHLEN];
 505  505  
 506  506          clilen = sizeof (cliaddr);
 507  507          connfd = accept(servfd, (struct sockaddr *)&cliaddr, &clilen);
 508  508  
 509  509          /*
 510  510           * After getting its ident string, tell client to get lost.
 511  511           */
 512  512          if (get_client_ident(connfd, NULL, NULL, 0, NULL) == 0) {
 513  513                  (void) snprintf(nak, sizeof (nak), "%lu\n",
 514  514                      clientpid);
 515  515                  (void) write(connfd, nak, strlen(nak));
 516  516          }
 517  517          (void) shutdown(connfd, SHUT_RDWR);
 518  518          (void) close(connfd);
 519  519  }
 520  520  
 521  521  static int
 522  522  accept_socket(int servfd, pid_t verpid)
 523  523  {
 524  524          int connfd;
 525  525          struct sockaddr_un cliaddr;
 526  526          socklen_t clilen = sizeof (cliaddr);
 527  527          ucred_t *cred = NULL;
 528  528          pid_t rpid = -1;
 529  529          int flags;
 530  530  
 531  531          connfd = accept(servfd, (struct sockaddr *)&cliaddr, &clilen);
 532  532          if (connfd == -1)
 533  533                  return (-1);
 534  534  
 535  535          /* Confirm connecting process is who we expect */
 536  536          if (getpeerucred(connfd, &cred) == 0) {
 537  537                  rpid = ucred_getpid((const ucred_t *)cred);
 538  538                  ucred_free(cred);
 539  539          }
 540  540          if (rpid == -1 || rpid != verpid) {
 541  541                  (void) shutdown(connfd, SHUT_RDWR);
 542  542                  (void) close(connfd);
 543  543                  return (-1);
 544  544          }
 545  545  
 546  546          flags = fcntl(connfd, F_GETFL, 0);
 547  547          if (flags != -1)
 548  548                  (void) fcntl(connfd, F_SETFL, flags | O_NONBLOCK | FD_CLOEXEC);
 549  549  
 550  550          return (connfd);
 551  551  }
 552  552  
 553  553  static void
 554  554  ctlcmd_process(int sockfd, int stdoutfd, unsigned int *flags)
 555  555  {
 556  556          char buf[BUFSIZ];
 557  557          int i;
 558  558          for (i = 0; i < BUFSIZ-1; i++) {
 559  559                  char c;
 560  560                  if (read(sockfd, &c, 1) != 1 ||
 561  561                      c == '\n' || c == '\0') {
 562  562                          break;
 563  563                  }
 564  564                  buf[i] = c;
 565  565          }
 566  566          if (i == 0) {
 567  567                  goto fail;
 568  568          }
 569  569          buf[i+1] = '\0';
 570  570  
 571  571          if (strncmp(buf, "TIOCSWINSZ ", 11) == 0) {
 572  572                  char *next = buf + 11;
 573  573                  struct winsize ws;
 574  574                  errno = 0;
 575  575                  ws.ws_row = strtol(next, &next, 10);
 576  576                  if (errno == EINVAL) {
 577  577                          goto fail;
 578  578                  }
 579  579                  ws.ws_col = strtol(next + 1, &next, 10);
 580  580                  if (errno == EINVAL) {
 581  581                          goto fail;
 582  582                  }
 583  583                  if (ioctl(stdoutfd, TIOCSWINSZ, &ws) == 0) {
 584  584                          (void) write(sockfd, "OK\n", 3);
 585  585                          return;
 586  586                  }
 587  587          }
 588  588          if (strncmp(buf, "SETFLAGS ", 9) == 0) {
 589  589                  char *next = buf + 9;
 590  590                  unsigned int result;
 591  591                  errno = 0;
 592  592                  result = strtoul(next, &next, 10);
 593  593                  if (errno == EINVAL) {
 594  594                          goto fail;
 595  595                  }
 596  596                  *flags = result;
 597  597                  (void) write(sockfd, "OK\n", 3);
 598  598                  return;
 599  599          }
 600  600  fail:
 601  601          (void) write(sockfd, "FAIL\n", 5);
 602  602  }
 603  603  
 604  604  /*
 605  605   * Check to see if the client at the other end of the socket is still alive; we
 606  606   * know it is not if it throws EPIPE at us when we try to write an otherwise
 607  607   * harmless 0-length message to it.
 608  608   */
 609  609  static int
 610  610  test_client(int clifd)
 611  611  {
 612  612          if ((write(clifd, "", 0) == -1) && errno == EPIPE)
 613  613                  return (-1);
 614  614          return (0);
 615  615  }
 616  616  
 617  617  /*
 618  618   * Modify the input string with json escapes. Since the destination can thus
 619  619   * be larger than the source, it may get truncated, although we do use a
 620  620   * larger buffer.
 621  621   */
 622  622  static void
 623  623  escape_json(char *sbuf, int slen, char *dbuf, int dlen)
 624  624  {
 625  625          int i;
 626  626          mbstate_t mbr;
 627  627          wchar_t c;
 628  628          size_t sz;
 629  629  
 630  630          bzero(&mbr, sizeof (mbr));
 631  631  
 632  632          sbuf[slen] = '\0';
 633  633          i = 0;
 634  634          while (i < dlen && (sz = mbrtowc(&c, sbuf, MB_CUR_MAX, &mbr)) > 0) {
 635  635                  switch (c) {
 636  636                  case '\\':
 637  637                          dbuf[i++] = '\\';
 638  638                          dbuf[i++] = '\\';
 639  639                          break;
 640  640  
 641  641                  case '"':
 642  642                          dbuf[i++] = '\\';
 643  643                          dbuf[i++] = '"';
 644  644                          break;
 645  645  
 646  646                  case '\b':
 647  647                          dbuf[i++] = '\\';
 648  648                          dbuf[i++] = 'b';
 649  649                          break;
 650  650  
 651  651                  case '\f':
 652  652                          dbuf[i++] = '\\';
 653  653                          dbuf[i++] = 'f';
 654  654                          break;
 655  655  
 656  656                  case '\n':
 657  657                          dbuf[i++] = '\\';
 658  658                          dbuf[i++] = 'n';
 659  659                          break;
 660  660  
 661  661                  case '\r':
 662  662                          dbuf[i++] = '\\';
 663  663                          dbuf[i++] = 'r';
 664  664                          break;
 665  665  
 666  666                  case '\t':
 667  667                          dbuf[i++] = '\\';
 668  668                          dbuf[i++] = 't';
 669  669                          break;
 670  670  
 671  671                  default:
 672  672                          if ((c >= 0x00 && c <= 0x1f) ||
 673  673                              (c > 0x7f && c <= 0xffff)) {
 674  674  
 675  675                                  i += snprintf(&dbuf[i], (dlen - i), "\\u%04x",
 676  676                                      (int)(0xffff & c));
 677  677                          } else if (c >= 0x20 && c <= 0x7f) {
 678  678                                  dbuf[i++] = 0xff & c;
 679  679                          }
 680  680  
 681  681                          break;
 682  682                  }
 683  683                  sbuf += sz;
 684  684          }
 685  685  
 686  686          if (i == dlen)
 687  687                  dbuf[--i] = '\0';
 688  688          else
 689  689                  dbuf[i] = '\0';
 690  690  }
 691  691  
 692  692  /*
 693  693   * We output to the log file as json.
 694  694   * ex. for string 'msg\n' on the zone's stdout:
 695  695   *    {"log":"msg\n","stream":"stdout","time":"2014-10-24T20:12:11.101973117Z"}
 696  696   *
 697  697   * We use ns in the last field of the timestamp for compatability.
 698  698   *
 699  699   * We keep track of the size of the log file and rotate it when we exceed
 700  700   * the log size limit (if one is set).
 701  701   */
 702  702  static void
 703  703  wr_log_msg(char *buf, int len, int from)
 704  704  {
 705  705          struct timeval tv;
 706  706          int olen;
 707  707          char ts[64];
 708  708          char nbuf[BUFSIZ * 2];
 709  709          char obuf[BUFSIZ * 2];
 710  710          static boolean_t log_wr_err = B_FALSE;
 711  711  
 712  712          if (logfd == -1)
 713  713                  return;
 714  714  
 715  715          escape_json(buf, len, nbuf, sizeof (nbuf));
 716  716  
 717  717          if (gettimeofday(&tv, NULL) != 0)
 718  718                  return;
 719  719          (void) strftime(ts, sizeof (ts), "%FT%T", gmtime(&tv.tv_sec));
 720  720  
 721  721          olen = snprintf(obuf, sizeof (obuf),
 722  722              "{\"log\":\"%s\",\"stream\":\"%s\",\"time\":\"%s.%ldZ\"}\n",
 723  723              nbuf, (from == 1) ? "stdout" : "stderr", ts, tv.tv_usec * 1000);
 724  724  
 725  725          if (write(logfd, obuf, olen) != olen) {
 726  726                  if (!log_wr_err) {
 727  727                          zerror(zlogp, B_TRUE, "log file write error");
 728  728                          log_wr_err = B_TRUE;
 729  729                  }
 730  730                  return;
 731  731          }
 732  732  
 733  733          log_sz += olen;
 734  734          if (log_rot_sz > 0 && log_sz >= log_rot_sz)
 735  735                  rotate_log();
 736  736  }
 737  737  
 738  738  /*
 739  739   * We want to sleep for a little while but need to be responsive if the zone is
 740  740   * halting. We poll/sleep on the event stream so we can notice if we're halting.
 741  741   * Return true if halting, otherwise false.
 742  742   */
 743  743  static boolean_t
 744  744  halt_sleep(int slptime)
 745  745  {
 746  746          struct pollfd evfd[1];
 747  747  
 748  748          evfd[0].fd = eventstream[1];
 749  749          evfd[0].events = POLLIN | POLLRDNORM | POLLRDBAND | POLLPRI;
 750  750  
 751  751          if (poll(evfd, 1, slptime) > 0) {
 752  752                  /* zone halting */
 753  753                  return (B_TRUE);
 754  754          }
 755  755          return (B_FALSE);
 756  756  }
 757  757  
 758  758  /*
 759  759   * This routine drives the logging and interactive I/O loop. It polls for
 760  760   * input from the zone side of the fd (output to stdout/stderr), and from the
 761  761   * client (input to the zone's stdin).  Additionally, it polls on the server
 762  762   * fd, and disconnects any clients that might try to hook up with the zone
 763  763   * while the fd's are in use.
 764  764   *
 765  765   * Data from the zone's stdout and stderr is formatted in json and written to
 766  766   * the log file whether an interactive client is connected or not.
 767  767   *
 768  768   * When the client first calls us up, it is expected to send a line giving its
 769  769   * "identity"; this consists of the string 'IDENT <pid> <locale>'. This is so
 770  770   * that we can report that the fd's are busy, along with some diagnostics
 771  771   * about who has them busy; the locale is ignore here but kept for compatability
 772  772   * with the zlogin code when running on the zone's console.
 773  773   *
 774  774   * We need to handle the case where there is no server within the zone (or
 775  775   * the server gets stuck) and data that we're writing to the zone server's
 776  776   * stdin fills the pipe. Because of the way the zfd device works writes can
 777  777   * flow into the stream and simply be dropped, if there is no server, or writes
 778  778   * could return -1 with EAGAIN if the server is stuck. Since we ignore errors
 779  779   * on the write to stdin, we won't get blocked in that case but we'd like to
 780  780   * avoid dropping initial input if the server within the zone hasn't started
 781  781   * yet. To handle this we wait to read initial input until we detect that there
 782  782   * is a server inside the zone. We have to poll for this so that we can
 783  783   * re-run the ioctl to notice when a server shows up. This poll/wait is handled
 784  784   * by halt_sleep() so that we can be responsive if the zone wants to halt.
 785  785   * We only do this check to avoid dropping initial input so it is possible for
 786  786   * the server within the zone to go away later. At that point zfd will just
 787  787   * drop any new input flowing into the stream.
 788  788   */
 789  789  static void
 790  790  do_zfd_io(int gzctlfd, int gzservfd, int gzerrfd, int stdinfd, int stdoutfd,
 791  791      int stderrfd)
 792  792  {
 793  793          struct pollfd pollfds[8];
 794  794          char ibuf[BUFSIZ + 1];
 795  795          int cc, ret;
 796  796          int ctlfd = -1;
 797  797          int clifd = -1;
 798  798          int clierrfd = -1;
 799  799          int pollerr = 0;
 800  800          char clilocale[MAXPATHLEN];
 801  801          pid_t clipid = 0;
 802  802          uint_t flags = 0;
 803  803          boolean_t stdin_ready = B_FALSE;
 804  804          int slptime = 250;      /* initial poll sleep time in ms */
 805  805  
 806  806          /* client control socket, watch for read events */
 807  807          pollfds[0].fd = ctlfd;
 808  808          pollfds[0].events = POLLIN | POLLRDNORM | POLLRDBAND |
 809  809              POLLPRI | POLLERR | POLLHUP | POLLNVAL;
 810  810  
 811  811          /* client socket, watch for read events */
 812  812          pollfds[1].fd = clifd;
 813  813          pollfds[1].events = pollfds[0].events;
 814  814  
 815  815          /* stdout, watch for read events */
 816  816          pollfds[2].fd = stdoutfd;
 817  817          pollfds[2].events = pollfds[0].events;
 818  818  
 819  819          /* stderr, watch for read events */
 820  820          pollfds[3].fd = stderrfd;
 821  821          pollfds[3].events = pollfds[0].events;
 822  822  
 823  823          /* the server control socket; watch for new connections */
 824  824          pollfds[4].fd = gzctlfd;
 825  825          pollfds[4].events = POLLIN | POLLRDNORM;
 826  826  
 827  827          /* the server stdin/out socket; watch for new connections */
 828  828          pollfds[5].fd = gzservfd;
 829  829          pollfds[5].events = POLLIN | POLLRDNORM;
 830  830  
 831  831          /* the server stderr socket; watch for new connections */
 832  832          pollfds[6].fd = gzerrfd;
 833  833          pollfds[6].events = POLLIN | POLLRDNORM;
 834  834  
 835  835          /* the eventstream; any input means the zone is halting */
 836  836          pollfds[7].fd = eventstream[1];
 837  837          pollfds[7].events = pollfds[0].events;
 838  838  
 839  839          while (!shutting_down) {
 840  840                  pollfds[0].revents = pollfds[1].revents = 0;
 841  841                  pollfds[2].revents = pollfds[3].revents = 0;
 842  842                  pollfds[4].revents = pollfds[5].revents = 0;
 843  843                  pollfds[6].revents = pollfds[7].revents = 0;
 844  844  
 845  845                  ret = poll(pollfds, 8, -1);
 846  846                  if (ret == -1 && errno != EINTR) {
 847  847                          zerror(zlogp, B_TRUE, "poll failed");
 848  848                          /* we are hosed, close connection */
 849  849                          break;
 850  850                  }
 851  851  
 852  852                  /* control events from client */
 853  853                  if (pollfds[0].revents &
 854  854                      (POLLIN | POLLRDNORM | POLLRDBAND | POLLPRI)) {
 855  855                          /* process control message */
 856  856                          ctlcmd_process(ctlfd, stdoutfd, &flags);
 857  857                  } else if (pollfds[0].revents) {
 858  858                          /* bail if any error occurs */
 859  859                          pollerr = pollfds[0].revents;
 860  860                          zerror(zlogp, B_FALSE, "closing connection "
 861  861                              "with control channel, pollerr %d\n", pollerr);
 862  862                          break;
 863  863                  }
 864  864  
 865  865                  /* event from client side */
 866  866                  if (pollfds[1].revents) {
 867  867                          if (stdin_ready) {
 868  868                                  if (pollfds[1].revents & (POLLIN |
 869  869                                      POLLRDNORM | POLLRDBAND | POLLPRI)) {
 870  870                                          errno = 0;
 871  871                                          cc = read(clifd, ibuf, BUFSIZ);
 872  872                                          if (cc > 0) {
 873  873                                                  /*
 874  874                                                   * See comment for this
 875  875                                                   * function on what happens if
 876  876                                                   * there is no reader in the
 877  877                                                   * zone. EOF is handled below.
 878  878                                                   */
 879  879                                                  (void) write(stdinfd, ibuf, cc);
 880  880                                          }
 881  881                                  } else if (pollfds[1].revents & (POLLERR |
 882  882                                      POLLNVAL))  {
 883  883                                          pollerr = pollfds[1].revents;
 884  884                                          zerror(zlogp, B_FALSE,
 885  885                                              "closing connection "
 886  886                                              "with client, pollerr %d\n",
 887  887                                              pollerr);
 888  888                                          break;
 889  889                                  }
 890  890  
 891  891                                  if (pollfds[1].revents & POLLHUP) {
 892  892                                          if (flags & ZLOGIN_ZFD_EOF) {
 893  893                                                  /*
 894  894                                                   * Let the client know. We've
 895  895                                                   * already serviced any pending
 896  896                                                   * regular input. Let the
 897  897                                                   * stream clear since the EOF
 898  898                                                   * ioctl jumps to the head.
 899  899                                                   */
 900  900                                                  (void) ioctl(stdinfd, I_FLUSH);
 901  901                                                  if (halt_sleep(250))
 902  902                                                          break;
 903  903                                                  (void) ioctl(stdinfd, ZFD_EOF);
 904  904                                          }
 905  905                                          break;
 906  906                                  }
 907  907                          } else {
 908  908                                  if (ioctl(stdinfd, ZFD_HAS_SLAVE) == 0) {
 909  909                                          stdin_ready = B_TRUE;
 910  910                                  } else {
 911  911                                          /*
 912  912                                           * There is nothing in the zone to read
 913  913                                           * our input. Presumably the user
 914  914                                           * providing input expects something to
 915  915                                           * show up, but that is no guarantee.
 916  916                                           * Since we haven't serviced the pending
 917  917                                           * input poll yet, we don't want to
 918  918                                           * immediately loop around but we also
 919  919                                           * need to be responsive if the zone is
 920  920                                           * halting.
 921  921                                           */
 922  922                                          if (halt_sleep(slptime))
 923  923                                                  break;
 924  924  
 925  925                                          if (slptime < 5000)
 926  926                                                  slptime += 250;
 927  927                                  }
 928  928                          }
 929  929                  }
 930  930  
 931  931                  /* event from the zone's stdout */
 932  932                  if (pollfds[2].revents) {
 933  933                          if (pollfds[2].revents &
 934  934                              (POLLIN | POLLRDNORM | POLLRDBAND | POLLPRI)) {
 935  935                                  errno = 0;
 936  936                                  cc = read(stdoutfd, ibuf, BUFSIZ);
 937  937                                  if (cc <= 0 && (errno != EINTR) &&
 938  938                                      (errno != EAGAIN))
 939  939                                          break;
 940  940                                  if (cc > 0) {
 941  941                                          wr_log_msg(ibuf, cc, 1);
 942  942  
 943  943                                          /*
 944  944                                           * Lose output if no one is listening,
 945  945                                           * otherwise pass it on.
 946  946                                           */
 947  947                                          if (clifd != -1)
 948  948                                                  (void) write(clifd, ibuf, cc);
 949  949                                  }
 950  950                          } else {
 951  951                                  pollerr = pollfds[2].revents;
 952  952                                  zerror(zlogp, B_FALSE,
 953  953                                      "closing connection with stdout zfd, "
 954  954                                      "pollerr %d\n", pollerr);
 955  955                                  break;
 956  956                          }
 957  957                  }
 958  958  
 959  959                  /* event from the zone's stderr */
 960  960                  if (pollfds[3].revents) {
 961  961                          if (pollfds[3].revents &
 962  962                              (POLLIN | POLLRDNORM | POLLRDBAND | POLLPRI)) {
 963  963                                  errno = 0;
 964  964                                  cc = read(stderrfd, ibuf, BUFSIZ);
 965  965                                  if (cc <= 0 && (errno != EINTR) &&
 966  966                                      (errno != EAGAIN))
 967  967                                          break;
 968  968                                  if (cc > 0) {
 969  969                                          wr_log_msg(ibuf, cc, 2);
 970  970  
 971  971                                          /*
 972  972                                           * Lose output if no one is listening,
 973  973                                           * otherwise pass it on.
 974  974                                           */
 975  975                                          if (clierrfd != -1)
 976  976                                                  (void) write(clierrfd, ibuf,
 977  977                                                      cc);
 978  978                                  }
 979  979                          } else {
 980  980                                  pollerr = pollfds[3].revents;
 981  981                                  zerror(zlogp, B_FALSE,
 982  982                                      "closing connection with stderr zfd, "
 983  983                                      "pollerr %d\n", pollerr);
 984  984                                  break;
 985  985                          }
 986  986                  }
 987  987  
 988  988                  /* connect event from server control socket */
 989  989                  if (pollfds[4].revents) {
 990  990                          if (ctlfd != -1) {
 991  991                                  /*
 992  992                                   * Test the client to see if it is really
 993  993                                   * still alive.  If it has died but we
 994  994                                   * haven't yet detected that, we might
 995  995                                   * deny a legitimate connect attempt.  If it
 996  996                                   * is dead, we break out; once we tear down
 997  997                                   * the old connection, the new connection
 998  998                                   * will happen.
 999  999                                   */
1000 1000                                  if (test_client(ctlfd) == -1) {
1001 1001                                          break;
1002 1002                                  }
1003 1003                                  /* we're already handling a client */
1004 1004                                  reject_client(gzctlfd, clipid);
1005 1005                          } else {
1006 1006                                  ctlfd = accept_client(gzctlfd, &clipid,
1007 1007                                      clilocale, sizeof (clilocale), &flags);
1008 1008                                  if (ctlfd != -1) {
1009 1009                                          pollfds[0].fd = ctlfd;
1010 1010                                  } else {
1011 1011                                          break;
1012 1012                                  }
1013 1013                          }
1014 1014                  }
1015 1015  
1016 1016                  /* connect event from server stdin/out socket */
1017 1017                  if (pollfds[5].revents) {
1018 1018                          if (ctlfd == -1) {
1019 1019                                  /*
1020 1020                                   * This shouldn't happen since the client is
1021 1021                                   * expected to connect on the control socket
1022 1022                                   * first. If we see this, tear everything down
1023 1023                                   * and start over.
1024 1024                                   */
1025 1025                                  zerror(zlogp, B_FALSE, "GZ zfd stdin/stdout "
1026 1026                                      "connection attempt with no GZ control\n");
1027 1027                                  break;
1028 1028                          }
1029 1029                          assert(clifd == -1);
1030 1030                          if ((clifd = accept_socket(gzservfd, clipid)) != -1) {
1031 1031                                  /* No need to watch for other new connections */
1032 1032                                  pollfds[5].fd = -1;
1033 1033                                  /* Client input is of interest, though */
1034 1034                                  pollfds[1].fd = clifd;
1035 1035                          } else {
1036 1036                                  break;
1037 1037                          }
1038 1038                  }
1039 1039  
1040 1040                  /* connection event from server stderr socket */
1041 1041                  if (pollfds[6].revents) {
1042 1042                          if (ctlfd == -1) {
1043 1043                                  /*
1044 1044                                   * Same conditions apply to stderr as stdin/out.
1045 1045                                   */
1046 1046                                  zerror(zlogp, B_FALSE, "GZ zfd stderr "
1047 1047                                      "connection attempt with no GZ control\n");
1048 1048                                  break;
1049 1049                          }
1050 1050                          assert(clierrfd == -1);
1051 1051                          if ((clierrfd = accept_socket(gzerrfd, clipid)) != -1) {
1052 1052                                  /* No need to watch for other new connections */
1053 1053                                  pollfds[6].fd = -1;
1054 1054                          } else {
1055 1055                                  break;
1056 1056                          }
1057 1057                  }
1058 1058  
1059 1059                  /*
1060 1060                   * Watch for events on the eventstream.  This is how we get
1061 1061                   * notified of the zone halting, etc.  It provides us a
1062 1062                   * "wakeup" from poll when important things happen, which
1063 1063                   * is good.
1064 1064                   */
1065 1065                  if (pollfds[7].revents) {
1066 1066                          break;
1067 1067                  }
1068 1068          }
1069 1069  
1070 1070          if (clifd != -1) {
1071 1071                  (void) shutdown(clifd, SHUT_RDWR);
1072 1072                  (void) close(clifd);
1073 1073          }
1074 1074  
1075 1075          if (clierrfd != -1) {
1076 1076                  (void) shutdown(clierrfd, SHUT_RDWR);
1077 1077                  (void) close(clierrfd);
1078 1078          }
1079 1079  }
1080 1080  
1081 1081  static int
1082 1082  open_fd(zlog_t *zlogp, int id, int rw)
1083 1083  {
1084 1084          int fd;
1085 1085          int flag = O_NONBLOCK | O_NOCTTY | O_CLOEXEC;
1086 1086          int retried = 0;
1087 1087          char stdpath[MAXPATHLEN];
1088 1088  
1089 1089          (void) snprintf(stdpath, sizeof (stdpath), "/dev/zfd/%s/master/%d",
1090 1090              zone_name, id);
1091 1091          flag |= rw;
1092 1092  
1093 1093          while (!shutting_down) {
1094 1094                  if ((fd = open(stdpath, flag)) != -1) {
1095 1095                          /*
1096 1096                           * Setting RPROTDIS on the stream means that the
1097 1097                           * control portion of messages received (which we don't
1098 1098                           * care about) will be discarded by the stream head. If
1099 1099                           * we allowed such messages, we wouldn't be able to use
1100 1100                           * read(2), as it fails (EBADMSG) when a message with a
1101 1101                           * control element is received.
1102 1102                           */
1103 1103                          if (ioctl(fd, I_SRDOPT, RNORM|RPROTDIS) == -1) {
1104 1104                                  zerror(zlogp, B_TRUE,
1105 1105                                      "failed to set options on zfd");
1106 1106                                  return (-1);
1107 1107                          }
1108 1108                          return (fd);
1109 1109                  }
1110 1110  
1111 1111                  if (retried++ > 60)
1112 1112                          break;
1113 1113  
1114 1114                  (void) sleep(1);
1115 1115          }
1116 1116  
1117 1117          zerror(zlogp, B_TRUE, "failed to open zfd");
1118 1118          return (-1);
1119 1119  }
1120 1120  
1121 1121  static void
1122 1122  open_logfile()
1123 1123  {
1124 1124          char logpath[MAXPATHLEN];
1125 1125  
1126 1126          logfd = -1;
1127 1127          log_sz = 0;
1128 1128  
1129 1129          (void) snprintf(logpath, sizeof (logpath), "%s/logs", zonepath);
1130 1130          (void) mkdir(logpath, 0700);
1131 1131  
1132 1132          (void) snprintf(logpath, sizeof (logpath), "%s/logs/%s", zonepath,
1133 1133              LOGNAME);
1134 1134  
1135 1135          if ((logfd = open(logpath, O_WRONLY | O_APPEND | O_CREAT,
1136 1136              0600)) == -1) {
1137 1137                  zerror(zlogp, B_TRUE, "failed to open log file");
1138 1138          } else {
1139 1139                  struct stat64 sb;
1140 1140  
1141 1141                  if (fstat64(logfd, &sb) == 0)
1142 1142                          log_sz = sb.st_size;
1143 1143          }
1144 1144  }
1145 1145  
1146 1146  static void
1147 1147  rotate_log()
1148 1148  {
1149 1149          time_t t;
1150 1150          struct tm gtm;
1151 1151          char onm[MAXPATHLEN], rnm[MAXPATHLEN];
1152 1152  
1153 1153          if ((t = time(NULL)) == (time_t)-1 || gmtime_r(&t, >m) == NULL) {
1154 1154                  zerror(zlogp, B_TRUE, "failed to format time");
1155 1155                  return;
1156 1156          }
1157 1157  
1158 1158          (void) snprintf(rnm, sizeof (rnm),
1159 1159              "%s/logs/%s.%d%02d%02dT%02d%02d%02dZ",
1160 1160              zonepath, LOGNAME, gtm.tm_year + 1900, gtm.tm_mon + 1, gtm.tm_mday,
1161 1161              gtm.tm_hour, gtm.tm_min, gtm.tm_sec);
1162 1162          (void) snprintf(onm, sizeof (onm), "%s/logs/%s", zonepath, LOGNAME);
1163 1163  
1164 1164          (void) close(logfd);
1165 1165          if (rename(onm, rnm) != 0)
1166 1166                  zerror(zlogp, B_TRUE, "failed to rotate log file");
1167 1167          open_logfile();
1168 1168  }
1169 1169  
1170 1170  
1171 1171  /* ARGSUSED */
1172 1172  void
1173 1173  hup_handler(int i)
1174 1174  {
1175 1175          if (logfd != -1) {
1176 1176                  (void) close(logfd);
1177 1177                  open_logfile();
1178 1178          }
1179 1179  }
1180 1180  
1181 1181  /*
1182 1182   * Body of the worker thread to log the zfd's stdout and stderr to a log file
1183 1183   * and to perform interactive IO to the stdin, stdout and stderr zfd's.
1184 1184   *
1185 1185   * The stdin, stdout and stderr are from the perspective of the process inside
1186 1186   * the zone, so the zoneadmd view is opposite (i.e. we write to the stdin fd
1187 1187   * and read from the stdout/stderr fds).
1188 1188   */
1189 1189  static void
1190 1190  srvr(void *modearg)
1191 1191  {
1192 1192          zfd_mode_t *mode = (zfd_mode_t *)modearg;
1193 1193          int gzctlfd = -1;
1194 1194          int gzoutfd = -1;
1195 1195          int stdinfd = -1;
1196 1196          int stdoutfd = -1;
1197 1197          sigset_t blockset;
1198 1198          int gzerrfd = -1;
1199 1199          int stderrfd = -1;
1200 1200          int flags;
  
    | 
      ↓ open down ↓ | 
    1200 lines elided | 
    
      ↑ open up ↑ | 
  
1201 1201          int len;
1202 1202          char ibuf[BUFSIZ + 1];
1203 1203  
1204 1204          if (!shutting_down && mode->zmode_gzlogging)
1205 1205                  open_logfile();
1206 1206  
1207 1207          /*
1208 1208           * This thread should receive SIGHUP so that it can close the log
1209 1209           * file, and reopen it, during log rotation.
1210 1210           */
1211      -        sigset(SIGHUP, hup_handler);
     1211 +        (void) sigset(SIGHUP, hup_handler);
1212 1212          (void) sigfillset(&blockset);
1213 1213          (void) sigdelset(&blockset, SIGHUP);
1214 1214          (void) thr_sigsetmask(SIG_BLOCK, &blockset, NULL);
1215 1215  
1216 1216          if (!shutting_down) {
1217 1217                  if (pipe(eventstream) != 0) {
1218 1218                          zerror(zlogp, B_TRUE, "failed to open logger control "
1219 1219                              "pipe");
1220 1220                          return;
1221 1221                  }
1222 1222          }
1223 1223  
1224 1224          while (!shutting_down) {
1225 1225                  if (init_server_sock(zlogp, &gzctlfd, "ctl") == -1) {
1226 1226                          zerror(zlogp, B_FALSE,
1227 1227                              "server setup: control socket init failed");
1228 1228                          goto death;
1229 1229                  }
1230 1230                  if (init_server_sock(zlogp, &gzoutfd, "out") == -1) {
1231 1231                          zerror(zlogp, B_FALSE,
1232 1232                              "server setup: stdout socket init failed");
1233 1233                          goto death;
1234 1234                  }
1235 1235                  if (init_server_sock(zlogp, &gzerrfd, "err") == -1) {
1236 1236                          zerror(zlogp, B_FALSE,
1237 1237                              "server setup: stderr socket init failed");
1238 1238                          goto death;
1239 1239                  }
1240 1240  
1241 1241                  if (mode->zmode_n_stddevs == 1) {
1242 1242                          if ((stdinfd = open_fd(zlogp, 0, O_RDWR)) == -1) {
1243 1243                                  goto death;
1244 1244                          }
1245 1245                          stdoutfd = stdinfd;
1246 1246                  } else {
1247 1247                          if ((stdinfd = open_fd(zlogp, 0, O_WRONLY)) == -1 ||
1248 1248                              (stdoutfd = open_fd(zlogp, 1, O_RDONLY)) == -1 ||
1249 1249                              (stderrfd = open_fd(zlogp, 2, O_RDONLY)) == -1) {
1250 1250                                  goto death;
1251 1251                          }
1252 1252                  }
1253 1253  
1254 1254                  do_zfd_io(gzctlfd, gzoutfd, gzerrfd, stdinfd, stdoutfd,
1255 1255                      stderrfd);
1256 1256  death:
1257 1257                  destroy_server_sock(gzctlfd, "ctl");
1258 1258                  destroy_server_sock(gzoutfd, "out");
1259 1259                  destroy_server_sock(gzerrfd, "err");
1260 1260  
1261 1261                  /* when shutting down, leave open until drained */
1262 1262                  if (!shutting_down) {
1263 1263                          (void) close(stdinfd);
1264 1264                          if (mode->zmode_n_stddevs == 3) {
1265 1265                                  (void) close(stdoutfd);
1266 1266                                  (void) close(stderrfd);
1267 1267                          }
1268 1268                  }
1269 1269          }
1270 1270  
1271 1271          /*
1272 1272           * Attempt to drain remaining log output from the zone prior to closing
1273 1273           * the file descriptors. This helps ensure that complete logs are
1274 1274           * captured during shutdown.
1275 1275           */
1276 1276          flags = fcntl(stdoutfd, F_GETFL, 0);
1277 1277          if (fcntl(stdoutfd, F_SETFL, flags | O_NONBLOCK) != -1) {
1278 1278                  while ((len = read(stdoutfd, ibuf, BUFSIZ)) > 0)
1279 1279                          wr_log_msg(ibuf, len, 1);
1280 1280          }
1281 1281          (void) close(stdoutfd);
1282 1282  
1283 1283          if (mode->zmode_n_stddevs > 1) {
1284 1284                  (void) close(stdinfd);
1285 1285                  flags = fcntl(stderrfd, F_GETFL, 0);
1286 1286                  if (fcntl(stderrfd, F_SETFL, flags | O_NONBLOCK) != -1) {
1287 1287                          while ((len = read(stderrfd, ibuf, BUFSIZ)) > 0)
1288 1288                                  wr_log_msg(ibuf, len, 2);
1289 1289                  }
1290 1290                  (void) close(stderrfd);
1291 1291          }
1292 1292  
1293 1293  
1294 1294          (void) close(eventstream[0]);
1295 1295          eventstream[0] = -1;
1296 1296          (void) close(eventstream[1]);
1297 1297          eventstream[1] = -1;
1298 1298          if (logfd != -1)
1299 1299                  (void) close(logfd);
1300 1300  }
1301 1301  
1302 1302  /*
1303 1303   * The meaning of the original legacy values for the zlog-mode evolved over
1304 1304   * time, to the point where the old names no longer made sense. The current
1305 1305   * values are simply positional letters used to indicate various capabilities.
1306 1306   * The following table shows the meaning of the mode values, along with the
1307 1307   * legacy name which we continue to support for compatability. Any future
1308 1308   * capability can add a letter to the left and '-' is implied for existing
1309 1309   * strings.
1310 1310   *
1311 1311   * zlog-mode    gz log - tty - ngz log
1312 1312   * ---------    ------   ---   -------
1313 1313   * gt- (int)       y      y       n
1314 1314   * g-- (log)       y      n       n
1315 1315   * gtn (nlint)     y      y       y
1316 1316   * g-n (nolog)     y      n       y
1317 1317   * -t-             n      y       n
1318 1318   * ---             n      n       n
1319 1319   *
1320 1320   * This function also obtains a maximum log size while it is reading the
1321 1321   * zone configuration.
1322 1322   */
1323 1323  static void
1324 1324  get_mode_logmax(zfd_mode_t *mode)
1325 1325  {
1326 1326          zone_dochandle_t handle;
1327 1327          struct zone_attrtab attr;
1328 1328  
1329 1329          bzero(mode, sizeof (zfd_mode_t));
1330 1330  
1331 1331          if ((handle = zonecfg_init_handle()) == NULL)
1332 1332                  return;
1333 1333  
1334 1334          if (zonecfg_get_handle(zone_name, handle) != Z_OK)
1335 1335                  goto done;
1336 1336  
1337 1337          if (zonecfg_setattrent(handle) != Z_OK)
1338 1338                  goto done;
1339 1339          while (zonecfg_getattrent(handle, &attr) == Z_OK) {
1340 1340                  if (strcmp(ZLOG_MODE, attr.zone_attr_name) == 0) {
1341 1341                          if (strcmp("g--", attr.zone_attr_value) == 0 ||
1342 1342                              strncmp("log", attr.zone_attr_value, 3) == 0) {
1343 1343                                  mode->zmode_gzlogging = B_TRUE;
1344 1344                                  mode->zmode_n_stddevs = 3;
1345 1345                                  mode->zmode_n_addl_devs = 0;
1346 1346                          } else if (strcmp("g-n", attr.zone_attr_value) == 0 ||
1347 1347                              strncmp("nolog", attr.zone_attr_value, 5) == 0) {
1348 1348                                  mode->zmode_gzlogging = B_TRUE;
1349 1349                                  mode->zmode_n_stddevs = 3;
1350 1350                                  mode->zmode_n_addl_devs = 2;
1351 1351                          } else if (strcmp("gt-", attr.zone_attr_value) == 0 ||
1352 1352                              strncmp("int", attr.zone_attr_value, 3) == 0) {
1353 1353                                  mode->zmode_gzlogging = B_TRUE;
1354 1354                                  mode->zmode_n_stddevs = 1;
1355 1355                                  mode->zmode_n_addl_devs = 0;
1356 1356                          } else if (strcmp("gtn", attr.zone_attr_value) == 0 ||
1357 1357                              strncmp("nlint", attr.zone_attr_value, 5) == 0) {
1358 1358                                  mode->zmode_gzlogging = B_TRUE;
1359 1359                                  mode->zmode_n_stddevs = 1;
1360 1360                                  mode->zmode_n_addl_devs = 1;
1361 1361                          } else if (strcmp("-t-", attr.zone_attr_value) == 0) {
1362 1362                                  mode->zmode_gzlogging = B_FALSE;
1363 1363                                  mode->zmode_n_stddevs = 1;
1364 1364                                  mode->zmode_n_addl_devs = 0;
1365 1365                          } else if (strcmp("---", attr.zone_attr_value) == 0) {
1366 1366                                  mode->zmode_gzlogging = B_FALSE;
1367 1367                                  mode->zmode_n_stddevs = 3;
1368 1368                                  mode->zmode_n_addl_devs = 0;
1369 1369                          }
1370 1370  
1371 1371                  } else if (strcmp(LOG_MAXSZ, attr.zone_attr_name) == 0) {
1372 1372                          char *p;
1373 1373                          long lval;
1374 1374  
1375 1375                          p = attr.zone_attr_value;
1376 1376                          lval = strtol(p, &p, 10);
  
    | 
      ↓ open down ↓ | 
    155 lines elided | 
    
      ↑ open up ↑ | 
  
1377 1377                          if (*p == '\0')
1378 1378                                  log_rot_sz = (size_t)lval;
1379 1379                  }
1380 1380          }
1381 1381          (void) zonecfg_endattrent(handle);
1382 1382  
1383 1383  done:
1384 1384          zonecfg_fini_handle(handle);
1385 1385  }
1386 1386  
     1387 +/* ARGSUSED -- "id" might be used in the future. */
1387 1388  void
1388 1389  create_log_thread(zlog_t *logp, zoneid_t id)
1389 1390  {
1390 1391          int res;
1391 1392  
1392 1393          shutting_down = 0;
1393 1394          zlogp = logp;
1394 1395  
1395 1396          get_mode_logmax(&mode);
1396 1397          if (mode.zmode_n_stddevs == 0)
1397 1398                  return;
1398 1399  
1399 1400          if (init_zfd_devs(zlogp, &mode) == -1) {
1400 1401                  zerror(zlogp, B_FALSE,
1401 1402                      "zfd setup: device initialization failed");
1402 1403                  return;
1403 1404          }
1404 1405  
1405 1406          res = thr_create(NULL, 0, (void * (*)(void *))srvr, (void *)&mode, 0,
1406 1407              &logger_tid);
1407 1408          if (res != 0) {
1408 1409                  zerror(zlogp, B_FALSE, "error %d creating logger thread", res);
1409 1410                  logger_tid = 0;
1410 1411          }
1411 1412  }
1412 1413  
1413 1414  void
1414 1415  destroy_log_thread()
1415 1416  {
1416 1417          if (logger_tid != 0) {
1417 1418                  int stop = 1;
1418 1419  
1419 1420                  shutting_down = 1;
1420 1421                  /* break out of poll to shutdown */
1421 1422                  if (eventstream[0] != -1)
1422 1423                          (void) write(eventstream[0], &stop, sizeof (stop));
1423 1424                  (void) thr_join(logger_tid, NULL, NULL);
1424 1425                  logger_tid = 0;
1425 1426          }
1426 1427  
1427 1428          (void) destroy_zfd_devs(zlogp);
1428 1429  }
  
    | 
      ↓ open down ↓ | 
    32 lines elided | 
    
      ↑ open up ↑ | 
  
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX