[CRIU] [PATCH 1/5] files: Fix crossing unused and service fds of shared fd tables

Andrei Vagin avagin at virtuozzo.com
Wed Jun 21 03:14:20 MSK 2017


This patch isn't a part of this series. Pls, rebase and send it
separately.

Thanks,
Andrei

On Wed, Jun 07, 2017 at 06:15:12PM +0300, Kirill Tkhai wrote:
> service_fd_id is id of a specific task, while other tasks
> in shared fd table group may have bigger id numbers.
> In this case given unused fd intersects with service fds
> of such tasks. This leads to undefined behaviour. Fix that.
> 
> Signed-off-by: Kirill Tkhai <ktkhai at virtuozzo.com>
> ---
>  criu/files.c             |    4 ++--
>  criu/include/servicefd.h |    4 +++-
>  criu/servicefd.c         |   12 ++++++++++--
>  3 files changed, 15 insertions(+), 5 deletions(-)
> 
> diff --git a/criu/files.c b/criu/files.c
> index 6aa88ba8b..73672b87e 100644
> --- a/criu/files.c
> +++ b/criu/files.c
> @@ -138,7 +138,7 @@ unsigned int find_unused_fd(struct pstree_item *task, int hint_fd)
>  		goto out;
>  	}
>  
> -	prev_fd = service_fd_min_fd() - 1;
> +	prev_fd = service_fd_min_fd(task) - 1;
>  	head = &rsti(task)->fds;
>  
>  	list_for_each_entry_reverse(fle, head, ps_list) {
> @@ -799,7 +799,7 @@ int prepare_fd_pid(struct pstree_item *item)
>  		if (ret <= 0)
>  			break;
>  
> -		if (e->fd >= service_fd_min_fd()) {
> +		if (e->fd >= service_fd_min_fd(item)) {
>  			ret = -1;
>  			pr_err("Too big FD number to restore %d\n", e->fd);
>  			break;
> diff --git a/criu/include/servicefd.h b/criu/include/servicefd.h
> index b77922394..c14e8ec87 100644
> --- a/criu/include/servicefd.h
> +++ b/criu/include/servicefd.h
> @@ -28,6 +28,8 @@ enum sfd_type {
>  	SERVICE_FD_MAX
>  };
>  
> +struct pstree_item;
> +
>  extern int clone_service_fd(int id);
>  extern int init_service_fd(void);
>  extern int get_service_fd(enum sfd_type type);
> @@ -36,6 +38,6 @@ extern int install_service_fd(enum sfd_type type, int fd);
>  extern int close_service_fd(enum sfd_type type);
>  extern bool is_service_fd(int fd, enum sfd_type type);
>  extern bool is_any_service_fd(int fd);
> -extern int service_fd_min_fd(void);
> +extern int service_fd_min_fd(struct pstree_item *item);
>  
>  #endif /* __CR_SERVICE_FD_H__ */
> diff --git a/criu/servicefd.c b/criu/servicefd.c
> index 245891b79..207693fb2 100644
> --- a/criu/servicefd.c
> +++ b/criu/servicefd.c
> @@ -9,6 +9,8 @@
>  #include "servicefd.h"
>  #include "bitops.h"
>  #include "criu-log.h"
> +#include "rst_info.h"
> +#include "pstree.h"
>  
>  #include "common/bug.h"
>  
> @@ -72,9 +74,15 @@ static int __get_service_fd(enum sfd_type type, int service_fd_id)
>  	return service_fd_rlim_cur - type - SERVICE_FD_MAX * service_fd_id;
>  }
>  
> -int service_fd_min_fd(void)
> +int service_fd_min_fd(struct pstree_item *item)
>  {
> -	return service_fd_rlim_cur - (SERVICE_FD_MAX - 1) - SERVICE_FD_MAX * service_fd_id;
> +	struct fdt *fdt = rsti(item)->fdt;
> +	int id = 0;
> +
> +	if (fdt)
> +		id = fdt->nr - 1;
> +
> +	return service_fd_rlim_cur - (SERVICE_FD_MAX - 1) - SERVICE_FD_MAX * id;
>  }
>  
>  int reserve_service_fd(enum sfd_type type)
> 


More information about the CRIU mailing list