Commit a7ef8753 by Serge Hallyn Committed by Stéphane Graber

bdev: allow unprivileged overlayfs snapshots

Also make sure to chown the new rootfs path to the container owner. This is how we make sure that the container root is allowed to write under delta0. Signed-off-by: 's avatarSerge Hallyn <serge.hallyn@ubuntu.com> Acked-by: 's avatarStéphane Graber <stgraber@ubuntu.com>
parent 061ba5d0
......@@ -2130,6 +2130,31 @@ bool bdev_is_dir(const char *path)
}
/*
* is an unprivileged user allowed to make this kind of snapshot
*/
static bool unpriv_snap_allowed(struct bdev *b, const char *t, bool snap,
bool maybesnap)
{
if (!t) {
// new type will be same as original
// (unless snap && b->type == dir, in which case it will be
// overlayfs -- which is also allowed)
if (strcmp(b->type, "dir") == 0 ||
strcmp(b->type, "overlayfs") == 0 ||
strcmp(b->type, "loop") == 0)
return true;
return false;
}
// unprivileged users can copy and snapshot dir, overlayfs,
// and loop. In particular, not zfs, btrfs, or lvm.
if (strcmp(t, "dir") == 0 || strcmp(t, "overlayfs") == 0 ||
strcmp(t, "loop") == 0)
return true;
return false;
}
/*
* If we're not snaphotting, then bdev_copy becomes a simple case of mount
* the original, mount the new, and rsync the contents.
*/
......@@ -2180,26 +2205,6 @@ struct bdev *bdev_copy(struct lxc_container *c0, const char *cname,
}
}
/* check for privilege */
if (am_unpriv()) {
if (snap && !maybe_snap) {
ERROR("Unprivileged users cannot snapshot");
bdev_put(orig);
return NULL;
}
if (bdevtype && strcmp(bdevtype, "dir") != 0) {
ERROR("Unprivileged users can only make dir copy-clones");
bdev_put(orig);
return NULL;
}
if (strcmp(orig->type, "dir") != 0) {
ERROR("Unprivileged users can only make dir copy-clones");
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
......@@ -2214,6 +2219,12 @@ struct bdev *bdev_copy(struct lxc_container *c0, const char *cname,
if (!bdevtype && !keepbdevtype && snap && strcmp(orig->type , "dir") == 0)
bdevtype = "overlayfs";
if (am_unpriv() && !unpriv_snap_allowed(orig, bdevtype, snap, maybe_snap)) {
ERROR("Unsupported snapshot type for unprivileged users");
bdev_put(orig);
return NULL;
}
*needs_rdep = 0;
if (bdevtype && strcmp(orig->type, "dir") == 0 &&
strcmp(bdevtype, "overlayfs") == 0)
......@@ -2232,6 +2243,10 @@ struct bdev *bdev_copy(struct lxc_container *c0, const char *cname,
bdev_put(new);
return NULL;
}
if (am_unpriv() && chown_mapped_root(new->src, c0->lxc_conf) < 0)
WARN("Failed to update ownership of %s", new->dest);
if (snap)
return new;
......
......@@ -3364,6 +3364,7 @@ int chown_mapped_root(char *path, struct lxc_conf *conf)
uid_t rootid;
pid_t pid;
unsigned long val;
char *chownpath = path;
if (!get_mapped_rootid(conf, ID_TYPE_UID, &val)) {
ERROR("No mapping for container root");
......@@ -3371,6 +3372,24 @@ int chown_mapped_root(char *path, struct lxc_conf *conf)
}
rootid = (uid_t) val;
/*
* In case of overlay, we want only the writeable layer
* to be chowned
*/
if (strncmp(path, "overlayfs:", 10) == 0) {
chownpath = strchr(path, ':');
if (!chownpath) {
ERROR("Bad overlay path: %s", path);
return -1;
}
chownpath = strchr(chownpath+1, ':');
if (!chownpath) {
ERROR("Bad overlay path: %s", path);
return -1;
}
chownpath++;
}
path = chownpath;
if (geteuid() == 0) {
if (chown(path, rootid, -1) < 0) {
ERROR("Error chowning %s", path);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment