[lxc-devel] [PATCH 1/1] overlayfs_clonepaths: if unpriv then rsync in a userns
Serge Hallyn
serge.hallyn at ubuntu.com
Thu Feb 13 06:52:52 UTC 2014
This allows lxc-snapshot and lxc-clone -s from an overlayfs container
to work unprivileged. (lxc-clone -s from a directory backed container
already did work)
Signed-off-by: Serge Hallyn <serge.hallyn at ubuntu.com>
---
src/lxc/bdev.c | 70 ++++++++++++++++++++++++++++++++++++++++++++++++++--------
src/lxc/bdev.h | 2 +-
2 files changed, 62 insertions(+), 10 deletions(-)
diff --git a/src/lxc/bdev.c b/src/lxc/bdev.c
index 1df602c..67fe72b 100644
--- a/src/lxc/bdev.c
+++ b/src/lxc/bdev.c
@@ -442,7 +442,7 @@ static char *dir_new_path(char *src, const char *oldname, const char *name,
*/
static int dir_clonepaths(struct bdev *orig, struct bdev *new, const char *oldname,
const char *cname, const char *oldpath, const char *lxcpath, int snap,
- uint64_t newsize)
+ uint64_t newsize, struct lxc_conf *conf)
{
int len, ret;
@@ -667,7 +667,7 @@ static int zfs_clone(const char *opath, const char *npath, const char *oname,
static int zfs_clonepaths(struct bdev *orig, struct bdev *new, const char *oldname,
const char *cname, const char *oldpath, const char *lxcpath, int snap,
- uint64_t newsize)
+ uint64_t newsize, struct lxc_conf *conf)
{
int len, ret;
@@ -1001,7 +1001,7 @@ static int is_blktype(struct bdev *b)
static int lvm_clonepaths(struct bdev *orig, struct bdev *new, const char *oldname,
const char *cname, const char *oldpath, const char *lxcpath, int snap,
- uint64_t newsize)
+ uint64_t newsize, struct lxc_conf *conf)
{
char fstype[100];
uint64_t size = newsize;
@@ -1374,7 +1374,7 @@ out:
static int btrfs_clonepaths(struct bdev *orig, struct bdev *new, const char *oldname,
const char *cname, const char *oldpath, const char *lxcpath, int snap,
- uint64_t newsize)
+ uint64_t newsize, struct lxc_conf *conf)
{
if (!orig->dest || !orig->src)
return -1;
@@ -1626,7 +1626,7 @@ static int do_loop_create(const char *path, uint64_t size, const char *fstype)
*/
static int loop_clonepaths(struct bdev *orig, struct bdev *new, const char *oldname,
const char *cname, const char *oldpath, const char *lxcpath, int snap,
- uint64_t newsize)
+ uint64_t newsize, struct lxc_conf *conf)
{
char fstype[100];
uint64_t size = newsize;
@@ -1826,9 +1826,40 @@ static int overlayfs_umount(struct bdev *bdev)
return umount(bdev->dest);
}
+struct rsync_data_char {
+ char *src;
+ char *dest;
+};
+
+static int rsync_delta(struct rsync_data_char *data)
+{
+ if (setgid(0) < 0) {
+ ERROR("Failed to setgid to 0");
+ return -1;
+ }
+ if (setgroups(0, NULL) < 0)
+ WARN("Failed to clear groups");
+ if (setuid(0) < 0) {
+ ERROR("Failed to setuid to 0");
+ return -1;
+ }
+ if (do_rsync(data->src, data->dest) < 0) {
+ ERROR("rsyncing %s to %s", data->src, data->dest);
+ return -1;
+ }
+
+ return 0;
+}
+
+static int rsync_delta_wrapper(void *data)
+{
+ struct rsync_data_char *arg = data;
+ return rsync_delta(arg);
+}
+
static int overlayfs_clonepaths(struct bdev *orig, struct bdev *new, const char *oldname,
const char *cname, const char *oldpath, const char *lxcpath, int snap,
- uint64_t newsize)
+ uint64_t newsize, struct lxc_conf *conf)
{
if (!snap) {
ERROR("overlayfs is only for snapshot clones");
@@ -1844,6 +1875,9 @@ static int overlayfs_clonepaths(struct bdev *orig, struct bdev *new, const char
if (mkdir_p(new->dest, 0755) < 0)
return -1;
+ if (am_unpriv() && chown_mapped_root(new->dest, conf) < 0)
+ WARN("Failed to update ownership of %s", new->dest);
+
if (strcmp(orig->type, "dir") == 0) {
char *delta;
int ret, len;
@@ -1864,6 +1898,8 @@ static int overlayfs_clonepaths(struct bdev *orig, struct bdev *new, const char
free(delta);
return -1;
}
+ if (am_unpriv() && chown_mapped_root(delta, conf) < 0)
+ WARN("Failed to update ownership of %s", delta);
// the src will be 'overlayfs:lowerdir:upperdir'
len = strlen(delta) + strlen(orig->src) + 12;
@@ -1897,7 +1933,22 @@ static int overlayfs_clonepaths(struct bdev *orig, struct bdev *new, const char
free(osrc);
return -ENOMEM;
}
- if (do_rsync(odelta, ndelta) < 0) {
+ if ((ret = mkdir(ndelta, 0755)) < 0) {
+ SYSERROR("error: mkdir %s", ndelta);
+ free(osrc);
+ free(ndelta);
+ return -1;
+ }
+ if (am_unpriv() && chown_mapped_root(ndelta, conf) < 0)
+ WARN("Failed to update ownership of %s", ndelta);
+ struct rsync_data_char rdata;
+ rdata.src = odelta;
+ rdata.dest = ndelta;
+ if (am_unpriv())
+ ret = userns_exec_1(conf, rsync_delta_wrapper, &rdata);
+ else
+ ret = rsync_delta(&rdata);
+ if (ret) {
free(osrc);
free(ndelta);
ERROR("copying overlayfs delta");
@@ -2079,7 +2130,7 @@ static int aufs_umount(struct bdev *bdev)
static int aufs_clonepaths(struct bdev *orig, struct bdev *new, const char *oldname,
const char *cname, const char *oldpath, const char *lxcpath, int snap,
- uint64_t newsize)
+ uint64_t newsize, struct lxc_conf *conf)
{
if (!snap) {
ERROR("aufs is only for snapshot clones");
@@ -2491,7 +2542,8 @@ struct bdev *bdev_copy(struct lxc_container *c0, const char *cname,
return NULL;
}
- if (new->ops->clone_paths(orig, new, oldname, cname, oldpath, lxcpath, snap, newsize) < 0) {
+ if (new->ops->clone_paths(orig, new, oldname, cname, oldpath, lxcpath,
+ snap, newsize, c0->lxc_conf) < 0) {
ERROR("failed getting pathnames for cloned storage: %s", src);
bdev_put(orig);
bdev_put(new);
diff --git a/src/lxc/bdev.h b/src/lxc/bdev.h
index 250e320..7efc164 100644
--- a/src/lxc/bdev.h
+++ b/src/lxc/bdev.h
@@ -62,7 +62,7 @@ struct bdev_ops {
/* given original mount, rename the paths for cloned container */
int (*clone_paths)(struct bdev *orig, struct bdev *new, const char *oldname,
const char *cname, const char *oldpath, const char *lxcpath,
- int snap, uint64_t newsize);
+ int snap, uint64_t newsize, struct lxc_conf *conf);
bool can_snapshot;
};
--
1.9.rc1
More information about the lxc-devel
mailing list