diff --git a/Documentation/criu.txt b/Documentation/criu.txt index 8b128f63e..8d2e91443 100644 --- a/Documentation/criu.txt +++ b/Documentation/criu.txt @@ -668,6 +668,9 @@ The 'mode' may be one of the following: build-ID cannot be obtained, 'chksm-first' method will be used. This is the default if mode is unspecified. +*--skip-file-rwx-check*:: + Skip checking file permissions (r/w/x for u/g/o) on restore. + *check* ~~~~~~~ Checks whether the kernel supports the features needed by *criu* to diff --git a/criu/config.c b/criu/config.c index 4023d807c..24c445c8b 100644 --- a/criu/config.c +++ b/criu/config.c @@ -696,6 +696,7 @@ int parse_options(int argc, char **argv, bool *usage_error, bool *has_exec_cmd, { "cgroup-yard", required_argument, 0, 1096 }, { "pre-dump-mode", required_argument, 0, 1097 }, { "file-validation", required_argument, 0, 1098 }, + BOOL_OPT("skip-file-rwx-check", &opts.skip_file_rwx_check), { "lsm-mount-context", required_argument, 0, 1099 }, { "network-lock", required_argument, 0, 1100 }, BOOL_OPT("mntns-compat-mode", &opts.mntns_compat_mode), diff --git a/criu/cr-service.c b/criu/cr-service.c index a6eb9ebd3..1d9f0aca3 100644 --- a/criu/cr-service.c +++ b/criu/cr-service.c @@ -464,6 +464,9 @@ static int setup_opts_from_req(int sk, CriuOpts *req) if (req->has_shell_job) opts.shell_job = req->shell_job; + if (req->has_skip_file_rwx_check) + opts.skip_file_rwx_check = req->skip_file_rwx_check; + if (req->has_file_locks) opts.handle_file_locks = req->file_locks; diff --git a/criu/crtools.c b/criu/crtools.c index cc8d9179f..8bcbe8e38 100644 --- a/criu/crtools.c +++ b/criu/crtools.c @@ -504,6 +504,9 @@ usage: " --file-validation METHOD\n" " pass the validation method to be used; argument\n" " can be 'filesize' or 'buildid' (default).\n" + " --skip-file-rwx-check\n" + " Skip checking file permissions\n" + " (r/w/x for u/g/o) on restore.\n" "\n" "Check options:\n" " Without options, \"criu check\" checks availability of absolutely required\n" diff --git a/criu/files-reg.c b/criu/files-reg.c index 0249063c2..ce8788637 100644 --- a/criu/files-reg.c +++ b/criu/files-reg.c @@ -2199,9 +2199,21 @@ ext: if (!validate_file(tmp, &st, rfi)) goto err; - if (rfi->rfe->has_mode && (st.st_mode != rfi->rfe->mode)) { - pr_err("File %s has bad mode 0%o (expect 0%o)\n", rfi->path, (int)st.st_mode, rfi->rfe->mode); - goto err; + if (rfi->rfe->has_mode) { + mode_t curr_mode = st.st_mode; + mode_t saved_mode = rfi->rfe->mode; + + if (opts.skip_file_rwx_check) { + curr_mode &= ~(S_IRWXU | S_IRWXG | S_IRWXO); + saved_mode &= ~(S_IRWXU | S_IRWXG | S_IRWXO); + } + + if (curr_mode != saved_mode) { + pr_err("File %s has bad mode 0%o (expect 0%o)\n" + "File r/w/x checks can be skipped with the --skip-file-rwx-check option\n", + rfi->path, (int)curr_mode, saved_mode); + goto err; + } } /* diff --git a/criu/include/cr_options.h b/criu/include/cr_options.h index bf1a762cc..e544a2d9a 100644 --- a/criu/include/cr_options.h +++ b/criu/include/cr_options.h @@ -179,6 +179,7 @@ struct cr_options { bool lazy_pages; char *work_dir; int network_lock_method; + int skip_file_rwx_check; /* * When we scheduler for removal some functionality we first diff --git a/images/rpc.proto b/images/rpc.proto index a6cc5da48..3cf431639 100644 --- a/images/rpc.proto +++ b/images/rpc.proto @@ -138,6 +138,7 @@ message criu_opts { optional string lsm_mount_context = 63; optional criu_network_lock_method network_lock = 64 [default = IPTABLES]; optional bool mntns_compat_mode = 65; + optional bool skip_file_rwx_check = 66; /* optional bool check_mounts = 128; */ } diff --git a/lib/c/criu.c b/lib/c/criu.c index 7807d7bc5..8171f7a12 100644 --- a/lib/c/criu.c +++ b/lib/c/criu.c @@ -555,6 +555,17 @@ void criu_set_shell_job(bool shell_job) criu_local_set_shell_job(global_opts, shell_job); } +void criu_local_set_skip_file_rwx_check(criu_opts *opts, bool skip_file_rwx_check) +{ + opts->rpc->has_skip_file_rwx_check = true; + opts->rpc->skip_file_rwx_check = skip_file_rwx_check; +} + +void criu_set_skip_file_rwx_check(bool skip_file_rwx_check) +{ + criu_local_set_skip_file_rwx_check(global_opts, skip_file_rwx_check); +} + void criu_local_set_orphan_pts_master(criu_opts *opts, bool orphan_pts_master) { opts->rpc->has_orphan_pts_master = true; diff --git a/lib/c/criu.h b/lib/c/criu.h index 7cc6a199c..c32a8a646 100644 --- a/lib/c/criu.h +++ b/lib/c/criu.h @@ -78,6 +78,7 @@ void criu_set_tcp_close(bool tcp_close); void criu_set_weak_sysctls(bool val); void criu_set_evasive_devices(bool evasive_devices); void criu_set_shell_job(bool shell_job); +void criu_set_skip_file_rwx_check(bool skip_file_rwx_check); void criu_set_orphan_pts_master(bool orphan_pts_master); void criu_set_file_locks(bool file_locks); void criu_set_track_mem(bool track_mem); @@ -238,6 +239,7 @@ void criu_local_set_tcp_close(criu_opts *opts, bool tcp_close); void criu_local_set_weak_sysctls(criu_opts *opts, bool val); void criu_local_set_evasive_devices(criu_opts *opts, bool evasive_devices); void criu_local_set_shell_job(criu_opts *opts, bool shell_job); +void criu_local_set_skip_file_rwx_check(criu_opts *opts, bool skip_file_rwx_check); void criu_local_set_orphan_pts_master(criu_opts *opts, bool orphan_pts_master); void criu_local_set_file_locks(criu_opts *opts, bool file_locks); void criu_local_set_track_mem(criu_opts *opts, bool track_mem);