[CRIU] Re: [PATCH] crtools: Make fdset operations robust against open() errors

Pavel Emelyanov xemul at parallels.com
Tue Jan 31 09:52:34 EST 2012


On 01/31/2012 06:29 PM, Cyrill Gorcunov wrote:
> 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>

Ack

> ---
> 
> 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[])



More information about the CRIU mailing list