[libvirt] [PATCH 1/1] lxc: use our own hand-rolled code in place of unlockpt and grantpt (v2)

Serge E. Hallyn serge.hallyn at canonical.com
Mon Oct 17 19:04:23 UTC 2011


The glibc ones cannot handle ptys opened in a devpts not mounted at
/dev/pts.

Changelog:
  Oct 17: Per Eli Qiao, use VIR_ALLOC_N when appropriate, make
          sure to check return values, and follow coding style
	  convention.
	  Change lxcGetTtyGid() to return -1 on error, otherwise
	  return gid in passed-in argument.

Signed-off-by: Serge Hallyn <serge.hallyn at canonical.com>
---
 src/lxc/lxc_controller.c |   89 +++++++++++++++++++++++++++++++++++++++++++--
 1 files changed, 85 insertions(+), 4 deletions(-)

diff --git a/src/lxc/lxc_controller.c b/src/lxc/lxc_controller.c
index 89ce7f5..8c9caee 100644
--- a/src/lxc/lxc_controller.c
+++ b/src/lxc/lxc_controller.c
@@ -41,6 +41,8 @@
 #include <locale.h>
 #include <linux/loop.h>
 #include <dirent.h>
+#include <grp.h>
+#include <sys/stat.h>
 
 #if HAVE_CAPNG
 # include <cap-ng.h>
@@ -781,6 +783,88 @@ static int lxcSetPersonality(virDomainDefPtr def)
 #endif
 
 static int
+lxcGetTtyGid(int *gid) {
+    char *grtmpbuf;
+    struct group grbuf;
+    size_t grbuflen = sysconf(_SC_GETGR_R_SIZE_MAX);
+    struct group *p;
+    int ret;
+    gid_t tty_gid = -1;
+
+    /* Get the group ID of the special `tty' group.  */
+    if (grbuflen == (size_t) -1L)
+        /* `sysconf' does not support _SC_GETGR_R_SIZE_MAX.
+           Try a moderate value.  */
+        grbuflen = 1024;
+
+    if ((VIR_ALLOC_N(grtmpbuf, grbuflen)) < 0)
+	    return -1;
+
+    ret = getgrnam_r("tty", &grbuf, grtmpbuf, grbuflen, &p);
+    if (ret || p != NULL)
+        tty_gid = p->gr_gid;
+
+    VIR_FREE(grtmpbuf);
+
+    *gid = tty_gid == -1 ? getgid() : tty_gid;
+    return 0;
+}
+
+#define ACCESSPERMS (S_IRWXU|S_IRWXG|S_IRWXO) /* 0777 */
+
+/* heavily borrowed from glibc, but don't assume devpts == "/dev/pts" */
+static int
+lxcCreateTty(char *ptmx, int *ttymaster, char **ttyName)
+{
+    int rc = -1;
+    int ret;
+    int ptyno;
+    uid_t uid;
+    gid_t gid;
+    struct stat st;
+    int unlock = 0;
+
+    if ((*ttymaster = open(ptmx, O_RDWR|O_NOCTTY|O_NONBLOCK)) < 0)
+        goto cleanup;
+
+    if (ioctl(*ttymaster, TIOCSPTLCK, &unlock) < 0)
+        goto cleanup;
+
+    if (ioctl(*ttymaster, TIOCGPTN, &ptyno) < 0)
+        goto cleanup;
+
+    if (fstat(*ttymaster, &st) < 0)
+        goto cleanup;
+
+    if (lxcGetTtyGid(&gid) < 0)
+        goto cleanup;
+
+    uid = getuid();
+    if (st.st_uid != uid || st.st_gid != gid)
+        if (fchown(*ttymaster, uid, gid) < 0)
+            goto cleanup;
+
+    if ((st.st_mode & ACCESSPERMS) != (S_IRUSR|S_IWUSR|S_IWGRP))
+        if (fchmod(*ttymaster, S_IRUSR|S_IWUSR|S_IWGRP) < 0)
+            goto cleanup;
+
+    if (VIR_ALLOC_N(*ttyName, PATH_MAX) < 0) {
+        errno = ENOMEM;
+        goto cleanup;
+    }
+
+    snprintf(*ttyName, PATH_MAX, "/dev/pts/%d", ptyno);
+
+    rc = 0;
+
+cleanup:
+    if (rc != 0)
+        VIR_FORCE_CLOSE(*ttymaster);
+
+    return rc;
+}
+
+static int
 lxcControllerRun(virDomainDefPtr def,
                  unsigned int nveths,
                  char **veths,
@@ -894,10 +978,7 @@ lxcControllerRun(virDomainDefPtr def,
 
     if (devptmx) {
         VIR_DEBUG("Opening tty on private %s", devptmx);
-        if (virFileOpenTtyAt(devptmx,
-                             &containerPty,
-                             &containerPtyPath,
-                             0) < 0) {
+        if (lxcCreateTty(devptmx, &containerPty, &containerPtyPath) < 0) {
             virReportSystemError(errno, "%s",
                                  _("Failed to allocate tty"));
             goto cleanup;
-- 
1.7.5.4




More information about the libvir-list mailing list