1 /* 2 * CDDL HEADER START 3 * 4 * The contents of this file are subject to the terms of the 5 * Common Development and Distribution License (the "License"). 6 * You may not use this file except in compliance with the License. 7 * 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9 * or http://www.opensolaris.org/os/licensing. 10 * See the License for the specific language governing permissions 11 * and limitations under the License. 12 * 13 * When distributing Covered Code, include this CDDL HEADER in each 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15 * If applicable, add the following below this CDDL HEADER, with the 16 * fields enclosed by brackets "[]" replaced with your own identifying 17 * information: Portions Copyright [yyyy] [name of copyright owner] 18 * 19 * CDDL HEADER END 20 */ 21 22 /* 23 * Copyright 2009 Sun Microsystems, Inc. All rights reserved. 24 * Use is subject to license terms. 25 * Copyright 2012 Joyent, Inc. All rights reserved. 26 * Copyright 2015 Nexenta Systems, Inc. All rights reserved. 27 */ 28 29 /* 30 * Console support for zones requires a significant infrastructure. The 31 * core pieces are contained in this file, but other portions of note 32 * are in the zlogin(1M) command, the zcons(7D) driver, and in the 33 * devfsadm(1M) misc_link generator. 34 * 35 * Care is taken to make the console behave in an "intuitive" fashion for 36 * administrators. Essentially, we try as much as possible to mimic the 37 * experience of using a system via a tip line and system controller. 38 * 39 * The zone console architecture looks like this: 40 * 41 * Global Zone | Non-Global Zone 42 * .--------------. | 43 * .-----------. | zoneadmd -z | | .--------. .---------. 44 * | zlogin -C | | myzone | | | ttymon | | syslogd | 45 * `-----------' `--------------' | `--------' `---------' 46 * | | | | | | | 47 * User | | | | | V V 48 * - - - - - - - - -|- - - -|- - - -|-|- - - - - - -|- - /dev/zconsole - - - 49 * Kernel V V | | | 50 * [AF_UNIX Socket] | `--------. .-------------' 51 * | | | 52 * | V V 53 * | +-----------+ 54 * | | ldterm, | 55 * | | etc. | 56 * | +-----------+ 57 * | +-[Anchor]--+ 58 * | | ptem | 59 * V +-----------+ 60 * +---master---+---slave---+ 61 * | | 62 * | zcons driver | 63 * | zonename="myzone" | 64 * +------------------------+ 65 * 66 * There are basically two major tasks which the console subsystem in 67 * zoneadmd accomplishes: 68 * 69 * - Setup and teardown of zcons driver instances. One zcons instance 70 * is maintained per zone; we take advantage of the libdevice APIs 71 * to online new instances of zcons as needed. Care is taken to 72 * prune and manage these appropriately; see init_console_dev() and 73 * destroy_console_dev(). The end result is the creation of the 74 * zcons(7D) instance and an open file descriptor to the master side. 75 * zcons instances are associated with zones via their zonename device 76 * property. This the console instance to persist across reboots, 77 * and while the zone is halted. 78 * 79 * - Acting as a server for 'zlogin -C' instances. When zlogin -C is 80 * run, zlogin connects to zoneadmd via unix domain socket. zoneadmd 81 * functions as a two-way proxy for console I/O, relaying user input 82 * to the master side of the console, and relaying output from the 83 * zone to the user. 84 */ 85 86 #include <sys/types.h> 87 #include <sys/socket.h> 88 #include <sys/stat.h> 89 #include <sys/termios.h> 90 #include <sys/zcons.h> 91 #include <sys/mkdev.h> 92 93 #include <assert.h> 94 #include <ctype.h> 95 #include <errno.h> 96 #include <fcntl.h> 97 #include <stdarg.h> 98 #include <stdio.h> 99 #include <stdlib.h> 100 #include <strings.h> 101 #include <stropts.h> 102 #include <thread.h> 103 #include <ucred.h> 104 #include <unistd.h> 105 #include <zone.h> 106 107 #include <libdevinfo.h> 108 #include <libdevice.h> 109 #include <libzonecfg.h> 110 111 #include <syslog.h> 112 #include <sys/modctl.h> 113 114 #include "zoneadmd.h" 115 116 #define ZCONSNEX_DEVTREEPATH "/pseudo/zconsnex@1" 117 #define ZCONSNEX_FILEPATH "/devices/pseudo/zconsnex@1" 118 119 #define CONSOLE_SOCKPATH ZONES_TMPDIR "/%s.console_sock" 120 121 static int serverfd = -1; /* console server unix domain socket fd */ 122 char boot_args[BOOTARGS_MAX]; 123 char bad_boot_arg[BOOTARGS_MAX]; 124 125 /* 126 * The eventstream is a simple one-directional flow of messages from the 127 * door server to the console subsystem, implemented with a pipe. 128 * It is used to wake up the console poller when it needs to take action, 129 * message the user, die off, etc. 130 */ 131 static int eventstream[2]; 132 133 134 135 int 136 eventstream_init() 137 { 138 if (pipe(eventstream) == -1) 139 return (-1); 140 return (0); 141 } 142 143 void 144 eventstream_write(zone_evt_t evt) 145 { 146 (void) write(eventstream[0], &evt, sizeof (evt)); 147 } 148 149 static zone_evt_t 150 eventstream_read(void) 151 { 152 zone_evt_t evt = Z_EVT_NULL; 153 154 (void) read(eventstream[1], &evt, sizeof (evt)); 155 return (evt); 156 } 157 158 /* 159 * count_console_devs() and its helper count_cb() do a walk of the 160 * subtree of the device tree where zone console nodes are represented. 161 * The goal is to count zone console instances already setup for a zone 162 * with the given name. More than 1 is anomolous, and our caller will 163 * have to deal with that if we find that's the case. 164 * 165 * Note: this algorithm is a linear search of nodes in the zconsnex subtree 166 * of the device tree, and could be a scalability problem, but I don't see 167 * how to avoid it. 168 */ 169 170 /* 171 * cb_data is shared by count_cb and destroy_cb for simplicity. 172 */ 173 struct cb_data { 174 zlog_t *zlogp; 175 int found; 176 int killed; 177 }; 178 179 static int 180 count_cb(di_node_t node, void *arg) 181 { 182 struct cb_data *cb = (struct cb_data *)arg; 183 char *prop_data; 184 185 if (di_prop_lookup_strings(DDI_DEV_T_ANY, node, "zonename", 186 &prop_data) != -1) { 187 assert(prop_data != NULL); 188 if (strcmp(prop_data, zone_name) == 0) { 189 cb->found++; 190 return (DI_WALK_CONTINUE); 191 } 192 } 193 return (DI_WALK_CONTINUE); 194 } 195 196 static int 197 count_console_devs(zlog_t *zlogp) 198 { 199 di_node_t root; 200 struct cb_data cb; 201 202 bzero(&cb, sizeof (cb)); 203 cb.zlogp = zlogp; 204 205 if ((root = di_init(ZCONSNEX_DEVTREEPATH, DINFOCPYALL)) == 206 DI_NODE_NIL) { 207 zerror(zlogp, B_TRUE, "%s failed", "di_init"); 208 return (-1); 209 } 210 211 (void) di_walk_node(root, DI_WALK_CLDFIRST, (void *)&cb, count_cb); 212 di_fini(root); 213 return (cb.found); 214 } 215 216 /* 217 * destroy_console_devs() and its helper destroy_cb() tears down any console 218 * instances associated with this zone. If things went very wrong, we 219 * might have more than one console instance hanging around. This routine 220 * hunts down and tries to remove all of them. Of course, if the console 221 * is open, the instance will not detach, which is a potential issue. 222 */ 223 static int 224 destroy_cb(di_node_t node, void *arg) 225 { 226 struct cb_data *cb = (struct cb_data *)arg; 227 char *prop_data; 228 char *tmp; 229 char devpath[MAXPATHLEN]; 230 devctl_hdl_t hdl; 231 232 if (di_prop_lookup_strings(DDI_DEV_T_ANY, node, "zonename", 233 &prop_data) == -1) 234 return (DI_WALK_CONTINUE); 235 236 assert(prop_data != NULL); 237 if (strcmp(prop_data, zone_name) != 0) { 238 /* this is the console for a different zone */ 239 return (DI_WALK_CONTINUE); 240 } 241 242 cb->found++; 243 tmp = di_devfs_path(node); 244 (void) snprintf(devpath, sizeof (devpath), "/devices/%s", tmp); 245 di_devfs_path_free(tmp); 246 247 if ((hdl = devctl_device_acquire(devpath, 0)) == NULL) { 248 zerror(cb->zlogp, B_TRUE, "WARNING: console %s found, " 249 "but it could not be controlled.", devpath); 250 return (DI_WALK_CONTINUE); 251 } 252 if (devctl_device_remove(hdl) == 0) { 253 cb->killed++; 254 } else { 255 zerror(cb->zlogp, B_TRUE, "WARNING: console %s found, " 256 "but it could not be removed.", devpath); 257 } 258 devctl_release(hdl); 259 return (DI_WALK_CONTINUE); 260 } 261 262 static int 263 destroy_console_devs(zlog_t *zlogp) 264 { 265 char conspath[MAXPATHLEN]; 266 di_node_t root; 267 struct cb_data cb; 268 int masterfd; 269 int slavefd; 270 271 /* 272 * Signal the master side to release its handle on the slave side by 273 * issuing a ZC_RELEASESLAVE ioctl. 274 */ 275 (void) snprintf(conspath, sizeof (conspath), "/dev/zcons/%s/%s", 276 zone_name, ZCONS_MASTER_NAME); 277 if ((masterfd = open(conspath, O_RDWR | O_NOCTTY)) != -1) { 278 (void) snprintf(conspath, sizeof (conspath), "/dev/zcons/%s/%s", 279 zone_name, ZCONS_SLAVE_NAME); 280 if ((slavefd = open(conspath, O_RDWR | O_NOCTTY)) != -1) { 281 if (ioctl(masterfd, ZC_RELEASESLAVE, 282 (caddr_t)(intptr_t)slavefd) != 0) 283 zerror(zlogp, B_TRUE, "WARNING: error while " 284 "releasing slave handle of zone console for" 285 " %s", zone_name); 286 (void) close(slavefd); 287 } else { 288 zerror(zlogp, B_TRUE, "WARNING: could not open slave " 289 "side of zone console for %s to release slave " 290 "handle", zone_name); 291 } 292 (void) close(masterfd); 293 } else { 294 zerror(zlogp, B_TRUE, "WARNING: could not open master side of " 295 "zone console for %s to release slave handle", zone_name); 296 } 297 298 bzero(&cb, sizeof (cb)); 299 cb.zlogp = zlogp; 300 301 if ((root = di_init(ZCONSNEX_DEVTREEPATH, DINFOCPYALL)) == 302 DI_NODE_NIL) { 303 zerror(zlogp, B_TRUE, "%s failed", "di_init"); 304 return (-1); 305 } 306 307 (void) di_walk_node(root, DI_WALK_CLDFIRST, (void *)&cb, destroy_cb); 308 if (cb.found > 1) { 309 zerror(zlogp, B_FALSE, "WARNING: multiple zone console " 310 "instances detected for zone '%s'; %d of %d " 311 "successfully removed.", 312 zone_name, cb.killed, cb.found); 313 } 314 315 di_fini(root); 316 return (0); 317 } 318 319 /* 320 * init_console_dev() drives the device-tree configuration of the zone 321 * console device. The general strategy is to use the libdevice (devctl) 322 * interfaces to instantiate a new zone console node. We do a lot of 323 * sanity checking, and are careful to reuse a console if one exists. 324 * 325 * Once the device is in the device tree, we kick devfsadm via di_init_devs() 326 * to ensure that the appropriate symlinks (to the master and slave console 327 * devices) are placed in /dev in the global zone. 328 */ 329 static int 330 init_console_dev(zlog_t *zlogp) 331 { 332 char conspath[MAXPATHLEN]; 333 devctl_hdl_t bus_hdl = NULL; 334 devctl_hdl_t dev_hdl = NULL; 335 devctl_ddef_t ddef_hdl = NULL; 336 di_devlink_handle_t dl = NULL; 337 int rv = -1; 338 int ndevs; 339 int masterfd; 340 int slavefd; 341 int i; 342 343 /* 344 * Don't re-setup console if it is working and ready already; just 345 * skip ahead to making devlinks, which we do for sanity's sake. 346 */ 347 ndevs = count_console_devs(zlogp); 348 if (ndevs == 1) { 349 goto devlinks; 350 } else if (ndevs > 1 || ndevs == -1) { 351 /* 352 * For now, this seems like a reasonable but harsh punishment. 353 * If needed, we could try to get clever and delete all but 354 * the console which is pointed at by the current symlink. 355 */ 356 if (destroy_console_devs(zlogp) == -1) { 357 goto error; 358 } 359 } 360 361 /* 362 * Time to make the consoles! 363 */ 364 if ((bus_hdl = devctl_bus_acquire(ZCONSNEX_FILEPATH, 0)) == NULL) { 365 zerror(zlogp, B_TRUE, "%s failed", "devctl_bus_acquire"); 366 goto error; 367 } 368 if ((ddef_hdl = devctl_ddef_alloc("zcons", 0)) == NULL) { 369 zerror(zlogp, B_TRUE, "failed to allocate ddef handle"); 370 goto error; 371 } 372 /* 373 * Set three properties on this node; the first is the name of the 374 * zone; the second is a flag which lets pseudo know that it is 375 * OK to automatically allocate an instance # for this device; 376 * the third tells the device framework not to auto-detach this 377 * node-- we need the node to still be there when we ask devfsadmd 378 * to make links, and when we need to open it. 379 */ 380 if (devctl_ddef_string(ddef_hdl, "zonename", zone_name) == -1) { 381 zerror(zlogp, B_TRUE, "failed to create zonename property"); 382 goto error; 383 } 384 if (devctl_ddef_int(ddef_hdl, "auto-assign-instance", 1) == -1) { 385 zerror(zlogp, B_TRUE, "failed to create auto-assign-instance " 386 "property"); 387 goto error; 388 } 389 if (devctl_ddef_int(ddef_hdl, "ddi-no-autodetach", 1) == -1) { 390 zerror(zlogp, B_TRUE, "failed to create ddi-no-auto-detach " 391 "property"); 392 goto error; 393 } 394 if (devctl_bus_dev_create(bus_hdl, ddef_hdl, 0, &dev_hdl) == -1) { 395 zerror(zlogp, B_TRUE, "failed to create console node"); 396 goto error; 397 } 398 399 devlinks: 400 if ((dl = di_devlink_init("zcons", DI_MAKE_LINK)) != NULL) { 401 (void) di_devlink_fini(&dl); 402 } else { 403 zerror(zlogp, B_TRUE, "failed to create devlinks"); 404 goto error; 405 } 406 407 /* 408 * Open the master side of the console and issue the ZC_HOLDSLAVE ioctl, 409 * which will cause the master to retain a reference to the slave. 410 * This prevents ttymon from blowing through the slave's STREAMS anchor. 411 */ 412 (void) snprintf(conspath, sizeof (conspath), "/dev/zcons/%s/%s", 413 zone_name, ZCONS_MASTER_NAME); 414 if ((masterfd = open(conspath, O_RDWR | O_NOCTTY)) == -1) { 415 zerror(zlogp, B_TRUE, "ERROR: could not open master side of " 416 "zone console for %s to acquire slave handle", zone_name); 417 goto error; 418 } 419 (void) snprintf(conspath, sizeof (conspath), "/dev/zcons/%s/%s", 420 zone_name, ZCONS_SLAVE_NAME); 421 if ((slavefd = open(conspath, O_RDWR | O_NOCTTY)) == -1) { 422 zerror(zlogp, B_TRUE, "ERROR: could not open slave side of zone" 423 " console for %s to acquire slave handle", zone_name); 424 (void) close(masterfd); 425 goto error; 426 } 427 /* 428 * This ioctl can occasionally return ENXIO if devfs doesn't have 429 * everything plumbed up yet due to heavy zone startup load. Wait for 430 * 1 sec. and retry a few times before we fail to boot the zone. 431 */ 432 for (i = 0; i < 5; i++) { 433 if (ioctl(masterfd, ZC_HOLDSLAVE, (caddr_t)(intptr_t)slavefd) 434 == 0) { 435 rv = 0; 436 break; 437 } else if (errno != ENXIO) { 438 break; 439 } 440 (void) sleep(1); 441 } 442 if (rv != 0) 443 zerror(zlogp, B_TRUE, "ERROR: error while acquiring slave " 444 "handle of zone console for %s", zone_name); 445 446 (void) close(slavefd); 447 (void) close(masterfd); 448 449 error: 450 if (ddef_hdl) 451 devctl_ddef_free(ddef_hdl); 452 if (bus_hdl) 453 devctl_release(bus_hdl); 454 if (dev_hdl) 455 devctl_release(dev_hdl); 456 return (rv); 457 } 458 459 static int 460 init_console_sock(zlog_t *zlogp) 461 { 462 int servfd; 463 struct sockaddr_un servaddr; 464 465 bzero(&servaddr, sizeof (servaddr)); 466 servaddr.sun_family = AF_UNIX; 467 (void) snprintf(servaddr.sun_path, sizeof (servaddr.sun_path), 468 CONSOLE_SOCKPATH, zone_name); 469 470 if ((servfd = socket(AF_UNIX, SOCK_STREAM, 0)) == -1) { 471 zerror(zlogp, B_TRUE, "console setup: could not create socket"); 472 return (-1); 473 } 474 (void) unlink(servaddr.sun_path); 475 476 if (bind(servfd, (struct sockaddr *)&servaddr, 477 sizeof (servaddr)) == -1) { 478 zerror(zlogp, B_TRUE, 479 "console setup: could not bind to socket"); 480 goto out; 481 } 482 483 if (listen(servfd, 4) == -1) { 484 zerror(zlogp, B_TRUE, 485 "console setup: could not listen on socket"); 486 goto out; 487 } 488 return (servfd); 489 490 out: 491 (void) unlink(servaddr.sun_path); 492 (void) close(servfd); 493 return (-1); 494 } 495 496 static void 497 destroy_console_sock(int servfd) 498 { 499 char path[MAXPATHLEN]; 500 501 (void) snprintf(path, sizeof (path), CONSOLE_SOCKPATH, zone_name); 502 (void) unlink(path); 503 (void) shutdown(servfd, SHUT_RDWR); 504 (void) close(servfd); 505 } 506 507 /* 508 * Read the "ident" string from the client's descriptor; this routine also 509 * tolerates being called with pid=NULL, for times when you want to "eat" 510 * the ident string from a client without saving it. 511 */ 512 static int 513 get_client_ident(int clifd, pid_t *pid, char *locale, size_t locale_len, 514 int *disconnect) 515 { 516 char buf[BUFSIZ], *bufp; 517 size_t buflen = sizeof (buf); 518 char c = '\0'; 519 int i = 0, r; 520 521 /* "eat up the ident string" case, for simplicity */ 522 if (pid == NULL) { 523 assert(locale == NULL && locale_len == 0); 524 while (read(clifd, &c, 1) == 1) { 525 if (c == '\n') 526 return (0); 527 } 528 } 529 530 bzero(buf, sizeof (buf)); 531 while ((buflen > 1) && (r = read(clifd, &c, 1)) == 1) { 532 buflen--; 533 if (c == '\n') 534 break; 535 536 buf[i] = c; 537 i++; 538 } 539 if (r == -1) 540 return (-1); 541 542 /* 543 * We've filled the buffer, but still haven't seen \n. Keep eating 544 * until we find it; we don't expect this to happen, but this is 545 * defensive. 546 */ 547 if (c != '\n') { 548 while ((r = read(clifd, &c, sizeof (c))) > 0) 549 if (c == '\n') 550 break; 551 } 552 553 /* 554 * Parse buffer for message of the form: 555 * IDENT <pid> <locale> <disconnect flag> 556 */ 557 bufp = buf; 558 if (strncmp(bufp, "IDENT ", 6) != 0) 559 return (-1); 560 bufp += 6; 561 errno = 0; 562 *pid = strtoll(bufp, &bufp, 10); 563 if (errno != 0) 564 return (-1); 565 566 while (*bufp != '\0' && isspace(*bufp)) 567 bufp++; 568 buflen = strlen(bufp) - 1; 569 *disconnect = atoi(&bufp[buflen]); 570 bufp[buflen - 1] = '\0'; 571 (void) strlcpy(locale, bufp, locale_len); 572 573 return (0); 574 } 575 576 static int 577 accept_client(int servfd, pid_t *pid, char *locale, size_t locale_len, 578 int *disconnect) 579 { 580 int connfd; 581 struct sockaddr_un cliaddr; 582 socklen_t clilen; 583 584 clilen = sizeof (cliaddr); 585 connfd = accept(servfd, (struct sockaddr *)&cliaddr, &clilen); 586 if (connfd == -1) 587 return (-1); 588 if (get_client_ident(connfd, pid, locale, locale_len, 589 disconnect) == -1) { 590 (void) shutdown(connfd, SHUT_RDWR); 591 (void) close(connfd); 592 return (-1); 593 } 594 (void) write(connfd, "OK\n", 3); 595 return (connfd); 596 } 597 598 static void 599 reject_client(int servfd, pid_t clientpid) 600 { 601 int connfd; 602 struct sockaddr_un cliaddr; 603 socklen_t clilen; 604 char nak[MAXPATHLEN]; 605 606 clilen = sizeof (cliaddr); 607 connfd = accept(servfd, (struct sockaddr *)&cliaddr, &clilen); 608 609 /* 610 * After hear its ident string, tell client to get lost. 611 */ 612 if (get_client_ident(connfd, NULL, NULL, 0, NULL) == 0) { 613 (void) snprintf(nak, sizeof (nak), "%lu\n", 614 clientpid); 615 (void) write(connfd, nak, strlen(nak)); 616 } 617 (void) shutdown(connfd, SHUT_RDWR); 618 (void) close(connfd); 619 } 620 621 static void 622 event_message(int clifd, char *clilocale, zone_evt_t evt, int dflag) 623 { 624 char *str, *lstr = NULL; 625 char lmsg[BUFSIZ]; 626 char outbuf[BUFSIZ]; 627 628 if (clifd == -1) 629 return; 630 631 switch (evt) { 632 case Z_EVT_ZONE_BOOTING: 633 if (*boot_args == '\0') { 634 str = "NOTICE: Zone booting up"; 635 break; 636 } 637 /*LINTED*/ 638 (void) snprintf(lmsg, sizeof (lmsg), localize_msg(clilocale, 639 "NOTICE: Zone booting up with arguments: %s"), boot_args); 640 lstr = lmsg; 641 break; 642 case Z_EVT_ZONE_READIED: 643 str = "NOTICE: Zone readied"; 644 break; 645 case Z_EVT_ZONE_HALTED: 646 if (dflag) 647 str = "NOTICE: Zone halted. Disconnecting..."; 648 else 649 str = "NOTICE: Zone halted"; 650 break; 651 case Z_EVT_ZONE_REBOOTING: 652 if (*boot_args == '\0') { 653 str = "NOTICE: Zone rebooting"; 654 break; 655 } 656 /*LINTED*/ 657 (void) snprintf(lmsg, sizeof (lmsg), localize_msg(clilocale, 658 "NOTICE: Zone rebooting with arguments: %s"), boot_args); 659 lstr = lmsg; 660 break; 661 case Z_EVT_ZONE_UNINSTALLING: 662 str = "NOTICE: Zone is being uninstalled. Disconnecting..."; 663 break; 664 case Z_EVT_ZONE_BOOTFAILED: 665 if (dflag) 666 str = "NOTICE: Zone boot failed. Disconnecting..."; 667 else 668 str = "NOTICE: Zone boot failed"; 669 break; 670 case Z_EVT_ZONE_BADARGS: 671 /*LINTED*/ 672 (void) snprintf(lmsg, sizeof (lmsg), 673 localize_msg(clilocale, 674 "WARNING: Ignoring invalid boot arguments: %s"), 675 bad_boot_arg); 676 lstr = lmsg; 677 break; 678 default: 679 return; 680 } 681 682 if (lstr == NULL) 683 lstr = localize_msg(clilocale, str); 684 (void) snprintf(outbuf, sizeof (outbuf), "\r\n[%s]\r\n", lstr); 685 (void) write(clifd, outbuf, strlen(outbuf)); 686 } 687 688 /* 689 * Check to see if the client at the other end of the socket is still 690 * alive; we know it is not if it throws EPIPE at us when we try to write 691 * an otherwise harmless 0-length message to it. 692 */ 693 static int 694 test_client(int clifd) 695 { 696 if ((write(clifd, "", 0) == -1) && errno == EPIPE) 697 return (-1); 698 return (0); 699 } 700 701 /* 702 * This routine drives the console I/O loop. It polls for input from the 703 * master side of the console (output to the console), and from the client 704 * (input from the console user). Additionally, it polls on the server fd, 705 * and disconnects any clients that might try to hook up with the zone while 706 * the console is in use. 707 * 708 * When the client first calls us up, it is expected to send a line giving 709 * its "identity"; this consists of the string 'IDENT <pid> <locale>'. 710 * This is so that we can report that the console is busy along with 711 * some diagnostics about who has it busy; the locale is used so that 712 * asynchronous messages about zone state (like the NOTICE: zone halted 713 * messages) can be output in the user's locale. 714 */ 715 static void 716 do_console_io(zlog_t *zlogp, int consfd, int servfd) 717 { 718 struct pollfd pollfds[4]; 719 char ibuf[BUFSIZ]; 720 int cc, ret; 721 int clifd = -1; 722 int pollerr = 0; 723 char clilocale[MAXPATHLEN]; 724 pid_t clipid = 0; 725 int disconnect = 0; 726 727 /* console side, watch for read events */ 728 pollfds[0].fd = consfd; 729 pollfds[0].events = POLLIN | POLLRDNORM | POLLRDBAND | 730 POLLPRI | POLLERR | POLLHUP | POLLNVAL; 731 732 /* client side, watch for read events */ 733 pollfds[1].fd = clifd; 734 pollfds[1].events = pollfds[0].events; 735 736 /* the server socket; watch for events (new connections) */ 737 pollfds[2].fd = servfd; 738 pollfds[2].events = pollfds[0].events; 739 740 /* the eventstram; watch for events (e.g.: zone halted) */ 741 pollfds[3].fd = eventstream[1]; 742 pollfds[3].events = pollfds[0].events; 743 744 for (;;) { 745 pollfds[0].revents = pollfds[1].revents = 0; 746 pollfds[2].revents = pollfds[3].revents = 0; 747 748 ret = poll(pollfds, 749 sizeof (pollfds) / sizeof (struct pollfd), -1); 750 if (ret == -1 && errno != EINTR) { 751 zerror(zlogp, B_TRUE, "poll failed"); 752 /* we are hosed, close connection */ 753 break; 754 } 755 756 /* event from console side */ 757 if (pollfds[0].revents) { 758 if (pollfds[0].revents & 759 (POLLIN | POLLRDNORM | POLLRDBAND | POLLPRI)) { 760 errno = 0; 761 cc = read(consfd, ibuf, BUFSIZ); 762 if (cc <= 0 && (errno != EINTR) && 763 (errno != EAGAIN)) 764 break; 765 /* 766 * Lose I/O if no one is listening 767 */ 768 if (clifd != -1 && cc > 0) 769 (void) write(clifd, ibuf, cc); 770 } else { 771 pollerr = pollfds[0].revents; 772 zerror(zlogp, B_FALSE, 773 "closing connection with (console) " 774 "pollerr %d\n", pollerr); 775 break; 776 } 777 } 778 779 /* event from client side */ 780 if (pollfds[1].revents) { 781 if (pollfds[1].revents & 782 (POLLIN | POLLRDNORM | POLLRDBAND | POLLPRI)) { 783 errno = 0; 784 cc = read(clifd, ibuf, BUFSIZ); 785 if (cc <= 0 && (errno != EINTR) && 786 (errno != EAGAIN)) 787 break; 788 (void) write(consfd, ibuf, cc); 789 } else { 790 pollerr = pollfds[1].revents; 791 zerror(zlogp, B_FALSE, 792 "closing connection with (client) " 793 "pollerr %d\n", pollerr); 794 break; 795 } 796 } 797 798 /* event from server socket */ 799 if (pollfds[2].revents && 800 (pollfds[2].revents & (POLLIN | POLLRDNORM))) { 801 if (clifd != -1) { 802 /* 803 * Test the client to see if it is really 804 * still alive. If it has died but we 805 * haven't yet detected that, we might 806 * deny a legitimate connect attempt. If it 807 * is dead, we break out; once we tear down 808 * the old connection, the new connection 809 * will happen. 810 */ 811 if (test_client(clifd) == -1) { 812 break; 813 } 814 /* we're already handling a client */ 815 reject_client(servfd, clipid); 816 817 818 } else if ((clifd = accept_client(servfd, &clipid, 819 clilocale, sizeof (clilocale), 820 &disconnect)) != -1) { 821 pollfds[1].fd = clifd; 822 823 } else { 824 break; 825 } 826 } 827 828 /* 829 * Watch for events on the eventstream. This is how we get 830 * notified of the zone halting, etc. It provides us a 831 * "wakeup" from poll when important things happen, which 832 * is good. 833 */ 834 if (pollfds[3].revents) { 835 int evt = eventstream_read(); 836 /* 837 * After we drain out the event, if we aren't servicing 838 * a console client, we hop back out to our caller, 839 * which will check to see if it is time to shutdown 840 * the daemon, or if we should take another console 841 * service lap. 842 */ 843 if (clifd == -1) { 844 break; 845 } 846 event_message(clifd, clilocale, evt, disconnect); 847 /* 848 * Special handling for the message that the zone is 849 * uninstalling; we boot the client, then break out 850 * of this function. When we return to the 851 * serve_console loop, we will see that the zone is 852 * in a state < READY, and so zoneadmd will shutdown. 853 */ 854 if (evt == Z_EVT_ZONE_UNINSTALLING) { 855 break; 856 } 857 /* 858 * Diconnect if -C and -d options were specified and 859 * zone was halted or failed to boot. 860 */ 861 if ((evt == Z_EVT_ZONE_HALTED || 862 evt == Z_EVT_ZONE_BOOTFAILED) && disconnect) { 863 break; 864 } 865 } 866 867 } 868 869 if (clifd != -1) { 870 (void) shutdown(clifd, SHUT_RDWR); 871 (void) close(clifd); 872 } 873 } 874 875 int 876 init_console(zlog_t *zlogp) 877 { 878 if (init_console_dev(zlogp) == -1) { 879 zerror(zlogp, B_FALSE, 880 "console setup: device initialization failed"); 881 return (-1); 882 } 883 884 if ((serverfd = init_console_sock(zlogp)) == -1) { 885 zerror(zlogp, B_FALSE, 886 "console setup: socket initialization failed"); 887 return (-1); 888 } 889 return (0); 890 } 891 892 /* 893 * serve_console() is the master loop for driving console I/O. It is also the 894 * routine which is ultimately responsible for "pulling the plug" on zoneadmd 895 * when it realizes that the daemon should shut down. 896 * 897 * The rules for shutdown are: there must be no console client, and the zone 898 * state must be < ready. However, we need to give things a chance to actually 899 * get going when the daemon starts up-- otherwise the daemon would immediately 900 * exit on startup if the zone was in the installed state, so we first drop 901 * into the do_console_io() loop in order to give *something* a chance to 902 * happen. 903 */ 904 void 905 serve_console(zlog_t *zlogp) 906 { 907 int masterfd; 908 zone_state_t zstate; 909 char conspath[MAXPATHLEN]; 910 911 (void) snprintf(conspath, sizeof (conspath), 912 "/dev/zcons/%s/%s", zone_name, ZCONS_MASTER_NAME); 913 914 for (;;) { 915 masterfd = open(conspath, O_RDWR|O_NONBLOCK|O_NOCTTY); 916 if (masterfd == -1) { 917 zerror(zlogp, B_TRUE, "failed to open console master"); 918 (void) mutex_lock(&lock); 919 goto death; 920 } 921 922 /* 923 * Setting RPROTDIS on the stream means that the control 924 * portion of messages received (which we don't care about) 925 * will be discarded by the stream head. If we allowed such 926 * messages, we wouldn't be able to use read(2), as it fails 927 * (EBADMSG) when a message with a control element is received. 928 */ 929 if (ioctl(masterfd, I_SRDOPT, RNORM|RPROTDIS) == -1) { 930 zerror(zlogp, B_TRUE, "failed to set options on " 931 "console master"); 932 (void) mutex_lock(&lock); 933 goto death; 934 } 935 936 do_console_io(zlogp, masterfd, serverfd); 937 938 /* 939 * We would prefer not to do this, but hostile zone processes 940 * can cause the stream to become tainted, and reads will 941 * fail. So, in case something has gone seriously ill, 942 * we dismantle the stream and reopen the console when we 943 * take another lap. 944 */ 945 (void) close(masterfd); 946 947 (void) mutex_lock(&lock); 948 /* 949 * We need to set death_throes (see below) atomically with 950 * respect to noticing that (a) we have no console client and 951 * (b) the zone is not installed. Otherwise we could get a 952 * request to boot during this time. Once we set death_throes, 953 * any incoming door stuff will be turned away. 954 */ 955 if (zone_get_state(zone_name, &zstate) == Z_OK) { 956 if (zstate < ZONE_STATE_READY) 957 goto death; 958 } else { 959 zerror(zlogp, B_FALSE, 960 "unable to determine state of zone"); 961 goto death; 962 } 963 /* 964 * Even if zone_get_state() fails, stay conservative, and 965 * take another lap. 966 */ 967 (void) mutex_unlock(&lock); 968 } 969 970 death: 971 assert(MUTEX_HELD(&lock)); 972 in_death_throes = B_TRUE; 973 (void) mutex_unlock(&lock); 974 975 destroy_console_sock(serverfd); 976 (void) destroy_console_devs(zlogp); 977 }