2
0
mirror of https://github.com/checkpoint-restore/criu synced 2025-08-31 14:25:49 +00:00

Add new command line option: --cgroup-yard

Instead of creating cgroup yard in CRIU, now we can create it externally
and pass it to CRIU. Useful if somebody doesn't want to grant
CAP_SYS_ADMIN to CRIU.

Signed-off-by: Michał Cłapiński <mclapinski@google.com>
This commit is contained in:
Michał Cłapiński
2019-08-08 18:49:13 +02:00
committed by Andrei Vagin
parent ad7e82a30f
commit 2f337652ad
10 changed files with 126 additions and 40 deletions

View File

@@ -266,10 +266,33 @@ For example, the command line for the above example should look like this:
discovered automatically (usually via */proc*). This option is
useful when one needs *criu* to skip some controllers.
*--cgroup-props-ignore-default*::
When combined with *--cgroup-props*, makes *criu* substitute
a predefined controller property with the new one shipped. If the option
is not used, the predefined properties are merged with the provided ones.
*--cgroup-yard* 'path'::
Instead of trying to mount cgroups in CRIU, provide a path to a directory
with already created cgroup yard. Useful if you don't want to grant
CAP_SYS_ADMIN to CRIU. For every cgroup mount there should be exactly one
directory. If there is only one controller in this mount, the dir's name
should be just the name of the controller. If there are multiple controllers
comounted, the directory name should have them be separated by a comma.
+
For example, if */proc/cgroups* looks like this:
+
----------
#subsys_name hierarchy num_cgroups enabled
cpu 1 1 1
devices 2 2 1
freezer 2 2 1
----------
+
then you can create the cgroup yard by the following commands:
+
----------
mkdir private_yard
cd private_yard
mkdir cpu
mount -t cgroup -o cpu none cpu
mkdir devices,freezer
mount -t cgroup -o devices,freezer none devices,freezer
----------
*--tcp-established*::
Checkpoint established TCP connections.
@@ -442,6 +465,11 @@ The 'mode' may be one of the following:
*ignore*::: Don't deal with cgroups and pretend that they don't exist.
*--cgroup-yard* 'path'::
Instead of trying to mount cgroups in CRIU, provide a path to a directory
with already created cgroup yard. For more information look in the *dump*
section.
*--cgroup-root* ['controller'*:*]/'newroot'::
Change the root cgroup the controller will be installed into. No controller
means that root is the default for all controllers not specified.

View File

@@ -549,8 +549,9 @@ static int collect_cgroups(struct list_head *ctls)
int fd = -1;
list_for_each_entry(cc, ctls, l) {
char path[PATH_MAX], mopts[1024], *root;
char path[PATH_MAX], *root;
char prefix[] = ".criu.cgmounts.XXXXXX";
const char namestr[] = "name=";
struct cg_controller *cg;
struct cg_root_opt *o;
@@ -568,7 +569,7 @@ static int collect_cgroups(struct list_head *ctls)
if (!current_controller) {
/* only allow "fake" controllers to be created this way */
if (!strstartswith(cc->name, "name=")) {
if (!strstartswith(cc->name, namestr)) {
pr_err("controller %s not found\n", cc->name);
return -1;
} else {
@@ -586,26 +587,45 @@ static int collect_cgroups(struct list_head *ctls)
if (!opts.manage_cgroups)
continue;
if (strstartswith(cc->name, "name="))
snprintf(mopts, sizeof(mopts), "none,%s", cc->name);
else
snprintf(mopts, sizeof(mopts), "%s", cc->name);
if (opts.cgroup_yard) {
char dir_path[PATH_MAX];
int off;
off = snprintf(dir_path, PATH_MAX, "%s/", opts.cgroup_yard);
if (strstartswith(cc->name, namestr))
snprintf(dir_path + off, PATH_MAX, "%s", cc->name + strlen(namestr));
else
snprintf(dir_path + off, PATH_MAX, "%s", cc->name);
if (mkdtemp(prefix) == NULL) {
pr_perror("can't make dir for cg mounts");
return -1;
fd = open(dir_path, O_RDONLY | O_DIRECTORY, 0);
if (fd < 0) {
pr_perror("couldn't open %s", dir_path);
return -1;
}
} else {
char mopts[1024];
if (strstartswith(cc->name, namestr))
snprintf(mopts, sizeof(mopts), "none,%s", cc->name);
else
snprintf(mopts, sizeof(mopts), "%s", cc->name);
if (mkdtemp(prefix) == NULL) {
pr_perror("can't make dir for cg mounts");
return -1;
}
if (mount("none", prefix, "cgroup", 0, mopts) < 0) {
pr_perror("couldn't mount %s", mopts);
rmdir(prefix);
return -1;
}
fd = open_detach_mount(prefix);
if (fd < 0)
return -1;
}
if (mount("none", prefix, "cgroup", 0, mopts) < 0) {
pr_perror("couldn't mount %s", mopts);
rmdir(prefix);
return -1;
}
fd = open_detach_mount(prefix);
if (fd < 0)
return -1;
path_pref_len = snprintf(path, PATH_MAX, "/proc/self/fd/%d", fd);
root = cc->path;
@@ -620,6 +640,7 @@ static int collect_cgroups(struct list_head *ctls)
snprintf(path + path_pref_len, PATH_MAX - path_pref_len, "%s", root);
ret = ftw(path, add_cgroup, 4);
if (ret < 0)
pr_perror("failed walking %s for empty cgroups", path);
@@ -1167,10 +1188,12 @@ void fini_cgroup(void)
return;
close_service_fd(CGROUP_YARD);
if (umount2(cg_yard, MNT_DETACH))
pr_perror("Unable to umount %s", cg_yard);
if (rmdir(cg_yard))
pr_perror("Unable to remove %s", cg_yard);
if (!opts.cgroup_yard) {
if (umount2(cg_yard, MNT_DETACH))
pr_perror("Unable to umount %s", cg_yard);
if (rmdir(cg_yard))
pr_perror("Unable to remove %s", cg_yard);
}
xfree(cg_yard);
cg_yard = NULL;
}
@@ -1652,20 +1675,28 @@ static int prepare_cgroup_sfd(CgroupEntry *ce)
pr_info("Preparing cgroups yard (cgroups restore mode %#x)\n",
opts.manage_cgroups);
off = sprintf(paux, ".criu.cgyard.XXXXXX");
if (mkdtemp(paux) == NULL) {
pr_perror("Can't make temp cgyard dir");
return -1;
}
if (opts.cgroup_yard) {
off = sprintf(paux, "%s", opts.cgroup_yard);
cg_yard = xstrdup(paux);
if (!cg_yard) {
rmdir(paux);
return -1;
}
cg_yard = xstrdup(paux);
if (!cg_yard)
return -1;
} else {
off = sprintf(paux, ".criu.cgyard.XXXXXX");
if (mkdtemp(paux) == NULL) {
pr_perror("Can't make temp cgyard dir");
return -1;
}
if (make_yard(cg_yard))
goto err;
cg_yard = xstrdup(paux);
if (!cg_yard) {
rmdir(paux);
return -1;
}
if (make_yard(cg_yard))
goto err;
}
pr_debug("Opening %s as cg yard\n", cg_yard);
i = open(cg_yard, O_DIRECTORY);

View File

@@ -516,6 +516,7 @@ int parse_options(int argc, char **argv, bool *usage_error,
{ "tls-key", required_argument, 0, 1095},
BOOL_OPT("tls", &opts.tls),
{"tls-no-cn-verify", no_argument, &opts.tls_no_cn_verify, true},
{ "cgroup-yard", required_argument, 0, 1096 },
{ },
};
@@ -814,6 +815,9 @@ int parse_options(int argc, char **argv, bool *usage_error,
case 1095:
SET_CHAR_OPTS(tls_key, optarg);
break;
case 1096:
SET_CHAR_OPTS(cgroup_yard, optarg);
break;
case 'V':
pr_msg("Version: %s\n", CRIU_VERSION);
if (strcmp(CRIU_GITID, "0"))

View File

@@ -608,6 +608,9 @@ static int setup_opts_from_req(int sk, CriuOpts *req)
goto err;
}
if (req->cgroup_yard)
SET_CHAR_OPTS(cgroup_yard, req->cgroup_yard);
if (req->tls_cacert)
SET_CHAR_OPTS(tls_cacert, req->tls_cacert);
if (req->tls_cacrl)

View File

@@ -366,6 +366,10 @@ usage:
" --cgroup-dump-controller NAME\n"
" define cgroup controller to be dumped\n"
" and skip anything else present in system\n"
" --cgroup-yard PATH\n"
" instead of trying to mount cgroups in CRIU, provide\n"
" a path to a directory with already created cgroup yard.\n"
" Useful if you don't want to grant CAP_SYS_ADMIN to CRIU\n"
" --lsm-profile TYPE:NAME\n"
" Specify an LSM profile to be used during restore.\n"
" The type can be either 'apparmor' or 'selinux'.\n"

View File

@@ -190,7 +190,7 @@ int prepare_inventory(InventoryEntry *he)
struct dmp_info d;
} crt = { .i.pid = &pid };
pr_info("Perparing image inventory (version %u)\n", CRTOOLS_IMAGES_V1);
pr_info("Preparing image inventory (version %u)\n", CRTOOLS_IMAGES_V1);
he->img_version = CRTOOLS_IMAGES_V1_1;
he->fdinfo_per_id = true;

View File

@@ -106,6 +106,7 @@ struct cr_options {
char *cgroup_props;
char *cgroup_props_file;
struct list_head new_cgroup_roots;
char *cgroup_yard;
bool autodetect_ext_mounts;
int enable_external_sharing;
int enable_external_masters;

View File

@@ -120,6 +120,7 @@ message criu_opts {
optional string tls_key = 57;
optional bool tls = 58;
optional bool tls_no_cn_verify = 59;
optional string cgroup_yard = 60;
/* optional bool check_mounts = 128; */
}

View File

@@ -987,6 +987,19 @@ int criu_local_add_cg_dump_controller(criu_opts *opts, const char *name)
return 0;
}
int criu_local_add_cg_yard(criu_opts *opts, const char *path)
{
char *new;
new = strdup(path);
if (!new)
return -ENOMEM;
free(opts->rpc->cgroup_yard);
opts->rpc->cgroup_yard = new;
return 0;
}
int criu_add_skip_mnt(const char *mnt)
{
return criu_local_add_skip_mnt(global_opts, mnt);

View File

@@ -207,6 +207,7 @@ int criu_local_add_irmap_path(criu_opts *opts, const char *path);
int criu_local_add_cg_props(criu_opts *opts, const char *stream);
int criu_local_add_cg_props_file(criu_opts *opts, const char *path);
int criu_local_add_cg_dump_controller(criu_opts *opts, const char *name);
int criu_local_add_cg_yard(criu_opts *opts, const char *path);
int criu_local_add_inherit_fd(criu_opts *opts, int fd, const char *key);
int criu_local_add_external(criu_opts *opts, const char *key);
int criu_local_set_page_server_address_port(criu_opts *opts, const char *address, int port);