[lxc-devel] [PATCH 2/2] fill_autodev: bind-mount if mknod fails (v3)

Serge Hallyn serge.hallyn at ubuntu.com
Mon Jan 12 23:56:28 UTC 2015


First, rename setup_autodev to fill_autodev, since all it
does is populate it, not fully set it up.

Secondly, if mknod of a device fails, then try bind-mounting
it from the host rather than failing immediately.

Note that this isn't an urgent patch because the common.userns
configuration hook already specifies bind,create=file mount
entries for all the devices we would want.

Changelog (v3): ignore if /dev doesn't exist

Signed-off-by: Serge Hallyn <serge.hallyn at ubuntu.com>
---
 src/lxc/conf.c | 28 ++++++++++++++++++++++++----
 1 file changed, 24 insertions(+), 4 deletions(-)

diff --git a/src/lxc/conf.c b/src/lxc/conf.c
index dff5020..19efe72 100644
--- a/src/lxc/conf.c
+++ b/src/lxc/conf.c
@@ -1155,7 +1155,7 @@ static const struct lxc_devs lxc_devs[] = {
 	{ "console",	S_IFCHR | S_IRUSR | S_IWUSR,	       5, 1	},
 };
 
-static int setup_autodev(const char *root)
+static int fill_autodev(const char *root)
 {
 	int ret;
 	char path[MAXPATHLEN];
@@ -1170,6 +1170,9 @@ static int setup_autodev(const char *root)
 		return -1;
 	}
 
+	if (!dir_exists(path))  // ignore, just don't try to fill in
+		return 0;
+
 	INFO("Populating /dev under %s", root);
 	cmask = umask(S_IXUSR | S_IXGRP | S_IXOTH);
 	for (i = 0; i < sizeof(lxc_devs) / sizeof(lxc_devs[0]); i++) {
@@ -1179,8 +1182,25 @@ static int setup_autodev(const char *root)
 			return -1;
 		ret = mknod(path, d->mode, makedev(d->maj, d->min));
 		if (ret && errno != EEXIST) {
-			SYSERROR("Error creating %s", d->name);
-			return -1;
+			char hostpath[MAXPATHLEN];
+			FILE *pathfile;
+
+			// 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;
+			pathfile = fopen(path, "wb");
+			if (!pathfile) {
+				SYSERROR("Failed to create device mount target '%s'", path);
+				return -1;
+			}
+			fclose(pathfile);
+			if (mount(hostpath, path, 0, MS_BIND, NULL) != 0) {
+				SYSERROR("Failed bind mounting device %s from host into container",
+					d->name);
+				return -1;
+			}
 		}
 	}
 	umask(cmask);
@@ -3847,7 +3867,7 @@ int lxc_setup(struct lxc_handler *handler)
 			ERROR("failed to run autodev hooks for container '%s'.", name);
 			return -1;
 		}
-		if (setup_autodev(lxc_conf->rootfs.mount)) {
+		if (fill_autodev(lxc_conf->rootfs.mount)) {
 			ERROR("failed to populate /dev in the container");
 			return -1;
 		}
-- 
2.1.0



More information about the lxc-devel mailing list