diff options
| author | Jerry Jelinek <jerry.jelinek@joyent.com> | 2017-01-06 12:55:13 +0000 |
|---|---|---|
| committer | Jerry Jelinek <jerry.jelinek@joyent.com> | 2017-01-06 16:04:40 +0000 |
| commit | 3bf32d20a3f6b8bfaabf39e2ef539e46e311e973 (patch) | |
| tree | f4ddeb64d73961aeae3888bf4f4204200fb0106c | |
| parent | 437707335ad6e34f26bc0e5c3617f80ae42eea45 (diff) | |
| download | illumos-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.c | 70 | ||||
| -rw-r--r-- | usr/src/uts/common/brand/lx/os/lx_brand.c | 15 | ||||
| -rw-r--r-- | usr/src/uts/common/brand/lx/sys/lx_brand.h | 4 | ||||
| -rw-r--r-- | usr/src/uts/common/brand/lx/syscall/lx_ioctl.c | 16 |
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); |
