[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