mirror of
https://github.com/checkpoint-restore/criu.git
synced 2026-01-23 02:14:37 +00:00
Enable changing of mount context on restore
This change is motivated by checkpointing and restoring container in Pods. When restoring a container into a new Pod the SELinux label of the existing Pod needs to be used and not the SELinux label saved during checkpointing. The option --lsm-profile already enables changing of process SELinux labels on restore. If there are, however, tmpfs checkpointed they will be mounted during restore with the same context as during checkpointing. This can look like the following example: context="system_u:object_r:container_file_t:s0:c82,c137" On restore we want to change this context to match the mount label of the Pod this container is restored into. Changing of the mount label is now possible with the new option --mount-context: criu restore --mount-context "system_u:object_r:container_file_t:s0:c204,c495" This will lead to mount options being changed to context="system_u:object_r:container_file_t:s0:c204,c495" Now the restored container can access all the files in the container again. This has been tested in combination with runc and CRI-O. Signed-off-by: Adrian Reber <areber@redhat.com>
This commit is contained in:
parent
5be71273f6
commit
64dd64e504
7 changed files with 99 additions and 2 deletions
|
|
@ -554,6 +554,28 @@ The 'mode' may be one of the following:
|
|||
Specify an LSM profile to be used during restore. The _type_ can be
|
||||
either *apparmor* or *selinux*.
|
||||
|
||||
*--lsm-mount-context* 'context'::
|
||||
Specify a new mount context to be used during restore.
|
||||
+
|
||||
This option will only replace existing mount context information
|
||||
with the one specified with this option. Mounts without the
|
||||
'context=' option will not be changed.
|
||||
+
|
||||
If a mountpoint has been checkpointed with an option like
|
||||
|
||||
context="system_u:object_r:container_file_t:s0:c82,c137"
|
||||
+
|
||||
it is possible to change this option using
|
||||
|
||||
--lsm-mount-context "system_u:object_r:container_file_t:s0:c204,c495"
|
||||
+
|
||||
which will result that the mountpoint will be restored
|
||||
with the new 'context='.
|
||||
+
|
||||
This option is useful if using *selinux* and if the *selinux*
|
||||
labels need to be changed on restore like if a container is
|
||||
restored into an existing Pod.
|
||||
|
||||
*--auto-dedup*::
|
||||
As soon as a page is restored it get punched out from image.
|
||||
|
||||
|
|
|
|||
|
|
@ -690,6 +690,7 @@ int parse_options(int argc, char **argv, bool *usage_error,
|
|||
{ "cgroup-yard", required_argument, 0, 1096 },
|
||||
{ "pre-dump-mode", required_argument, 0, 1097},
|
||||
{ "file-validation", required_argument, 0, 1098 },
|
||||
{ "lsm-mount-context", required_argument, 0, 1099 },
|
||||
{ },
|
||||
};
|
||||
|
||||
|
|
@ -1019,6 +1020,9 @@ int parse_options(int argc, char **argv, bool *usage_error,
|
|||
if (parse_file_validation_method(&opts, optarg))
|
||||
return 2;
|
||||
break;
|
||||
case 1099:
|
||||
SET_CHAR_OPTS(lsm_mount_context, optarg);
|
||||
break;
|
||||
case 'V':
|
||||
pr_msg("Version: %s\n", CRIU_VERSION);
|
||||
if (strcmp(CRIU_GITID, "0"))
|
||||
|
|
|
|||
|
|
@ -623,6 +623,9 @@ static int setup_opts_from_req(int sk, CriuOpts *req)
|
|||
SET_CHAR_OPTS(lsm_profile, req->lsm_profile);
|
||||
}
|
||||
|
||||
if (req->lsm_mount_context)
|
||||
SET_CHAR_OPTS(lsm_mount_context, req->lsm_mount_context);
|
||||
|
||||
if (req->has_timeout)
|
||||
opts.timeout = req->timeout;
|
||||
|
||||
|
|
|
|||
|
|
@ -422,6 +422,10 @@ usage:
|
|||
" --lsm-profile TYPE:NAME\n"
|
||||
" Specify an LSM profile to be used during restore.\n"
|
||||
" The type can be either 'apparmor' or 'selinux'.\n"
|
||||
" --lsm-mount-context CTX\n"
|
||||
" Specify a mount context to be used during restore.\n"
|
||||
" Only mounts with an existing context will have their\n"
|
||||
" mount context replaced with CTX.\n"
|
||||
" --skip-mnt PATH ignore this mountpoint when dumping the mount namespace\n"
|
||||
" --enable-fs FSNAMES a comma separated list of filesystem names or \"all\"\n"
|
||||
" force criu to (try to) dump/restore these filesystem's\n"
|
||||
|
|
|
|||
|
|
@ -145,6 +145,7 @@ struct cr_options {
|
|||
struct list_head irmap_scan_paths;
|
||||
bool lsm_supplied;
|
||||
char *lsm_profile;
|
||||
char *lsm_mount_context;
|
||||
unsigned int timeout;
|
||||
unsigned int empty_ns;
|
||||
int tcp_skip_in_flight;
|
||||
|
|
|
|||
66
criu/mount.c
66
criu/mount.c
|
|
@ -45,6 +45,8 @@
|
|||
#define BINFMT_MISC_HOME "proc/sys/fs/binfmt_misc"
|
||||
#define CRTIME_MNT_ID 0
|
||||
|
||||
#define CONTEXT_OPT "context="
|
||||
|
||||
/* A helper mount_info entry for the roots yard */
|
||||
static struct mount_info *root_yard_mp = NULL;
|
||||
|
||||
|
|
@ -2942,6 +2944,66 @@ static int get_mp_mountpoint(char *mountpoint, struct mount_info *mi, char *root
|
|||
return 0;
|
||||
}
|
||||
|
||||
static char *mount_update_lsm_context(char *mount_opts)
|
||||
{
|
||||
cleanup_free char *before_context = NULL;
|
||||
char *other_options;
|
||||
char *context_start;
|
||||
char *context_end;
|
||||
char *old_context;
|
||||
char *new_options;
|
||||
int ret;
|
||||
|
||||
old_context = strstr(mount_opts, CONTEXT_OPT);
|
||||
|
||||
if (!old_context || !opts.lsm_mount_context)
|
||||
return xstrdup(mount_opts);
|
||||
|
||||
/*
|
||||
* If the user specified a different mount_context we need
|
||||
* to replace the existing mount context in the mount
|
||||
* options with the one specified by the user.
|
||||
*
|
||||
* The original mount options will be something like:
|
||||
*
|
||||
* context="system_u:object_r:container_file_t:s0:c82,c137",inode64
|
||||
*
|
||||
* and it needs to be replaced with opts.lsm_mount_context.
|
||||
*
|
||||
* The content between 'context=' and ',inode64' will be replaced
|
||||
* with opts.lsm_mount_context in quotes.
|
||||
*/
|
||||
|
||||
/* Skip 'context=' */
|
||||
context_start = old_context + strlen(CONTEXT_OPT);
|
||||
if (context_start[0] == '"' && context_start + 1 < mount_opts + strlen(mount_opts)) {
|
||||
/* Skip quotes */
|
||||
context_end = strchr(context_start + 1, '"');
|
||||
if (!context_end) {
|
||||
pr_err("Failed parsing mount option 'context'\n");
|
||||
return NULL;
|
||||
}
|
||||
} else {
|
||||
context_end = context_start;
|
||||
}
|
||||
|
||||
/* Find next after optionally skipping quotes. */
|
||||
other_options = strchr(context_end, ',');
|
||||
|
||||
before_context = xstrdup(mount_opts);
|
||||
if (unlikely(!before_context))
|
||||
return NULL;
|
||||
before_context[context_start - mount_opts] = 0;
|
||||
|
||||
ret = asprintf(&new_options, "%s\"%s\"%s", before_context,
|
||||
opts.lsm_mount_context, other_options ? other_options : "");
|
||||
if (unlikely(ret < 0))
|
||||
return NULL;
|
||||
pr_debug("\t\tChanged mount 'context=' to %s\n", new_options);
|
||||
|
||||
return new_options;
|
||||
}
|
||||
|
||||
static int collect_mnt_from_image(struct mount_info **head, struct mount_info **tail, struct ns_id *nsid)
|
||||
{
|
||||
MntEntry *me = NULL;
|
||||
|
|
@ -3006,8 +3068,8 @@ static int collect_mnt_from_image(struct mount_info **head, struct mount_info **
|
|||
if (!pm->source)
|
||||
goto err;
|
||||
|
||||
pm->options = xstrdup(me->options);
|
||||
if (!pm->options)
|
||||
pm->options = mount_update_lsm_context(me->options);
|
||||
if (unlikely(!pm->options))
|
||||
goto err;
|
||||
|
||||
if (me->fstype != FSTYPE__AUTO && me->fsname) {
|
||||
|
|
|
|||
|
|
@ -130,6 +130,7 @@ message criu_opts {
|
|||
optional string cgroup_yard = 60;
|
||||
optional criu_pre_dump_mode pre_dump_mode = 61 [default = SPLICE];
|
||||
optional int32 pidfd_store_sk = 62;
|
||||
optional string lsm_mount_context = 63;
|
||||
/* optional bool check_mounts = 128; */
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue