]> git.ipfire.org Git - thirdparty/lxc.git/commitdiff
conf: lxc_setup_ttydir_console()
authorChristian Brauner <christian.brauner@ubuntu.com>
Mon, 8 May 2017 19:13:37 +0000 (21:13 +0200)
committerChristian Brauner <christian.brauner@ubuntu.com>
Tue, 9 May 2017 21:21:24 +0000 (23:21 +0200)
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 <christian.brauner@ubuntu.com>
src/lxc/conf.c

index 0ba854b47366fba84b328e8f1b2274653db76c5a..f17465015c520a9b39eeda13e376a1a29428cfd7 100644 (file)
@@ -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 = safe_mount(path, lxcpath, "none", MS_MOVE, NULL, rootfs->mount);
+               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);