[CRIU] [PATCH 5/6] kdat: Check for KCMP_EPOLL_TFD

Andrei Vagin avagin at virtuozzo.com
Fri Apr 6 02:05:55 MSK 2018


On Tue, Apr 03, 2018 at 08:46:49PM +0300, Cyrill Gorcunov wrote:
> This feature will be needed to support duplicated
> target file descriptors in epoll.
> 
> Signed-off-by: Cyrill Gorcunov <gorcunov at gmail.com>
> ---
>  criu/include/kcmp.h    | 10 ++++++++
>  criu/include/kerndat.h |  1 +
>  criu/kerndat.c         | 64 +++++++++++++++++++++++++++++++++++++++++++++++++-
>  3 files changed, 74 insertions(+), 1 deletion(-)
> 
> diff --git a/criu/include/kcmp.h b/criu/include/kcmp.h
> index 76f557bff047..b6d3519a0c5c 100644
> --- a/criu/include/kcmp.h
> +++ b/criu/include/kcmp.h
> @@ -1,6 +1,8 @@
>  #ifndef __CR_KCMP_H__
>  #define __CR_KCMP_H__
>  
> +#include <stdint.h>
> +
>  enum kcmp_type {
>  	KCMP_FILE,
>  	KCMP_VM,
> @@ -9,8 +11,16 @@ enum kcmp_type {
>  	KCMP_SIGHAND,
>  	KCMP_IO,
>  	KCMP_SYSVSEM,
> +	KCMP_EPOLL_TFD,
>  
>  	KCMP_TYPES,
>  };
>  
> +/* Slot for KCMP_EPOLL_TFD */
> +typedef struct {
> +	uint32_t efd;		/* epoll file descriptor */
> +	uint32_t tfd;		/* target file number */
> +	uint32_t toff;		/* target offset within same numbered sequence */
> +} kcmp_epoll_slot_t;
> +
>  #endif /* __CR_KCMP_H__ */
> diff --git a/criu/include/kerndat.h b/criu/include/kerndat.h
> index 28a84fb0d583..af6b5c5c3a38 100644
> --- a/criu/include/kerndat.h
> +++ b/criu/include/kerndat.h
> @@ -77,6 +77,7 @@ struct kerndat_s {
>  	bool has_pid_for_children_ns;
>  	bool x86_has_ptrace_fpu_xsave_bug;
>  	bool has_inotify_setnextwd;
> +	bool has_kcmp_epoll_tfd;
>  };
>  
>  extern struct kerndat_s kdat;
> diff --git a/criu/kerndat.c b/criu/kerndat.c
> index 227d429f9dde..456adbf2851f 100644
> --- a/criu/kerndat.c
> +++ b/criu/kerndat.c
> @@ -13,7 +13,7 @@
>  #include <arpa/inet.h>  /* for sockaddr_in and inet_ntoa() */
>  #include <sys/prctl.h>
>  #include <sys/inotify.h>
> -
> +#include <sys/epoll.h>
>  
>  #include "common/config.h"
>  #include "int.h"
> @@ -40,6 +40,7 @@
>  #include "prctl.h"
>  #include "uffd.h"
>  #include "vdso.h"
> +#include "kcmp.h"
>  
>  struct kerndat_s kdat = {
>  };
> @@ -819,6 +820,65 @@ int kerndat_has_inotify_setnextwd(void)
>  	return ret;
>  }
>  
> +static int kerndat_has_kcmp_epoll_tfd(void)
> +{
> +	kcmp_epoll_slot_t epoll_slot = { };
> +	struct epoll_event ev;
> +	int ret = -1;
> +	int pipefd[2];
> +	int epollfd;
> +	int fddup;
> +
> +	if (pipe(pipefd)) {
> +		pr_perror("Can't create pipe");
> +		return -1;
> +	}
> +
> +	epollfd = epoll_create1(0);
> +	if (epollfd < 0) {

pipefd descriptors leaks

> +		pr_perror("epoll_create1 failed");
> +		return -1;
> +	}
> +
> +	memset(&ev, 0xff, sizeof(ev));
> +	ev.events = EPOLLIN | EPOLLOUT;
> +
> +	if (epoll_ctl(epollfd, EPOLL_CTL_ADD, pipefd[0], &ev)) {
> +		pr_perror("epoll_ctl failed");

leak opened descriptors

> +		return -1;
> +	}
> +
> +	fddup = dup(pipefd[1]);
> +	if (fddup < 0) {
> +		pr_perror("dup2 failed");
> +		goto out;
> +	}
> +
> +	if (epoll_ctl(epollfd, EPOLL_CTL_ADD, fddup, &ev)) {
> +		pr_perror("epoll_ctl failed");
> +		close(fddup);
> +		goto out;
> +	}
> +	close(fddup);
> +
> +	epoll_slot = (kcmp_epoll_slot_t) {
> +		.efd	= epollfd,
> +		.tfd	= fddup,
> +		.toff	= 0,
> +	};
> +
> +	ret = syscall(SYS_kcmp, getpid(), getpid(),
> +		      KCMP_EPOLL_TFD, pipefd[1], (void *)&epoll_slot);
> +	if (ret == 0)
> +		kdat.has_kcmp_epoll_tfd = true;
> +
> +out:
> +	close(pipefd[0]);
> +	close(pipefd[1]);
> +	close(epollfd);
> +	return ret;
> +}
> +
>  int __attribute__((weak)) kdat_x86_has_ptrace_fpu_xsave_bug(void)
>  {
>  	return 0;
> @@ -1124,6 +1184,8 @@ int kerndat_init(void)
>  		ret = kerndat_x86_has_ptrace_fpu_xsave_bug();
>  	if (!ret)
>  		ret = kerndat_has_inotify_setnextwd();
> +	if (!ret)
> +		ret = kerndat_has_kcmp_epoll_tfd();
>  
>  	kerndat_lsm();
>  	kerndat_mmap_min_addr();
> -- 
> 2.14.3
> 
> _______________________________________________
> CRIU mailing list
> CRIU at openvz.org
> https://lists.openvz.org/mailman/listinfo/criu


More information about the CRIU mailing list