]> git.proxmox.com Git - mirror_lxc.git/commitdiff
bdev: allow unprivileged overlayfs snapshots
authorSerge Hallyn <serge.hallyn@ubuntu.com>
Tue, 11 Feb 2014 19:43:19 +0000 (13:43 -0600)
committerStéphane Graber <stgraber@ubuntu.com>
Tue, 11 Feb 2014 23:58:42 +0000 (18:58 -0500)
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: Serge Hallyn <serge.hallyn@ubuntu.com>
Acked-by: Stéphane Graber <stgraber@ubuntu.com>
src/lxc/bdev.c
src/lxc/conf.c

index 01c06e1040717b1cc08f72d8a65316cfe947914c..7f8ab9cba6d2fb6942dc46eb22be65d23a67b3f7 100644 (file)
@@ -2129,6 +2129,31 @@ bool bdev_is_dir(const char *path)
        return ret;
 }
 
+/*
+ * 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;
 
index 4e25432c491487c4f716e09dbc8bc18338a04709..522c5901cb585da5b5bc452d0b75f74ae3f96bf8 100644 (file)
@@ -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);