Commit f84ea82b authored by Pavel Tikhomirov's avatar Pavel Tikhomirov Committed by Andrei Vagin

image/dedup: use userns_call to be able to open images for write

When restoring a task in it's user namespace we had: "Unable to open
pages-3.img: Permission denied" when trying to open pages images for
write. (Write is needed for memory images deduplication feature to
work.)

These patch makes do_open_image open images fd through usernsd, to have
root permissions.

Also increase MAX_UNSFD_MSG_SIZE as path and metadata don't fit, and
remove a workaround in prepare_vma_ios.
Signed-off-by: 's avatarPavel Tikhomirov <ptikhomirov@virtuozzo.com>
Signed-off-by: 's avatarAndrei Vagin <avagin@gmail.com>
parent 76f8c090
......@@ -17,6 +17,7 @@
#include "images/inventory.pb-c.h"
#include "images/pagemap.pb-c.h"
#include "proc_parse.h"
#include "namespaces.h"
bool ns_per_id = false;
bool img_common_magic = true;
......@@ -367,13 +368,49 @@ static int img_write_magic(struct cr_img *img, int oflags, int type)
return write_img(img, &imgset_template[type].magic);
}
struct openat_args {
char path[PATH_MAX];
int flags;
int err;
int mode;
};
static int userns_openat(void *arg, int dfd, int pid)
{
struct openat_args *pa = (struct openat_args *)arg;
int ret;
ret = openat(dfd, pa->path, pa->flags, pa->mode);
if (ret < 0)
pa->err = errno;
return ret;
}
static int do_open_image(struct cr_img *img, int dfd, int type, unsigned long oflags, char *path)
{
int ret, flags;
flags = oflags & ~(O_NOBUF | O_SERVICE | O_FORCE_LOCAL);
ret = openat(dfd, path, flags, CR_FD_PERM);
/*
* For pages images dedup we need to open images read-write on
* restore, that may require proper capabilities, so we ask
* usernsd to do it for us
*/
if (root_ns_mask & CLONE_NEWUSER &&
type == CR_FD_PAGES && oflags & O_RDWR) {
struct openat_args pa = {
.flags = flags,
.err = 0,
.mode = CR_FD_PERM,
};
snprintf(pa.path, PATH_MAX, "%s", path);
ret = userns_call(userns_openat, UNS_FDOUT, &pa, sizeof(struct openat_args), dfd);
if (ret < 0)
errno = pa.err;
} else
ret = openat(dfd, path, flags, CR_FD_PERM);
if (ret < 0) {
if (!(flags & O_CREAT) && (errno == ENOENT || ret == -ENOENT)) {
pr_info("No %s image\n", path);
......
......@@ -198,7 +198,7 @@ typedef int (*uns_call_t)(void *arg, int fd, pid_t pid);
*/
#define UNS_FDOUT 0x2
#define MAX_UNSFD_MSG_SIZE 4096
#define MAX_UNSFD_MSG_SIZE 8192
/*
* When we're restoring inside user namespace, some things are
......
......@@ -1299,20 +1299,12 @@ static int prepare_vma_ios(struct pstree_item *t, struct task_restore_args *ta)
{
struct cr_img *pages;
/* if auto-dedup is on we need RDWR mode to be able to punch holes
* in the input files (in restorer.c)
/*
* If auto-dedup is on we need RDWR mode to be able to punch holes in
* the input files (in restorer.c)
*/
pages = open_image(CR_FD_PAGES, opts.auto_dedup ? O_RDWR : O_RSTR,
rsti(t)->pages_img_id);
/* When running inside namespace we might lack privileges to open the file
* for writing.
* TODO: use userns_call to do the opening instead of downgrading to opening
* read-only.
*/
if (!pages && opts.auto_dedup) {
pr_warn("Failed to open image read-write, trying read-only instead. auto-dedup won't work\n");
pages = open_image(CR_FD_PAGES, O_RSTR, rsti(t)->pages_img_id);
}
if (!pages)
return -1;
......
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