2 * Check decoding of kcmp syscall.
4 * Copyright (c) 2016-2017 Eugene Syromyatnikov <evgsyr@gmail.com>
5 * Copyright (c) 2016-2019 The strace developers.
8 * SPDX-License-Identifier: GPL-2.0-or-later
29 * We prefer to use system headers in order to catch some possible deviations in
30 * system's headers from our perception of reality, but happy to include our own
31 * definitions as well.
33 # ifdef HAVE_LINUX_KCMP_H
34 # include <linux/kcmp.h>
40 # define KCMP_SIGHAND 4
42 # define KCMP_SYSVSEM 6
45 /* All other kcmp types have been added atomically */
46 # define KCMP_EPOLL_TFD 7
48 # ifndef HAVE_STRUCT_KCMP_EPOLL_SLOT
49 struct kcmp_epoll_slot {
56 static const kernel_ulong_t kcmp_max_type = KCMP_EPOLL_TFD;
58 static const char null_path[] = "/dev/null";
59 static const char zero_path[] = "/dev/zero";
65 printpidfd(const char *prefix, pid_t pid, unsigned fd)
67 printf("%s%d", prefix, fd);
71 * Last argument is optional and is used as follows:
72 * * When type is KCMP_EPOLL_TFD, it signalises whether idx2 is a valid
76 do_kcmp(kernel_ulong_t pid1, kernel_ulong_t pid2, kernel_ulong_t type,
77 const char *type_str, kernel_ulong_t idx1, kernel_ulong_t idx2, ...)
82 rc = syscall(__NR_kcmp, pid1, pid2, type, idx1, idx2);
83 errstr = sprintrc(rc);
85 printf("kcmp(%d, %d, ", (int) pid1, (int) pid2);
88 printf("%s", type_str);
90 printf("%#x /* KCMP_??? */", (int) type);
92 if (type == KCMP_FILE) {
93 printpidfd(", ", pid1, idx1);
94 printpidfd(", ", pid2, idx2);
95 } else if (type == KCMP_EPOLL_TFD) {
100 valid_ptr = va_arg(ap, int);
103 printpidfd(", ", pid1, idx1);
107 struct kcmp_epoll_slot *slot =
108 (struct kcmp_epoll_slot *) (uintptr_t) idx2;
110 printpidfd("{efd=", pid2, slot->efd);
111 printpidfd(", tfd=", pid2, slot->tfd);
112 printf(", toff=%llu}", (unsigned long long) slot->toff);
115 printf("%#llx", (unsigned long long) idx2);
119 } else if (type > kcmp_max_type) {
120 printf(", %#llx, %#llx",
121 (unsigned long long) idx1, (unsigned long long) idx2);
124 printf(") = %s\n", errstr);
130 static const kernel_ulong_t bogus_pid1 =
131 (kernel_ulong_t) 0xdeadca75face1057ULL;
132 static const kernel_ulong_t bogus_pid2 =
133 (kernel_ulong_t) 0xdefaced1defaced2ULL;
134 static const kernel_ulong_t bogus_type =
135 (kernel_ulong_t) 0xbadc0dedda7adeadULL;
136 static const kernel_ulong_t bogus_idx1 =
137 (kernel_ulong_t) 0xdec0ded3dec0ded4ULL;
138 static const kernel_ulong_t bogus_idx2 =
139 (kernel_ulong_t) 0xba5e1e55deadc0deULL;
140 static const struct kcmp_epoll_slot slot_data[] = {
141 { 0xdeadc0de, 0xfacef157, 0xbadc0ded },
142 { NULL_FD, ZERO_FD, 0 },
145 static kernel_ulong_t ptr_check =
146 F8ILL_KULONG_SUPPORTED ? F8ILL_KULONG_MASK : 0;
150 TAIL_ALLOC_OBJECT_CONST_PTR(struct kcmp_epoll_slot, slot);
152 /* Open some files to test printpidfd */
153 fd = open(null_path, O_RDONLY);
155 perror_msg_and_fail("open(\"%s\")", null_path);
157 if (dup2(fd, NULL_FD) < 0)
158 perror_msg_and_fail("dup2(fd, NULL_FD)");
162 fd = open(zero_path, O_RDONLY);
164 perror_msg_and_fail("open(\"%s\")", zero_path);
166 if (dup2(fd, ZERO_FD) < 0)
167 perror_msg_and_fail("dup2(fd, ZERO_FD)");
174 do_kcmp(bogus_pid1, bogus_pid2, bogus_type, NULL, bogus_idx1,
176 do_kcmp(F8ILL_KULONG_MASK, F8ILL_KULONG_MASK, kcmp_max_type + 1, NULL,
179 /* KCMP_FILE is the only type which has additional args */
180 do_kcmp(3141592653U, 2718281828U, ARG_STR(KCMP_FILE), bogus_idx1,
182 do_kcmp(-1, -1, ARG_STR(KCMP_FILE), NULL_FD, ZERO_FD);
184 /* Types without additional args */
185 do_kcmp(-1, -1, ARG_STR(KCMP_VM), bogus_idx1, bogus_idx2);
186 do_kcmp(-1, -1, ARG_STR(KCMP_FILES), bogus_idx1, bogus_idx2);
187 do_kcmp(-1, -1, ARG_STR(KCMP_FS), bogus_idx1, bogus_idx2);
188 do_kcmp(-1, -1, ARG_STR(KCMP_SIGHAND), bogus_idx1, bogus_idx2);
189 do_kcmp(-1, -1, ARG_STR(KCMP_IO), bogus_idx1, bogus_idx2);
190 do_kcmp(-1, -1, ARG_STR(KCMP_SYSVSEM), bogus_idx1, bogus_idx2);
192 /* KCMP_EPOLL_TFD checks */
193 do_kcmp(-1, -1, ARG_STR(KCMP_EPOLL_TFD),
194 F8ILL_KULONG_MASK | 2718281828U, ptr_check, 0);
195 do_kcmp(-1, -1, ARG_STR(KCMP_EPOLL_TFD),
196 3141592653U, (uintptr_t) slot + 1, 0);
198 for (i = 0; i < ARRAY_SIZE(slot_data); i++) {
199 memcpy(slot, slot_data + i, sizeof(*slot));
201 do_kcmp(getpid(), getppid(), ARG_STR(KCMP_EPOLL_TFD), NULL_FD,
202 (uintptr_t) slot, 1);
205 puts("+++ exited with 0 +++");
212 SKIP_MAIN_UNDEFINED("__NR_kcmp");