lxc/0012-mount-make-possible-to-bind-mount-proc-and-sys-fs.patch
lifeng68 d05d52b196 mount: make possible to bind mount /proc and /sys/fs
1. add check whether have /proc mounts entry, if has, skip the auto mount proc
2. mount cgroup before do mount entrys
3. pass if the mount on top of /proc and the source of the mount is a proc filesystem

Signed-off-by: lifeng68 <lifeng68@huawei.com>
2020-11-27 16:34:43 +08:00

205 lines
6.5 KiB
Diff

From 53ca847c8d21b1e422745a221d49ddf61679d4dd Mon Sep 17 00:00:00 2001
From: lifeng68 <lifeng68@huawei.com>
Date: Fri, 27 Nov 2020 16:02:25 +0800
Subject: [PATCH] mount: make possible to bind mount /proc and /sys/fs
1. add check whether have /proc mounts entry, if has, skip the auto
mount proc
2. mount cgroup before do mount entrys
3. pass if the mount on top of /proc and the source of the mount is a proc filesystem
Signed-off-by: lifeng68 <lifeng68@huawei.com>
---
src/lxc/conf.c | 95 +++++++++++++++++++++++++++++++++++++++++++++++---
src/lxc/path.c | 2 +-
2 files changed, 92 insertions(+), 5 deletions(-)
diff --git a/src/lxc/conf.c b/src/lxc/conf.c
index ce5bab9c5..c3610ae33 100644
--- a/src/lxc/conf.c
+++ b/src/lxc/conf.c
@@ -2581,7 +2581,7 @@ retry:
/* isulad: checkMountDestination checks to ensure that the mount destination is not over the top of /proc.
* dest is required to be an abs path and have any symlinks resolved before calling this function. */
-static int check_mount_destination(const char *rootfs, const char *dest)
+static int check_mount_destination(const char *rootfs, const char *dest, const char *src)
{
const char *invalid_destinations[] = {
"/proc",
@@ -2641,10 +2641,28 @@ static int check_mount_destination(const char *rootfs, const char *dest)
return -1;
}
relpath = path_relative(fullpath, dest);
+ DEBUG("dst path %s get relative path %s with full path %s,src:%s", dest, relpath, fullpath, src);
free(fullpath);
- if (!relpath)
+ if (!relpath) {
+ ERROR("Failed to get relpath for %s related to %s", dest, fullpath);
return -1;
- if (!strcmp(relpath, ".") || strncmp(relpath, "..", 2)) {
+ }
+ // pass if the mount path is outside of invalid proc
+ if (strncmp(relpath, "..", 2) == 0) {
+ free(relpath);
+ continue;
+ }
+ if (strcmp(relpath, ".") == 0) {
+ if (src == NULL) {
+ free(relpath);
+ continue;
+ }
+ // pass if the mount on top of /proc and the source of the mount is a proc filesystem
+ if (has_fs_type(src, PROC_SUPER_MAGIC)) {
+ WARN("src %s is proc allow mount on-top of %s", src, *invalid);
+ free(relpath);
+ continue;
+ }
ERROR("%s cannot be mounted because it is located inside %s", dest, *invalid);
free(relpath);
return -1;
@@ -2706,7 +2724,7 @@ static inline int mount_entry_on_generic(struct mntent *mntent,
}
dest = rpath;
- ret = check_mount_destination(rootfs_path, dest);
+ ret = check_mount_destination(rootfs_path, dest, mntent->mnt_fsname);
if (ret) {
ERROR("Mount destination is invalid: '%s'", dest);
lxc_write_error_message(rootfs->errfd, "%s:%d: mount destination is invalid: '%s'.",
@@ -3119,6 +3137,52 @@ static bool need_setup_dev(const struct lxc_conf *conf, struct lxc_list *mount)
return true;
}
}
+
+static bool have_proc_bind_mount_entry(FILE *file)
+{
+ bool have_bind_proc = false;
+ char buf[PATH_MAX] = { 0 };
+ struct mntent mntent;
+
+ while (getmntent_r(file, &mntent, buf, sizeof(buf))) {
+ mntent.mnt_dir = lxc_string_replace(SPACE_MAGIC_STR, " ", mntent.mnt_dir);
+ if(mntent.mnt_dir == NULL) {
+ SYSERROR("memory allocation error");
+ continue;
+ }
+
+ DEBUG("parsed mnt %s, %s, %s", mntent.mnt_fsname, mntent.mnt_dir, mntent.mnt_type);
+
+ if (strcmp(mntent.mnt_dir, "proc") == 0 && strcmp(mntent.mnt_type, "bind") == 0) {
+ have_bind_proc = true;
+ }
+
+ free(mntent.mnt_dir);
+ mntent.mnt_dir = NULL;
+
+ if (have_bind_proc)
+ return true;
+ }
+
+ return false;
+}
+
+// returns true if /proc needs to be set up.
+static bool need_setup_proc(const struct lxc_conf *conf, struct lxc_list *mount)
+{
+ __do_fclose FILE *f = NULL;
+
+ f = make_anonymous_mount_file(mount, conf->lsm_aa_allow_nesting);
+ if (f == NULL)
+ return true;
+
+ if (have_proc_bind_mount_entry(f)) {
+ return false;
+ } else {
+ return true;
+ }
+}
+
#endif
static int parse_cap(const char *cap)
@@ -4870,6 +4934,7 @@ int lxc_setup(struct lxc_handler *handler)
char *keyring_context = NULL;
#ifdef HAVE_ISULAD
bool setup_dev = true;
+ bool setup_proc = true;
#endif
ret = lxc_setup_rootfs_prepare_root(lxc_conf, name, lxcpath);
@@ -4930,6 +4995,17 @@ int lxc_setup(struct lxc_handler *handler)
ret = lxc_mount_auto_mounts(lxc_conf, lxc_conf->auto_mounts & ~LXC_AUTO_CGROUP_MASK, handler);
if (ret < 0)
return log_error(-1, "Failed to setup first automatic mounts");
+
+#ifdef HAVE_ISULAD
+ /* Now mount only cgroups, if wanted. Before, /sys could not have been
+ * mounted. It is guaranteed to be mounted now either through
+ * automatically or via fstab entries.
+ */
+ ret = lxc_mount_auto_mounts(lxc_conf, lxc_conf->auto_mounts & LXC_AUTO_CGROUP_MASK, handler);
+ if (ret < 0)
+ return log_error(-1, "Failed to setup remaining automatic mounts");
+#endif
+
#ifdef HAVE_ISULAD
ret = setup_mount(lxc_conf, &lxc_conf->rootfs, lxc_conf->fstab, name, lxcpath, lxc_conf->lsm_se_mount_context);
#else
@@ -4950,6 +5026,7 @@ int lxc_setup(struct lxc_handler *handler)
return log_error(-1, "Failed to setup mount entries");
#ifdef HAVE_ISULAD
setup_dev = need_setup_dev(lxc_conf, &lxc_conf->mount_list);
+ setup_proc = need_setup_proc(lxc_conf, &lxc_conf->mount_list);
#endif
}
@@ -4975,6 +5052,7 @@ int lxc_setup(struct lxc_handler *handler)
}
}
+#ifndef HAVE_ISULAD
/* Now mount only cgroups, if wanted. Before, /sys could not have been
* mounted. It is guaranteed to be mounted now either through
* automatically or via fstab entries.
@@ -4982,6 +5060,7 @@ int lxc_setup(struct lxc_handler *handler)
ret = lxc_mount_auto_mounts(lxc_conf, lxc_conf->auto_mounts & LXC_AUTO_CGROUP_MASK, handler);
if (ret < 0)
return log_error(-1, "Failed to setup remaining automatic mounts");
+#endif
ret = run_lxc_hooks(name, "mount", lxc_conf, NULL);
if (ret < 0)
@@ -5026,9 +5105,17 @@ int lxc_setup(struct lxc_handler *handler)
if (ret < 0)
return log_error(-1, "Failed to setup \"/dev\" symlinks");
+#ifdef HAVE_ISULAD
+ if (setup_proc) {
+ ret = lxc_create_tmp_proc_mount(lxc_conf);
+ if (ret < 0)
+ return log_error(-1, "Failed to \"/proc\" LSMs");
+ }
+#else
ret = lxc_create_tmp_proc_mount(lxc_conf);
if (ret < 0)
return log_error(-1, "Failed to \"/proc\" LSMs");
+#endif
#ifdef HAVE_ISULAD
/* Ask father to run oci prestart hooks and wait for him to finish. */
diff --git a/src/lxc/path.c b/src/lxc/path.c
index 65b8aadbf..46256cb26 100644
--- a/src/lxc/path.c
+++ b/src/lxc/path.c
@@ -652,4 +652,4 @@ char *path_relative(const char *basepath, const char *targpath)
}
return safe_strdup(targ + t0);
-}
+}
\ No newline at end of file
--
2.25.1