summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJerry Jelinek <jerry.jelinek@joyent.com>2017-01-06 12:55:13 +0000
committerJerry Jelinek <jerry.jelinek@joyent.com>2017-01-06 16:04:40 +0000
commit3bf32d20a3f6b8bfaabf39e2ef539e46e311e973 (patch)
treef4ddeb64d73961aeae3888bf4f4204200fb0106c
parent437707335ad6e34f26bc0e5c3617f80ae42eea45 (diff)
downloadillumos-joyent-3bf32d20a3f6b8bfaabf39e2ef539e46e311e973.tar.gz
OS-5412 'screen' doesn't run on centos7
Reviewed by: Patrick Mooney <patrick.mooney@joyent.com> Reviewed by: Ryan Zezeski <ryan.zeseski@joyent.com> Approved by: Patrick Mooney <patrick.mooney@joyent.com>
-rw-r--r--usr/src/lib/brand/lx/lx_support/lx_support.c70
-rw-r--r--usr/src/uts/common/brand/lx/os/lx_brand.c15
-rw-r--r--usr/src/uts/common/brand/lx/sys/lx_brand.h4
-rw-r--r--usr/src/uts/common/brand/lx/syscall/lx_ioctl.c16
4 files changed, 100 insertions, 5 deletions
diff --git a/usr/src/lib/brand/lx/lx_support/lx_support.c b/usr/src/lib/brand/lx/lx_support/lx_support.c
index 65679b0603..ef4e614e99 100644
--- a/usr/src/lib/brand/lx/lx_support/lx_support.c
+++ b/usr/src/lib/brand/lx/lx_support/lx_support.c
@@ -21,7 +21,7 @@
/*
* Copyright 2009 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
- * Copyright 2016 Joyent, Inc.
+ * Copyright 2017 Joyent, Inc.
*/
/*
@@ -163,6 +163,72 @@ lxs_getattrs(zone_dochandle_t zdh, char **krelease)
lxs_err(gettext("error accessing zone configuration"));
}
+/*
+ * Attempt to lookup the "tty" gid from within the zone's /etc/group file.
+ * The gid is used to emulate existing Linux udev behavior for setting the gid
+ * on a pty. If we cannot lookup the gid for some reason, we still allow
+ * the zone to boot.
+ *
+ * Because we're reading the lx zone's /etc/group file, we have to parse it
+ * ourselves, but this is simple since we only need the gid.
+ */
+static void
+lxs_set_ttygid(zoneid_t zoneid)
+{
+ char buf[MAXPATHLEN];
+ FILE *fp;
+ gid_t tty_gid = 0;
+
+ if (snprintf(buf, sizeof (buf), "%s/root/etc/group", zoneroot) >=
+ sizeof (buf))
+ return;
+
+ if ((fp = fopen(buf, "r")) == NULL)
+ return;
+
+ /*
+ * Look for the "tty" line and get the gid. Note that this loop will
+ * properly handle a long line that won't fit into buf on a single
+ * fgets. The subsequent fgets will consume more of the line but we
+ * continue on through that. In practice this is unlikely to occur.
+ */
+ while (fgets(buf, sizeof (buf), fp) != NULL) {
+ char *p, *p_id;
+ long val;
+
+ /* group name */
+ if ((p = strchr(buf, ':')) == NULL)
+ continue;
+ *p = '\0';
+ if (strcmp(buf, "tty") != 0)
+ continue;
+
+ /* found tty entry, skip the "x" field */
+ if ((p = strchr(p + 1, ':')) == NULL)
+ goto done;
+ /* gid field */
+ p_id = p + 1;
+ if ((p = strchr(p_id, ':')) == NULL)
+ goto done;
+ *p = '\0';
+
+ errno = 0;
+ val = strtol(p_id, &p, 10);
+ /* Perform simple validation on the gid */
+ if (errno != 0 || *p != '\0' || val > MAXUID || val < 0)
+ goto done;
+ tty_gid = (gid_t)val;
+ break;
+ }
+
+ if (tty_gid != 0)
+ (void) zone_setattr(zoneid, LX_ATTR_TTY_GID, &tty_gid,
+ sizeof (tty_gid));
+
+done:
+ fclose(fp);
+}
+
static int
lxs_boot()
{
@@ -205,6 +271,8 @@ lxs_boot()
lxs_err(gettext("unable to set kernel version"));
}
+ lxs_set_ttygid(zoneid);
+
return (0);
}
diff --git a/usr/src/uts/common/brand/lx/os/lx_brand.c b/usr/src/uts/common/brand/lx/os/lx_brand.c
index 4fbf8530bb..839ff9219a 100644
--- a/usr/src/uts/common/brand/lx/os/lx_brand.c
+++ b/usr/src/uts/common/brand/lx/os/lx_brand.c
@@ -25,7 +25,7 @@
*/
/*
- * Copyright 2016, Joyent, Inc. All rights reserved.
+ * Copyright 2017, Joyent, Inc. All rights reserved.
*/
/*
@@ -408,6 +408,19 @@ lx_setattr(zone_t *zone, int attr, void *ubuf, size_t ubufsz)
mutex_exit(&lxzd->lxzd_lock);
return (0);
}
+ case LX_ATTR_TTY_GID: {
+ gid_t gid;
+ if (ubufsz != sizeof (gid)) {
+ return (ERANGE);
+ }
+ if (copyin(ubuf, &gid, ubufsz) != 0) {
+ return (EFAULT);
+ }
+ mutex_enter(&lxzd->lxzd_lock);
+ lxzd->lxzd_ttygrp = gid;
+ mutex_exit(&lxzd->lxzd_lock);
+ return (0);
+ }
default:
return (EINVAL);
}
diff --git a/usr/src/uts/common/brand/lx/sys/lx_brand.h b/usr/src/uts/common/brand/lx/sys/lx_brand.h
index 8e239a4f2a..147e8961f2 100644
--- a/usr/src/uts/common/brand/lx/sys/lx_brand.h
+++ b/usr/src/uts/common/brand/lx/sys/lx_brand.h
@@ -24,7 +24,7 @@
*/
/*
- * Copyright 2016 Joyent, Inc.
+ * Copyright 2017 Joyent, Inc.
*/
#ifndef _LX_BRAND_H
@@ -162,6 +162,7 @@ typedef enum lx_ptrace_options {
#define LX_ATTR_KERN_RELEASE ZONE_ATTR_BRAND_ATTRS
#define LX_ATTR_KERN_VERSION (ZONE_ATTR_BRAND_ATTRS + 1)
+#define LX_ATTR_TTY_GID (ZONE_ATTR_BRAND_ATTRS + 2)
/*
* Aux vector containing phdr of Linux executable and ehdr of interpreter
@@ -606,6 +607,7 @@ typedef struct lx_zone_data {
char lxzd_kernel_version[LX_KERN_VERSION_MAX];
ksocket_t lxzd_ioctl_sock;
char lxzd_bootid[LX_BOOTID_LEN]; /* procfs boot_id */
+ gid_t lxzd_ttygrp; /* tty gid for pty chown */
vfs_t *lxzd_cgroup; /* cgroup for this zone */
list_t *lxzd_vdisks; /* virtual disks (zvols) */
dev_t lxzd_zfs_dev; /* major num for zfs */
diff --git a/usr/src/uts/common/brand/lx/syscall/lx_ioctl.c b/usr/src/uts/common/brand/lx/syscall/lx_ioctl.c
index 17dff2a840..88b025643f 100644
--- a/usr/src/uts/common/brand/lx/syscall/lx_ioctl.c
+++ b/usr/src/uts/common/brand/lx/syscall/lx_ioctl.c
@@ -10,7 +10,7 @@
*/
/*
- * Copyright 2016 Joyent, Inc.
+ * Copyright 2017 Joyent, Inc.
*/
#include <sys/errno.h>
@@ -1021,6 +1021,7 @@ ict_gptn(file_t *fp, int cmd, intptr_t arg, int lxcmd)
pt_own_t pto;
int error, rv;
int ptyno;
+ lx_zone_data_t *lxzd = ztolxzd(curproc->p_zone);
/* This operation is only valid for the lx_ptm device. */
if (getmajor(fp->f_vnode->v_rdev) != ddi_name_to_major(LX_PTM_DRV))
@@ -1028,7 +1029,18 @@ ict_gptn(file_t *fp, int cmd, intptr_t arg, int lxcmd)
cr = CRED();
pto.pto_ruid = cr->cr_uid;
- pto.pto_rgid = cr->cr_gid;
+ /*
+ * Both Linux and our native code (see grantpt() in native libc)
+ * prefer assigning the "tty" gid to the new pty. On Linux this is
+ * done by udev. Since we're in the kernel we cannot lookup the gid, so
+ * we rely on the lx_support program to initialize the value in the
+ * zone data at boot time.
+ */
+ if (lxzd->lxzd_ttygrp == 0) {
+ pto.pto_rgid = cr->cr_gid;
+ } else {
+ pto.pto_rgid = lxzd->lxzd_ttygrp;
+ }
istr.ic_cmd = OWNERPT;
istr.ic_len = sizeof (pto);