criu: check if pidfd_getfd syscall is supported

pidfd_getfd syscall will be needed later to send pidfds between
pre-dump/dump iterations for pid reuse detection.

v2:
	- check size written/read of val_a/val_b is correct
	- return with error when val_a != val_b

Signed-off-by: Zeyad Yasser <zeyady98@gmail.com>
This commit is contained in:
Zeyad Yasser 2021-02-26 22:32:39 +02:00 committed by Andrei Vagin
parent 30e8d8cadf
commit a9508c9864
8 changed files with 74 additions and 0 deletions

View file

@ -117,3 +117,4 @@ fsconfig 431 431 (int fd, unsigned int cmd, const char *key, const char *value
fsmount 432 432 (int fd, unsigned int flags, unsigned int attr_flags)
clone3 435 435 (struct clone_args *uargs, size_t size)
pidfd_open 434 434 (pid_t pid, unsigned int flags)
pidfd_getfd 438 438 (int pidfd, int targetfd, unsigned int flags)

View file

@ -114,3 +114,4 @@ __NR_fsconfig 5431 sys_fsconfig (int fd, unsigned int cmd, const char *key,
__NR_fsmount 5432 sys_fsmount (int fd, unsigned int flags, unsigned int attr_flags)
__NR_clone3 5435 sys_clone3 (struct clone_args *uargs, size_t size)
__NR_pidfd_open 5434 sys_pidfd_open (pid_t pid, unsigned int flags)
__NR_pidfd_getfd 5438 sys_pidfd_getfd (int pidfd, int targetfd, unsigned int flags)

View file

@ -113,3 +113,4 @@ __NR_fsconfig 431 sys_fsconfig (int fd, unsigned int cmd, const char *key, co
__NR_fsmount 432 sys_fsmount (int fd, unsigned int flags, unsigned int attr_flags)
__NR_clone3 435 sys_clone3 (struct clone_args *uargs, size_t size)
__NR_pidfd_open 434 sys_pidfd_open (pid_t pid, unsigned int flags)
__NR_pidfd_getfd 438 sys_pidfd_getfd (int pidfd, int targetfd, unsigned int flags)

View file

@ -113,3 +113,4 @@ __NR_fsconfig 431 sys_fsconfig (int fd, unsigned int cmd, const char *key, co
__NR_fsmount 432 sys_fsmount (int fd, unsigned int flags, unsigned int attr_flags)
__NR_clone3 435 sys_clone3 (struct clone_args *uargs, size_t size)
__NR_pidfd_open 434 sys_pidfd_open (pid_t pid, unsigned int flags)
__NR_pidfd_getfd 438 sys_pidfd_getfd (int pidfd, int targetfd, unsigned int flags)

View file

@ -101,3 +101,4 @@ __NR_fsconfig 431 sys_fsconfig (int fd, unsigned int cmd, const char *key, co
__NR_fsmount 432 sys_fsmount (int fd, unsigned int flags, unsigned int attr_flags)
__NR_clone3 435 sys_clone3 (struct clone_args *uargs, size_t size)
__NR_pidfd_open 434 sys_pidfd_open (pid_t pid, unsigned int flags)
__NR_pidfd_getfd 438 sys_pidfd_getfd (int pidfd, int targetfd, unsigned int flags)

View file

@ -112,3 +112,4 @@ __NR_fsconfig 431 sys_fsconfig (int fd, unsigned int cmd, const char *key, c
__NR_fsmount 432 sys_fsmount (int fd, unsigned int flags, unsigned int attr_flags)
__NR_clone3 435 sys_clone3 (struct clone_args *uargs, size_t size)
__NR_pidfd_open 434 sys_pidfd_open (pid_t pid, unsigned int flags)
__NR_pidfd_getfd 438 sys_pidfd_getfd (int pidfd, int targetfd, unsigned int flags)

View file

@ -70,6 +70,7 @@ struct kerndat_s {
bool has_timens;
bool has_newifindex;
bool has_pidfd_open;
bool has_pidfd_getfd;
};
extern struct kerndat_s kdat;

View file

@ -1068,6 +1068,69 @@ static void kerndat_has_pidfd_open(void)
close_safe(&pidfd);
}
static int kerndat_has_pidfd_getfd(void)
{
int ret;
int fds[2];
int val_a, val_b;
int pidfd, stolen_fd;
ret = 0;
if (socketpair(AF_UNIX, SOCK_DGRAM, 0, fds)) {
pr_perror("Can't open unix socket pair");
ret = -1;
goto out;
}
val_a = 1984;
if (write(fds[0], &val_a, sizeof(val_a)) != sizeof(val_a)) {
pr_perror("Can't write to socket");
ret = -1;
goto close_pair;
}
pidfd = syscall(SYS_pidfd_open, getpid(), 0);
if (pidfd == -1) {
pr_warn("Can't get pidfd\n");
/*
* If pidfd_open is not supported then pidfd_getfd
* will not be supported as well.
*/
kdat.has_pidfd_getfd = false;
goto close_pair;
}
stolen_fd = syscall(SYS_pidfd_getfd, pidfd, fds[1], 0);
if (stolen_fd == -1) {
kdat.has_pidfd_getfd = false;
goto close_all;
}
if (read(fds[1], &val_b, sizeof(val_b)) != sizeof(val_b)) {
pr_perror("Can't read from socket");
ret = -1;
goto close_all;
}
if (val_b == val_a) {
kdat.has_pidfd_getfd = true;
} else {
/* If val_b != val_a then something unexpected happend. */
pr_err("Unexpected value read from socket\n");
ret = -1;
}
close_all:
close_safe(&stolen_fd);
close_safe(&pidfd);
close_pair:
close(fds[0]);
close(fds[1]);
out:
return ret;
}
int kerndat_init(void)
{
int ret;
@ -1205,6 +1268,10 @@ int kerndat_init(void)
pr_err("kerndat_has_newifindex failed when initializing kerndat.\n");
ret = -1;
}
if (!ret && kerndat_has_pidfd_getfd()) {
pr_err("kerndat_has_pidfd_getfd failed when initializing kerndat.\n");
ret = -1;
}
if (!ret)
kerndat_has_pidfd_open();