lxc_log_define(bdev, lxc);
+struct rsync_data_char {
+ char *src;
+ char *dest;
+};
+
static int do_rsync(const char *src, const char *dest)
{
// call out to rsync
return ret;
}
+static int btrfs_snapshot_wrapper(void *data)
+{
+ struct rsync_data_char *arg = 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;
+ }
+ return btrfs_snapshot(arg->src, arg->dest);
+}
+
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, struct lxc_conf *conf)
if (orig->mntopts && (new->mntopts = strdup(orig->mntopts)) == NULL)
return -1;
- if (snap)
- return btrfs_snapshot(orig->dest, new->dest);
+ if (snap) {
+ struct rsync_data_char sdata;
+ if (!am_unpriv())
+ return btrfs_snapshot(orig->dest, new->dest);
+ sdata.dest = new->dest;
+ sdata.src = orig->dest;
+ return userns_exec_1(conf, btrfs_snapshot_wrapper, &sdata);
+ }
if (rmdir(new->dest) < 0 && errno != -ENOENT) {
SYSERROR("removing %s", new->dest);
args.name[BTRFS_SUBVOL_NAME_MAX-1] = 0;
ret = ioctl(fd, BTRFS_IOC_SNAP_DESTROY, &args);
INFO("btrfs: snapshot create ioctl returned %d", ret);
+ if (ret < 0 && errno == EPERM)
+ INFO("Is the rootfs mounted with -o user_subvol_rm_allowed?");
free(newfull);
close(fd);
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) {
// overlayfs -- which is also allowed)
if (strcmp(b->type, "dir") == 0 ||
strcmp(b->type, "overlayfs") == 0 ||
+ strcmp(b->type, "btrfs") == 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)
+ strcmp(t, "btrfs") == 0 || strcmp(t, "loop") == 0)
return true;
return false;
}
fprintf(stderr, "You lack access to %s\n", my_args.lxcpath[0]);
exit(1);
}
- if (strcmp(my_args.bdevtype, "dir") && strcmp(my_args.bdevtype, "_unset")) {
- fprintf(stderr, "Unprivileged users can only create directory backed containers\n");
+ if (strcmp(my_args.bdevtype, "dir") && strcmp(my_args.bdevtype, "_unset") &&
+ strcmp(my_args.bdevtype, "btrfs")) {
+ fprintf(stderr, "Unprivileged users cannot create %s containers", my_args.bdevtype);
exit(1);
}
}