[lxc-devel] [PATCH 1/1] always check whether rootfs is shared
Serge Hallyn
serge.hallyn at ubuntu.com
Tue Feb 25 05:08:26 UTC 2014
(this expands on Dwight's recent patch, commit c597baa8f9)
After unshare(CLONE_NEWNS) and before doing any mounting, always
check whether rootfs is shared. Otherwise template runs or clone
scripts can bleed mount activity to the host.
Signed-off-by: Serge Hallyn <serge.hallyn at ubuntu.com>
---
src/lxc/attach.c | 7 +++++++
src/lxc/bdev.c | 7 +++++++
src/lxc/conf.c | 40 ----------------------------------------
src/lxc/lxc_usernsexec.c | 7 +++++++
src/lxc/lxccontainer.c | 6 ++++++
src/lxc/utils.c | 40 ++++++++++++++++++++++++++++++++++++++++
src/lxc/utils.h | 2 ++
7 files changed, 69 insertions(+), 40 deletions(-)
diff --git a/src/lxc/attach.c b/src/lxc/attach.c
index f12d216..9136ec2 100644
--- a/src/lxc/attach.c
+++ b/src/lxc/attach.c
@@ -220,6 +220,13 @@ static int lxc_attach_remount_sys_proc(void)
return -1;
}
+ if (detect_shared_rootfs()) {
+ if (mount(NULL, "/", NULL, MS_SLAVE|MS_REC, NULL)) {
+ SYSERROR("Failed to make / rslave to run rsync");
+ ERROR("Continuing...");
+ }
+ }
+
/* assume /proc is always mounted, so remount it */
ret = umount2("/proc", MNT_DETACH);
if (ret < 0) {
diff --git a/src/lxc/bdev.c b/src/lxc/bdev.c
index 952cfeb..40f70c5 100644
--- a/src/lxc/bdev.c
+++ b/src/lxc/bdev.c
@@ -302,6 +302,13 @@ static int detect_fs(struct bdev *bdev, char *type, int len)
if (unshare(CLONE_NEWNS) < 0)
exit(1);
+ if (detect_shared_rootfs()) {
+ if (mount(NULL, "/", NULL, MS_SLAVE|MS_REC, NULL)) {
+ SYSERROR("Failed to make / rslave to run rsync");
+ ERROR("Continuing...");
+ }
+ }
+
ret = mount_unknown_fs(srcdev, bdev->dest, bdev->mntopts);
if (ret < 0) {
ERROR("failed mounting %s onto %s to detect fstype", srcdev, bdev->dest);
diff --git a/src/lxc/conf.c b/src/lxc/conf.c
index c9dd7ac..fc39897 100644
--- a/src/lxc/conf.c
+++ b/src/lxc/conf.c
@@ -1427,46 +1427,6 @@ static int setup_autodev(const char *root)
}
/*
- * Detect whether / is mounted MS_SHARED. The only way I know of to
- * check that is through /proc/self/mountinfo.
- * I'm only checking for /. If the container rootfs or mount location
- * is MS_SHARED, but not '/', then you're out of luck - figuring that
- * out would be too much work to be worth it.
- */
-#define LINELEN 4096
-int detect_shared_rootfs(void)
-{
- char buf[LINELEN], *p;
- FILE *f;
- int i;
- char *p2;
-
- f = fopen("/proc/self/mountinfo", "r");
- if (!f)
- return 0;
- while (fgets(buf, LINELEN, f)) {
- for (p = buf, i=0; p && i < 4; i++)
- p = index(p+1, ' ');
- if (!p)
- continue;
- p2 = index(p+1, ' ');
- if (!p2)
- continue;
- *p2 = '\0';
- if (strcmp(p+1, "/") == 0) {
- // this is '/'. is it shared?
- p = index(p2+1, ' ');
- if (p && strstr(p, "shared:")) {
- fclose(f);
- return 1;
- }
- }
- }
- fclose(f);
- return 0;
-}
-
-/*
* I'll forgive you for asking whether all of this is needed :) The
* answer is yes.
* pivot_root will fail if the new root, the put_old dir, or the parent
diff --git a/src/lxc/lxc_usernsexec.c b/src/lxc/lxc_usernsexec.c
index e40fa53..6784633 100644
--- a/src/lxc/lxc_usernsexec.c
+++ b/src/lxc/lxc_usernsexec.c
@@ -35,6 +35,7 @@
#include <fcntl.h>
#include <sys/stat.h>
#include <sys/types.h>
+#include <sys/mount.h>
#include <sys/wait.h>
#include <sched.h>
#include <pwd.h>
@@ -111,6 +112,12 @@ static int do_child(void *vargv)
perror("unshare CLONE_NEWNS");
return -1;
}
+ if (detect_shared_rootfs()) {
+ if (mount(NULL, "/", NULL, MS_SLAVE|MS_REC, NULL)) {
+ printf("Failed to make / rslave to run rsync");
+ return -1;
+ }
+ }
execvp(argv[0], argv);
perror("execvpe");
return -1;
diff --git a/src/lxc/lxccontainer.c b/src/lxc/lxccontainer.c
index 0d89d11..8eb2d8b 100644
--- a/src/lxc/lxccontainer.c
+++ b/src/lxc/lxccontainer.c
@@ -2502,6 +2502,12 @@ static int clone_update_rootfs(struct clone_update_data *data)
bdev_put(bdev);
return -1;
}
+ if (detect_shared_rootfs()) {
+ if (mount(NULL, "/", NULL, MS_SLAVE|MS_REC, NULL)) {
+ SYSERROR("Failed to make / rslave to run rsync");
+ ERROR("Continuing...");
+ }
+ }
if (bdev->ops->mount(bdev) < 0) {
bdev_put(bdev);
return -1;
diff --git a/src/lxc/utils.c b/src/lxc/utils.c
index 52e4c86..da7c3b4 100644
--- a/src/lxc/utils.c
+++ b/src/lxc/utils.c
@@ -1194,3 +1194,43 @@ uint64_t fnv_64a_buf(void *buf, size_t len, uint64_t hval)
return hval;
}
+
+/*
+ * Detect whether / is mounted MS_SHARED. The only way I know of to
+ * check that is through /proc/self/mountinfo.
+ * I'm only checking for /. If the container rootfs or mount location
+ * is MS_SHARED, but not '/', then you're out of luck - figuring that
+ * out would be too much work to be worth it.
+ */
+#define LINELEN 4096
+int detect_shared_rootfs(void)
+{
+ char buf[LINELEN], *p;
+ FILE *f;
+ int i;
+ char *p2;
+
+ f = fopen("/proc/self/mountinfo", "r");
+ if (!f)
+ return 0;
+ while (fgets(buf, LINELEN, f)) {
+ for (p = buf, i=0; p && i < 4; i++)
+ p = index(p+1, ' ');
+ if (!p)
+ continue;
+ p2 = index(p+1, ' ');
+ if (!p2)
+ continue;
+ *p2 = '\0';
+ if (strcmp(p+1, "/") == 0) {
+ // this is '/'. is it shared?
+ p = index(p2+1, ' ');
+ if (p && strstr(p, "shared:")) {
+ fclose(f);
+ return 1;
+ }
+ }
+ }
+ fclose(f);
+ return 0;
+}
diff --git a/src/lxc/utils.h b/src/lxc/utils.h
index f6f3373..dcf0e34 100644
--- a/src/lxc/utils.h
+++ b/src/lxc/utils.h
@@ -276,3 +276,5 @@ extern bool dir_exists(const char *path);
#define FNV1A_64_INIT ((uint64_t)0xcbf29ce484222325ULL)
uint64_t fnv_64a_buf(void *buf, size_t len, uint64_t hval);
#endif
+
+int detect_shared_rootfs(void);
--
1.9.0
More information about the lxc-devel
mailing list