From edf77341a57a81d8a5c9b9a767d8ba79f26ba8c4 Mon Sep 17 00:00:00 2001 From: Serge Hallyn Date: Thu, 16 Oct 2014 15:10:21 +0000 Subject: [PATCH] overlay and aufs clone_paths: be more robust MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Currently when we clone a container, bdev_copy passes NULL as dst argument of bdev_init, then sees bdev->dest (as a result) is NULL, and sets bdev->dest to $lxcpath/$name/rootfs. so $ops->clone_paths() can assume that "/rootfs" is at the end of the path. The overlayfs and aufs clonepaths do assume that and index to endofstring-6 and append delta0. Let's be more robust by actually finding the last / in the path. Then, instead of always setting oldbdev->dest to $lxcpath/$name/rootfs, set it to oldbdev->src. Else dir_clonepaths fails when mounting src onto dest bc dest does not exist. We could also fix that by creating bdev->dest if needed, but that addes an empty directory to the old container. This fixes 'lxc-clone -o x1 -n x2' if x1 has lxc.rootfs = /var/lib/lxc/x1/x and makes the overlayfs and aufs paths less fragile should something else change. Signed-off-by: Serge Hallyn Acked-by: Stéphane Graber --- src/lxc/bdev.c | 68 ++++++++++++++++++++++---------------------------- 1 file changed, 30 insertions(+), 38 deletions(-) diff --git a/src/lxc/bdev.c b/src/lxc/bdev.c index 4fc10f2aa1..8a819abed9 100644 --- a/src/lxc/bdev.c +++ b/src/lxc/bdev.c @@ -2265,20 +2265,24 @@ static int overlayfs_clonepaths(struct bdev *orig, struct bdev *new, const char WARN("Failed to update ownership of %s", new->dest); if (strcmp(orig->type, "dir") == 0) { - char *delta; - int ret, len; + char *delta, *lastslash; + int ret, len, lastslashidx; // if we have /var/lib/lxc/c2/rootfs, then delta will be // /var/lib/lxc/c2/delta0 - delta = strdup(new->dest); - if (!delta) { - return -1; - } - if (strlen(delta) < 6) { - free(delta); + lastslash = strrchr(new->dest, '/'); + if (!lastslash) return -22; - } - strcpy(&delta[strlen(delta)-6], "delta0"); + if (strlen(lastslash) < 7) + return -22; + lastslash++; + lastslashidx = lastslash - new->dest; + + delta = malloc(lastslashidx + 7); + if (!delta) + return -1; + strncpy(delta, new->dest, lastslashidx+1); + strcpy(delta+lastslashidx, "delta0"); if ((ret = mkdir(delta, 0755)) < 0) { SYSERROR("error: mkdir %s", delta); free(delta); @@ -2319,7 +2323,7 @@ static int overlayfs_clonepaths(struct bdev *orig, struct bdev *new, const char free(osrc); return -ENOMEM; } - if ((ret = mkdir(ndelta, 0755)) < 0) { + if ((ret = mkdir(ndelta, 0755)) < 0 && errno != EEXIST) { SYSERROR("error: mkdir %s", ndelta); free(osrc); free(ndelta); @@ -2560,20 +2564,24 @@ static int aufs_clonepaths(struct bdev *orig, struct bdev *new, const char *oldn return -1; if (strcmp(orig->type, "dir") == 0) { - char *delta; - int ret, len; + char *delta, *lastslash; + int ret, len, lastslashidx; // if we have /var/lib/lxc/c2/rootfs, then delta will be // /var/lib/lxc/c2/delta0 - delta = strdup(new->dest); - if (!delta) { - return -1; - } - if (strlen(delta) < 6) { - free(delta); + lastslash = strrchr(new->dest, '/'); + if (!lastslash) return -22; - } - strcpy(&delta[strlen(delta)-6], "delta0"); + if (strlen(lastslash) < 7) + return -22; + lastslash++; + lastslashidx = lastslash - new->dest; + + delta = malloc(lastslashidx + 7); + if (!delta) + return -1; + strncpy(delta, new->dest, lastslashidx+1); + strcpy(delta+lastslashidx, "delta0"); if ((ret = mkdir(delta, 0755)) < 0) { SYSERROR("error: mkdir %s", delta); free(delta); @@ -3248,28 +3256,12 @@ struct bdev *bdev_copy(struct lxc_container *c0, const char *cname, return NULL; } - orig = bdev_init(c0->lxc_conf, src, NULL, NULL); + orig = bdev_init(c0->lxc_conf, src, src, NULL); if (!orig) { ERROR("failed to detect blockdev type for %s", src); return NULL; } - if (!orig->dest) { - int ret; - orig->dest = malloc(MAXPATHLEN); - if (!orig->dest) { - ERROR("out of memory"); - bdev_put(orig); - return NULL; - } - ret = snprintf(orig->dest, MAXPATHLEN, "%s/%s/rootfs", oldpath, oldname); - if (ret < 0 || ret >= MAXPATHLEN) { - ERROR("rootfs path too long"); - bdev_put(orig); - return NULL; - } - } - /* * special case for snapshot - if caller requested maybe_snapshot and * keepbdevtype and backing store is directory, then proceed with a copy