]> git.proxmox.com Git - mirror_lxc.git/commitdiff
aufs: Support unprivileged clone, mount
authorKATOH Yasufumi <karma@jazz.email.ne.jp>
Thu, 21 May 2015 08:36:49 +0000 (17:36 +0900)
committerStéphane Graber <stgraber@ubuntu.com>
Tue, 26 May 2015 20:01:28 +0000 (16:01 -0400)
Current aufs supports FS_USERNS_MOUNT by using allow_userns module
parameter. It allows root in userns to mount aufs.

This patch allows an unprivileged container to use aufs. The value of
xino option is changed to /dev/shm/aufs.xino that an unpriv user can
write.

Signed-off-by: KATOH Yasufumi <karma@jazz.email.ne.jp>
Acked-by: Serge E. Hallyn <serge.hallyn@ubuntu.com>
src/lxc/bdev.c

index d45b21690e2d04ed96af752d248fd70f8100a9dd..53465b1c6d5241c2b0623fe1711b4a7e95d5277d 100644 (file)
@@ -2564,12 +2564,12 @@ static int aufs_detect(const char *path)
 //
 static int aufs_mount(struct bdev *bdev)
 {
-       char *options, *dup, *lower, *upper, *rundir;
+       char *options, *dup, *lower, *upper;
        int len;
        unsigned long mntflags;
        char *mntdata;
-       char *runpath;
        int ret;
+       const char *xinopath = "/dev/shm/aufs.xino";
 
        if (strcmp(bdev->type, "aufs"))
                return -22;
@@ -2595,41 +2595,24 @@ static int aufs_mount(struct bdev *bdev)
        // TODO We should check whether bdev->src is a blockdev, and if so
        // but for now, only support aufs of a basic directory
 
-       rundir = get_rundir();
-       if (!rundir)
-               return -1;
-
-       len = strlen(rundir) + strlen("/lxc") + 1;
-       runpath = alloca(len);
-       ret = snprintf(runpath, len, "%s/lxc", rundir);
-       if (ret < 0 || ret >= len) {
-               free(mntdata);
-               free(rundir);
-               return -1;
-       }
-       if (mkdir_p(runpath, 0755) < 0) {
-               free(mntdata);
-               free(rundir);
-               return -1;
-       }
-
        // AUFS does not work on top of certain filesystems like (XFS or Btrfs)
-       // so add xino=RUNDIR/lxc/aufs.xino parameter to mount options
+       // so add xino=/dev/shm/aufs.xino parameter to mount options.
+       // The same xino option can be specified to multiple aufs mounts, and
+       // a xino file is not shared among multiple aufs mounts.
        //
        // see http://www.mail-archive.com/aufs-users@lists.sourceforge.net/msg02587.html
+       //     http://www.mail-archive.com/aufs-users@lists.sourceforge.net/msg05126.html
        if (mntdata) {
-               len = strlen(lower) + strlen(upper) + strlen(runpath) + strlen("br==rw:=ro,,xino=/aufs.xino") + strlen(mntdata) + 1;
+               len = strlen(lower) + strlen(upper) + strlen(xinopath) + strlen("br==rw:=ro,,xino=") + strlen(mntdata) + 1;
                options = alloca(len);
-               ret = snprintf(options, len, "br=%s=rw:%s=ro,%s,xino=%s/aufs.xino", upper, lower, mntdata, runpath);
+               ret = snprintf(options, len, "br=%s=rw:%s=ro,%s,xino=%s", upper, lower, mntdata, xinopath);
        }
        else {
-               len = strlen(lower) + strlen(upper) + strlen(runpath) + strlen("br==rw:=ro,xino=/aufs.xino") + 1;
+               len = strlen(lower) + strlen(upper) + strlen(xinopath) + strlen("br==rw:=ro,xino=") + 1;
                options = alloca(len);
-               ret = snprintf(options, len, "br=%s=rw:%s=ro,xino=%s/aufs.xino", upper, lower, runpath);
+               ret = snprintf(options, len, "br=%s=rw:%s=ro,xino=%s", upper, lower, xinopath);
        }
 
-       free(rundir);
-
        if (ret < 0 || ret >= len) {
                free(mntdata);
                return -1;
@@ -2672,6 +2655,9 @@ static int aufs_clonepaths(struct bdev *orig, struct bdev *new, const char *oldn
        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, *lastslash;
                int ret, len, lastslashidx;
@@ -2696,6 +2682,8 @@ static int aufs_clonepaths(struct bdev *orig, struct bdev *new, const char *oldn
                        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 'aufs:lowerdir:upperdir'
                len = strlen(delta) + strlen(orig->src) + 12;
@@ -2729,7 +2717,23 @@ static int aufs_clonepaths(struct bdev *orig, struct bdev *new, const char *oldn
                        free(osrc);
                        return -ENOMEM;
                }
-               if (do_rsync(odelta, ndelta) < 0) {
+               if ((ret = mkdir(ndelta, 0755)) < 0 && errno != EEXIST) {
+                       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 aufs delta");
@@ -3318,6 +3322,7 @@ static bool unpriv_snap_allowed(struct bdev *b, const char *t, bool snap,
                // (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, "aufs") == 0 ||
                                strcmp(b->type, "overlayfs") == 0 ||
                                strcmp(b->type, "btrfs") == 0 ||
                                strcmp(b->type, "loop") == 0)
@@ -3327,8 +3332,11 @@ static bool unpriv_snap_allowed(struct bdev *b, const char *t, bool snap,
 
        // 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, "btrfs") == 0 || strcmp(t, "loop") == 0)
+       if (strcmp(t, "dir") == 0 ||
+               strcmp(t, "aufs") == 0 ||
+               strcmp(t, "overlayfs") == 0 ||
+               strcmp(t, "btrfs") == 0 ||
+               strcmp(t, "loop") == 0)
                return true;
        return false;
 }