1 /*
2 * Check decoding of pidfd_getfd syscall.
3 *
4 * Copyright (c) 2019 Dmitry V. Levin <ldv@strace.io>
5 * Copyright (c) 2020-2021 The strace developers.
6 * All rights reserved.
7 *
8 * SPDX-License-Identifier: GPL-2.0-or-later
9 */
10
11 #include "tests.h"
12 #include "scno.h"
13
14 #include <assert.h>
15 #include <signal.h>
16 #include <stdio.h>
17 #include <stdlib.h>
18 #include <unistd.h>
19 #include <sys/wait.h>
20
21 #ifndef PIDFD_PATH
22 # define PIDFD_PATH ""
23 #endif
24 #ifndef FD0_PATH
25 # define FD0_PATH ""
26 #endif
27 #ifndef PRINT_PIDFD
28 # define PRINT_PIDFD 0
29 #endif
30 #ifndef SKIP_IF_PROC_IS_UNAVAILABLE
31 # define SKIP_IF_PROC_IS_UNAVAILABLE
32 #endif
33
34 static const char *errstr;
35
36 static long
37 k_pidfd_getfd(const unsigned int pidfd, const unsigned int fd,
38 const unsigned int flags)
39 {
40 const kernel_ulong_t fill = (kernel_ulong_t) 0xdefaced00000000ULL;
41 const kernel_ulong_t bad = (kernel_ulong_t) 0xbadc0dedbadc0dedULL;
42 const kernel_ulong_t arg1 = fill | pidfd;
43 const kernel_ulong_t arg2 = fill | fd;
44 const kernel_ulong_t arg3 = fill | flags;
45 const long rc = syscall(__NR_pidfd_getfd,
46 arg1, arg2, arg3, bad, bad, bad);
47 errstr = sprintrc(rc);
48 return rc;
49 }
50
51 int
52 main(void)
53 {
54 SKIP_IF_PROC_IS_UNAVAILABLE;
55
56 long rc;
57
58 rc = k_pidfd_getfd(-1U, -1U, 0);
59 printf("pidfd_getfd(-1, -1, 0) = %s\n", errstr);
60
61 rc = k_pidfd_getfd(0, 0, 0xbadc0ded);
62 printf("pidfd_getfd(0" FD0_PATH ", 0, 0xbadc0ded) = %s\n", errstr);
63
64 int child_wait_fds[2];
65 if (pipe(child_wait_fds))
66 perror_msg_and_fail("pipe");
67
68 int dupfd = dup(0);
69 int pid = fork();
70 if (pid == 0) {
71 close(0);
72 close(child_wait_fds[1]);
73 if (read(child_wait_fds[0], &child_wait_fds[1], sizeof(int)))
74 _exit(2);
75 _exit(0);
76 }
77 close(dupfd);
78
79 int pidfd = syscall(__NR_pidfd_open, pid, 0);
80 #if PRINT_PIDFD
81 char pidfd_str[sizeof("<pid:>") + 3 * sizeof(int)];
82 snprintf(pidfd_str, sizeof(pidfd_str), "<pid:%d>", pid);
83 #else
84 const char *pidfd_str = PIDFD_PATH;
85 #endif
86 rc = k_pidfd_getfd(pidfd, dupfd, 0);
87 printf("pidfd_getfd(%d%s, %d%s, 0) = %s%s\n",
88 pidfd, pidfd >= 0 ? pidfd_str : "",
89 dupfd, pidfd >= 0 ? FD0_PATH : "",
90 errstr, rc >= 0 ? FD0_PATH : "");
91
92 puts("+++ exited with 0 +++");
93
94 close(child_wait_fds[1]);
95 int status;
96 assert(wait(&status) == pid);
97 assert(status == 0);
98
99 return 0;
100 }