summaryrefslogtreecommitdiff
path: root/usr/src/cmd/zoneadmd
diff options
context:
space:
mode:
authorjv227347 <Jordan.Vaughan@Sun.com>2009-02-11 16:27:07 -0800
committerjv227347 <Jordan.Vaughan@Sun.com>2009-02-11 16:27:07 -0800
commit9d5056ea37dd689d393cb1715ae29551bc0eba2e (patch)
tree2ded8162b05256c00eca68dff3f1b1eafe933d87 /usr/src/cmd/zoneadmd
parenta0b8f2d7676d6b7913f3ba65b3f9b28f37aaae71 (diff)
downloadillumos-joyent-9d5056ea37dd689d393cb1715ae29551bc0eba2e.tar.gz
6498835 zone console stream module config is too fragile
Diffstat (limited to 'usr/src/cmd/zoneadmd')
-rw-r--r--usr/src/cmd/zoneadmd/vplat.c4
-rw-r--r--usr/src/cmd/zoneadmd/zcons.c196
-rw-r--r--usr/src/cmd/zoneadmd/zoneadmd.c8
-rw-r--r--usr/src/cmd/zoneadmd/zoneadmd.h5
4 files changed, 70 insertions, 143 deletions
diff --git a/usr/src/cmd/zoneadmd/vplat.c b/usr/src/cmd/zoneadmd/vplat.c
index 6f3d16e5a8..8314387396 100644
--- a/usr/src/cmd/zoneadmd/vplat.c
+++ b/usr/src/cmd/zoneadmd/vplat.c
@@ -4598,10 +4598,6 @@ vplat_teardown(zlog_t *zlogp, boolean_t unmount_cmd, boolean_t rebooting)
goto error;
}
- /* destroy zconsole before umount /dev */
- if (!unmount_cmd)
- destroy_console_slave();
-
if (unmount_filesystems(zlogp, zoneid, unmount_cmd) != 0) {
zerror(zlogp, B_FALSE,
"unable to unmount file systems in zone");
diff --git a/usr/src/cmd/zoneadmd/zcons.c b/usr/src/cmd/zoneadmd/zcons.c
index a8961c8eaf..6704eb1563 100644
--- a/usr/src/cmd/zoneadmd/zcons.c
+++ b/usr/src/cmd/zoneadmd/zcons.c
@@ -20,12 +20,10 @@
*/
/*
- * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
-#pragma ident "%Z%%M% %I% %E% SMI"
-
/*
* Console support for zones requires a significant infrastructure. The
* core pieces are contained in this file, but other portions of note
@@ -63,7 +61,7 @@
* | zonename="myzone" |
* +------------------------+
*
- * There are basically three major tasks which the console subsystem in
+ * There are basically two major tasks which the console subsystem in
* zoneadmd accomplishes:
*
* - Setup and teardown of zcons driver instances. One zcons instance
@@ -76,16 +74,6 @@
* property. This the console instance to persist across reboots,
* and while the zone is halted.
*
- * - Initialization of the slave side of the console. This is
- * accomplished by pushing various STREAMS modules onto the console.
- * The ptem(7M) module gets special treatment, and is anchored into
- * place using the I_ANCHOR facility. This is so that the zcons driver
- * always has terminal semantics, as would a real hardware terminal.
- * This means that ttymon(1M) works unmodified; at boot time, ttymon
- * will do its own plumbing of the console stream, and will even
- * I_POP modules off. Hence the anchor, which assures that ptem will
- * never be I_POP'd.
- *
* - Acting as a server for 'zlogin -C' instances. When zlogin -C is
* run, zlogin connects to zoneadmd via unix domain socket. zoneadmd
* functions as a two-way proxy for console I/O, relaying user input
@@ -129,21 +117,10 @@
#define CONSOLE_SOCKPATH ZONES_TMPDIR "/%s.console_sock"
-static int slavefd = -1; /* slave side of console */
static int serverfd = -1; /* console server unix domain socket fd */
char boot_args[BOOTARGS_MAX];
char bad_boot_arg[BOOTARGS_MAX];
-static struct termios base_termios = { /* from init.c */
- BRKINT|ICRNL|IXON|IMAXBEL, /* iflag */
- OPOST|ONLCR|TAB3, /* oflag */
- CS8|CREAD|B9600, /* cflag */
- ISIG|ICANON|ECHO|ECHOE|ECHOK|ECHOCTL|ECHOKE|IEXTEN, /* lflag */
- CINTR, CQUIT, CERASE, CKILL, CEOF, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0
-};
-
/*
* The eventstream is a simple one-directional flow of messages from the
* door server to the console subsystem, implemented with a pipe.
@@ -284,8 +261,38 @@ destroy_cb(di_node_t node, void *arg)
static int
destroy_console_devs(zlog_t *zlogp)
{
+ char conspath[MAXPATHLEN];
di_node_t root;
struct cb_data cb;
+ int masterfd;
+ int slavefd;
+
+ /*
+ * Signal the master side to release its handle on the slave side by
+ * issuing a ZC_RELEASESLAVE ioctl.
+ */
+ (void) snprintf(conspath, sizeof (conspath), "/dev/zcons/%s/%s",
+ zone_name, ZCONS_MASTER_NAME);
+ if ((masterfd = open(conspath, O_RDWR | O_NOCTTY)) != -1) {
+ (void) snprintf(conspath, sizeof (conspath), "/dev/zcons/%s/%s",
+ zone_name, ZCONS_SLAVE_NAME);
+ if ((slavefd = open(conspath, O_RDWR | O_NOCTTY)) != -1) {
+ if (ioctl(masterfd, ZC_RELEASESLAVE,
+ (caddr_t)(intptr_t)slavefd) != 0)
+ zerror(zlogp, B_TRUE, "WARNING: error while "
+ "releasing slave handle of zone console for"
+ " %s", zone_name);
+ (void) close(slavefd);
+ } else {
+ zerror(zlogp, B_TRUE, "WARNING: could not open slave "
+ "side of zone console for %s to release slave "
+ "handle", zone_name);
+ }
+ (void) close(masterfd);
+ } else {
+ zerror(zlogp, B_TRUE, "WARNING: could not open master side of "
+ "zone console for %s to release slave handle", zone_name);
+ }
bzero(&cb, sizeof (cb));
cb.zlogp = zlogp;
@@ -321,10 +328,15 @@ destroy_console_devs(zlog_t *zlogp)
static int
init_console_dev(zlog_t *zlogp)
{
- devctl_hdl_t bus_hdl = NULL, dev_hdl = NULL;
+ char conspath[MAXPATHLEN];
+ devctl_hdl_t bus_hdl = NULL;
+ devctl_hdl_t dev_hdl = NULL;
devctl_ddef_t ddef_hdl = NULL;
di_devlink_handle_t dl = NULL;
- int rv = -1, ndevs;
+ int rv = -1;
+ int ndevs;
+ int masterfd;
+ int slavefd;
/*
* Don't re-setup console if it is working and ready already; just
@@ -390,116 +402,42 @@ devlinks:
goto error;
}
- rv = 0;
-error:
- if (ddef_hdl)
- devctl_ddef_free(ddef_hdl);
- if (bus_hdl)
- devctl_release(bus_hdl);
- if (dev_hdl)
- devctl_release(dev_hdl);
- return (rv);
-}
-
-/*
- * init_console_slave() sets up the console slave device; the device node
- * itself has already been set up in the device tree; the primary job
- * here is to do some STREAMS plumbing.
- *
- * The slave side of the console is opened and the appropriate STREAMS
- * modules are pushed on. A wrinkle is that 'ptem' must be anchored
- * in place (see streamio(7i) since we always want the console to
- * have terminal semantics.)
- */
-int
-init_console_slave(zlog_t *zlogp)
-{
- char zconspath[MAXPATHLEN];
-
- if (slavefd != -1)
- return (0);
-
- (void) snprintf(zconspath, sizeof (zconspath),
- "/dev/zcons/%s/%s", zone_name, ZCONS_SLAVE_NAME);
-
- if ((slavefd = open(zconspath, O_RDWR | O_NOCTTY)) < 0) {
- zerror(zlogp, B_TRUE, "failed to open %s", zconspath);
- goto error;
- }
-
- /*
- * Just to make sure the whole stream is pristine.
- */
- (void) ioctl(slavefd, I_FLUSH, FLUSHRW);
-
- /*
- * Push hardware emulation (ptem) module; we would rather not, but
- * are forced to push ldterm and ttcompat here. Ultimately ttymon
- * will pop them off, so we ANCHOR only ptem.
- *
- * We need to use __I_PUSH_NOCTTY instead of I_PUSH here, otherwise
- * we'll end up having the slave device as *our* controling terminal.
- */
- if (ioctl(slavefd, __I_PUSH_NOCTTY, "ptem") == -1) {
- zerror(zlogp, B_TRUE, "failed to push ptem module");
- goto error;
- }
-
/*
- * Anchor the stream to prevent malicious or accidental I_POP of ptem.
+ * Open the master side of the console and issue the ZC_HOLDSLAVE ioctl,
+ * which will cause the master to retain a reference to the slave.
+ * This prevents ttymon from blowing through the slave's STREAMS anchor.
*/
- if (ioctl(slavefd, I_ANCHOR) == -1) {
- zerror(zlogp, B_TRUE, "failed to set stream anchor");
- goto error;
- }
-
- if (ioctl(slavefd, __I_PUSH_NOCTTY, "ldterm") == -1) {
- zerror(zlogp, B_TRUE, "failed to push ldterm module");
- goto error;
- }
- if (ioctl(slavefd, __I_PUSH_NOCTTY, "ttcompat") == -1) {
- zerror(zlogp, B_TRUE, "failed to push ttcompat module");
+ (void) snprintf(conspath, sizeof (conspath), "/dev/zcons/%s/%s",
+ zone_name, ZCONS_MASTER_NAME);
+ if ((masterfd = open(conspath, O_RDWR | O_NOCTTY)) == -1) {
+ zerror(zlogp, B_TRUE, "ERROR: could not open master side of "
+ "zone console for %s to acquire slave handle", zone_name);
goto error;
}
-
- /*
- * Setup default terminal settings
- */
- if (tcsetattr(slavefd, TCSAFLUSH, &base_termios) == -1) {
- zerror(zlogp, B_TRUE, "failed to set base terminal settings");
+ (void) snprintf(conspath, sizeof (conspath), "/dev/zcons/%s/%s",
+ zone_name, ZCONS_SLAVE_NAME);
+ if ((slavefd = open(conspath, O_RDWR | O_NOCTTY)) == -1) {
+ zerror(zlogp, B_TRUE, "ERROR: could not open slave side of zone"
+ " console for %s to acquire slave handle", zone_name);
+ (void) close(masterfd);
goto error;
}
-
- return (0);
-
-error:
- if (slavefd != -1)
- (void) close(slavefd);
- slavefd = -1;
- zerror(zlogp, B_FALSE, "could not initialize console slave");
- return (-1);
-}
-
-void
-destroy_console_slave(void)
-{
+ if (ioctl(masterfd, ZC_HOLDSLAVE, (caddr_t)(intptr_t)slavefd) == 0)
+ rv = 0;
+ else
+ zerror(zlogp, B_TRUE, "ERROR: error while acquiring slave "
+ "handle of zone console for %s", zone_name);
(void) close(slavefd);
- slavefd = -1;
-}
-
-/*
- * Restore initial terminal attributes to the zone console.
- */
-void
-reset_slave_terminal(zlog_t *zlogp)
-{
- assert(slavefd != -1);
+ (void) close(masterfd);
- /* Probably not fatal, so we drive on if it fails */
- if (tcsetattr(slavefd, TCSAFLUSH, &base_termios) == -1) {
- zerror(zlogp, B_TRUE, "WARNING: failed to set terminal "
- "settings.");
- }
+error:
+ if (ddef_hdl)
+ devctl_ddef_free(ddef_hdl);
+ if (bus_hdl)
+ devctl_release(bus_hdl);
+ if (dev_hdl)
+ devctl_release(dev_hdl);
+ return (rv);
}
static int
diff --git a/usr/src/cmd/zoneadmd/zoneadmd.c b/usr/src/cmd/zoneadmd/zoneadmd.c
index 813369a773..240985f427 100644
--- a/usr/src/cmd/zoneadmd/zoneadmd.c
+++ b/usr/src/cmd/zoneadmd/zoneadmd.c
@@ -20,7 +20,7 @@
*/
/*
- * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
@@ -767,10 +767,6 @@ zone_bootup(zlog_t *zlogp, const char *bootargs, int zstate)
if (brand_prestatechg(zlogp, zstate, Z_BOOT) != 0)
return (-1);
- if (init_console_slave(zlogp) != 0)
- return (-1);
- reset_slave_terminal(zlogp);
-
if ((zoneid = getzoneidbyname(zone_name)) == -1) {
zerror(zlogp, B_TRUE, "unable to get zoneid");
return (-1);
@@ -1908,7 +1904,7 @@ main(int argc, char *argv[])
* serve_console_sock() below gets called, and any pending
* connection is accept()ed).
*/
- if (!zonecfg_in_alt_root() && init_console(zlogp) == -1)
+ if (!zonecfg_in_alt_root() && init_console(zlogp) < 0)
goto child_out;
/*
diff --git a/usr/src/cmd/zoneadmd/zoneadmd.h b/usr/src/cmd/zoneadmd/zoneadmd.h
index 97b5cc6d1e..181f3c3c1b 100644
--- a/usr/src/cmd/zoneadmd/zoneadmd.h
+++ b/usr/src/cmd/zoneadmd/zoneadmd.h
@@ -20,7 +20,7 @@
*/
/*
- * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
@@ -143,9 +143,6 @@ extern void resolve_lofs(zlog_t *zlogp, char *path, size_t pathlen);
/*
* Console subsystem routines.
*/
-extern int init_console_slave(zlog_t *);
-extern void destroy_console_slave(void);
-extern void reset_slave_terminal(zlog_t *);
extern int init_console(zlog_t *);
extern void serve_console(zlog_t *);