[lxc-devel] [lxcfs/master] lxcfs on ramfs
brauner on Github
lxc-bot at linuxcontainers.org
Sun Sep 4 16:39:20 UTC 2016
A non-text attachment was scrubbed...
Name: not available
Type: text/x-mailbox
Size: 934 bytes
Desc: not available
URL: <http://lists.linuxcontainers.org/pipermail/lxc-devel/attachments/20160904/4dfbdf7c/attachment.bin>
-------------- next part --------------
From 9601d540c0f5a0ebfc71491356b6ca6226f161ef Mon Sep 17 00:00:00 2001
From: Christian Brauner <christian.brauner at mailbox.org>
Date: Sun, 4 Sep 2016 17:33:09 +0200
Subject: [PATCH 1/3] bindings: add function to check fs type
We use statfs directly because statvfs proved unreliable in my testing. It's
f_fsid field does not seem to work correctly with linux/magic.h macros.
Signed-off-by: Christian Brauner <christian.brauner at mailbox.org>
---
bindings.c | 7 +++++++
1 file changed, 7 insertions(+)
diff --git a/bindings.c b/bindings.c
index ac88f48..be2b163 100644
--- a/bindings.c
+++ b/bindings.c
@@ -22,6 +22,7 @@
#include <time.h>
#include <unistd.h>
#include <wait.h>
+#include <linux/magic.h>
#include <linux/sched.h>
#include <sys/epoll.h>
#include <sys/mman.h>
@@ -29,6 +30,7 @@
#include <sys/param.h>
#include <sys/socket.h>
#include <sys/syscall.h>
+#include <sys/vfs.h>
#include "bindings.h"
#include "config.h" // for VERSION
@@ -4149,6 +4151,11 @@ static bool umount_if_mounted(void)
return true;
}
+bool has_fs_type(const struct statfs *fs, __fsword_t magic_val)
+{
+ return (fs->f_type == (__fsword_t)magic_val);
+}
+
static int pivot_enter(void)
{
int ret = -1, oldroot = -1, newroot = -1;
From a61c06a971a7e8861dd9c0714f7039eabce01a18 Mon Sep 17 00:00:00 2001
From: Christian Brauner <christian.brauner at mailbox.org>
Date: Sun, 4 Sep 2016 17:42:22 +0200
Subject: [PATCH 2/3] bindings: agnostic naming
- non-functional changes
Signed-off-by: Christian Brauner <christian.brauner at mailbox.org>
---
bindings.c | 13 +++++++------
1 file changed, 7 insertions(+), 6 deletions(-)
diff --git a/bindings.c b/bindings.c
index be2b163..9ff6c1f 100644
--- a/bindings.c
+++ b/bindings.c
@@ -4156,7 +4156,7 @@ bool has_fs_type(const struct statfs *fs, __fsword_t magic_val)
return (fs->f_type == (__fsword_t)magic_val);
}
-static int pivot_enter(void)
+static int permute_and_enter(void)
{
int ret = -1, oldroot = -1, newroot = -1;
@@ -4214,7 +4214,7 @@ static int pivot_enter(void)
}
/* Prepare our new clean root. */
-static int pivot_prepare(void)
+static int permute_prepare(void)
{
if (mkdir(ROOTDIR, 0700) < 0 && errno != EEXIST) {
lxcfs_error("%s\n", "Failed to create directory for new root.");
@@ -4239,14 +4239,15 @@ static int pivot_prepare(void)
return 0;
}
-static bool pivot_new_root(void)
+/* Calls chroot() on ramfs, pivot_root() in all other cases. */
+static bool permute_root(void)
{
/* Prepare new root. */
- if (pivot_prepare() < 0)
+ if (permute_prepare() < 0)
return false;
/* Pivot into new root. */
- if (pivot_enter() < 0)
+ if (permute_and_enter() < 0)
return false;
return true;
@@ -4330,7 +4331,7 @@ static bool cgfs_setup_controllers(void)
return false;
}
- if (!pivot_new_root())
+ if (!permute_root())
return false;
return true;
From 80b1bee81320195c7dd1893953519d76e4c1d054 Mon Sep 17 00:00:00 2001
From: Christian Brauner <christian.brauner at mailbox.org>
Date: Sun, 4 Sep 2016 18:07:01 +0200
Subject: [PATCH 3/3] bindings: use chroot() on ramfs
- Detect whether we are on a ramfs. We first try via statfs and check for
RAMFS_MAGIC. This may report TMPFS_MAGIC although it should better report
RAMFS_MAGIC. In this case, parse /proc/self/mountinfo and check for
- rootfs rootfs
like we do in LXC.
- When we are on ramfs use chroot(), otherwise use pivot_root().
Signed-off-by: Christian Brauner <christian.brauner at mailbox.org>
---
bindings.c | 150 +++++++++++++++++++++++++++++++++++++++++++++++--------------
1 file changed, 117 insertions(+), 33 deletions(-)
diff --git a/bindings.c b/bindings.c
index 9ff6c1f..c27a9d3 100644
--- a/bindings.c
+++ b/bindings.c
@@ -4151,14 +4151,118 @@ static bool umount_if_mounted(void)
return true;
}
-bool has_fs_type(const struct statfs *fs, __fsword_t magic_val)
+/*
+ * looking at fs/proc_namespace.c, it appears we can
+ * actually expect the rootfs entry to very specifically contain
+ * " - rootfs rootfs "
+ * IIUC, so long as we've chrooted so that rootfs is not our root,
+ * the rootfs entry should always be skipped in mountinfo contents.
+ */
+static bool is_on_ramfs(void)
+{
+ FILE *f;
+ char *p, *p2;
+ char *line = NULL;
+ size_t len = 0;
+ int i;
+
+ f = fopen("/proc/self/mountinfo", "r");
+ if (!f)
+ return false;
+
+ while (getline(&line, &len, f) != -1) {
+ for (p = line, i = 0; p && i < 4; i++)
+ p = strchr(p + 1, ' ');
+ if (!p)
+ continue;
+ p2 = strchr(p + 1, ' ');
+ if (!p2)
+ continue;
+ *p2 = '\0';
+ if (strcmp(p + 1, "/") == 0) {
+ // this is '/'. is it the ramfs?
+ p = strchr(p2 + 1, '-');
+ if (p && strncmp(p, "- rootfs rootfs ", 16) == 0) {
+ fclose(f);
+ return true;
+ }
+ }
+ }
+ fclose(f);
+ return false;
+}
+
+static bool has_fs_type(const struct statfs *fs, __fsword_t magic_val)
{
return (fs->f_type == (__fsword_t)magic_val);
}
+static int pivot_enter(const int oldroot, const int newroot)
+{
+ /* pivot_root into our new root fs */
+ if (pivot_root(".", ".") < 0) {
+ lxcfs_error("pivot_root() syscall failed: %s.\n", strerror(errno));
+ return -1;
+ }
+
+ /*
+ * At this point the old-root is mounted on top of our new-root.
+ * To unmounted it we must not be chdir'd into it, so escape back
+ * to the old-root.
+ */
+ if (fchdir(oldroot) < 0) {
+ lxcfs_error("%s\n", "Failed to enter old root.");
+ return -1;
+ }
+
+ if (umount2(".", MNT_DETACH) < 0) {
+ lxcfs_error("%s\n", "Failed to detach old root.");
+ return -1;
+ }
+
+ if (fchdir(newroot) < 0) {
+ lxcfs_error("%s\n", "Failed to re-enter new root.");
+ return -1;
+ }
+
+ return 0;
+}
+
+static int chroot_enter()
+{
+ if (mount(ROOTDIR, "/", NULL, MS_REC | MS_BIND, NULL)) {
+ lxcfs_error("Failed to recursively bind-mount %s into /.", ROOTDIR);
+ return -1;
+ }
+
+ if (chroot(".") < 0) {
+ lxcfs_error("Call to chroot() failed: %s.\n", strerror(errno));
+ return -1;
+ }
+
+ if (chdir("/") < 0) {
+ lxcfs_error("Failed to change directory: %s.\n", strerror(errno));
+ return -1;
+ }
+
+ return 0;
+}
+
static int permute_and_enter(void)
{
int ret = -1, oldroot = -1, newroot = -1;
+ struct statfs sb;
+
+ if (statfs("/", &sb) < 0) {
+ lxcfs_error("%s\n", "Could not stat / mountpoint.");
+ return 1;
+ }
+
+ /* has_fs_type() is not reliable. When the ramfs is a tmpfs it will
+ * likely report TMPFS_MAGIC. Hence, when it reports no we still check
+ * /proc/1/mountinfo. */
+ if (has_fs_type(&sb, RAMFS_MAGIC) || is_on_ramfs())
+ return chroot_enter();
oldroot = open("/", O_DIRECTORY | O_RDONLY);
if (oldroot < 0) {
@@ -4178,28 +4282,8 @@ static int permute_and_enter(void)
goto err;
}
- /* pivot_root into our new root fs */
- if (pivot_root(".", ".") < 0) {
- lxcfs_error("pivot_root() syscall failed: %s.\n", strerror(errno));
- goto err;
- }
-
- /*
- * At this point the old-root is mounted on top of our new-root.
- * To unmounted it we must not be chdir'd into it, so escape back
- * to the old-root.
- */
- if (fchdir(oldroot) < 0) {
- lxcfs_error("%s\n", "Failed to enter old root.");
- goto err;
- }
- if (umount2(".", MNT_DETACH) < 0) {
- lxcfs_error("%s\n", "Failed to detach old root.");
- goto err;
- }
-
- if (fchdir(newroot) < 0) {
- lxcfs_error("%s\n", "Failed to re-enter new root.");
+ if (pivot_enter(oldroot, newroot) < 0) {
+ lxcfs_error("%s\n", "Could not perform pivot root.");
goto err;
}
@@ -4216,6 +4300,16 @@ static int permute_and_enter(void)
/* Prepare our new clean root. */
static int permute_prepare(void)
{
+ if (mount(NULL, "/", NULL, MS_REC | MS_PRIVATE, 0) < 0) {
+ lxcfs_error("Failed to remount / private: %s.\n", strerror(errno));
+ return false;
+ }
+
+ if (mount("tmpfs", BASEDIR, "tmpfs", 0, "size=100000,mode=700") < 0) {
+ lxcfs_error("%s\n", "Failed to mount tmpfs over lxcfs cgroup mountpoint.");
+ return false;
+ }
+
if (mkdir(ROOTDIR, 0700) < 0 && errno != EEXIST) {
lxcfs_error("%s\n", "Failed to create directory for new root.");
return -1;
@@ -4270,16 +4364,6 @@ static bool setup_cgfs_dir(void)
return false;
}
- if (mount(NULL, "/", NULL, MS_REC | MS_PRIVATE, 0) < 0) {
- lxcfs_error("Failed to remount / private: %s.\n", strerror(errno));
- return false;
- }
-
- if (mount("tmpfs", BASEDIR, "tmpfs", 0, "size=100000,mode=700") < 0) {
- lxcfs_error("%s\n", "Failed to mount tmpfs over lxcfs cgroup mountpoint.");
- return false;
- }
-
return true;
}
More information about the lxc-devel
mailing list