mirror of
https://github.com/checkpoint-restore/criu.git
synced 2026-07-18 00:58:31 +00:00
criu: fix double-open of userns image in --stream mode
restore_userns_binfmt_misc() was opening the userns image a second
time, but criu-image-streamer rejects duplicate file requests:
criu-image-streamer Error: CRIU is requesting the image file
userns-15.img multiple times. This is not allowed to keep the
memory usage low
Fix by pre-reading the image once in a new read_user_ns_img()
helper, called from prepare_namespace_before_tasks() which runs
before the first clone(). Following the same pattern as NetnsEntry
on net namespace ids, the UsernsEntry is stored in a new 'user.e'
field on the ns_id structure for the user namespace. Both the CRIU
coordinator (prepare_userns) and the forked root task
(restore_userns_binfmt_misc) look up the ns_id and access the
entry from there -- no second open_image() call is needed.
Tested with:
sudo ./test/zdtm.py run --stream -t zdtm/static/env00 --ignore-taint
sudo ./test/zdtm.py run --stream -t zdtm/static/env00 --ignore-taint -f uns
Both pass with the fix applied.
Fixes: e6510a338a ("criu: Support binfmt_misc sandboxing")
Fixes: #2924
Signed-off-by: Ahmed Elaidy <elaidya225@gmail.com>
This commit is contained in:
parent
8c29a7ccd5
commit
6b291033f9
2 changed files with 57 additions and 16 deletions
|
|
@ -7,6 +7,7 @@
|
|||
#include "files.h"
|
||||
#include "common/list.h"
|
||||
#include "images/netdev.pb-c.h"
|
||||
#include "images/userns.pb-c.h"
|
||||
|
||||
#ifndef CLONE_NEWNS
|
||||
#define CLONE_NEWNS 0x00020000
|
||||
|
|
@ -138,6 +139,10 @@ struct ns_id {
|
|||
struct list_head links;
|
||||
NetnsEntry *netns;
|
||||
} net;
|
||||
|
||||
struct {
|
||||
UsernsEntry *e;
|
||||
} user;
|
||||
};
|
||||
};
|
||||
extern struct ns_id *ns_ids;
|
||||
|
|
|
|||
|
|
@ -1581,19 +1581,49 @@ int stop_usernsd(void)
|
|||
return ret;
|
||||
}
|
||||
|
||||
int prepare_userns(struct pstree_item *item)
|
||||
static int read_user_ns_img(void)
|
||||
{
|
||||
struct ns_id *ns;
|
||||
struct cr_img *img;
|
||||
UsernsEntry *e;
|
||||
int ret;
|
||||
|
||||
img = open_image(CR_FD_USERNS, O_RSTR, item->ids->user_ns_id);
|
||||
if (!(root_ns_mask & CLONE_NEWUSER))
|
||||
return 0;
|
||||
|
||||
ns = lookup_ns_by_id(root_item->ids->user_ns_id, &user_ns_desc);
|
||||
if (!ns) {
|
||||
pr_err("Can not find user ns\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
img = open_image(CR_FD_USERNS, O_RSTR, root_item->ids->user_ns_id);
|
||||
if (!img)
|
||||
return -1;
|
||||
ret = pb_read_one(img, &e, PB_USERNS);
|
||||
ret = pb_read_one(img, &ns->user.e, PB_USERNS);
|
||||
close_image(img);
|
||||
if (ret < 0)
|
||||
if (ret < 0) {
|
||||
pr_err("Can not read userns object\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int prepare_userns(struct pstree_item *item)
|
||||
{
|
||||
struct ns_id *ns;
|
||||
UsernsEntry *e;
|
||||
|
||||
ns = lookup_ns_by_id(item->ids->user_ns_id, &user_ns_desc);
|
||||
if (!ns) {
|
||||
pr_err("Can not find user ns\n");
|
||||
return -1;
|
||||
}
|
||||
e = ns->user.e;
|
||||
if (!e) {
|
||||
pr_err("userns image was not pre-read\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (write_id_map(item->pid->real, e->uid_map, e->n_uid_map, "uid_map"))
|
||||
return -1;
|
||||
|
|
@ -1606,24 +1636,27 @@ int prepare_userns(struct pstree_item *item)
|
|||
|
||||
int restore_userns_binfmt_misc(struct pstree_item *item)
|
||||
{
|
||||
struct cr_img *img;
|
||||
struct ns_id *ns;
|
||||
UsernsEntry *e;
|
||||
int ret = 0;
|
||||
int ret;
|
||||
|
||||
img = open_image(CR_FD_USERNS, O_RSTR, item->ids->user_ns_id);
|
||||
if (!img)
|
||||
ns = lookup_ns_by_id(item->ids->user_ns_id, &user_ns_desc);
|
||||
if (!ns) {
|
||||
pr_err("Can not find user ns\n");
|
||||
return -1;
|
||||
ret = pb_read_one(img, &e, PB_USERNS);
|
||||
close_image(img);
|
||||
if (ret < 0)
|
||||
}
|
||||
e = ns->user.e;
|
||||
if (!e) {
|
||||
pr_err("userns image was not pre-read\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (binfmt_misc_restore_sandboxed(item->pid->real, e->binfmt_misc, e->n_binfmt_misc))
|
||||
ret = -1;
|
||||
ret = binfmt_misc_restore_sandboxed(item->pid->real, e->binfmt_misc, e->n_binfmt_misc);
|
||||
|
||||
userns_entry__free_unpacked(e, NULL);
|
||||
userns_entry__free_unpacked(ns->user.e, NULL);
|
||||
ns->user.e = NULL;
|
||||
|
||||
return ret < 0 ? -1 : 0;
|
||||
return ret ? -1 : 0;
|
||||
}
|
||||
|
||||
int collect_namespaces(bool for_dump)
|
||||
|
|
@ -1887,6 +1920,9 @@ int prepare_namespace_before_tasks(void)
|
|||
if (read_pid_ns_img())
|
||||
goto err_img;
|
||||
|
||||
if (read_user_ns_img())
|
||||
goto err_img;
|
||||
|
||||
return 0;
|
||||
|
||||
err_img:
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue