[CRIU] [PATCH] crtools: Make fdset operations robust against open()
errors
Cyrill Gorcunov
gorcunov at openvz.org
Tue Jan 31 09:29:07 EST 2012
There are two cases for cr_fdset_open
- It might be called with already allocated
memory so we should reuse it.
- It might be called with NULL pointing out
that caller expects us to allocate memory.
If an open() error happens somewhere inside cr_fdset_open
it requires two error paths
- Just close all files opened but don't free memory
if it was not allocated by us
- Close all files opened *and* free memory allocated
by us.
In any case we should close all files opened so close_cr_fdset()
helper is splitted into two parts.
Also the caller should be ready for such semantics as well and
do not re-assign pointers obtained but simply test for NULL
on results.
Signed-off-by: Cyrill Gorcunov <gorcunov at openvz.org>
---
This one should do the trick I think.
cr-dump.c | 8 ++---
crtools.c | 85 +++++++++++++++++++++++++++++++++++++-----------------------
2 files changed, 55 insertions(+), 38 deletions(-)
diff --git a/cr-dump.c b/cr-dump.c
index a4b938f..8a76987 100644
--- a/cr-dump.c
+++ b/cr-dump.c
@@ -1214,8 +1214,8 @@ static int dump_one_task(struct pstree_item *item, struct cr_fdset *cr_fdset)
goto err;
};
- cr_fdset = cr_fdset_open(item->pid, CR_FD_DESC_TASK, cr_fdset);
- if (!cr_fdset)
+ ret = -1;
+ if (!cr_fdset_open(item->pid, CR_FD_DESC_TASK, cr_fdset))
goto err;
ret = collect_mappings(pid, pid_dir, &vma_area_list);
@@ -1350,9 +1350,7 @@ int cr_dump_tasks(pid_t pid, struct cr_options *opts)
goto err;
if (item->pid == pid) {
- cr_fdset = cr_fdset_open(item->pid,
- CR_FD_DESC_USE(CR_FD_PSTREE), cr_fdset);
- if (!cr_fdset)
+ if (!cr_fdset_open(item->pid, CR_FD_DESC_USE(CR_FD_PSTREE), cr_fdset))
goto err;
if (dump_pstree(pid, &pstree_list, cr_fdset))
goto err;
diff --git a/crtools.c b/crtools.c
index 560c609..faabf18 100644
--- a/crtools.c
+++ b/crtools.c
@@ -123,22 +123,55 @@ static struct cr_fdset *alloc_cr_fdset(void)
return cr_fdset;
}
+void __close_cr_fdset(struct cr_fdset *cr_fdset)
+{
+ unsigned int i;
+
+ if (!cr_fdset)
+ return;
+
+ for (i = 0; i < CR_FD_MAX; i++) {
+ if (cr_fdset->fds[i] == -1)
+ continue;
+ pr_debug("Closed %d/%d\n", i, cr_fdset->fds[i]);
+ close_safe(&cr_fdset->fds[i]);
+ cr_fdset->fds[i] = -1;
+ }
+}
+
+void close_cr_fdset(struct cr_fdset **cr_fdset)
+{
+ if (!cr_fdset || !*cr_fdset)
+ return;
+
+ __close_cr_fdset(*cr_fdset);
+
+ xfree(*cr_fdset);
+ *cr_fdset = NULL;
+}
+
struct cr_fdset *cr_fdset_open(int pid, unsigned long use_mask, struct cr_fdset *cr_fdset)
{
+ struct cr_fdset *fdset;
unsigned int i;
int ret = -1;
char path[PATH_MAX];
- if (cr_fdset == NULL) {
- cr_fdset = alloc_cr_fdset();
- if (!cr_fdset)
+ /*
+ * We either reuse existing fdset or create new one.
+ */
+ if (!cr_fdset) {
+ fdset = alloc_cr_fdset();
+ if (!fdset)
goto err;
- }
+ } else
+ fdset = cr_fdset;
for (i = 0; i < CR_FD_MAX; i++) {
if (!(use_mask & CR_FD_DESC_USE(i)))
continue;
- if (cr_fdset->fds[i] != -1)
+
+ if (fdset->fds[i] != -1)
continue;
ret = get_image_path(path, sizeof(path),
@@ -157,15 +190,21 @@ struct cr_fdset *cr_fdset_open(int pid, unsigned long use_mask, struct cr_fdset
pr_perror("Unable to open %s", path);
goto err;
}
+ fdset->fds[i] = ret;
pr_debug("Opened %s with %d\n", path, ret);
if (write_img(ret, &fdset_template[i].magic))
goto err;
-
- cr_fdset->fds[i] = ret;
}
+
+ return fdset;
+
err:
- return cr_fdset;
+ if (fdset != cr_fdset)
+ __close_cr_fdset(fdset);
+ else
+ close_cr_fdset(&fdset);
+ return NULL;
}
struct cr_fdset *prep_cr_fdset_for_restore(int pid, unsigned long use_mask)
@@ -194,43 +233,23 @@ struct cr_fdset *prep_cr_fdset_for_restore(int pid, unsigned long use_mask)
pr_perror("Unable to open %s", path);
goto err;
}
+ cr_fdset->fds[i] = ret;
pr_debug("Opened %s with %d\n", path, ret);
if (read_img(ret, &magic) < 0)
goto err;
if (magic != fdset_template[i].magic) {
- close(ret);
pr_err("Magic doesn't match for %s\n", path);
goto err;
}
- cr_fdset->fds[i] = ret;
}
-err:
- return cr_fdset;
-}
-
-void close_cr_fdset(struct cr_fdset **cr_fdset)
-{
- struct cr_fdset *fdset;
- unsigned int i;
-
- if (!cr_fdset || !*cr_fdset)
- return;
-
- fdset = *cr_fdset;
-
- for (i = 0; i < CR_FD_MAX; i++) {
- if (fdset->fds[i] == -1)
- continue;
- pr_debug("Closed %d/%d\n", i, fdset->fds[i]);
- close(fdset->fds[i]);
- fdset->fds[i] = -1;
- }
+ return cr_fdset;
- xfree(fdset);
- *cr_fdset = NULL;
+err:
+ close_cr_fdset(&cr_fdset);
+ return NULL;
}
int main(int argc, char *argv[])
--
1.7.7.6
More information about the CRIU
mailing list