mirror of
https://github.com/checkpoint-restore/criu
synced 2025-09-04 16:25:31 +00:00
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: Cyrill Gorcunov <gorcunov@openvz.org> Acked-by: Pavel Emelyanov <xemul@parallels.com>
This commit is contained in:
@@ -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)
|
|||||||
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;
|
||||||
|
85
crtools.c
85
crtools.c
@@ -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
|
|||||||
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)
|
|||||||
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;
|
return cr_fdset;
|
||||||
}
|
|
||||||
|
|
||||||
void close_cr_fdset(struct cr_fdset **cr_fdset)
|
err:
|
||||||
{
|
close_cr_fdset(&cr_fdset);
|
||||||
struct cr_fdset *fdset;
|
return NULL;
|
||||||
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;
|
|
||||||
}
|
|
||||||
|
|
||||||
xfree(fdset);
|
|
||||||
*cr_fdset = NULL;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int main(int argc, char *argv[])
|
int main(int argc, char *argv[])
|
||||||
|
Reference in New Issue
Block a user