[lxc-devel] [PATCH] Update absolute paths for overlay and aufs mounts
Christian Brauner
christianvanbrauner at gmail.com
Fri Oct 9 12:50:44 UTC 2015
When using overlay and aufs mounts with lxc.mount.entry users have to specify
absolute paths for upperdir and workdir which will then get created
automatically by mount_entry_create_overlay_dirs() and
mount_entry_create_aufs_dirs() in conf.c. When we clone a container with
overlay or aufs lxc.mount.entry entries we need to update these absolute paths.
In order to do this we add the function update_union_mount_entry_paths() in
lxccontainer.c. The function operates on c->lxc_conf->unexpanded_config instead
of the intuitively plausible c->lxc_conf->mount_list because the latter also
contains mounts from other files as well as generic mounts.
NOTE: This function does not sanitize paths apart from removing trailing
slashes. (So when a user specifies //home//someone/// it will be cleaned to
//home//someone. This is the minimal path cleansing which is also done by
lxc_container_new().) But the mount_entry_create_overlay_dirs() and
mount_entry_create_aufs_dirs() functions both try to be extremely strict about
when to create upperdirs and workdirs. They will only accept sanitized paths,
i.e. they require /home/someone. I think this is a (safety) virtue and we
should consider sanitizing paths in general. In short:
update_union_mount_entry_paths() does update all absolute paths to the new
container but mount_entry_create_overlay_dirs() and
mount_entry_create_aufs_dirs() will still refuse to create upperdir and workdir
when the updated path is unclean. This happens easily when e.g. a user calls
lxc-clone -o OLD -n NEW -P //home//chb///.
Signed-off-by: Christian Brauner <christianvanbrauner at gmail.com>
---
src/lxc/lxccontainer.c | 108 ++++++++++++++++++++++++++++++++++++++++++++++++-
1 file changed, 107 insertions(+), 1 deletion(-)
diff --git a/src/lxc/lxccontainer.c b/src/lxc/lxccontainer.c
index 42e23e7..7a93f8b 100644
--- a/src/lxc/lxccontainer.c
+++ b/src/lxc/lxccontainer.c
@@ -2894,6 +2894,105 @@ static int create_file_dirname(char *path, struct lxc_conf *conf)
return ret;
}
+/* When we clone a container with overlay or aufs lxc.mount.entry entries we
+* need to update these absolute paths. In order to do this we add the function
+* update_union_mount_entry_paths() in lxccontainer.c. The function operates on
+* c->lxc_conf->unexpanded_config instead of the intuitively plausible
+* c->lxc_conf->mount_list because the latter also contains mounts from other
+* files as well as generic mounts. */
+static int update_union_mount_entry_paths(struct lxc_conf *lxc_conf,
+ const char *lxc_path,
+ const char *lxc_name,
+ const char *newpath,
+ const char *newname)
+{
+ char new_upper[MAXPATHLEN];
+ char new_work[MAXPATHLEN];
+ char old_upper[MAXPATHLEN];
+ char old_work[MAXPATHLEN];
+ char *cleanpath = NULL;
+ char *mnt_entry = NULL;
+ char *new_unexpanded_config = NULL;
+ char *tmp_unexpanded_config = NULL;
+ char *tmp = NULL;
+ int ret = 0;
+ size_t len = 0;
+ struct lxc_list *iterator;
+
+ cleanpath = strdup(newpath);
+ if (!cleanpath)
+ goto err;
+
+ remove_trailing_slashes(cleanpath);
+
+ ret = snprintf(old_work, MAXPATHLEN, "workdir=%s/%s", lxc_path, lxc_name);
+ if (ret < 0 || ret >= MAXPATHLEN)
+ goto err;
+
+ ret = snprintf(new_work, MAXPATHLEN, "workdir=%s/%s", cleanpath, newname);
+ if (ret < 0 || ret >= MAXPATHLEN)
+ goto err;
+
+ lxc_list_for_each(iterator, &lxc_conf->mount_list) {
+ mnt_entry = iterator->elem;
+ if (strstr(lxc_conf->unexpanded_config, mnt_entry)) {
+ if (strstr(mnt_entry, "overlay"))
+ tmp = "upperdir";
+ else if (strstr(mnt_entry, "aufs"))
+ tmp = "br";
+ if (!tmp)
+ continue;
+
+ ret = snprintf(old_upper, MAXPATHLEN, "%s=%s/%s", tmp, lxc_path, lxc_name);
+ if (ret < 0 || ret >= MAXPATHLEN)
+ goto err;
+
+ ret = snprintf(new_upper, MAXPATHLEN, "%s=%s/%s", tmp, cleanpath, newname);
+ if (ret < 0 || ret >= MAXPATHLEN)
+ goto err;
+
+ if (strstr(mnt_entry, old_upper))
+ tmp_unexpanded_config = lxc_string_replace(old_upper, new_upper, lxc_conf->unexpanded_config);
+
+ if (tmp_unexpanded_config && strstr(mnt_entry, old_work))
+ new_unexpanded_config = lxc_string_replace(old_work, new_work, tmp_unexpanded_config);
+
+ if (!new_unexpanded_config && !tmp_unexpanded_config)
+ continue;
+
+ if (new_unexpanded_config) {
+ free(lxc_conf->unexpanded_config);
+ lxc_conf->unexpanded_config = strdup(new_unexpanded_config);
+ } else if (tmp_unexpanded_config) {
+ free(lxc_conf->unexpanded_config);
+ lxc_conf->unexpanded_config = strdup(tmp_unexpanded_config);
+ }
+
+ if (lxc_conf->unexpanded_config) {
+ len = strlen(lxc_conf->unexpanded_config);
+ lxc_conf->unexpanded_len = len;
+ lxc_conf->unexpanded_alloced = len + 1;
+ }
+
+ free(new_unexpanded_config);
+ free(tmp_unexpanded_config);
+ new_unexpanded_config = NULL;
+ tmp_unexpanded_config = NULL;
+ tmp = NULL;
+
+ if (!lxc_conf->unexpanded_config)
+ goto err;
+ }
+ }
+ free(cleanpath);
+ return 0;
+
+err:
+ free(cleanpath);
+ INFO("%s", "Failed to update config file");
+ return -1;
+}
+
static struct lxc_container *do_lxcapi_clone(struct lxc_container *c, const char *newname,
const char *lxcpath, int flags,
const char *bdevtype, const char *bdevdata, uint64_t newsize,
@@ -2953,7 +3052,9 @@ static struct lxc_container *do_lxcapi_clone(struct lxc_container *c, const char
fclose(fout);
c->lxc_conf->rootfs.path = origroot;
- sprintf(newpath, "%s/%s/rootfs", lxcpath, newname);
+ ret = snprintf(newpath, MAXPATHLEN, "%s/%s/rootfs", lxcpath, newname);
+ if (ret < 0 || ret >= MAXPATHLEN)
+ goto out;
if (mkdir(newpath, 0755) < 0) {
SYSERROR("error creating %s", newpath);
goto out;
@@ -3009,10 +3110,15 @@ static struct lxc_container *do_lxcapi_clone(struct lxc_container *c, const char
}
}
+ // update absolute paths for union mount directories
+ if (update_union_mount_entry_paths(c2->lxc_conf, c->config_path, c->name, lxcpath, newname) < 0)
+ goto out;
+
// We've now successfully created c2's storage, so clear it out if we
// fail after this
storage_copied = 1;
+
if (!c2->save_config(c2, NULL))
goto out;
--
2.6.1
More information about the lxc-devel
mailing list