From: Christian Brauner Date: Sun, 22 Mar 2020 13:03:03 +0000 (+0100) Subject: overlay: rewrite and simplify X-Git-Tag: lxc-4.0.0~6^2~1 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=facdf92587cade4c0e0f7b66037f645b680a81b0;p=thirdparty%2Flxc.git overlay: rewrite and simplify Signed-off-by: Christian Brauner --- diff --git a/src/lxc/conf.c b/src/lxc/conf.c index 066a600d6..2de772511 100644 --- a/src/lxc/conf.c +++ b/src/lxc/conf.c @@ -2795,8 +2795,8 @@ int lxc_map_ids(struct lxc_list *idmap, pid_t pid) /* Return the host uid/gid to which the container root is mapped in val. * Return true if id was found, false otherwise. */ -bool get_mapped_rootid(struct lxc_conf *conf, enum idtype idtype, - unsigned long *val) +static bool get_mapped_rootid(const struct lxc_conf *conf, enum idtype idtype, + unsigned long *val) { unsigned nsid; struct id_map *map; @@ -2820,7 +2820,7 @@ bool get_mapped_rootid(struct lxc_conf *conf, enum idtype idtype, return false; } -int mapped_hostid(unsigned id, struct lxc_conf *conf, enum idtype idtype) +int mapped_hostid(unsigned id, const struct lxc_conf *conf, enum idtype idtype) { struct id_map *map; struct lxc_list *it; @@ -2871,7 +2871,7 @@ int chown_mapped_root_exec_wrapper(void *args) * root is privileged with respect to hostuid/hostgid X, allowing * him to do the chown. */ -int chown_mapped_root(const char *path, struct lxc_conf *conf) +int chown_mapped_root(const char *path, const struct lxc_conf *conf) { uid_t rootuid, rootgid; unsigned long val; diff --git a/src/lxc/conf.h b/src/lxc/conf.h index 5b6fb9a13..7f91c9fb9 100644 --- a/src/lxc/conf.h +++ b/src/lxc/conf.h @@ -437,9 +437,9 @@ extern int lxc_setup(struct lxc_handler *handler); extern int lxc_setup_parent(struct lxc_handler *handler); extern int setup_resource_limits(struct lxc_list *limits, pid_t pid); extern int find_unmapped_nsid(struct lxc_conf *conf, enum idtype idtype); -extern int mapped_hostid(unsigned id, struct lxc_conf *conf, +extern int mapped_hostid(unsigned id, const struct lxc_conf *conf, enum idtype idtype); -extern int chown_mapped_root(const char *path, struct lxc_conf *conf); +extern int chown_mapped_root(const char *path, const struct lxc_conf *conf); extern int userns_exec_1(struct lxc_conf *conf, int (*fn)(void *), void *data, const char *fn_name); extern int userns_exec_full(struct lxc_conf *conf, int (*fn)(void *), diff --git a/src/lxc/list.h b/src/lxc/list.h index 0356641b8..e329b7e00 100644 --- a/src/lxc/list.h +++ b/src/lxc/list.h @@ -58,19 +58,19 @@ static inline void lxc_list_add_elem(struct lxc_list *list, void *elem) } /* Retrieve first element of list. */ -static inline void *lxc_list_first_elem(struct lxc_list *list) +static inline void *lxc_list_first_elem(const struct lxc_list *list) { return list->next->elem; } /* Retrieve last element of list. */ -static inline void *lxc_list_last_elem(struct lxc_list *list) +static inline void *lxc_list_last_elem(const struct lxc_list *list) { return list->prev->elem; } /* Determine if list is empty. */ -static inline int lxc_list_empty(struct lxc_list *list) +static inline int lxc_list_empty(const struct lxc_list *list) { return list == list->next; } diff --git a/src/lxc/lxccontainer.c b/src/lxc/lxccontainer.c index b30864bb5..38439b80b 100644 --- a/src/lxc/lxccontainer.c +++ b/src/lxc/lxccontainer.c @@ -1275,7 +1275,7 @@ static struct lxc_storage *do_storage_create(struct lxc_container *c, if (ret < 0 || (size_t)ret >= len) return NULL; - bdev = storage_create(dest, type, c->name, specs); + bdev = storage_create(dest, type, c->name, specs, c->lxc_conf); if (!bdev) { ERROR("Failed to create \"%s\" storage", type); return NULL; @@ -1290,8 +1290,7 @@ static struct lxc_storage *do_storage_create(struct lxc_container *c, /* If we are not root, chown the rootfs dir to root in the target user * namespace. */ - ret = geteuid(); - if (ret != 0 || (c->lxc_conf && !lxc_list_empty(&c->lxc_conf->id_map))) { + if (am_guest_unpriv() || !lxc_list_empty(&c->lxc_conf->id_map)) { ret = chown_mapped_root(bdev->dest, c->lxc_conf); if (ret < 0) { ERROR("Error chowning \"%s\" to container root", bdev->dest); diff --git a/src/lxc/storage/btrfs.c b/src/lxc/storage/btrfs.c index be66aef77..47f2dd3c4 100644 --- a/src/lxc/storage/btrfs.c +++ b/src/lxc/storage/btrfs.c @@ -906,7 +906,7 @@ int btrfs_destroy(struct lxc_storage *orig) } int btrfs_create(struct lxc_storage *bdev, const char *dest, const char *n, - struct bdev_specs *specs) + struct bdev_specs *specs, const struct lxc_conf *conf) { int ret; size_t len; diff --git a/src/lxc/storage/btrfs.h b/src/lxc/storage/btrfs.h index edd7bb0ad..c7f45eb4d 100644 --- a/src/lxc/storage/btrfs.h +++ b/src/lxc/storage/btrfs.h @@ -366,8 +366,8 @@ extern int btrfs_clonepaths(struct lxc_storage *orig, struct lxc_storage *new, const char *oldname, const char *cname, const char *oldpath, const char *lxcpath, int snap, uint64_t newsize, struct lxc_conf *conf); -extern int btrfs_create(struct lxc_storage *bdev, const char *dest, - const char *n, struct bdev_specs *specs); +extern int btrfs_create(struct lxc_storage *bdev, const char *dest, const char *n, + struct bdev_specs *specs, const struct lxc_conf *conf); extern int btrfs_destroy(struct lxc_storage *orig); extern bool btrfs_detect(const char *path); extern int btrfs_mount(struct lxc_storage *bdev); diff --git a/src/lxc/storage/dir.c b/src/lxc/storage/dir.c index 393fb5016..9b3e673b3 100644 --- a/src/lxc/storage/dir.c +++ b/src/lxc/storage/dir.c @@ -58,7 +58,7 @@ int dir_clonepaths(struct lxc_storage *orig, struct lxc_storage *new, } int dir_create(struct lxc_storage *bdev, const char *dest, const char *n, - struct bdev_specs *specs) + struct bdev_specs *specs, const struct lxc_conf *conf) { int ret; const char *src; diff --git a/src/lxc/storage/dir.h b/src/lxc/storage/dir.h index c7661f5b0..d24a71fb4 100644 --- a/src/lxc/storage/dir.h +++ b/src/lxc/storage/dir.h @@ -17,7 +17,7 @@ extern int dir_clonepaths(struct lxc_storage *orig, struct lxc_storage *new, const char *oldpath, const char *lxcpath, int snap, uint64_t newsize, struct lxc_conf *conf); extern int dir_create(struct lxc_storage *bdev, const char *dest, const char *n, - struct bdev_specs *specs); + struct bdev_specs *specs, const struct lxc_conf *conf); extern int dir_destroy(struct lxc_storage *orig); extern bool dir_detect(const char *path); extern int dir_mount(struct lxc_storage *bdev); diff --git a/src/lxc/storage/loop.c b/src/lxc/storage/loop.c index ad3701cd6..eebc1b67c 100644 --- a/src/lxc/storage/loop.c +++ b/src/lxc/storage/loop.c @@ -114,7 +114,7 @@ int loop_clonepaths(struct lxc_storage *orig, struct lxc_storage *new, } int loop_create(struct lxc_storage *bdev, const char *dest, const char *n, - struct bdev_specs *specs) + struct bdev_specs *specs, const struct lxc_conf *conf) { __do_free char *srcdev = NULL; const char *fstype; diff --git a/src/lxc/storage/loop.h b/src/lxc/storage/loop.h index b22d34fd1..66681db8f 100644 --- a/src/lxc/storage/loop.h +++ b/src/lxc/storage/loop.h @@ -17,7 +17,7 @@ extern int loop_clonepaths(struct lxc_storage *orig, struct lxc_storage *new, const char *oldpath, const char *lxcpath, int snap, uint64_t newsize, struct lxc_conf *conf); extern int loop_create(struct lxc_storage *bdev, const char *dest, - const char *n, struct bdev_specs *specs); + const char *n, struct bdev_specs *specs, const struct lxc_conf *conf); extern int loop_destroy(struct lxc_storage *orig); extern bool loop_detect(const char *path); extern int loop_mount(struct lxc_storage *bdev); diff --git a/src/lxc/storage/lvm.c b/src/lxc/storage/lvm.c index 30e3e697a..437677cf4 100644 --- a/src/lxc/storage/lvm.c +++ b/src/lxc/storage/lvm.c @@ -609,7 +609,7 @@ int lvm_destroy(struct lxc_storage *orig) } int lvm_create(struct lxc_storage *bdev, const char *dest, const char *n, - struct bdev_specs *specs) + struct bdev_specs *specs, const struct lxc_conf *conf) { const char *vg, *thinpool, *fstype, *lv = n; uint64_t sz; diff --git a/src/lxc/storage/lvm.h b/src/lxc/storage/lvm.h index e4ef0611e..7c2fbea65 100644 --- a/src/lxc/storage/lvm.h +++ b/src/lxc/storage/lvm.h @@ -24,7 +24,7 @@ extern int lvm_clonepaths(struct lxc_storage *orig, struct lxc_storage *new, uint64_t newsize, struct lxc_conf *conf); extern int lvm_destroy(struct lxc_storage *orig); extern int lvm_create(struct lxc_storage *bdev, const char *dest, const char *n, - struct bdev_specs *specs); + struct bdev_specs *specs, const struct lxc_conf *conf); extern bool lvm_create_clone(struct lxc_conf *conf, struct lxc_storage *orig, struct lxc_storage *new, uint64_t newsize); extern bool lvm_create_snapshot(struct lxc_conf *conf, struct lxc_storage *orig, diff --git a/src/lxc/storage/nbd.c b/src/lxc/storage/nbd.c index 4a4395bf0..ba4207380 100644 --- a/src/lxc/storage/nbd.c +++ b/src/lxc/storage/nbd.c @@ -91,7 +91,7 @@ int nbd_clonepaths(struct lxc_storage *orig, struct lxc_storage *new, } int nbd_create(struct lxc_storage *bdev, const char *dest, const char *n, - struct bdev_specs *specs) + struct bdev_specs *specs, const struct lxc_conf *conf) { return -ENOSYS; } diff --git a/src/lxc/storage/nbd.h b/src/lxc/storage/nbd.h index 86f59461f..b01c486df 100644 --- a/src/lxc/storage/nbd.h +++ b/src/lxc/storage/nbd.h @@ -17,7 +17,7 @@ extern int nbd_clonepaths(struct lxc_storage *orig, struct lxc_storage *new, const char *oldpath, const char *lxcpath, int snap, uint64_t newsize, struct lxc_conf *conf); extern int nbd_create(struct lxc_storage *bdev, const char *dest, const char *n, - struct bdev_specs *specs); + struct bdev_specs *specs, const struct lxc_conf *conf); extern int nbd_destroy(struct lxc_storage *orig); extern bool nbd_detect(const char *path); extern int nbd_mount(struct lxc_storage *bdev); diff --git a/src/lxc/storage/overlay.c b/src/lxc/storage/overlay.c index 2195b76e4..a18b947fa 100644 --- a/src/lxc/storage/overlay.c +++ b/src/lxc/storage/overlay.c @@ -57,234 +57,133 @@ int ovl_clonepaths(struct lxc_storage *orig, struct lxc_storage *new, const char return -1; } - if (am_guest_unpriv()) { + if (am_guest_unpriv() || !lxc_list_empty(&conf->id_map)) { ret = chown_mapped_root(new->dest, conf); if (ret < 0) WARN("Failed to update ownership of %s", new->dest); } if (strcmp(orig->type, "dir") == 0) { - char *delta, *lastslash; - char *work; - int len, lastslashidx; + __do_free char *delta = NULL, *work = NULL; + int len; - /* If we have "/var/lib/lxc/c2/rootfs" then delta will be - * "/var/lib/lxc/c2/delta0". - */ - lastslash = strrchr(new->dest, '/'); - if (!lastslash) { - ERROR("Failed to detect \"/\" in string \"%s\"", - new->dest); - return -22; - } - - if (strlen(lastslash) < STRLITERALLEN("/rootfs")) { - ERROR("Failed to detect \"/rootfs\" in string \"%s\"", - new->dest); - return -22; - } - - lastslash++; - lastslashidx = lastslash - new->dest; - - delta = malloc(lastslashidx + 7); - if (!delta) { - ERROR("Failed to allocate memory"); - return -1; - } - - memcpy(delta, new->dest, lastslashidx + 1); - memcpy(delta + lastslashidx, "delta0", STRLITERALLEN("delta0")); - delta[lastslashidx + STRLITERALLEN("delta0")] = '\0'; - - ret = mkdir(delta, 0755); - if (ret < 0 && errno != EEXIST) { - SYSERROR("Failed to create directory \"%s\"", delta); - free(delta); - return -1; - } + delta = must_make_path(lxcpath, cname, LXC_OVERLAY_DELTA_PATH, NULL); - if (am_guest_unpriv()) { - ret = chown_mapped_root(delta, conf); - if (ret < 0) - WARN("Failed to update ownership of %s", delta); - } + ret = mkdir_p(delta, 0755); + if (ret < 0 && errno != EEXIST) + return log_error_errno(-errno, errno, "Failed to create directory \"%s\"", delta); - /* Make workdir for overlayfs.v22 or higher: + /* + * Make workdir for overlayfs.v22 or higher: * The workdir will be - * /var/lib/lxc/c2/olwork + * /var/lib/lxc/c2/LXC_OVERLAY_WORK_PATH * and is used to prepare files before they are atomically * switched to the overlay destination. Workdirs need to be on * the same filesystem as the upperdir so it's OK for it to be * empty. */ - work = malloc(lastslashidx + 7); - if (!work) { - ERROR("Failed to allocate memory"); - free(delta); - return -1; - } + work = must_make_path(lxcpath, cname, LXC_OVERLAY_WORK_PATH, NULL); - memcpy(work, new->dest, lastslashidx + 1); - memcpy(work + lastslashidx, "olwork", STRLITERALLEN("olwork")); - work[lastslashidx + STRLITERALLEN("olwork")] = '\0'; + ret = mkdir_p(work, 0755); + if (ret < 0 && errno != EEXIST) + return log_error_errno(-errno, errno, "Failed to create directory \"%s\"", work); - ret = mkdir(work, 0755); - if (ret < 0) { - SYSERROR("Failed to create directory \"%s\"", work); - free(delta); - free(work); - return -1; - } + if (am_guest_unpriv() || !lxc_list_empty(&conf->id_map)) { + __do_free char *lxc_overlay_delta_dir = NULL, + *lxc_overlay_private_dir = NULL; + + lxc_overlay_private_dir = must_make_path(lxcpath, cname, LXC_OVERLAY_PRIVATE_DIR, NULL); + ret = chown_mapped_root(lxc_overlay_private_dir, conf); + if (ret < 0) + WARN("Failed to update ownership of %s", lxc_overlay_private_dir); + + lxc_overlay_delta_dir = must_make_path(lxcpath, cname, LXC_OVERLAY_DELTA_PATH, NULL); + ret = chown_mapped_root(lxc_overlay_delta_dir, conf); + if (ret < 0) + WARN("Failed to update ownership of %s", lxc_overlay_delta_dir); - if (am_guest_unpriv()) { ret = chown_mapped_root(work, conf); if (ret < 0) WARN("Failed to update ownership of %s", work); } - free(work); - /* strlen("overlay:") = 8 - * + - * strlen(delta) - * + - * : - * + - * strlen(src) - * + - * \0 - */ src = lxc_storage_get_path(orig->src, orig->type); - len = 8 + strlen(delta) + 1 + strlen(src) + 1; + len = STRLITERALLEN("overlay") + STRLITERALLEN(":") + + strlen(src) + STRLITERALLEN(":") + strlen(delta) + 1; + new->src = malloc(len); - if (!new->src) { - ERROR("Failed to allocate memory"); - free(delta); - return -ENOMEM; - } + if (!new->src) + return log_error_errno(-ENOMEM, ENOMEM, "Failed to allocate memory"); ret = snprintf(new->src, len, "overlay:%s:%s", src, delta); - free(delta); - if (ret < 0 || (size_t)ret >= len) { - ERROR("Failed to create string"); - return -1; - } + if (ret < 0 || (size_t)ret >= len) + return log_error_errno(-EIO, EIO, "Failed to create string"); } else if (!strcmp(orig->type, "overlayfs") || !strcmp(orig->type, "overlay")) { - char *clean_old_path, *clean_new_path; - char *lastslash, *ndelta, *nsrc, *odelta, *osrc, *s1, *s2, *s3, - *work; - int lastslashidx; + __do_free char *clean_old_path = NULL, *clean_new_path = NULL, + *ndelta = NULL, *osrc = NULL, *work = NULL; + char *nsrc, *odelta, *s1, *s2, *s3; size_t len, name_len; osrc = strdup(orig->src); - if (!osrc) { - ERROR("Failed to duplicate string \"%s\"", orig->src); - return -22; - } + if (!osrc) + return log_error_errno(-22, ENOMEM, "Failed to duplicate string \"%s\"", orig->src); nsrc = osrc; - if (strncmp(osrc, "overlay:", 8) == 0) - nsrc += 8; - else if (strncmp(osrc, "overlayfs:", 10) == 0) - nsrc += 10; + if (strncmp(osrc, "overlay:", STRLITERALLEN("overlay:")) == 0) + nsrc += STRLITERALLEN("overlay:"); + else if (strncmp(osrc, "overlayfs:", STRLITERALLEN("overlayfs:")) == 0) + nsrc += STRLITERALLEN("overlayfs:"); odelta = strchr(nsrc, ':'); - if (!odelta) { - ERROR("Failed to find \":\" in \"%s\"", nsrc); - free(osrc); - return -22; - } + if (!odelta) + return log_error_errno(-22, ENOENT, "Failed to find \":\" in \"%s\"", nsrc); *odelta = '\0'; odelta++; - ndelta = must_make_path(lxcpath, cname, "delta0", NULL); - - ret = mkdir(ndelta, 0755); - if (ret < 0 && errno != EEXIST) { - SYSERROR("Failed to create directory \"%s\"", ndelta); - free(osrc); - free(ndelta); - return -1; - } + ndelta = must_make_path(lxcpath, cname, LXC_OVERLAY_DELTA_PATH, NULL); - if (am_guest_unpriv()) { - ret = chown_mapped_root(ndelta, conf); - if (ret < 0) - WARN("Failed to update ownership of %s", - ndelta); - } + ret = mkdir_p(ndelta, 0755); + if (ret < 0 && errno != EEXIST) + return log_error_errno(-errno, errno, "Failed to create directory \"%s\"", ndelta); /* Make workdir for overlayfs.v22 or higher (See the comment * further up.). */ - lastslash = strrchr(ndelta, '/'); - if (!lastslash) { - ERROR("Failed to detect \"/\" in \"%s\"", ndelta); - free(osrc); - free(ndelta); - return -1; - } - lastslash++; - lastslashidx = lastslash - ndelta; - - work = malloc(lastslashidx + 7); - if (!work) { - free(osrc); - free(ndelta); - ERROR("Failed to allocate memory"); - return -1; - } + work = must_make_path(lxcpath, cname, LXC_OVERLAY_WORK_PATH, NULL); + ret = mkdir_p(work, 0755); + if (ret < 0 && errno != EEXIST) + return log_error_errno(-errno, errno, "Failed to create directory \"%s\"", ndelta); - memcpy(work, ndelta, lastslashidx + 1); - memcpy(work + lastslashidx, "olwork", STRLITERALLEN("olwork")); - work[lastslashidx + STRLITERALLEN("olwork")] = '\0'; + if (am_guest_unpriv() || !lxc_list_empty(&conf->id_map)) { + __do_free char *lxc_overlay_delta_dir = NULL, + *lxc_overlay_private_dir = NULL; - ret = mkdir(work, 0755); - if (ret < 0 && errno != EEXIST) { - SYSERROR("Failed to create directory \"%s\"", ndelta); - free(osrc); - free(ndelta); - free(work); - return -1; - } + lxc_overlay_private_dir = must_make_path(lxcpath, cname, LXC_OVERLAY_PRIVATE_DIR, NULL); + ret = chown_mapped_root(lxc_overlay_private_dir, conf); + if (ret < 0) + WARN("Failed to update ownership of %s", lxc_overlay_private_dir); + + lxc_overlay_delta_dir = must_make_path(lxcpath, cname, LXC_OVERLAY_DELTA_PATH, NULL); + ret = chown_mapped_root(lxc_overlay_delta_dir, conf); + if (ret < 0) + WARN("Failed to update ownership of %s", lxc_overlay_delta_dir); - if (am_guest_unpriv()) { ret = chown_mapped_root(work, conf); if (ret < 0) WARN("Failed to update ownership of %s", work); } - free(work); - /* strlen("overlay:") = 8 - * + - * strlen(delta) - * + - * : - * + - * strlen(src) - * + - * \0 - */ - len = 8 + strlen(ndelta) + 1 + strlen(nsrc) + 1; + len = STRLITERALLEN("overlay") + STRLITERALLEN(":") + strlen(nsrc) + STRLITERALLEN(":") + strlen(ndelta) + 1; new->src = malloc(len); - if (!new->src) { - free(osrc); - free(ndelta); - ERROR("Failed to allocate memory"); - return -ENOMEM; - } + if (!new->src) + return log_error_errno(-ENOMEM, ENOMEM, "Failed to allocate memory"); + ret = snprintf(new->src, len, "overlay:%s:%s", nsrc, ndelta); - if (ret < 0 || (size_t)ret >= len) { - ERROR("Failed to create string"); - free(osrc); - free(ndelta); - return -1; - } + if (ret < 0 || (size_t)ret >= len) + return log_error_errno(-EIO, EIO, "Failed to create string"); ret = ovl_do_rsync(odelta, ndelta, conf); - free(osrc); - free(ndelta); if (ret < 0) return -1; @@ -295,29 +194,19 @@ int ovl_clonepaths(struct lxc_storage *orig, struct lxc_storage *new, const char */ clean_old_path = lxc_deslashify(oldpath); if (!clean_old_path) - return -1; + return log_error_errno(-ENOMEM, ENOMEM, "Failed to create clean path for \"%s\"", oldpath); clean_new_path = lxc_deslashify(lxcpath); - if (!clean_new_path) { - free(clean_old_path); - return -1; - } + if (!clean_new_path) + return log_error_errno(-ENOMEM, ENOMEM, "Failed to create clean path for \"%s\"", lxcpath); s1 = strrchr(clean_old_path, '/'); - if (!s1) { - ERROR("Failed to detect \"/\" in string \"%s\"", clean_old_path); - free(clean_old_path); - free(clean_new_path); - return -1; - } + if (!s1) + return log_error_errno(-ENOENT, ENOENT, "Failed to detect \"/\" in string \"%s\"", clean_old_path); s2 = strrchr(clean_new_path, '/'); - if (!s2) { - ERROR("Failed to detect \"/\" in string \"%s\"", clean_new_path); - free(clean_old_path); - free(clean_new_path); - return -1; - } + if (!s2) + return log_error_errno(-ENOENT, ENOENT, "Failed to detect \"/\" in string \"%s\"", clean_new_path); if (!strncmp(s1, "/snaps", STRLITERALLEN("/snaps"))) { s1 = clean_new_path; @@ -328,8 +217,6 @@ int ovl_clonepaths(struct lxc_storage *orig, struct lxc_storage *new, const char s2 = clean_new_path; s3 = (char *)oldname; } else { - free(clean_old_path); - free(clean_new_path); return 0; } @@ -338,34 +225,23 @@ int ovl_clonepaths(struct lxc_storage *orig, struct lxc_storage *new, const char char *tmp; tmp = (char *)(s2 + len + 1); - if (*tmp == '\0') { - free(clean_old_path); - free(clean_new_path); + if (*tmp == '\0') return 0; - } name_len = strlen(s3); - if (strncmp(s3, tmp, name_len)) { - free(clean_old_path); - free(clean_new_path); + if (strncmp(s3, tmp, name_len)) return 0; - } - free(clean_old_path); - free(clean_new_path); return LXC_CLONE_SNAPSHOT; } - free(clean_old_path); - free(clean_new_path); return 0; } else { - ERROR("overlay clone of %s container is not yet supported", - orig->type); - /* Note, supporting this will require ovl_mount supporting + /* + * Note, supporting this will require ovl_mount supporting * mounting of the underlay. No big deal, just needs to be done. */ - return -1; + return log_error_errno(-EINVAL, EINVAL, "overlay clone of %s container is not yet supported", orig->type); } return 0; @@ -373,65 +249,60 @@ int ovl_clonepaths(struct lxc_storage *orig, struct lxc_storage *new, const char /* To say "lxc-create -t ubuntu -n o1 -B overlay" means you want * "//rootfs" to have the created container, while all changes - * after starting the container are written to "//delta0". + * after starting the container are written to "//LXC_OVERLAY_DELTA_PATH". */ int ovl_create(struct lxc_storage *bdev, const char *dest, const char *n, - struct bdev_specs *specs) + struct bdev_specs *specs, const struct lxc_conf *conf) { - char *delta; + __do_free char *delta = NULL, *tmp = NULL; int ret; - size_t len, newlen; + size_t len; len = strlen(dest); - if (len < 8 || strcmp(dest + len - 7, "/rootfs")) { - ERROR("Failed to detect \"/rootfs\" in \"%s\"", dest); - return -1; - } + if (len < 8 || strcmp(dest + len - STRLITERALLEN("/rootfs"), "/rootfs")) + return log_error_errno(-ENOENT, ENOENT, "Failed to detect \"/rootfs\" in \"%s\"", dest); bdev->dest = strdup(dest); - if (!bdev->dest) { - ERROR("Failed to duplicate string \"%s\"", dest); - return -1; - } + if (!bdev->dest) + return log_error_errno(-ENOMEM, ENOMEM, "Failed to duplicate string \"%s\"", dest); - delta = strdup(dest); - if (!delta) { - ERROR("Failed to allocate memory"); - return -1; - } - memcpy(delta + len - 6, "delta0", STRLITERALLEN("delta0")); + tmp = strndup(dest, len - STRLITERALLEN("/rootfs")); + if (!tmp) + return log_error_errno(-ENOMEM, ENOMEM, "Failed to duplicate string \"%s\"", dest); + + delta = must_make_path(tmp, LXC_OVERLAY_DELTA_PATH, NULL); ret = mkdir_p(delta, 0755); - if (ret < 0) { - SYSERROR("Failed to create directory \"%s\"", delta); - free(delta); - return -1; + if (ret < 0 && errno != EEXIST) + return log_error_errno(-errno, errno, "Failed to create directory \"%s\"", delta); + + if (am_guest_unpriv() || !lxc_list_empty(&conf->id_map)) { + __do_free char *lxc_overlay_private_dir = NULL; + + lxc_overlay_private_dir = must_make_path(tmp, LXC_OVERLAY_PRIVATE_DIR, NULL); + ret = chown_mapped_root(lxc_overlay_private_dir, conf); + if (ret < 0) + WARN("Failed to update ownership of %s", lxc_overlay_private_dir); + + ret = chown_mapped_root(delta, conf); + if (ret < 0) + WARN("Failed to update ownership of %s", delta); } /* overlay:lower:upper */ - newlen = (2 * len) + strlen("overlay:") + 2; - bdev->src = malloc(newlen); - if (!bdev->src) { - ERROR("Failed to allocate memory"); - free(delta); - return -1; - } + len = STRLITERALLEN("overlay") + STRLITERALLEN(":") + len + STRLITERALLEN(":") + strlen(delta) + 1; + bdev->src = malloc(len); + if (!bdev->src) + return log_error_errno(-ENOMEM, ENOMEM, "Failed to allocate memory"); - ret = snprintf(bdev->src, newlen, "overlay:%s:%s", dest, delta); - if (ret < 0 || (size_t)ret >= newlen) { - ERROR("Failed to create string"); - free(delta); - return -1; - } + ret = snprintf(bdev->src, len, "overlay:%s:%s", dest, delta); + if (ret < 0 || (size_t)ret >= len) + return log_error_errno(-EIO, EIO, "Failed to create rootfs path"); ret = mkdir_p(bdev->dest, 0755); - if (ret < 0) { - SYSERROR("Failed to create directory \"%s\"", bdev->dest); - free(delta); - return -1; - } + if (ret < 0 && errno != EEXIST) + return log_error_errno(-errno, errno, "Failed to create directory \"%s\"", bdev->dest); - free(delta); return 0; } @@ -475,7 +346,6 @@ int ovl_mount(struct lxc_storage *bdev) *options_work = NULL; char *tmp, *dup, *lower, *upper; char *work, *lastslash; - int lastslashidx; size_t len, len2; unsigned long mntflags; char *mntdata; @@ -494,17 +364,15 @@ int ovl_mount(struct lxc_storage *bdev) * mount -t overlay * -o upperdir=${upper},lowerdir=${lower} lower dest */ dup = strdup(bdev->src); - if (!dup) { - ERROR("Failed to allocate memory"); - return -1; - } + if (!dup) + return log_error_errno(-ENOMEM, ENOMEM, "Failed to allocate memory"); upper = dup; lower = dup; - if (strncmp(dup, "overlay:", 8) == 0) - lower += 8; - else if (strncmp(dup, "overlayfs:", 10) == 0) - lower += 10; + if (strncmp(dup, "overlay:", STRLITERALLEN("overlay:")) == 0) + lower += STRLITERALLEN("overlay:"); + else if (strncmp(dup, "overlayfs:", STRLITERALLEN("overlayfs:")) == 0) + lower += STRLITERALLEN("overlayfs:"); if (upper != lower) upper = lower; @@ -532,9 +400,9 @@ int ovl_mount(struct lxc_storage *bdev) /* overlayfs.v22 or higher needs workdir option: * if upper is - * /var/lib/lxc/c2/delta0 + * /var/lib/lxc/c2/LXC_OVERLAY_DELTA_PATH * then workdir is - * /var/lib/lxc/c2/olwork + * /var/lib/lxc/c2/LXC_OVERLAY_WORK_PATH */ lastslash = strrchr(upper, '/'); if (!lastslash) { @@ -543,19 +411,9 @@ int ovl_mount(struct lxc_storage *bdev) return -22; } - lastslash++; - lastslashidx = lastslash - upper; - - work = malloc(lastslashidx + 7); - if (!work) { - ERROR("Failed to allocate memory"); - free(dup); - return -22; - } - - memcpy(work, upper, lastslashidx + 1); - memcpy(work + lastslashidx, "olwork", STRLITERALLEN("olwork")); - work[lastslashidx + STRLITERALLEN("olwork")] = '\0'; + upper[lastslash - upper] = '\0'; + work = must_make_path(upper, LXC_OVERLAY_WORK_DIR, NULL); + upper[lastslash - upper] = '/'; ret = parse_mntopts(bdev->mntopts, &mntflags, &mntdata); if (ret < 0) { diff --git a/src/lxc/storage/overlay.h b/src/lxc/storage/overlay.h index b8349b63d..b64406b0c 100644 --- a/src/lxc/storage/overlay.h +++ b/src/lxc/storage/overlay.h @@ -25,7 +25,7 @@ extern int ovl_clonepaths(struct lxc_storage *orig, struct lxc_storage *new, const char *oldpath, const char *lxcpath, int snap, uint64_t newsize, struct lxc_conf *conf); extern int ovl_create(struct lxc_storage *bdev, const char *dest, const char *n, - struct bdev_specs *specs); + struct bdev_specs *specs, const struct lxc_conf *conf); extern int ovl_destroy(struct lxc_storage *orig); extern bool ovl_detect(const char *path); extern int ovl_mount(struct lxc_storage *bdev); diff --git a/src/lxc/storage/rbd.c b/src/lxc/storage/rbd.c index 6402dc775..e7ba8930c 100644 --- a/src/lxc/storage/rbd.c +++ b/src/lxc/storage/rbd.c @@ -77,7 +77,7 @@ int rbd_clonepaths(struct lxc_storage *orig, struct lxc_storage *new, } int rbd_create(struct lxc_storage *bdev, const char *dest, const char *n, - struct bdev_specs *specs) + struct bdev_specs *specs, const struct lxc_conf *conf) { const char *rbdpool, *fstype; uint64_t size; diff --git a/src/lxc/storage/rbd.h b/src/lxc/storage/rbd.h index 1537bf269..f051c2ad0 100644 --- a/src/lxc/storage/rbd.h +++ b/src/lxc/storage/rbd.h @@ -17,7 +17,7 @@ extern int rbd_clonepaths(struct lxc_storage *orig, struct lxc_storage *new, const char *oldpath, const char *lxcpath, int snap, uint64_t newsize, struct lxc_conf *conf); extern int rbd_create(struct lxc_storage *bdev, const char *dest, const char *n, - struct bdev_specs *specs); + struct bdev_specs *specs, const struct lxc_conf *conf); extern int rbd_destroy(struct lxc_storage *orig); extern bool rbd_detect(const char *path); extern int rbd_mount(struct lxc_storage *bdev); diff --git a/src/lxc/storage/storage.c b/src/lxc/storage/storage.c index c05d1294a..3f1b713f6 100644 --- a/src/lxc/storage/storage.c +++ b/src/lxc/storage/storage.c @@ -259,7 +259,8 @@ struct lxc_storage *storage_get(const char *type) static struct lxc_storage *do_storage_create(const char *dest, const char *type, const char *cname, - struct bdev_specs *specs) + struct bdev_specs *specs, + const struct lxc_conf *conf) { int ret; struct lxc_storage *bdev; @@ -271,7 +272,7 @@ static struct lxc_storage *do_storage_create(const char *dest, const char *type, if (!bdev) return NULL; - ret = bdev->ops->create(bdev, dest, cname, specs); + ret = bdev->ops->create(bdev, dest, cname, specs, conf); if (ret < 0) { storage_put(bdev); return NULL; @@ -521,14 +522,15 @@ on_error_put_orig: * @specs: details about the backing store to create, like fstype */ struct lxc_storage *storage_create(const char *dest, const char *type, - const char *cname, struct bdev_specs *specs) + const char *cname, struct bdev_specs *specs, + const struct lxc_conf *conf) { int ret; struct lxc_storage *bdev; char *best_options[] = {"btrfs", "zfs", "lvm", "dir", "rbd", NULL}; if (!type) - return do_storage_create(dest, "dir", cname, specs); + return do_storage_create(dest, "dir", cname, specs, conf); ret = strcmp(type, "best"); if (ret == 0) { @@ -537,7 +539,7 @@ struct lxc_storage *storage_create(const char *dest, const char *type, * opinionated preferences. */ for (i = 0; best_options[i]; i++) { - bdev = do_storage_create(dest, best_options[i], cname, specs); + bdev = do_storage_create(dest, best_options[i], cname, specs, conf); if (bdev) return bdev; } @@ -552,13 +554,13 @@ struct lxc_storage *storage_create(const char *dest, const char *type, dup = must_copy_string(type); lxc_iterate_parts(token, dup, ",") { - bdev = do_storage_create(dest, token, cname, specs); + bdev = do_storage_create(dest, token, cname, specs, conf); if (bdev) return bdev; } } - return do_storage_create(dest, type, cname, specs); + return do_storage_create(dest, type, cname, specs, conf); } bool storage_destroy(struct lxc_conf *conf) diff --git a/src/lxc/storage/storage.h b/src/lxc/storage/storage.h index acf35e4e9..59ec5a989 100644 --- a/src/lxc/storage/storage.h +++ b/src/lxc/storage/storage.h @@ -54,7 +54,7 @@ struct lxc_storage_ops { int (*umount)(struct lxc_storage *bdev); int (*destroy)(struct lxc_storage *bdev); int (*create)(struct lxc_storage *bdev, const char *dest, const char *n, - struct bdev_specs *specs); + struct bdev_specs *specs, const struct lxc_conf *conf); /* given original mount, rename the paths for cloned container */ int (*clone_paths)(struct lxc_storage *orig, struct lxc_storage *new, const char *oldname, const char *cname, @@ -111,7 +111,8 @@ extern struct lxc_storage *storage_copy(struct lxc_container *c, bool *needs_rdep); extern struct lxc_storage *storage_create(const char *dest, const char *type, const char *cname, - struct bdev_specs *specs); + struct bdev_specs *specs, + const struct lxc_conf *conf); extern void storage_put(struct lxc_storage *bdev); extern bool storage_destroy(struct lxc_conf *conf); extern bool rootfs_is_blockdev(struct lxc_conf *conf); diff --git a/src/lxc/storage/storage_utils.h b/src/lxc/storage/storage_utils.h index 356ff95d8..81c1e2bfe 100644 --- a/src/lxc/storage/storage_utils.h +++ b/src/lxc/storage/storage_utils.h @@ -5,9 +5,19 @@ #include #include +#include #include #include "conf.h" +#include "macro.h" + +#define LXC_OVERLAY_PRIVATE_DIR "overlay" +#define LXC_OVERLAY_DELTA_DIR "delta" +#define LXC_OVERLAY_WORK_DIR "work" +#define LXC_OVERLAY_DELTA_PATH LXC_OVERLAY_PRIVATE_DIR "/" LXC_OVERLAY_DELTA_DIR +#define LXC_OVERLAY_WORK_PATH LXC_OVERLAY_PRIVATE_DIR "/" LXC_OVERLAY_WORK_DIR +#define LXC_OVERLAY_PATH_LEN \ + (STRLITERALLEN(LXC_OVERLAY_PRIVATE_DIR) + STRLITERALLEN("/") + 256 + 1) struct lxc_storage; struct lxc_conf; diff --git a/src/lxc/storage/zfs.c b/src/lxc/storage/zfs.c index 7438dd3fb..d745f2e39 100644 --- a/src/lxc/storage/zfs.c +++ b/src/lxc/storage/zfs.c @@ -684,7 +684,7 @@ int zfs_destroy(struct lxc_storage *orig) } int zfs_create(struct lxc_storage *bdev, const char *dest, const char *n, - struct bdev_specs *specs) + struct bdev_specs *specs, const struct lxc_conf *conf) { const char *zfsroot; int ret; diff --git a/src/lxc/storage/zfs.h b/src/lxc/storage/zfs.h index 855898c37..bacbcb242 100644 --- a/src/lxc/storage/zfs.h +++ b/src/lxc/storage/zfs.h @@ -18,7 +18,7 @@ extern int zfs_clonepaths(struct lxc_storage *orig, struct lxc_storage *new, const char *oldpath, const char *lxcpath, int snap, uint64_t newsize, struct lxc_conf *conf); extern int zfs_create(struct lxc_storage *bdev, const char *dest, const char *n, - struct bdev_specs *specs); + struct bdev_specs *specs, const struct lxc_conf *conf); extern int zfs_destroy(struct lxc_storage *orig); extern bool zfs_detect(const char *path); extern int zfs_mount(struct lxc_storage *bdev); diff --git a/src/lxc/tools/lxc_copy.c b/src/lxc/tools/lxc_copy.c index 8d06a8a93..2180321b8 100644 --- a/src/lxc/tools/lxc_copy.c +++ b/src/lxc/tools/lxc_copy.c @@ -772,9 +772,11 @@ static char *mount_tmpfs(const char *oldname, const char *newname, goto err_close; if (!arg->keepname) { - ret = fprintf(fp, "mkdir -p %s/%s/delta0/etc\n" - "echo %s > %s/%s/delta0/etc/hostname\n", - path, newname, newname, path, newname); + ret = fprintf(fp, + "mkdir -p %s/%s/%s/etc\n" + "echo %s > %s/%s/%s/etc/hostname\n", + path, newname, LXC_OVERLAY_DELTA_PATH, newname, + path, newname, LXC_OVERLAY_DELTA_PATH); if (ret < 0) goto err_close; }