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 2006 Sun Microsystems, Inc. All rights reserved. 24 * Use is subject to license terms. 25 */ 26 27 #pragma ident "%Z%%M% %I% %E% SMI" 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 three 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 * - Initialization of the slave side of the console. This is 80 * accomplished by pushing various STREAMS modules onto the console. 81 * The ptem(7M) module gets special treatment, and is anchored into 82 * place using the I_ANCHOR facility. This is so that the zcons driver 83 * always has terminal semantics, as would a real hardware terminal. 84 * This means that ttymon(1M) works unmodified; at boot time, ttymon 85 * will do its own plumbing of the console stream, and will even 86 * I_POP modules off. Hence the anchor, which assures that ptem will 87 * never be I_POP'd. 88 * 89 * - Acting as a server for 'zlogin -C' instances. When zlogin -C is 90 * run, zlogin connects to zoneadmd via unix domain socket. zoneadmd 91 * functions as a two-way proxy for console I/O, relaying user input 92 * to the master side of the console, and relaying output from the 93 * zone to the user. 94 */ 95 96 #include <sys/types.h> 97 #include <sys/socket.h> 98 #include <sys/stat.h> 99 #include <sys/termios.h> 100 #include <sys/zcons.h> 101 102 #include <assert.h> 103 #include <ctype.h> 104 #include <errno.h> 105 #include <fcntl.h> 106 #include <stdarg.h> 107 #include <stdio.h> 108 #include <stdlib.h> 109 #include <strings.h> 110 #include <stropts.h> 111 #include <thread.h> 112 #include <ucred.h> 113 #include <unistd.h> 114 #include <zone.h> 115 116 #include <libdevinfo.h> 117 #include <libdevice.h> 118 #include <libzonecfg.h> 119 120 #include <syslog.h> 121 122 #include "zoneadmd.h" 123 124 #define ZCONSNEX_DEVTREEPATH "/pseudo/zconsnex@1" 125 #define ZCONSNEX_FILEPATH "/devices/pseudo/zconsnex@1" 126 127 #define CONSOLE_SOCKPATH ZONES_TMPDIR "/%s.console_sock" 128 129 static int slavefd = -1; /* slave side of console */ 130 static int serverfd = -1; /* console server unix domain socket fd */ 131 132 static struct termios base_termios = { /* from init.c */ 133 BRKINT|ICRNL|IXON|IMAXBEL, /* iflag */ 134 OPOST|ONLCR|TAB3, /* oflag */ 135 CS8|CREAD|B9600, /* cflag */ 136 ISIG|ICANON|ECHO|ECHOE|ECHOK|ECHOCTL|ECHOKE|IEXTEN, /* lflag */ 137 CINTR, CQUIT, CERASE, CKILL, CEOF, 0, 0, 0, 138 0, 0, 0, 0, 0, 0, 0, 0, 139 0, 0, 0 140 }; 141 142 /* 143 * The eventstream is a simple one-directional flow of messages from the 144 * door server to the console subsystem, implemented with a pipe. 145 * It is used to wake up the console poller when it needs to take action, 146 * message the user, die off, etc. 147 */ 148 static int eventstream[2]; 149 150 int 151 eventstream_init() 152 { 153 if (pipe(eventstream) == -1) 154 return (-1); 155 return (0); 156 } 157 158 void 159 eventstream_write(zone_evt_t evt) 160 { 161 (void) write(eventstream[0], &evt, sizeof (evt)); 162 } 163 164 static zone_evt_t 165 eventstream_read(void) 166 { 167 zone_evt_t evt = Z_EVT_NULL; 168 169 (void) read(eventstream[1], &evt, sizeof (evt)); 170 return (evt); 171 } 172 173 /* 174 * count_console_devs() and its helper count_cb() do a walk of the 175 * subtree of the device tree where zone console nodes are represented. 176 * The goal is to count zone console instances already setup for a zone 177 * with the given name. More than 1 is anomolous, and our caller will 178 * have to deal with that if we find that's the case. 179 * 180 * Note: this algorithm is a linear search of nodes in the zconsnex subtree 181 * of the device tree, and could be a scalability problem, but I don't see 182 * how to avoid it. 183 */ 184 185 /* 186 * cb_data is shared by count_cb and destroy_cb for simplicity. 187 */ 188 struct cb_data { 189 zlog_t *zlogp; 190 int found; 191 int killed; 192 }; 193 194 static int 195 count_cb(di_node_t node, void *arg) 196 { 197 struct cb_data *cb = (struct cb_data *)arg; 198 char *prop_data; 199 200 if (di_prop_lookup_strings(DDI_DEV_T_ANY, node, "zonename", 201 &prop_data) != -1) { 202 assert(prop_data != NULL); 203 if (strcmp(prop_data, zone_name) == 0) { 204 cb->found++; 205 return (DI_WALK_CONTINUE); 206 } 207 } 208 return (DI_WALK_CONTINUE); 209 } 210 211 static int 212 count_console_devs(zlog_t *zlogp) 213 { 214 di_node_t root; 215 struct cb_data cb; 216 217 bzero(&cb, sizeof (cb)); 218 cb.zlogp = zlogp; 219 220 if ((root = di_init(ZCONSNEX_DEVTREEPATH, DINFOCPYALL)) == 221 DI_NODE_NIL) { 222 zerror(zlogp, B_TRUE, "%s failed", "di_init"); 223 return (-1); 224 } 225 226 (void) di_walk_node(root, DI_WALK_CLDFIRST, (void *)&cb, count_cb); 227 di_fini(root); 228 return (cb.found); 229 } 230 231 /* 232 * destroy_console_devs() and its helper destroy_cb() tears down any console 233 * instances associated with this zone. If things went very wrong, we 234 * might have more than one console instance hanging around. This routine 235 * hunts down and tries to remove all of them. Of course, if the console 236 * is open, the instance will not detach, which is a potential issue. 237 */ 238 static int 239 destroy_cb(di_node_t node, void *arg) 240 { 241 struct cb_data *cb = (struct cb_data *)arg; 242 char *prop_data; 243 char *tmp; 244 char devpath[MAXPATHLEN]; 245 devctl_hdl_t hdl; 246 247 if (di_prop_lookup_strings(DDI_DEV_T_ANY, node, "zonename", 248 &prop_data) == -1) 249 return (DI_WALK_CONTINUE); 250 251 assert(prop_data != NULL); 252 if (strcmp(prop_data, zone_name) != 0) { 253 /* this is the console for a different zone */ 254 return (DI_WALK_CONTINUE); 255 } 256 257 cb->found++; 258 tmp = di_devfs_path(node); 259 (void) snprintf(devpath, sizeof (devpath), "/devices/%s", tmp); 260 di_devfs_path_free(tmp); 261 262 if ((hdl = devctl_device_acquire(devpath, 0)) == NULL) { 263 zerror(cb->zlogp, B_TRUE, "WARNING: console %s found, " 264 "but it could not be controlled.", devpath); 265 return (DI_WALK_CONTINUE); 266 } 267 if (devctl_device_remove(hdl) == 0) { 268 cb->killed++; 269 } else { 270 zerror(cb->zlogp, B_TRUE, "WARNING: console %s found, " 271 "but it could not be removed.", devpath); 272 } 273 devctl_release(hdl); 274 return (DI_WALK_CONTINUE); 275 } 276 277 static int 278 destroy_console_devs(zlog_t *zlogp) 279 { 280 di_node_t root; 281 struct cb_data cb; 282 283 bzero(&cb, sizeof (cb)); 284 cb.zlogp = zlogp; 285 286 if ((root = di_init(ZCONSNEX_DEVTREEPATH, DINFOCPYALL)) == 287 DI_NODE_NIL) { 288 zerror(zlogp, B_TRUE, "%s failed", "di_init"); 289 return (-1); 290 } 291 292 (void) di_walk_node(root, DI_WALK_CLDFIRST, (void *)&cb, destroy_cb); 293 if (cb.found > 1) { 294 zerror(zlogp, B_FALSE, "WARNING: multiple zone console " 295 "instances detected for zone '%s'; %d of %d " 296 "successfully removed.", 297 zone_name, cb.killed, cb.found); 298 } 299 300 di_fini(root); 301 return (0); 302 } 303 304 /* 305 * init_console_dev() drives the device-tree configuration of the zone 306 * console device. The general strategy is to use the libdevice (devctl) 307 * interfaces to instantiate a new zone console node. We do a lot of 308 * sanity checking, and are careful to reuse a console if one exists. 309 * 310 * Once the device is in the device tree, we kick devfsadm via di_init_devs() 311 * to ensure that the appropriate symlinks (to the master and slave console 312 * devices) are placed in /dev in the global zone. 313 */ 314 static int 315 init_console_dev(zlog_t *zlogp) 316 { 317 devctl_hdl_t bus_hdl = NULL, dev_hdl = NULL; 318 devctl_ddef_t ddef_hdl = NULL; 319 di_devlink_handle_t dl = NULL; 320 int rv = -1, ndevs; 321 322 /* 323 * Don't re-setup console if it is working and ready already; just 324 * skip ahead to making devlinks, which we do for sanity's sake. 325 */ 326 ndevs = count_console_devs(zlogp); 327 if (ndevs == 1) { 328 goto devlinks; 329 } else if (ndevs > 1 || ndevs == -1) { 330 /* 331 * For now, this seems like a reasonable but harsh punishment. 332 * If needed, we could try to get clever and delete all but 333 * the console which is pointed at by the current symlink. 334 */ 335 if (destroy_console_devs(zlogp) == -1) { 336 goto error; 337 } 338 } 339 340 /* 341 * Time to make the consoles! 342 */ 343 if ((bus_hdl = devctl_bus_acquire(ZCONSNEX_FILEPATH, 0)) == NULL) { 344 zerror(zlogp, B_TRUE, "%s failed", "devctl_bus_acquire"); 345 goto error; 346 } 347 if ((ddef_hdl = devctl_ddef_alloc("zcons", 0)) == NULL) { 348 zerror(zlogp, B_TRUE, "failed to allocate ddef handle"); 349 goto error; 350 } 351 /* 352 * Set three properties on this node; the first is the name of the 353 * zone; the second is a flag which lets pseudo know that it is 354 * OK to automatically allocate an instance # for this device; 355 * the third tells the device framework not to auto-detach this 356 * node-- we need the node to still be there when we ask devfsadmd 357 * to make links, and when we need to open it. 358 */ 359 if (devctl_ddef_string(ddef_hdl, "zonename", zone_name) == -1) { 360 zerror(zlogp, B_TRUE, "failed to create zonename property"); 361 goto error; 362 } 363 if (devctl_ddef_int(ddef_hdl, "auto-assign-instance", 1) == -1) { 364 zerror(zlogp, B_TRUE, "failed to create auto-assign-instance " 365 "property"); 366 goto error; 367 } 368 if (devctl_ddef_int(ddef_hdl, "ddi-no-autodetach", 1) == -1) { 369 zerror(zlogp, B_TRUE, "failed to create ddi-no-auto-detach " 370 "property"); 371 goto error; 372 } 373 if (devctl_bus_dev_create(bus_hdl, ddef_hdl, 0, &dev_hdl) == -1) { 374 zerror(zlogp, B_TRUE, "failed to create console node"); 375 goto error; 376 } 377 378 devlinks: 379 if ((dl = di_devlink_init("zcons", DI_MAKE_LINK)) != NULL) { 380 (void) di_devlink_fini(&dl); 381 } else { 382 zerror(zlogp, B_TRUE, "failed to create devlinks"); 383 goto error; 384 } 385 386 rv = 0; 387 error: 388 if (ddef_hdl) 389 devctl_ddef_free(ddef_hdl); 390 if (bus_hdl) 391 devctl_release(bus_hdl); 392 if (dev_hdl) 393 devctl_release(dev_hdl); 394 return (rv); 395 } 396 397 /* 398 * prep_console_slave() takes care of setting up the console slave device 399 * (the side that the zone will eventually open). It is a helper for 400 * init_console_slave(). 401 * 402 * We have to mknod and setup the console device; then the slave side is 403 * opened, and the appropriate STREAMS modules are pushed on. A wrinkle is that 404 * 'ptem' must be anchored in place (see streamio(7i) since we always want the 405 * console to have terminal semantics. 406 */ 407 static int 408 prep_console_slave(zlog_t *zlogp, char *zonepath) 409 { 410 char slavename[MAXPATHLEN]; 411 char zoneslavename[MAXPATHLEN]; 412 struct stat st; 413 414 assert(slavefd == -1); 415 416 (void) snprintf(slavename, sizeof (slavename), 417 "/dev/zcons/%s/%s", zone_name, ZCONS_SLAVE_NAME); 418 419 (void) snprintf(zoneslavename, sizeof (zoneslavename), 420 "%s/dev/zconsole", zonepath); 421 422 /* 423 * We mknod the zone console in $zonepath/dev/; someday it would 424 * be nice to not have to manually mknod this stuff-- if possible, 425 * we could move this into devfsadm. 426 */ 427 if (stat(slavename, &st) == -1) { 428 zerror(zlogp, B_TRUE, "failed to stat %s", slavename); 429 goto error; 430 } 431 (void) unlink(zoneslavename); 432 if (mknod(zoneslavename, st.st_mode, st.st_rdev) == -1) { 433 zerror(zlogp, B_TRUE, "failed to mknod %s", zoneslavename); 434 goto error; 435 } 436 (void) chown(zoneslavename, st.st_uid, st.st_gid); 437 if ((slavefd = open(zoneslavename, O_RDWR | O_NOCTTY)) < 0) { 438 zerror(zlogp, B_TRUE, "failed to open %s", zoneslavename); 439 return (-1); 440 } 441 442 /* 443 * Just to make sure the whole stream is pristine. 444 */ 445 (void) ioctl(slavefd, I_FLUSH, FLUSHRW); 446 447 /* 448 * Push hardware emulation (ptem) module; we would rather not, but 449 * are forced to push ldterm and ttcompat here. Ultimately ttymon 450 * will pop them off, so we ANCHOR only ptem. 451 * 452 * We need to use __I_PUSH_NOCTTY instead of I_PUSH here, otherwise 453 * we'll end up having the slave device as *our* controling terminal. 454 */ 455 if (ioctl(slavefd, __I_PUSH_NOCTTY, "ptem") == -1) { 456 zerror(zlogp, B_TRUE, "failed to push ptem module"); 457 goto error; 458 } 459 460 /* 461 * Anchor the stream to prevent malicious or accidental I_POP of ptem. 462 */ 463 if (ioctl(slavefd, I_ANCHOR) == -1) { 464 zerror(zlogp, B_TRUE, "failed to set stream anchor"); 465 goto error; 466 } 467 468 if (ioctl(slavefd, __I_PUSH_NOCTTY, "ldterm") == -1) { 469 zerror(zlogp, B_TRUE, "failed to push ldterm module"); 470 goto error; 471 } 472 if (ioctl(slavefd, __I_PUSH_NOCTTY, "ttcompat") == -1) { 473 zerror(zlogp, B_TRUE, "failed to push ttcompat module"); 474 goto error; 475 } 476 477 /* 478 * Setup default terminal settings 479 */ 480 if (tcsetattr(slavefd, TCSAFLUSH, &base_termios) == -1) { 481 zerror(zlogp, B_TRUE, "failed to set base terminal settings"); 482 goto error; 483 } 484 485 return (0); 486 error: 487 (void) close(slavefd); 488 slavefd = -1; 489 return (-1); 490 } 491 492 /* 493 * init_console_slave() sets up the console slave device; the device node 494 * itself has already been set up in the device tree; the primary job 495 * here is to do some STREAMS plumbing (via prep_console_slave()) and then 496 * to establish some symlinks. Eventually we should move that functionality 497 * into devfsadm. 498 */ 499 int 500 init_console_slave(zlog_t *zlogp) 501 { 502 char zonepath[MAXPATHLEN]; 503 504 if (slavefd != -1) 505 return (0); 506 507 if (zone_get_zonepath(zone_name, zonepath, sizeof (zonepath)) != Z_OK) { 508 zerror(zlogp, B_TRUE, "unable to determine zone root"); 509 return (-1); 510 } 511 512 if (prep_console_slave(zlogp, zonepath) == -1) { 513 zerror(zlogp, B_FALSE, "could not prep console slave"); 514 return (-1); 515 } 516 517 return (0); 518 } 519 520 void 521 destroy_console_slave(void) 522 { 523 (void) close(slavefd); 524 slavefd = -1; 525 } 526 527 /* 528 * Restore initial terminal attributes to the zone console. 529 */ 530 void 531 reset_slave_terminal(zlog_t *zlogp) 532 { 533 assert(slavefd != -1); 534 535 /* Probably not fatal, so we drive on if it fails */ 536 if (tcsetattr(slavefd, TCSAFLUSH, &base_termios) == -1) { 537 zerror(zlogp, B_TRUE, "WARNING: failed to set terminal " 538 "settings."); 539 } 540 } 541 542 static int 543 init_console_sock(zlog_t *zlogp) 544 { 545 int servfd; 546 struct sockaddr_un servaddr; 547 548 bzero(&servaddr, sizeof (servaddr)); 549 servaddr.sun_family = AF_UNIX; 550 (void) snprintf(servaddr.sun_path, sizeof (servaddr.sun_path), 551 CONSOLE_SOCKPATH, zone_name); 552 553 if ((servfd = socket(AF_UNIX, SOCK_STREAM, 0)) == -1) { 554 zerror(zlogp, B_TRUE, "console setup: could not create socket"); 555 return (-1); 556 } 557 (void) unlink(servaddr.sun_path); 558 559 if (bind(servfd, (struct sockaddr *)&servaddr, 560 sizeof (servaddr)) == -1) { 561 zerror(zlogp, B_TRUE, 562 "console setup: could not bind to socket"); 563 goto out; 564 } 565 566 if (listen(servfd, 4) == -1) { 567 zerror(zlogp, B_TRUE, 568 "console setup: could not listen on socket"); 569 goto out; 570 } 571 return (servfd); 572 573 out: 574 (void) unlink(servaddr.sun_path); 575 (void) close(servfd); 576 return (-1); 577 } 578 579 static void 580 destroy_console_sock(int servfd) 581 { 582 char path[MAXPATHLEN]; 583 584 (void) snprintf(path, sizeof (path), CONSOLE_SOCKPATH, zone_name); 585 (void) unlink(path); 586 (void) shutdown(servfd, SHUT_RDWR); 587 (void) close(servfd); 588 } 589 590 /* 591 * Read the "ident" string from the client's descriptor; this routine also 592 * tolerates being called with pid=NULL, for times when you want to "eat" 593 * the ident string from a client without saving it. 594 */ 595 static int 596 get_client_ident(int clifd, pid_t *pid, char *locale, size_t locale_len) 597 { 598 char buf[BUFSIZ], *bufp; 599 size_t buflen = sizeof (buf); 600 char c = '\0'; 601 int i = 0, r; 602 603 /* "eat up the ident string" case, for simplicity */ 604 if (pid == NULL) { 605 assert(locale == NULL && locale_len == 0); 606 while (read(clifd, &c, 1) == 1) { 607 if (c == '\n') 608 return (0); 609 } 610 } 611 612 bzero(buf, sizeof (buf)); 613 while ((buflen > 1) && (r = read(clifd, &c, 1)) == 1) { 614 buflen--; 615 if (c == '\n') 616 break; 617 618 buf[i] = c; 619 i++; 620 } 621 if (r == -1) 622 return (-1); 623 624 /* 625 * We've filled the buffer, but still haven't seen \n. Keep eating 626 * until we find it; we don't expect this to happen, but this is 627 * defensive. 628 */ 629 if (c != '\n') { 630 while ((r = read(clifd, &c, sizeof (c))) > 0) 631 if (c == '\n') 632 break; 633 } 634 635 /* 636 * Parse buffer for message of the form: IDENT <pid> <locale> 637 */ 638 bufp = buf; 639 if (strncmp(bufp, "IDENT ", 6) != 0) 640 return (-1); 641 bufp += 6; 642 errno = 0; 643 *pid = strtoll(bufp, &bufp, 10); 644 if (errno != 0) 645 return (-1); 646 647 while (*bufp != '\0' && isspace(*bufp)) 648 bufp++; 649 (void) strlcpy(locale, bufp, locale_len); 650 651 return (0); 652 } 653 654 static int 655 accept_client(int servfd, pid_t *pid, char *locale, size_t locale_len) 656 { 657 int connfd; 658 struct sockaddr_un cliaddr; 659 socklen_t clilen; 660 661 clilen = sizeof (cliaddr); 662 connfd = accept(servfd, (struct sockaddr *)&cliaddr, &clilen); 663 if (connfd == -1) 664 return (-1); 665 if (get_client_ident(connfd, pid, locale, locale_len) == -1) { 666 (void) shutdown(connfd, SHUT_RDWR); 667 (void) close(connfd); 668 return (-1); 669 } 670 (void) write(connfd, "OK\n", 3); 671 return (connfd); 672 } 673 674 static void 675 reject_client(int servfd, pid_t clientpid) 676 { 677 int connfd; 678 struct sockaddr_un cliaddr; 679 socklen_t clilen; 680 char nak[MAXPATHLEN]; 681 682 clilen = sizeof (cliaddr); 683 connfd = accept(servfd, (struct sockaddr *)&cliaddr, &clilen); 684 685 /* 686 * After hear its ident string, tell client to get lost. 687 */ 688 if (get_client_ident(connfd, NULL, NULL, 0) == 0) { 689 (void) snprintf(nak, sizeof (nak), "%lu\n", 690 clientpid); 691 (void) write(connfd, nak, strlen(nak)); 692 } 693 (void) shutdown(connfd, SHUT_RDWR); 694 (void) close(connfd); 695 } 696 697 static void 698 event_message(int clifd, char *clilocale, zone_evt_t evt) 699 { 700 char msg[BUFSIZ]; 701 char *str; 702 const char *fmt; 703 704 if (clifd == -1) 705 return; 706 707 switch (evt) { 708 case Z_EVT_ZONE_BOOTING: 709 str = "Zone booting up"; 710 break; 711 case Z_EVT_ZONE_READIED: 712 str = "Zone readied"; 713 break; 714 case Z_EVT_ZONE_HALTED: 715 str = "Zone halted"; 716 break; 717 case Z_EVT_ZONE_REBOOTING: 718 str = "Zone rebooting"; 719 break; 720 case Z_EVT_ZONE_UNINSTALLING: 721 str = "Zone is being uninstalled. Disconnecting..."; 722 break; 723 case Z_EVT_ZONE_BOOTFAILED: 724 str = "Zone boot failed"; 725 break; 726 default: 727 return; 728 } 729 str = localize_msg(clilocale, str); 730 fmt = localize_msg(clilocale, "\r\n[NOTICE: %s]\r\n"); 731 (void) snprintf(msg, sizeof (msg), fmt, str); 732 (void) write(clifd, msg, strlen(msg)); 733 } 734 735 /* 736 * Check to see if the client at the other end of the socket is still 737 * alive; we know it is not if it throws EPIPE at us when we try to write 738 * an otherwise harmless 0-length message to it. 739 */ 740 static int 741 test_client(int clifd) 742 { 743 if ((write(clifd, "", 0) == -1) && errno == EPIPE) 744 return (-1); 745 return (0); 746 } 747 748 /* 749 * This routine drives the console I/O loop. It polls for input from the 750 * master side of the console (output to the console), and from the client 751 * (input from the console user). Additionally, it polls on the server fd, 752 * and disconnects any clients that might try to hook up with the zone while 753 * the console is in use. 754 * 755 * When the client first calls us up, it is expected to send a line giving 756 * its "identity"; this consists of the string 'IDENT <pid> <locale>'. 757 * This is so that we can report that the console is busy along with 758 * some diagnostics about who has it busy; the locale is used so that 759 * asynchronous messages about zone state (like the NOTICE: zone halted 760 * messages) can be output in the user's locale. 761 */ 762 static void 763 do_console_io(zlog_t *zlogp, int consfd, int servfd) 764 { 765 struct pollfd pollfds[4]; 766 char ibuf[BUFSIZ]; 767 int cc, ret; 768 int clifd = -1; 769 int pollerr = 0; 770 char clilocale[MAXPATHLEN]; 771 pid_t clipid = 0; 772 773 /* console side, watch for read events */ 774 pollfds[0].fd = consfd; 775 pollfds[0].events = POLLIN | POLLRDNORM | POLLRDBAND | 776 POLLPRI | POLLERR | POLLHUP | POLLNVAL; 777 778 /* client side, watch for read events */ 779 pollfds[1].fd = clifd; 780 pollfds[1].events = pollfds[0].events; 781 782 /* the server socket; watch for events (new connections) */ 783 pollfds[2].fd = servfd; 784 pollfds[2].events = pollfds[0].events; 785 786 /* the eventstram; watch for events (e.g.: zone halted) */ 787 pollfds[3].fd = eventstream[1]; 788 pollfds[3].events = pollfds[0].events; 789 790 for (;;) { 791 pollfds[0].revents = pollfds[1].revents = 0; 792 pollfds[2].revents = pollfds[3].revents = 0; 793 794 ret = poll(pollfds, 795 sizeof (pollfds) / sizeof (struct pollfd), -1); 796 if (ret == -1 && errno != EINTR) { 797 zerror(zlogp, B_TRUE, "poll failed"); 798 /* we are hosed, close connection */ 799 break; 800 } 801 802 /* event from console side */ 803 if (pollfds[0].revents) { 804 if (pollfds[0].revents & 805 (POLLIN | POLLRDNORM | POLLRDBAND | POLLPRI)) { 806 errno = 0; 807 cc = read(consfd, ibuf, BUFSIZ); 808 if (cc <= 0 && (errno != EINTR) && 809 (errno != EAGAIN)) 810 break; 811 /* 812 * Lose I/O if no one is listening 813 */ 814 if (clifd != -1 && cc > 0) 815 (void) write(clifd, ibuf, cc); 816 } else { 817 pollerr = pollfds[0].revents; 818 zerror(zlogp, B_FALSE, 819 "closing connection with (console) " 820 "pollerr %d\n", pollerr); 821 break; 822 } 823 } 824 825 /* event from client side */ 826 if (pollfds[1].revents) { 827 if (pollfds[1].revents & 828 (POLLIN | POLLRDNORM | POLLRDBAND | POLLPRI)) { 829 errno = 0; 830 cc = read(clifd, ibuf, BUFSIZ); 831 if (cc <= 0 && (errno != EINTR) && 832 (errno != EAGAIN)) 833 break; 834 (void) write(consfd, ibuf, cc); 835 } else { 836 pollerr = pollfds[1].revents; 837 zerror(zlogp, B_FALSE, 838 "closing connection with (client) " 839 "pollerr %d\n", pollerr); 840 break; 841 } 842 } 843 844 /* event from server socket */ 845 if (pollfds[2].revents && 846 (pollfds[2].revents & (POLLIN | POLLRDNORM))) { 847 if (clifd != -1) { 848 /* 849 * Test the client to see if it is really 850 * still alive. If it has died but we 851 * haven't yet detected that, we might 852 * deny a legitimate connect attempt. If it 853 * is dead, we break out; once we tear down 854 * the old connection, the new connection 855 * will happen. 856 */ 857 if (test_client(clifd) == -1) { 858 break; 859 } 860 /* we're already handling a client */ 861 reject_client(servfd, clipid); 862 863 864 } else if ((clifd = accept_client(servfd, &clipid, 865 clilocale, sizeof (clilocale))) != -1) { 866 pollfds[1].fd = clifd; 867 868 } else { 869 break; 870 } 871 } 872 873 /* 874 * Watch for events on the eventstream. This is how we get 875 * notified of the zone halting, etc. It provides us a 876 * "wakeup" from poll when important things happen, which 877 * is good. 878 */ 879 if (pollfds[3].revents) { 880 int evt = eventstream_read(); 881 /* 882 * After we drain out the event, if we aren't servicing 883 * a console client, we hop back out to our caller, 884 * which will check to see if it is time to shutdown 885 * the daemon, or if we should take another console 886 * service lap. 887 */ 888 if (clifd == -1) { 889 break; 890 } 891 event_message(clifd, clilocale, evt); 892 /* 893 * Special handling for the message that the zone is 894 * uninstalling; we boot the client, then break out 895 * of this function. When we return to the 896 * serve_console loop, we will see that the zone is 897 * in a state < READY, and so zoneadmd will shutdown. 898 */ 899 if (evt == Z_EVT_ZONE_UNINSTALLING) { 900 break; 901 } 902 } 903 904 } 905 906 if (clifd != -1) { 907 (void) shutdown(clifd, SHUT_RDWR); 908 (void) close(clifd); 909 } 910 } 911 912 int 913 init_console(zlog_t *zlogp) 914 { 915 if (init_console_dev(zlogp) == -1) { 916 zerror(zlogp, B_FALSE, 917 "console setup: device initialization failed"); 918 return (-1); 919 } 920 921 if ((serverfd = init_console_sock(zlogp)) == -1) { 922 zerror(zlogp, B_FALSE, 923 "console setup: socket initialization failed"); 924 return (-1); 925 } 926 return (0); 927 } 928 929 /* 930 * serve_console() is the master loop for driving console I/O. It is also the 931 * routine which is ultimately responsible for "pulling the plug" on zoneadmd 932 * when it realizes that the daemon should shut down. 933 * 934 * The rules for shutdown are: there must be no console client, and the zone 935 * state must be < ready. However, we need to give things a chance to actually 936 * get going when the daemon starts up-- otherwise the daemon would immediately 937 * exit on startup if the zone was in the installed state, so we first drop 938 * into the do_console_io() loop in order to give *something* a chance to 939 * happen. 940 */ 941 void 942 serve_console(zlog_t *zlogp) 943 { 944 int masterfd; 945 zone_state_t zstate; 946 char conspath[MAXPATHLEN]; 947 948 (void) snprintf(conspath, sizeof (conspath), 949 "/dev/zcons/%s/%s", zone_name, ZCONS_MASTER_NAME); 950 951 for (;;) { 952 masterfd = open(conspath, O_RDWR|O_NONBLOCK|O_NOCTTY); 953 if (masterfd == -1) { 954 zerror(zlogp, B_TRUE, "failed to open console master"); 955 (void) mutex_lock(&lock); 956 goto death; 957 } 958 959 /* 960 * Setting RPROTDIS on the stream means that the control 961 * portion of messages received (which we don't care about) 962 * will be discarded by the stream head. If we allowed such 963 * messages, we wouldn't be able to use read(2), as it fails 964 * (EBADMSG) when a message with a control element is received. 965 */ 966 if (ioctl(masterfd, I_SRDOPT, RNORM|RPROTDIS) == -1) { 967 zerror(zlogp, B_TRUE, "failed to set options on " 968 "console master"); 969 (void) mutex_lock(&lock); 970 goto death; 971 } 972 973 do_console_io(zlogp, masterfd, serverfd); 974 975 /* 976 * We would prefer not to do this, but hostile zone processes 977 * can cause the stream to become tainted, and reads will 978 * fail. So, in case something has gone seriously ill, 979 * we dismantle the stream and reopen the console when we 980 * take another lap. 981 */ 982 (void) close(masterfd); 983 984 (void) mutex_lock(&lock); 985 /* 986 * We need to set death_throes (see below) atomically with 987 * respect to noticing that (a) we have no console client and 988 * (b) the zone is not installed. Otherwise we could get a 989 * request to boot during this time. Once we set death_throes, 990 * any incoming door stuff will be turned away. 991 */ 992 if (zone_get_state(zone_name, &zstate) == Z_OK) { 993 if (zstate < ZONE_STATE_READY) 994 goto death; 995 } else { 996 zerror(zlogp, B_FALSE, 997 "unable to determine state of zone"); 998 goto death; 999 } 1000 /* 1001 * Even if zone_get_state() fails, stay conservative, and 1002 * take another lap. 1003 */ 1004 (void) mutex_unlock(&lock); 1005 } 1006 1007 death: 1008 assert(MUTEX_HELD(&lock)); 1009 in_death_throes = B_TRUE; 1010 (void) mutex_unlock(&lock); 1011 1012 destroy_console_sock(serverfd); 1013 (void) destroy_console_devs(zlogp); 1014 } 1015