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(1) command, the zcons(4D) driver, and in the 33 * devfsadm(8) 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 * +---manager--+-subsidiary+ 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(4D) instance and an open file descriptor to the manager 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 manager 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 managerfd; 269 int subfd; 270 271 /* 272 * Signal the manager side to release its handle on the subsidiary side 273 * by issuing a ZC_RELEASESUBSID ioctl. 274 */ 275 (void) snprintf(conspath, sizeof (conspath), "/dev/zcons/%s/%s", 276 zone_name, ZCONS_MANAGER_NAME); 277 if ((managerfd = open(conspath, O_RDWR | O_NOCTTY)) != -1) { 278 (void) snprintf(conspath, sizeof (conspath), "/dev/zcons/%s/%s", 279 zone_name, ZCONS_SUBSIDIARY_NAME); 280 if ((subfd = open(conspath, O_RDWR | O_NOCTTY)) != -1) { 281 if (ioctl(managerfd, ZC_RELEASESUBSID, 282 (caddr_t)(intptr_t)subfd) != 0) 283 zerror(zlogp, B_TRUE, "WARNING: error while " 284 "releasing subsidiary handle of zone " 285 "console for %s", zone_name); 286 (void) close(subfd); 287 } else { 288 zerror(zlogp, B_TRUE, "WARNING: could not open " 289 "subsidiary side of zone console for %s to " 290 "release subsidiary handle", zone_name); 291 } 292 (void) close(managerfd); 293 } else { 294 zerror(zlogp, B_TRUE, "WARNING: could not open manager side of " 295 "zone console for %s to release subsidiary handle", 296 zone_name); 297 } 298 299 bzero(&cb, sizeof (cb)); 300 cb.zlogp = zlogp; 301 302 if ((root = di_init(ZCONSNEX_DEVTREEPATH, DINFOCPYALL)) == 303 DI_NODE_NIL) { 304 zerror(zlogp, B_TRUE, "%s failed", "di_init"); 305 return (-1); 306 } 307 308 (void) di_walk_node(root, DI_WALK_CLDFIRST, (void *)&cb, destroy_cb); 309 if (cb.found > 1) { 310 zerror(zlogp, B_FALSE, "WARNING: multiple zone console " 311 "instances detected for zone '%s'; %d of %d " 312 "successfully removed.", 313 zone_name, cb.killed, cb.found); 314 } 315 316 di_fini(root); 317 return (0); 318 } 319 320 /* 321 * init_console_dev() drives the device-tree configuration of the zone 322 * console device. The general strategy is to use the libdevice (devctl) 323 * interfaces to instantiate a new zone console node. We do a lot of 324 * sanity checking, and are careful to reuse a console if one exists. 325 * 326 * Once the device is in the device tree, we kick devfsadm via di_init_devs() 327 * to ensure that the appropriate symlinks (to the manager and subsidiary 328 * console devices) are placed in /dev in the global zone. 329 */ 330 static int 331 init_console_dev(zlog_t *zlogp) 332 { 333 char conspath[MAXPATHLEN]; 334 devctl_hdl_t bus_hdl = NULL; 335 devctl_hdl_t dev_hdl = NULL; 336 devctl_ddef_t ddef_hdl = NULL; 337 di_devlink_handle_t dl = NULL; 338 int rv = -1; 339 int ndevs; 340 int managerfd; 341 int subfd; 342 int i; 343 344 /* 345 * Don't re-setup console if it is working and ready already; just 346 * skip ahead to making devlinks, which we do for sanity's sake. 347 */ 348 ndevs = count_console_devs(zlogp); 349 if (ndevs == 1) { 350 goto devlinks; 351 } else if (ndevs > 1 || ndevs == -1) { 352 /* 353 * For now, this seems like a reasonable but harsh punishment. 354 * If needed, we could try to get clever and delete all but 355 * the console which is pointed at by the current symlink. 356 */ 357 if (destroy_console_devs(zlogp) == -1) { 358 goto error; 359 } 360 } 361 362 /* 363 * Time to make the consoles! 364 */ 365 if ((bus_hdl = devctl_bus_acquire(ZCONSNEX_FILEPATH, 0)) == NULL) { 366 zerror(zlogp, B_TRUE, "%s failed", "devctl_bus_acquire"); 367 goto error; 368 } 369 if ((ddef_hdl = devctl_ddef_alloc("zcons", 0)) == NULL) { 370 zerror(zlogp, B_TRUE, "failed to allocate ddef handle"); 371 goto error; 372 } 373 /* 374 * Set three properties on this node; the first is the name of the 375 * zone; the second is a flag which lets pseudo know that it is 376 * OK to automatically allocate an instance # for this device; 377 * the third tells the device framework not to auto-detach this 378 * node-- we need the node to still be there when we ask devfsadmd 379 * to make links, and when we need to open it. 380 */ 381 if (devctl_ddef_string(ddef_hdl, "zonename", zone_name) == -1) { 382 zerror(zlogp, B_TRUE, "failed to create zonename property"); 383 goto error; 384 } 385 if (devctl_ddef_int(ddef_hdl, "auto-assign-instance", 1) == -1) { 386 zerror(zlogp, B_TRUE, "failed to create auto-assign-instance " 387 "property"); 388 goto error; 389 } 390 if (devctl_ddef_int(ddef_hdl, "ddi-no-autodetach", 1) == -1) { 391 zerror(zlogp, B_TRUE, "failed to create ddi-no-auto-detach " 392 "property"); 393 goto error; 394 } 395 if (devctl_bus_dev_create(bus_hdl, ddef_hdl, 0, &dev_hdl) == -1) { 396 zerror(zlogp, B_TRUE, "failed to create console node"); 397 goto error; 398 } 399 400 devlinks: 401 if ((dl = di_devlink_init("zcons", DI_MAKE_LINK)) != NULL) { 402 (void) di_devlink_fini(&dl); 403 } else { 404 zerror(zlogp, B_TRUE, "failed to create devlinks"); 405 goto error; 406 } 407 408 /* 409 * Open the manager side of the console and issue the ZC_HOLDSUBSID 410 * ioctl, which will cause the manager to retain a reference to the 411 * subsidiary. This prevents ttymon from blowing through the 412 * subsidiary's STREAMS anchor. 413 */ 414 (void) snprintf(conspath, sizeof (conspath), "/dev/zcons/%s/%s", 415 zone_name, ZCONS_MANAGER_NAME); 416 if ((managerfd = open(conspath, O_RDWR | O_NOCTTY)) == -1) { 417 zerror(zlogp, B_TRUE, "ERROR: could not open manager side of " 418 "zone console for %s to acquire subsidiary handle", 419 zone_name); 420 goto error; 421 } 422 (void) snprintf(conspath, sizeof (conspath), "/dev/zcons/%s/%s", 423 zone_name, ZCONS_SUBSIDIARY_NAME); 424 if ((subfd = open(conspath, O_RDWR | O_NOCTTY)) == -1) { 425 zerror(zlogp, B_TRUE, "ERROR: could not open subsidiary side " 426 "of zone console for %s to acquire subsidiary handle", 427 zone_name); 428 (void) close(managerfd); 429 goto error; 430 } 431 /* 432 * This ioctl can occasionally return ENXIO if devfs doesn't have 433 * everything plumbed up yet due to heavy zone startup load. Wait for 434 * 1 sec. and retry a few times before we fail to boot the zone. 435 */ 436 for (i = 0; i < 5; i++) { 437 if (ioctl(managerfd, ZC_HOLDSUBSID, (caddr_t)(intptr_t)subfd) 438 == 0) { 439 rv = 0; 440 break; 441 } else if (errno != ENXIO) { 442 break; 443 } 444 (void) sleep(1); 445 } 446 if (rv != 0) 447 zerror(zlogp, B_TRUE, "ERROR: error while acquiring " 448 "subsidiary handle of zone console for %s", zone_name); 449 450 (void) close(subfd); 451 (void) close(managerfd); 452 453 error: 454 if (ddef_hdl) 455 devctl_ddef_free(ddef_hdl); 456 if (bus_hdl) 457 devctl_release(bus_hdl); 458 if (dev_hdl) 459 devctl_release(dev_hdl); 460 return (rv); 461 } 462 463 static int 464 init_console_sock(zlog_t *zlogp) 465 { 466 int servfd; 467 struct sockaddr_un servaddr; 468 469 bzero(&servaddr, sizeof (servaddr)); 470 servaddr.sun_family = AF_UNIX; 471 (void) snprintf(servaddr.sun_path, sizeof (servaddr.sun_path), 472 CONSOLE_SOCKPATH, zone_name); 473 474 if ((servfd = socket(AF_UNIX, SOCK_STREAM, 0)) == -1) { 475 zerror(zlogp, B_TRUE, "console setup: could not create socket"); 476 return (-1); 477 } 478 (void) unlink(servaddr.sun_path); 479 480 if (bind(servfd, (struct sockaddr *)&servaddr, 481 sizeof (servaddr)) == -1) { 482 zerror(zlogp, B_TRUE, 483 "console setup: could not bind to socket"); 484 goto out; 485 } 486 487 if (listen(servfd, 4) == -1) { 488 zerror(zlogp, B_TRUE, 489 "console setup: could not listen on socket"); 490 goto out; 491 } 492 return (servfd); 493 494 out: 495 (void) unlink(servaddr.sun_path); 496 (void) close(servfd); 497 return (-1); 498 } 499 500 static void 501 destroy_console_sock(int servfd) 502 { 503 char path[MAXPATHLEN]; 504 505 (void) snprintf(path, sizeof (path), CONSOLE_SOCKPATH, zone_name); 506 (void) unlink(path); 507 (void) shutdown(servfd, SHUT_RDWR); 508 (void) close(servfd); 509 } 510 511 /* 512 * Read the "ident" string from the client's descriptor; this routine also 513 * tolerates being called with pid=NULL, for times when you want to "eat" 514 * the ident string from a client without saving it. 515 */ 516 static int 517 get_client_ident(int clifd, pid_t *pid, char *locale, size_t locale_len, 518 int *disconnect) 519 { 520 char buf[BUFSIZ], *bufp; 521 size_t buflen = sizeof (buf); 522 char c = '\0'; 523 int i = 0, r; 524 525 /* "eat up the ident string" case, for simplicity */ 526 if (pid == NULL) { 527 assert(locale == NULL && locale_len == 0); 528 while (read(clifd, &c, 1) == 1) { 529 if (c == '\n') 530 return (0); 531 } 532 } 533 534 bzero(buf, sizeof (buf)); 535 while ((buflen > 1) && (r = read(clifd, &c, 1)) == 1) { 536 buflen--; 537 if (c == '\n') 538 break; 539 540 buf[i] = c; 541 i++; 542 } 543 if (r == -1) 544 return (-1); 545 546 /* 547 * We've filled the buffer, but still haven't seen \n. Keep eating 548 * until we find it; we don't expect this to happen, but this is 549 * defensive. 550 */ 551 if (c != '\n') { 552 while ((r = read(clifd, &c, sizeof (c))) > 0) 553 if (c == '\n') 554 break; 555 } 556 557 /* 558 * Parse buffer for message of the form: 559 * IDENT <pid> <locale> <disconnect flag> 560 */ 561 bufp = buf; 562 if (strncmp(bufp, "IDENT ", 6) != 0) 563 return (-1); 564 bufp += 6; 565 errno = 0; 566 *pid = strtoll(bufp, &bufp, 10); 567 if (errno != 0) 568 return (-1); 569 570 while (*bufp != '\0' && isspace(*bufp)) 571 bufp++; 572 buflen = strlen(bufp) - 1; 573 *disconnect = atoi(&bufp[buflen]); 574 bufp[buflen - 1] = '\0'; 575 (void) strlcpy(locale, bufp, locale_len); 576 577 return (0); 578 } 579 580 static int 581 accept_client(int servfd, pid_t *pid, char *locale, size_t locale_len, 582 int *disconnect) 583 { 584 int connfd; 585 struct sockaddr_un cliaddr; 586 socklen_t clilen; 587 588 clilen = sizeof (cliaddr); 589 connfd = accept(servfd, (struct sockaddr *)&cliaddr, &clilen); 590 if (connfd == -1) 591 return (-1); 592 if (get_client_ident(connfd, pid, locale, locale_len, 593 disconnect) == -1) { 594 (void) shutdown(connfd, SHUT_RDWR); 595 (void) close(connfd); 596 return (-1); 597 } 598 (void) write(connfd, "OK\n", 3); 599 return (connfd); 600 } 601 602 static void 603 reject_client(int servfd, pid_t clientpid) 604 { 605 int connfd; 606 struct sockaddr_un cliaddr; 607 socklen_t clilen; 608 char nak[MAXPATHLEN]; 609 610 clilen = sizeof (cliaddr); 611 connfd = accept(servfd, (struct sockaddr *)&cliaddr, &clilen); 612 613 /* 614 * After hear its ident string, tell client to get lost. 615 */ 616 if (get_client_ident(connfd, NULL, NULL, 0, NULL) == 0) { 617 (void) snprintf(nak, sizeof (nak), "%lu\n", 618 clientpid); 619 (void) write(connfd, nak, strlen(nak)); 620 } 621 (void) shutdown(connfd, SHUT_RDWR); 622 (void) close(connfd); 623 } 624 625 static void 626 event_message(int clifd, char *clilocale, zone_evt_t evt, int dflag) 627 { 628 char *str, *lstr = NULL; 629 char lmsg[BUFSIZ]; 630 char outbuf[BUFSIZ]; 631 632 if (clifd == -1) 633 return; 634 635 switch (evt) { 636 case Z_EVT_ZONE_BOOTING: 637 if (*boot_args == '\0') { 638 str = "NOTICE: Zone booting up"; 639 break; 640 } 641 /*LINTED*/ 642 (void) snprintf(lmsg, sizeof (lmsg), localize_msg(clilocale, 643 "NOTICE: Zone booting up with arguments: %s"), boot_args); 644 lstr = lmsg; 645 break; 646 case Z_EVT_ZONE_READIED: 647 str = "NOTICE: Zone readied"; 648 break; 649 case Z_EVT_ZONE_HALTED: 650 if (dflag) 651 str = "NOTICE: Zone halted. Disconnecting..."; 652 else 653 str = "NOTICE: Zone halted"; 654 break; 655 case Z_EVT_ZONE_REBOOTING: 656 if (*boot_args == '\0') { 657 str = "NOTICE: Zone rebooting"; 658 break; 659 } 660 /*LINTED*/ 661 (void) snprintf(lmsg, sizeof (lmsg), localize_msg(clilocale, 662 "NOTICE: Zone rebooting with arguments: %s"), boot_args); 663 lstr = lmsg; 664 break; 665 case Z_EVT_ZONE_UNINSTALLING: 666 str = "NOTICE: Zone is being uninstalled. Disconnecting..."; 667 break; 668 case Z_EVT_ZONE_BOOTFAILED: 669 if (dflag) 670 str = "NOTICE: Zone boot failed. Disconnecting..."; 671 else 672 str = "NOTICE: Zone boot failed"; 673 break; 674 case Z_EVT_ZONE_BADARGS: 675 /*LINTED*/ 676 (void) snprintf(lmsg, sizeof (lmsg), 677 localize_msg(clilocale, 678 "WARNING: Ignoring invalid boot arguments: %s"), 679 bad_boot_arg); 680 lstr = lmsg; 681 break; 682 default: 683 return; 684 } 685 686 if (lstr == NULL) 687 lstr = localize_msg(clilocale, str); 688 (void) snprintf(outbuf, sizeof (outbuf), "\r\n[%s]\r\n", lstr); 689 (void) write(clifd, outbuf, strlen(outbuf)); 690 } 691 692 /* 693 * Check to see if the client at the other end of the socket is still 694 * alive; we know it is not if it throws EPIPE at us when we try to write 695 * an otherwise harmless 0-length message to it. 696 */ 697 static int 698 test_client(int clifd) 699 { 700 if ((write(clifd, "", 0) == -1) && errno == EPIPE) 701 return (-1); 702 return (0); 703 } 704 705 /* 706 * This routine drives the console I/O loop. It polls for input from the 707 * manager side of the console (output to the console), and from the client 708 * (input from the console user). Additionally, it polls on the server fd, 709 * and disconnects any clients that might try to hook up with the zone while 710 * the console is in use. 711 * 712 * When the client first calls us up, it is expected to send a line giving 713 * its "identity"; this consists of the string 'IDENT <pid> <locale>'. 714 * This is so that we can report that the console is busy along with 715 * some diagnostics about who has it busy; the locale is used so that 716 * asynchronous messages about zone state (like the NOTICE: zone halted 717 * messages) can be output in the user's locale. 718 */ 719 static void 720 do_console_io(zlog_t *zlogp, int consfd, int servfd) 721 { 722 struct pollfd pollfds[4]; 723 char ibuf[BUFSIZ]; 724 int cc, ret; 725 int clifd = -1; 726 int pollerr = 0; 727 char clilocale[MAXPATHLEN]; 728 pid_t clipid = 0; 729 int disconnect = 0; 730 731 /* console side, watch for read events */ 732 pollfds[0].fd = consfd; 733 pollfds[0].events = POLLIN | POLLRDNORM | POLLRDBAND | 734 POLLPRI | POLLERR | POLLHUP | POLLNVAL; 735 736 /* client side, watch for read events */ 737 pollfds[1].fd = clifd; 738 pollfds[1].events = pollfds[0].events; 739 740 /* the server socket; watch for events (new connections) */ 741 pollfds[2].fd = servfd; 742 pollfds[2].events = pollfds[0].events; 743 744 /* the eventstram; watch for events (e.g.: zone halted) */ 745 pollfds[3].fd = eventstream[1]; 746 pollfds[3].events = pollfds[0].events; 747 748 for (;;) { 749 pollfds[0].revents = pollfds[1].revents = 0; 750 pollfds[2].revents = pollfds[3].revents = 0; 751 752 ret = poll(pollfds, 753 sizeof (pollfds) / sizeof (struct pollfd), -1); 754 if (ret == -1 && errno != EINTR) { 755 zerror(zlogp, B_TRUE, "poll failed"); 756 /* we are hosed, close connection */ 757 break; 758 } 759 760 /* event from console side */ 761 if (pollfds[0].revents) { 762 if (pollfds[0].revents & 763 (POLLIN | POLLRDNORM | POLLRDBAND | POLLPRI)) { 764 errno = 0; 765 cc = read(consfd, ibuf, BUFSIZ); 766 if (cc <= 0 && (errno != EINTR) && 767 (errno != EAGAIN)) 768 break; 769 /* 770 * Lose I/O if no one is listening 771 */ 772 if (clifd != -1 && cc > 0) 773 (void) write(clifd, ibuf, cc); 774 } else { 775 pollerr = pollfds[0].revents; 776 zerror(zlogp, B_FALSE, 777 "closing connection with (console) " 778 "pollerr %d\n", pollerr); 779 break; 780 } 781 } 782 783 /* event from client side */ 784 if (pollfds[1].revents) { 785 if (pollfds[1].revents & 786 (POLLIN | POLLRDNORM | POLLRDBAND | POLLPRI)) { 787 errno = 0; 788 cc = read(clifd, ibuf, BUFSIZ); 789 if (cc <= 0 && (errno != EINTR) && 790 (errno != EAGAIN)) 791 break; 792 (void) write(consfd, ibuf, cc); 793 } else { 794 pollerr = pollfds[1].revents; 795 zerror(zlogp, B_FALSE, 796 "closing connection with (client) " 797 "pollerr %d\n", pollerr); 798 break; 799 } 800 } 801 802 /* event from server socket */ 803 if (pollfds[2].revents && 804 (pollfds[2].revents & (POLLIN | POLLRDNORM))) { 805 if (clifd != -1) { 806 /* 807 * Test the client to see if it is really 808 * still alive. If it has died but we 809 * haven't yet detected that, we might 810 * deny a legitimate connect attempt. If it 811 * is dead, we break out; once we tear down 812 * the old connection, the new connection 813 * will happen. 814 */ 815 if (test_client(clifd) == -1) { 816 break; 817 } 818 /* we're already handling a client */ 819 reject_client(servfd, clipid); 820 821 822 } else if ((clifd = accept_client(servfd, &clipid, 823 clilocale, sizeof (clilocale), 824 &disconnect)) != -1) { 825 pollfds[1].fd = clifd; 826 827 } else { 828 break; 829 } 830 } 831 832 /* 833 * Watch for events on the eventstream. This is how we get 834 * notified of the zone halting, etc. It provides us a 835 * "wakeup" from poll when important things happen, which 836 * is good. 837 */ 838 if (pollfds[3].revents) { 839 int evt = eventstream_read(); 840 /* 841 * After we drain out the event, if we aren't servicing 842 * a console client, we hop back out to our caller, 843 * which will check to see if it is time to shutdown 844 * the daemon, or if we should take another console 845 * service lap. 846 */ 847 if (clifd == -1) { 848 break; 849 } 850 event_message(clifd, clilocale, evt, disconnect); 851 /* 852 * Special handling for the message that the zone is 853 * uninstalling; we boot the client, then break out 854 * of this function. When we return to the 855 * serve_console loop, we will see that the zone is 856 * in a state < READY, and so zoneadmd will shutdown. 857 */ 858 if (evt == Z_EVT_ZONE_UNINSTALLING) { 859 break; 860 } 861 /* 862 * Diconnect if -C and -d options were specified and 863 * zone was halted or failed to boot. 864 */ 865 if ((evt == Z_EVT_ZONE_HALTED || 866 evt == Z_EVT_ZONE_BOOTFAILED) && disconnect) { 867 break; 868 } 869 } 870 871 } 872 873 if (clifd != -1) { 874 (void) shutdown(clifd, SHUT_RDWR); 875 (void) close(clifd); 876 } 877 } 878 879 int 880 init_console(zlog_t *zlogp) 881 { 882 if (init_console_dev(zlogp) == -1) { 883 zerror(zlogp, B_FALSE, 884 "console setup: device initialization failed"); 885 return (-1); 886 } 887 888 if ((serverfd = init_console_sock(zlogp)) == -1) { 889 zerror(zlogp, B_FALSE, 890 "console setup: socket initialization failed"); 891 return (-1); 892 } 893 return (0); 894 } 895 896 /* 897 * serve_console() is the master loop for driving console I/O. It is also the 898 * routine which is ultimately responsible for "pulling the plug" on zoneadmd 899 * when it realizes that the daemon should shut down. 900 * 901 * The rules for shutdown are: there must be no console client, and the zone 902 * state must be < ready. However, we need to give things a chance to actually 903 * get going when the daemon starts up-- otherwise the daemon would immediately 904 * exit on startup if the zone was in the installed state, so we first drop 905 * into the do_console_io() loop in order to give *something* a chance to 906 * happen. 907 */ 908 void 909 serve_console(zlog_t *zlogp) 910 { 911 int managerfd; 912 zone_state_t zstate; 913 char conspath[MAXPATHLEN]; 914 915 (void) snprintf(conspath, sizeof (conspath), 916 "/dev/zcons/%s/%s", zone_name, ZCONS_MANAGER_NAME); 917 918 for (;;) { 919 managerfd = open(conspath, O_RDWR|O_NONBLOCK|O_NOCTTY); 920 if (managerfd == -1) { 921 zerror(zlogp, B_TRUE, "failed to open console manager"); 922 (void) mutex_lock(&lock); 923 goto death; 924 } 925 926 /* 927 * Setting RPROTDIS on the stream means that the control 928 * portion of messages received (which we don't care about) 929 * will be discarded by the stream head. If we allowed such 930 * messages, we wouldn't be able to use read(2), as it fails 931 * (EBADMSG) when a message with a control element is received. 932 */ 933 if (ioctl(managerfd, I_SRDOPT, RNORM|RPROTDIS) == -1) { 934 zerror(zlogp, B_TRUE, "failed to set options on " 935 "console manager"); 936 (void) mutex_lock(&lock); 937 goto death; 938 } 939 940 do_console_io(zlogp, managerfd, serverfd); 941 942 /* 943 * We would prefer not to do this, but hostile zone processes 944 * can cause the stream to become tainted, and reads will 945 * fail. So, in case something has gone seriously ill, 946 * we dismantle the stream and reopen the console when we 947 * take another lap. 948 */ 949 (void) close(managerfd); 950 951 (void) mutex_lock(&lock); 952 /* 953 * We need to set death_throes (see below) atomically with 954 * respect to noticing that (a) we have no console client and 955 * (b) the zone is not installed. Otherwise we could get a 956 * request to boot during this time. Once we set death_throes, 957 * any incoming door stuff will be turned away. 958 */ 959 if (zone_get_state(zone_name, &zstate) == Z_OK) { 960 if (zstate < ZONE_STATE_READY) 961 goto death; 962 } else { 963 zerror(zlogp, B_FALSE, 964 "unable to determine state of zone"); 965 goto death; 966 } 967 /* 968 * Even if zone_get_state() fails, stay conservative, and 969 * take another lap. 970 */ 971 (void) mutex_unlock(&lock); 972 } 973 974 death: 975 assert(MUTEX_HELD(&lock)); 976 in_death_throes = B_TRUE; 977 (void) mutex_unlock(&lock); 978 979 destroy_console_sock(serverfd); 980 (void) destroy_console_devs(zlogp); 981 } 982