Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/checkpoint-restore/criu.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPavel Tikhomirov <ptikhomirov@virtuozzo.com>2020-02-13 10:43:14 +0300
committerAndrei Vagin <avagin@gmail.com>2022-04-29 03:53:52 +0300
commit5a0943c900caf9ba195e14e18acaa707d72bed1a (patch)
tree5bb1991f9a658948c94c572695ae4ef87292db19 /criu/files-reg.c
parent64b58b51413b06bd99e4b922c1c690845134e290 (diff)
files-reg: fix error handling in open_path
1) On error paths need to close fd and unlock mutex. 2) Make rfi_remap return special return code to identify EEXIST from linkat_hard, all other errors should be reported up. 3) Report unlinkat error as criu should not corrupt fs. Cherry-picked from Virtuozzo criu: https://src.openvz.org/projects/OVZ/repos/criu/commits/fe1d0be14 Changes: use close_safe(), fix order in "Fake %s -> %s link" error message. Signed-off-by: Pavel Tikhomirov <ptikhomirov@virtuozzo.com>
Diffstat (limited to 'criu/files-reg.c')
-rw-r--r--criu/files-reg.c47
1 files changed, 31 insertions, 16 deletions
diff --git a/criu/files-reg.c b/criu/files-reg.c
index 679477c1c..4560f253e 100644
--- a/criu/files-reg.c
+++ b/criu/files-reg.c
@@ -1867,6 +1867,9 @@ out:
* This routine properly resolves d's path handling ghost/link-remaps.
* The open_cb is a routine that does actual open, it differs for
* files, directories, fifos, etc.
+ *
+ * Return 0 on success, -1 on error and 1 to indicate soft error, which can be
+ * retried.
*/
static int rfi_remap(struct reg_file_info *rfi, int *level)
@@ -1932,6 +1935,8 @@ out_root:
int errno_saved = errno;
rm_parent_dirs(mntns_root, path, *level);
errno = errno_saved;
+ if (errno == EEXIST)
+ return 1;
return -1;
}
@@ -2008,11 +2013,12 @@ static bool validate_file(const int fd, const struct stat *fd_status, const stru
int open_path(struct file_desc *d, int (*open_cb)(int mntns_root, struct reg_file_info *, void *), void *arg)
{
- int tmp, mntns_root, level = 0;
+ int tmp = -1, mntns_root, level = 0;
struct reg_file_info *rfi;
char *orig_path = NULL;
char path[PATH_MAX];
int inh_fd = -1;
+ int ret;
if (inherited_fd(d, &tmp))
return tmp;
@@ -2049,14 +2055,9 @@ int open_path(struct file_desc *d, int (*open_cb)(int mntns_root, struct reg_fil
*/
orig_path = rfi->path;
rfi->path = rfi->remap->rpath;
- } else if (rfi_remap(rfi, &level) < 0) {
+ } else if ((ret = rfi_remap(rfi, &level)) == 1) {
static char tmp_path[PATH_MAX];
- if (errno != EEXIST) {
- pr_perror("Can't link %s -> %s", rfi->remap->rpath, rfi->path);
- return -1;
- }
-
/*
* The file whose name we're trying to create
* exists. Need to pick some other one, we're
@@ -2070,12 +2071,15 @@ int open_path(struct file_desc *d, int (*open_cb)(int mntns_root, struct reg_fil
orig_path = rfi->path;
rfi->path = tmp_path;
snprintf(tmp_path, sizeof(tmp_path), "%s.cr_link", orig_path);
- pr_debug("Fake %s -> %s link\n", rfi->path, rfi->remap->rpath);
+ pr_debug("Fake %s -> %s link\n", rfi->remap->rpath, rfi->path);
- if (rfi_remap(rfi, &level) < 0) {
+ if (rfi_remap(rfi, &level)) {
pr_perror("Can't create even fake link!");
- return -1;
+ goto err;
}
+ } else if (ret < 0) {
+ pr_perror("Can't link %s -> %s", rfi->remap->rpath, rfi->path);
+ goto err;
}
}
@@ -2085,7 +2089,7 @@ ext:
if (tmp < 0) {
pr_perror("Can't open file %s", rfi->path);
close_safe(&inh_fd);
- return -1;
+ goto err;
}
close_safe(&inh_fd);
@@ -2094,15 +2098,15 @@ ext:
if (fstat(tmp, &st) < 0) {
pr_perror("Can't fstat opened file");
- return -1;
+ goto err;
}
if (!validate_file(tmp, &st, rfi))
- return -1;
+ 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);
- return -1;
+ goto err;
}
/*
@@ -2115,7 +2119,11 @@ ext:
if (rfi->remap) {
if (!rfi->remap->is_dir) {
- unlinkat(mntns_root, rfi->path, 0);
+ pr_debug("Unlink: %d:%s\n", rfi->rfe->mnt_id, rfi->path);
+ if (unlinkat(mntns_root, rfi->path, 0)) {
+ pr_perror("Failed to unlink the remap file");
+ goto err;
+ }
rm_parent_dirs(mntns_root, rfi->path, level);
}
@@ -2124,10 +2132,17 @@ ext:
if (orig_path)
rfi->path = orig_path;
- if (restore_fown(tmp, rfi->rfe->fown))
+ if (restore_fown(tmp, rfi->rfe->fown)) {
+ close(tmp);
return -1;
+ }
return tmp;
+err:
+ if (rfi->remap)
+ mutex_unlock(remap_open_lock);
+ close_safe(&tmp);
+ return -1;
}
int do_open_reg_noseek_flags(int ns_root_fd, struct reg_file_info *rfi, void *arg)