The following pull request was submitted through Github.
It can be accessed and reviewed at: https://github.com/lxc/lxc/pull/1544

This e-mail was sent by the LXC bot, direct replies will not reach the author
unless they happen to be subscribed to this list.

=== Description (from pull-request) ===
Signed-off-by: Christian Brauner <[email protected]>
From 3f79ef1f49ffd0f3809059b54af196b30fc483ed Mon Sep 17 00:00:00 2001
From: Christian Brauner <[email protected]>
Date: Mon, 8 May 2017 19:38:59 +0200
Subject: [PATCH 1/6] conf: non-functional changes lxc_fill_autodev()

Signed-off-by: Christian Brauner <[email protected]>
---
 src/lxc/conf.c | 35 +++++++++++++++++++++--------------
 1 file changed, 21 insertions(+), 14 deletions(-)

diff --git a/src/lxc/conf.c b/src/lxc/conf.c
index 8c10b9c..9f8c90b 100644
--- a/src/lxc/conf.c
+++ b/src/lxc/conf.c
@@ -1172,25 +1172,24 @@ static const struct lxc_devs lxc_devs[] = {
        { "console",    S_IFCHR | S_IRUSR | S_IWUSR,           5, 1     },
 };
 
-static int fill_autodev(const struct lxc_rootfs *rootfs, bool mount_console)
+static int lxc_fill_autodev(const struct lxc_rootfs *rootfs, bool 
mount_console)
 {
        int ret;
        char path[MAXPATHLEN];
        int i;
        mode_t cmask;
 
-       INFO("Creating initial consoles under container /dev");
-
        ret = snprintf(path, MAXPATHLEN, "%s/dev", rootfs->path ? rootfs->mount 
: "");
        if (ret < 0 || ret >= MAXPATHLEN) {
                ERROR("Error calculating container /dev location");
                return -1;
        }
 
-       if (!dir_exists(path)) // ignore, just don't try to fill in
+       /* ignore, just don't try to fill in */
+       if (!dir_exists(path))
                return 0;
 
-       INFO("Populating container /dev");
+       INFO("populating container /dev");
        cmask = umask(S_IXUSR | S_IXGRP | S_IXOTH);
        for (i = 0; i < sizeof(lxc_devs) / sizeof(lxc_devs[0]); i++) {
                const struct lxc_devs *d = &lxc_devs[i];
@@ -1201,13 +1200,20 @@ static int fill_autodev(const struct lxc_rootfs 
*rootfs, bool mount_console)
                ret = snprintf(path, MAXPATHLEN, "%s/dev/%s", rootfs->path ? 
rootfs->mount : "", d->name);
                if (ret < 0 || ret >= MAXPATHLEN)
                        return -1;
+
                ret = mknod(path, d->mode, makedev(d->maj, d->min));
-               if (ret && errno != EEXIST) {
+               if (ret < 0) {
                        char hostpath[MAXPATHLEN];
                        FILE *pathfile;
 
-                       // Unprivileged containers cannot create devices, so
-                       // bind mount the device from the host
+                       if (errno == EEXIST) {
+                               DEBUG("\"%s\" device already existed", path);
+                               continue;
+                       }
+
+                       /* Unprivileged containers cannot create devices, so
+                        * bind mount the device from the host.
+                        */
                        ret = snprintf(hostpath, MAXPATHLEN, "/dev/%s", 
d->name);
                        if (ret < 0 || ret >= MAXPATHLEN)
                                return -1;
@@ -1217,17 +1223,18 @@ static int fill_autodev(const struct lxc_rootfs 
*rootfs, bool mount_console)
                                return -1;
                        }
                        fclose(pathfile);
-                       if (safe_mount(hostpath, path, 0, MS_BIND, NULL,
-                                               rootfs->path ? rootfs->mount : 
NULL) != 0) {
-                               SYSERROR("Failed bind mounting device %s from 
host into container",
-                                       d->name);
+                       if (safe_mount(hostpath, path, 0, MS_BIND, NULL, 
rootfs->path ? rootfs->mount : NULL) != 0) {
+                               SYSERROR("Failed bind mounting device %s from 
host into container", d->name);
                                return -1;
                        }
+                       DEBUG("bind mounted \"%s\" onto \"%s\"", hostpath, 
path);
+               } else {
+                       DEBUG("created device node \"%s\"", path);
                }
        }
        umask(cmask);
 
-       INFO("Populated container /dev");
+       INFO("populated container /dev");
        return 0;
 }
 
@@ -4047,7 +4054,7 @@ int lxc_setup(struct lxc_handler *handler)
                        ERROR("failed to run autodev hooks for container 
'%s'.", name);
                        return -1;
                }
-               if (fill_autodev(&lxc_conf->rootfs, mount_console)) {
+               if (lxc_fill_autodev(&lxc_conf->rootfs, mount_console)) {
                        ERROR("failed to populate /dev in the container");
                        return -1;
                }

From 757afce6c4a6367b56ca21eaea04c2dc560c434d Mon Sep 17 00:00:00 2001
From: Christian Brauner <[email protected]>
Date: Mon, 8 May 2017 19:39:41 +0200
Subject: [PATCH 2/6] conf: remove /dev/console from lxc_fill_autodev()

Signed-off-by: Christian Brauner <[email protected]>
---
 src/lxc/conf.c | 4 ----
 1 file changed, 4 deletions(-)

diff --git a/src/lxc/conf.c b/src/lxc/conf.c
index 9f8c90b..e3a73d6 100644
--- a/src/lxc/conf.c
+++ b/src/lxc/conf.c
@@ -1169,7 +1169,6 @@ static const struct lxc_devs lxc_devs[] = {
        { "urandom",    S_IFCHR | S_IRWXU | S_IRWXG | S_IRWXO, 1, 9     },
        { "random",     S_IFCHR | S_IRWXU | S_IRWXG | S_IRWXO, 1, 8     },
        { "tty",        S_IFCHR | S_IRWXU | S_IRWXG | S_IRWXO, 5, 0     },
-       { "console",    S_IFCHR | S_IRUSR | S_IWUSR,           5, 1     },
 };
 
 static int lxc_fill_autodev(const struct lxc_rootfs *rootfs, bool 
mount_console)
@@ -1194,9 +1193,6 @@ static int lxc_fill_autodev(const struct lxc_rootfs 
*rootfs, bool mount_console)
        for (i = 0; i < sizeof(lxc_devs) / sizeof(lxc_devs[0]); i++) {
                const struct lxc_devs *d = &lxc_devs[i];
 
-               if (!strcmp(d->name, "console") && !mount_console)
-                       continue;
-
                ret = snprintf(path, MAXPATHLEN, "%s/dev/%s", rootfs->path ? 
rootfs->mount : "", d->name);
                if (ret < 0 || ret >= MAXPATHLEN)
                        return -1;

From 2c7cf14807de0c70a26b1b8365149af394732412 Mon Sep 17 00:00:00 2001
From: Christian Brauner <[email protected]>
Date: Mon, 8 May 2017 19:43:58 +0200
Subject: [PATCH 3/6] conf: non-functional changes lxc_setup()

Signed-off-by: Christian Brauner <[email protected]>
---
 src/lxc/conf.c | 4 +---
 1 file changed, 1 insertion(+), 3 deletions(-)

diff --git a/src/lxc/conf.c b/src/lxc/conf.c
index e3a73d6..8354fa6 100644
--- a/src/lxc/conf.c
+++ b/src/lxc/conf.c
@@ -4044,13 +4044,11 @@ int lxc_setup(struct lxc_handler *handler)
        }
 
        if (lxc_conf->autodev > 0) {
-               bool mount_console = lxc_conf->console.path && 
!strcmp(lxc_conf->console.path, "none");
-
                if (run_lxc_hooks(name, "autodev", lxc_conf, lxcpath, NULL)) {
                        ERROR("failed to run autodev hooks for container 
'%s'.", name);
                        return -1;
                }
-               if (lxc_fill_autodev(&lxc_conf->rootfs, mount_console)) {
+               if (lxc_fill_autodev(&lxc_conf->rootfs)) {
                        ERROR("failed to populate /dev in the container");
                        return -1;
                }

From ba9e9f98edf70b53c1ac2e188d5f3a16216ae8c0 Mon Sep 17 00:00:00 2001
From: Christian Brauner <[email protected]>
Date: Mon, 8 May 2017 20:01:22 +0200
Subject: [PATCH 4/6] conf: non-functional changes to console functions

Signed-off-by: Christian Brauner <[email protected]>
---
 src/lxc/conf.c | 90 ++++++++++++++++++++++++++++------------------------------
 1 file changed, 44 insertions(+), 46 deletions(-)

diff --git a/src/lxc/conf.c b/src/lxc/conf.c
index 8354fa6..120cee0 100644
--- a/src/lxc/conf.c
+++ b/src/lxc/conf.c
@@ -1484,23 +1484,21 @@ static int setup_personality(int persona)
        return 0;
 }
 
-static int setup_dev_console(const struct lxc_rootfs *rootfs,
-                        const struct lxc_console *console)
+static int lxc_setup_dev_console(const struct lxc_rootfs *rootfs,
+                                const struct lxc_console *console)
 {
        char path[MAXPATHLEN];
        int ret, fd;
 
        ret = snprintf(path, sizeof(path), "%s/dev/console", rootfs->mount);
-       if (ret >= sizeof(path)) {
-               ERROR("console path too long");
+       if (ret < 0 || (size_t)ret >= sizeof(path))
                return -1;
-       }
 
        fd = open(path, O_CREAT | O_EXCL, S_IXUSR | S_IXGRP | S_IXOTH);
        if (fd < 0) {
                if (errno != EEXIST) {
                        SYSERROR("failed to create console");
-                       return -1;
+                       return -errno;
                }
        } else {
                close(fd);
@@ -1512,57 +1510,56 @@ static int setup_dev_console(const struct lxc_rootfs 
*rootfs,
        }
 
        if (chmod(console->name, S_IXUSR | S_IXGRP | S_IXOTH)) {
-               SYSERROR("failed to set mode '0%o' to '%s'",
-                        S_IXUSR | S_IXGRP | S_IXOTH, console->name);
-               return -1;
+               SYSERROR("failed to set mode '0%o' to '%s'", S_IXUSR | S_IXGRP 
| S_IXOTH, console->name);
+               return -errno;
        }
 
-       if (safe_mount(console->name, path, "none", MS_BIND, 0, rootfs->mount)) 
{
+       if (safe_mount(console->name, path, "none", MS_BIND, 0, rootfs->mount) 
< 0) {
                ERROR("failed to mount '%s' on '%s'", console->name, path);
                return -1;
        }
 
-       INFO("console has been setup");
+       DEBUG("mounted pts device \"%s\" onto \"%s\"", console->name, path);
        return 0;
 }
 
-static int setup_ttydir_console(const struct lxc_rootfs *rootfs,
-                        const struct lxc_console *console,
-                        char *ttydir)
+static int lxc_setup_ttydir_console(const struct lxc_rootfs *rootfs,
+                                   const struct lxc_console *console,
+                                   char *ttydir)
 {
-       char path[MAXPATHLEN], lxcpath[MAXPATHLEN];
        int ret;
+       char path[MAXPATHLEN], lxcpath[MAXPATHLEN];
 
        /* create rootfs/dev/<ttydir> directory */
-       ret = snprintf(path, sizeof(path), "%s/dev/%s", rootfs->mount,
-                      ttydir);
-       if (ret >= sizeof(path))
+       ret = snprintf(path, sizeof(path), "%s/dev/%s", rootfs->mount, ttydir);
+       if (ret < 0 || (size_t)ret >= sizeof(path))
                return -1;
+
        ret = mkdir(path, 0755);
        if (ret && errno != EEXIST) {
                SYSERROR("failed with errno %d to create %s", errno, path);
-               return -1;
+               return -errno;
        }
-       INFO("created %s", path);
+       DEBUG("created directory for console and tty devices at \%s\"", path);
 
-       ret = snprintf(lxcpath, sizeof(lxcpath), "%s/dev/%s/console",
-                      rootfs->mount, ttydir);
-       if (ret >= sizeof(lxcpath)) {
-               ERROR("console path too long");
+       ret = snprintf(lxcpath, sizeof(lxcpath), "%s/dev/%s/console", 
rootfs->mount, ttydir);
+       if (ret < 0 || (size_t)ret >= sizeof(lxcpath))
+               return -1;
+
+       ret = snprintf(path, sizeof(path), "%s/dev/console", rootfs->mount);
+       if (ret < 0 || (size_t)ret >= sizeof(lxcpath))
                return -1;
-       }
 
-       snprintf(path, sizeof(path), "%s/dev/console", rootfs->mount);
        ret = unlink(path);
        if (ret && errno != ENOENT) {
-               SYSERROR("error unlinking %s", path);
-               return -1;
+               SYSERROR("error removing \"%s\"", path);
+               return -errno;
        }
 
        ret = creat(lxcpath, 0660);
-       if (ret==-1 && errno != EEXIST) {
+       if (ret == -1 && errno != EEXIST) {
                SYSERROR("error %d creating %s", errno, lxcpath);
-               return -1;
+               return -errno;
        }
        if (ret >= 0)
                close(ret);
@@ -1572,39 +1569,40 @@ static int setup_ttydir_console(const struct lxc_rootfs 
*rootfs,
                return 0;
        }
 
-       if (safe_mount(console->name, lxcpath, "none", MS_BIND, 0, 
rootfs->mount)) {
+       if (safe_mount(console->name, lxcpath, "none", MS_BIND, 0, 
rootfs->mount) < 0) {
                ERROR("failed to mount '%s' on '%s'", console->name, lxcpath);
                return -1;
        }
+       DEBUG("mounted \"%s\" onto \"%s\"", console->name, lxcpath);
 
        /* create symlink from rootfs/dev/console to 'lxc/console' */
        ret = snprintf(lxcpath, sizeof(lxcpath), "%s/console", ttydir);
-       if (ret >= sizeof(lxcpath)) {
-               ERROR("lxc/console path too long");
+       if (ret < 0 || (size_t)ret >= sizeof(lxcpath))
                return -1;
-       }
+
        ret = symlink(lxcpath, path);
-       if (ret) {
-               SYSERROR("failed to create symlink for console");
+       if (ret < 0) {
+               SYSERROR("failed to create symlink for console from \"%s\" to 
\"%s\"", lxcpath, path);
                return -1;
        }
 
-       INFO("console has been setup on %s", lxcpath);
-
+       DEBUG("console has been setup under \"%s\" and symlinked to \"%s\"", 
lxcpath, path);
        return 0;
 }
 
-static int setup_console(const struct lxc_rootfs *rootfs,
-                        const struct lxc_console *console,
-                        char *ttydir)
+static int lxc_setup_console(const struct lxc_rootfs *rootfs,
+                            const struct lxc_console *console, char *ttydir)
 {
-       /* We don't have a rootfs, /dev/console will be shared */
-       if (!rootfs->path)
+       /* We don't have a rootfs, /dev/console will be shared. */
+       if (!rootfs->path) {
+               DEBUG("/dev/console will be shared with the host");
                return 0;
+       }
+
        if (!ttydir)
-               return setup_dev_console(rootfs, console);
+               return lxc_setup_dev_console(rootfs, console);
 
-       return setup_ttydir_console(rootfs, console, ttydir);
+       return lxc_setup_ttydir_console(rootfs, console, ttydir);
 }
 
 static int setup_kmsg(const struct lxc_rootfs *rootfs,
@@ -4054,7 +4052,7 @@ int lxc_setup(struct lxc_handler *handler)
                }
        }
 
-       if (!lxc_conf->is_execute && setup_console(&lxc_conf->rootfs, 
&lxc_conf->console, lxc_conf->ttydir)) {
+       if (!lxc_conf->is_execute && lxc_setup_console(&lxc_conf->rootfs, 
&lxc_conf->console, lxc_conf->ttydir)) {
                ERROR("failed to setup the console for '%s'", name);
                return -1;
        }

From 04975e43869f576a6c207f34ed87b7cc3447ad9d Mon Sep 17 00:00:00 2001
From: Christian Brauner <[email protected]>
Date: Mon, 8 May 2017 21:11:58 +0200
Subject: [PATCH 5/6] conf: improve lxc_setup_dev_console()

In case the user did request a console to be set up unmount any prior
bind-mount for it.

Signed-off-by: Christian Brauner <[email protected]>
---
 src/lxc/conf.c | 35 +++++++++++++++++++++++++++++------
 1 file changed, 29 insertions(+), 6 deletions(-)

diff --git a/src/lxc/conf.c b/src/lxc/conf.c
index 120cee0..0ba854b 100644
--- a/src/lxc/conf.c
+++ b/src/lxc/conf.c
@@ -1171,7 +1171,7 @@ static const struct lxc_devs lxc_devs[] = {
        { "tty",        S_IFCHR | S_IRWXU | S_IRWXG | S_IRWXO, 5, 0     },
 };
 
-static int lxc_fill_autodev(const struct lxc_rootfs *rootfs, bool 
mount_console)
+static int lxc_fill_autodev(const struct lxc_rootfs *rootfs)
 {
        int ret;
        char path[MAXPATHLEN];
@@ -1490,10 +1490,38 @@ static int lxc_setup_dev_console(const struct 
lxc_rootfs *rootfs,
        char path[MAXPATHLEN];
        int ret, fd;
 
+       if (console->path && !strcmp(console->path, "none"))
+               return 0;
+
        ret = snprintf(path, sizeof(path), "%s/dev/console", rootfs->mount);
        if (ret < 0 || (size_t)ret >= sizeof(path))
                return -1;
 
+       /* When we are asked to setup a console we remove any previous
+        * /dev/console bind-mounts.
+        */
+       ret = umount(path);
+       if (ret < 0) {
+               if (errno != EINVAL && errno != ENOENT) {
+                       /* EINVAL: path is not a mountpoint
+                        * ENOENT: path does not exist
+                        * anything else means something weird is happening.
+                        */
+                       ERROR("failed to unmount \"%s\": %s", path, 
strerror(errno));
+                       return -errno;
+               }
+       } else {
+               DEBUG("unmounted console \"%s\"", path);
+       }
+       ret = unlink(path);
+       if (ret && errno != ENOENT) {
+               SYSERROR("error unlinking %s", path);
+               return -errno;
+       }
+
+       /* For unprivileged containers autodev or automounts will already have
+        * taken care of creating /dev/console.
+        */
        fd = open(path, O_CREAT | O_EXCL, S_IXUSR | S_IXGRP | S_IXOTH);
        if (fd < 0) {
                if (errno != EEXIST) {
@@ -1504,11 +1532,6 @@ static int lxc_setup_dev_console(const struct lxc_rootfs 
*rootfs,
                close(fd);
        }
 
-       if (console->master < 0) {
-               INFO("no console");
-               return 0;
-       }
-
        if (chmod(console->name, S_IXUSR | S_IXGRP | S_IXOTH)) {
                SYSERROR("failed to set mode '0%o' to '%s'", S_IXUSR | S_IXGRP 
| S_IXOTH, console->name);
                return -errno;

From 0c1d6669250bf9652d2a87fb1df9025cc0bf7e6a Mon Sep 17 00:00:00 2001
From: Christian Brauner <[email protected]>
Date: Mon, 8 May 2017 21:13:37 +0200
Subject: [PATCH 6/6] conf: lxc_setup_ttydir_console()

In case the user specified

lxc.console = none
lxc.devttydir = bla
lxc.mount.entry = /dev/console dev/console none bind,create=file 0 0

move the mount under /dev/bla/console

If he requested a mknod()ed /dev/console rename it to /dev/bla/console.

Signed-off-by: Christian Brauner <[email protected]>
---
 src/lxc/conf.c | 90 +++++++++++++++++++++++++++++++++++++++++++++-------------
 1 file changed, 71 insertions(+), 19 deletions(-)

diff --git a/src/lxc/conf.c b/src/lxc/conf.c
index 0ba854b..134f4d3 100644
--- a/src/lxc/conf.c
+++ b/src/lxc/conf.c
@@ -1569,16 +1569,6 @@ static int lxc_setup_ttydir_console(const struct 
lxc_rootfs *rootfs,
        if (ret < 0 || (size_t)ret >= sizeof(lxcpath))
                return -1;
 
-       ret = snprintf(path, sizeof(path), "%s/dev/console", rootfs->mount);
-       if (ret < 0 || (size_t)ret >= sizeof(lxcpath))
-               return -1;
-
-       ret = unlink(path);
-       if (ret && errno != ENOENT) {
-               SYSERROR("error removing \"%s\"", path);
-               return -errno;
-       }
-
        ret = creat(lxcpath, 0660);
        if (ret == -1 && errno != EEXIST) {
                SYSERROR("error %d creating %s", errno, lxcpath);
@@ -1587,22 +1577,84 @@ static int lxc_setup_ttydir_console(const struct 
lxc_rootfs *rootfs,
        if (ret >= 0)
                close(ret);
 
-       if (console->master < 0) {
-               INFO("no console");
-               return 0;
-       }
-
-       if (safe_mount(console->name, lxcpath, "none", MS_BIND, 0, 
rootfs->mount) < 0) {
-               ERROR("failed to mount '%s' on '%s'", console->name, lxcpath);
+       ret = snprintf(path, sizeof(path), "%s/dev/console", rootfs->mount);
+       if (ret < 0 || (size_t)ret >= sizeof(lxcpath))
                return -1;
+
+       /* When we are asked to setup a console we remove any previous
+        * /dev/console bind-mounts.
+        */
+       if (console->path && !strcmp(console->path, "none")) {
+               struct stat st;
+               ret = stat(path, &st);
+               if (ret < 0) {
+                       if (errno == ENOENT)
+                               return 0;
+                       SYSERROR("failed stat() \"%s\"", path);
+                       return -errno;
+               }
+
+               /* /dev/console must be character device with major number 5 and
+                * minor number 1. If not, give benefit of the doubt and assume
+                * the user has mounted something else right there on purpose.
+                */
+               if (((st.st_mode & S_IFMT) != S_IFCHR) || major(st.st_rdev) != 
5 || minor(st.st_rdev) != 1)
+                       return 0;
+
+               /* In case the user requested a bind-mount for /dev/console and
+                * requests a ttydir we move the mount to the
+                * /dev/<ttydir/console. If it is a character device created via
+                * mknod() we simply rename it.
+                */
+               ret = mount(path, lxcpath, "none", MS_MOVE, NULL);
+               if (ret < 0) {
+                       if (errno != EINVAL) {
+                               ERROR("failed to MS_MOVE \"%s\" to \"%s\": %s", 
path, lxcpath, strerror(errno));
+                               return -errno;
+                       }
+                       /* path was not a mountpoint */
+                       ret = rename(path, lxcpath);
+                       if (ret < 0) {
+                               ERROR("failed to rename \"%s\" to \"%s\": %s", 
path, lxcpath, strerror(errno));
+                               return -errno;
+                       }
+                       DEBUG("renamed \"%s\" to \"%s\"", path, lxcpath);
+               } else {
+                       DEBUG("moved mount \"%s\" to \"%s\"", path, lxcpath);
+               }
+       } else {
+               ret = umount(path);
+               if (ret < 0) {
+                       if (errno != EINVAL && errno != ENOENT) {
+                               /* EINVAL: path is not a mountpoint
+                                * ENOENT: path does not exist
+                                * anything else means something weird is 
happening.
+                                */
+                               ERROR("failed to unmount \"%s\": %s", path, 
strerror(errno));
+                               return -errno;
+                       }
+               } else {
+                       DEBUG("unmounted console \"%s\"", path);
+               }
+
+               if (safe_mount(console->name, lxcpath, "none", MS_BIND, 0, 
rootfs->mount) < 0) {
+                       ERROR("failed to mount '%s' on '%s'", console->name, 
lxcpath);
+                       return -1;
+               }
+               DEBUG("mounted \"%s\" onto \"%s\"", console->name, lxcpath);
        }
-       DEBUG("mounted \"%s\" onto \"%s\"", console->name, lxcpath);
 
-       /* create symlink from rootfs/dev/console to 'lxc/console' */
+       /* create symlink from rootfs /dev/console to '<ttydir>/console' */
        ret = snprintf(lxcpath, sizeof(lxcpath), "%s/console", ttydir);
        if (ret < 0 || (size_t)ret >= sizeof(lxcpath))
                return -1;
 
+       ret = unlink(path);
+       if (ret && errno != ENOENT) {
+               SYSERROR("error unlinking %s", path);
+               return -errno;
+       }
+
        ret = symlink(lxcpath, path);
        if (ret < 0) {
                SYSERROR("failed to create symlink for console from \"%s\" to 
\"%s\"", lxcpath, path);
_______________________________________________
lxc-devel mailing list
[email protected]
http://lists.linuxcontainers.org/listinfo/lxc-devel

Reply via email to