From 5e6c303f9ead9f801b6b17cb1f4f97b7fae39509 Mon Sep 17 00:00:00 2001 From: Alban Crequy Date: Mon, 16 Mar 2015 15:16:22 +0100 Subject: [PATCH 1/4] stage1: prepare-app: prepare /sys for apps https://github.com/coreos/rocket/issues/606 --- stage1/rootfs/prepare-app/prepare-app.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/stage1/rootfs/prepare-app/prepare-app.c b/stage1/rootfs/prepare-app/prepare-app.c index d719369..5a3607a 100644 --- a/stage1/rootfs/prepare-app/prepare-app.c +++ b/stage1/rootfs/prepare-app/prepare-app.c @@ -38,6 +38,7 @@ int main(int argc, char *argv[]) "dev", "dev/net", "proc", + "sys", NULL }; static const char *devnodes[] = { @@ -117,5 +118,11 @@ int main(int argc, char *argv[]) "Path too long: \"%s\"", to); pexit_if(mount("/proc", to, "bind", MS_BIND, NULL) == -1, "Mounting /proc on \"%s\" failed", to); + + exit_if(snprintf(to, sizeof(to), "%s/sys", root) >= sizeof(to), + "Path too long: \"%s\"", to); + pexit_if(mount("/sys", to, "bind", MS_BIND, NULL) == -1, + "Mounting /sys on \"%s\" failed", to); + return EXIT_SUCCESS; } From deb079a16e13604291b23a4573f14794491fa605 Mon Sep 17 00:00:00 2001 From: Alban Crequy Date: Mon, 16 Mar 2015 17:31:58 +0100 Subject: [PATCH 2/4] stage1: prepare-app: make stage2's root a mount point It is needed to run Docker inside Rocket: https://github.com/coreos/rocket/issues/506 --- stage1/rootfs/prepare-app/prepare-app.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/stage1/rootfs/prepare-app/prepare-app.c b/stage1/rootfs/prepare-app/prepare-app.c index 5a3607a..9193d8f 100644 --- a/stage1/rootfs/prepare-app/prepare-app.c +++ b/stage1/rootfs/prepare-app/prepare-app.c @@ -66,6 +66,13 @@ int main(int argc, char *argv[]) pexit_if(rootfd < 0, "Failed to open directory \"%s\"", root); + /* Make stage2's root a mount point. Chrooting an application in a + * directory which is not a mount point is not nice because the + * application would not be able to remount "/" it as private mount. + * This allows Docker to run inside Rocket. */ + pexit_if(mount(root, root, "bind", MS_BIND, NULL) == -1, + "Make / a mount point failed"); + /* First, create the directories */ for (i = 0; dirs[i]; i++) { pexit_if(mkdirat(rootfd, dirs[i], 0755) == -1 && errno != EEXIST, From cf0028c11f2e0125c4c8eae955304ee78700c252 Mon Sep 17 00:00:00 2001 From: Alban Crequy Date: Mon, 16 Mar 2015 17:36:29 +0100 Subject: [PATCH 3/4] stage1: prepare-app: prepare /dev/shm for apps Docker needs /dev/shm: https://github.com/coreos/rocket/issues/506 --- stage1/rootfs/prepare-app/prepare-app.c | 17 +++++++++++++---- 1 file changed, 13 insertions(+), 4 deletions(-) diff --git a/stage1/rootfs/prepare-app/prepare-app.c b/stage1/rootfs/prepare-app/prepare-app.c index 9193d8f..dda128a 100644 --- a/stage1/rootfs/prepare-app/prepare-app.c +++ b/stage1/rootfs/prepare-app/prepare-app.c @@ -37,6 +37,7 @@ int main(int argc, char *argv[]) static const char *dirs[] = { "dev", "dev/net", + "dev/shm", "proc", "sys", NULL @@ -62,10 +63,6 @@ int main(int argc, char *argv[]) root = argv[1]; - rootfd = open(root, O_DIRECTORY | O_CLOEXEC); - pexit_if(rootfd < 0, - "Failed to open directory \"%s\"", root); - /* Make stage2's root a mount point. Chrooting an application in a * directory which is not a mount point is not nice because the * application would not be able to remount "/" it as private mount. @@ -73,6 +70,10 @@ int main(int argc, char *argv[]) pexit_if(mount(root, root, "bind", MS_BIND, NULL) == -1, "Make / a mount point failed"); + rootfd = open(root, O_DIRECTORY | O_CLOEXEC); + pexit_if(rootfd < 0, + "Failed to open directory \"%s\"", root); + /* First, create the directories */ for (i = 0; dirs[i]; i++) { pexit_if(mkdirat(rootfd, dirs[i], 0755) == -1 && errno != EEXIST, @@ -121,15 +122,23 @@ int main(int argc, char *argv[]) "Mounting \"%s\" on \"%s\" failed", from, to); } + /* /proc */ exit_if(snprintf(to, sizeof(to), "%s/proc", root) >= sizeof(to), "Path too long: \"%s\"", to); pexit_if(mount("/proc", to, "bind", MS_BIND, NULL) == -1, "Mounting /proc on \"%s\" failed", to); + /* /sys */ exit_if(snprintf(to, sizeof(to), "%s/sys", root) >= sizeof(to), "Path too long: \"%s\"", to); pexit_if(mount("/sys", to, "bind", MS_BIND, NULL) == -1, "Mounting /sys on \"%s\" failed", to); + /* /dev/shm */ + exit_if(snprintf(to, sizeof(to), "%s/dev/shm", root) >= sizeof(to), + "Path too long: \"%s\"", to); + pexit_if(mount("/dev/shm", to, "bind", MS_BIND, NULL) == -1, + "Mounting /dev/shm on \"%s\" failed", to); + return EXIT_SUCCESS; } From f70c4e8d0732436d7bd0af77d3a56e92b47677f6 Mon Sep 17 00:00:00 2001 From: Alban Crequy Date: Tue, 17 Mar 2015 11:44:23 +0100 Subject: [PATCH 4/4] stage1: prepare-app: unlink /dev/shm symlink when it exists --- stage1/rootfs/prepare-app/prepare-app.c | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) diff --git a/stage1/rootfs/prepare-app/prepare-app.c b/stage1/rootfs/prepare-app/prepare-app.c index dda128a..5936526 100644 --- a/stage1/rootfs/prepare-app/prepare-app.c +++ b/stage1/rootfs/prepare-app/prepare-app.c @@ -34,6 +34,10 @@ static int exit_err; int main(int argc, char *argv[]) { + static const char *unlink_paths[] = { + "dev/shm", + NULL + }; static const char *dirs[] = { "dev", "dev/net", @@ -74,11 +78,22 @@ int main(int argc, char *argv[]) pexit_if(rootfd < 0, "Failed to open directory \"%s\"", root); - /* First, create the directories */ + /* Some images have annoying symlinks that are resolved as dangling + * links before the chroot in stage1. E.g. "/dev/shm" -> "/run/shm" + * Just remove the symlinks. + */ + for (i = 0; unlink_paths[i]; i++) { + pexit_if(unlinkat(rootfd, unlink_paths[i], 0) != 0 + && errno != ENOENT && errno != EISDIR, + "Failed to unlink \"%s\"", unlink_paths[i]) + } + + /* Create the directories */ for (i = 0; dirs[i]; i++) { pexit_if(mkdirat(rootfd, dirs[i], 0755) == -1 && errno != EEXIST, "Failed to create directory \"%s/%s\"", root, dirs[i]); } + close(rootfd); /* systemd-nspawn already creates few /dev entries in the container