Commit 7705df53 authored by Cyrill Gorcunov's avatar Cyrill Gorcunov

crtools: Make fdset operations robust against open() errors

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: 's avatarCyrill Gorcunov <gorcunov@openvz.org>
Acked-by: 's avatarPavel Emelyanov <xemul@parallels.com>
parent 6c1e5978
...@@ -1214,8 +1214,8 @@ static int dump_one_task(struct pstree_item *item, struct cr_fdset *cr_fdset) ...@@ -1214,8 +1214,8 @@ static int dump_one_task(struct pstree_item *item, struct cr_fdset *cr_fdset)
goto err; goto err;
}; };
cr_fdset = cr_fdset_open(item->pid, CR_FD_DESC_TASK, cr_fdset); ret = -1;
if (!cr_fdset) if (!cr_fdset_open(item->pid, CR_FD_DESC_TASK, cr_fdset))
goto err; goto err;
ret = collect_mappings(pid, pid_dir, &vma_area_list); ret = collect_mappings(pid, pid_dir, &vma_area_list);
...@@ -1350,9 +1350,7 @@ int cr_dump_tasks(pid_t pid, struct cr_options *opts) ...@@ -1350,9 +1350,7 @@ int cr_dump_tasks(pid_t pid, struct cr_options *opts)
goto err; goto err;
if (item->pid == pid) { if (item->pid == pid) {
cr_fdset = cr_fdset_open(item->pid, if (!cr_fdset_open(item->pid, CR_FD_DESC_USE(CR_FD_PSTREE), cr_fdset))
CR_FD_DESC_USE(CR_FD_PSTREE), cr_fdset);
if (!cr_fdset)
goto err; goto err;
if (dump_pstree(pid, &pstree_list, cr_fdset)) if (dump_pstree(pid, &pstree_list, cr_fdset))
goto err; goto err;
......
...@@ -123,22 +123,55 @@ static struct cr_fdset *alloc_cr_fdset(void) ...@@ -123,22 +123,55 @@ static struct cr_fdset *alloc_cr_fdset(void)
return cr_fdset; 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 *cr_fdset_open(int pid, unsigned long use_mask, struct cr_fdset *cr_fdset)
{ {
struct cr_fdset *fdset;
unsigned int i; unsigned int i;
int ret = -1; int ret = -1;
char path[PATH_MAX]; char path[PATH_MAX];
if (cr_fdset == NULL) { /*
cr_fdset = alloc_cr_fdset(); * We either reuse existing fdset or create new one.
if (!cr_fdset) */
if (!cr_fdset) {
fdset = alloc_cr_fdset();
if (!fdset)
goto err; goto err;
} } else
fdset = cr_fdset;
for (i = 0; i < CR_FD_MAX; i++) { for (i = 0; i < CR_FD_MAX; i++) {
if (!(use_mask & CR_FD_DESC_USE(i))) if (!(use_mask & CR_FD_DESC_USE(i)))
continue; continue;
if (cr_fdset->fds[i] != -1)
if (fdset->fds[i] != -1)
continue; continue;
ret = get_image_path(path, sizeof(path), 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 ...@@ -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); pr_perror("Unable to open %s", path);
goto err; goto err;
} }
fdset->fds[i] = ret;
pr_debug("Opened %s with %d\n", path, ret); pr_debug("Opened %s with %d\n", path, ret);
if (write_img(ret, &fdset_template[i].magic)) if (write_img(ret, &fdset_template[i].magic))
goto err; goto err;
cr_fdset->fds[i] = ret;
} }
return fdset;
err: 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) 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) ...@@ -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); pr_perror("Unable to open %s", path);
goto err; goto err;
} }
cr_fdset->fds[i] = ret;
pr_debug("Opened %s with %d\n", path, ret); pr_debug("Opened %s with %d\n", path, ret);
if (read_img(ret, &magic) < 0) if (read_img(ret, &magic) < 0)
goto err; goto err;
if (magic != fdset_template[i].magic) { if (magic != fdset_template[i].magic) {
close(ret);
pr_err("Magic doesn't match for %s\n", path); pr_err("Magic doesn't match for %s\n", path);
goto err; 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 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;
}
xfree(fdset); err:
*cr_fdset = NULL; close_cr_fdset(&cr_fdset);
return NULL;
} }
int main(int argc, char *argv[]) int main(int argc, char *argv[])
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment