Loading...
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 | // SPDX-License-Identifier: GPL-2.0 #define _GNU_SOURCE #include <stdio.h> #include <stdlib.h> #include <signal.h> #include <limits.h> #include <unistd.h> #include <errno.h> #include <string.h> #include <fcntl.h> #include <linux/unistd.h> #include <linux/kcmp.h> #include <sys/syscall.h> #include <sys/types.h> #include <sys/stat.h> #include <sys/wait.h> #include <sys/epoll.h> #include "../kselftest.h" static long sys_kcmp(int pid1, int pid2, int type, unsigned long fd1, unsigned long fd2) { return syscall(__NR_kcmp, pid1, pid2, type, fd1, fd2); } static const unsigned int duped_num = 64; int main(int argc, char **argv) { const char kpath[] = "kcmp-test-file"; struct kcmp_epoll_slot epoll_slot; struct epoll_event ev; int pid1, pid2; int pipefd[2]; int fd1, fd2; int epollfd; int status; int fddup; fd1 = open(kpath, O_RDWR | O_CREAT | O_TRUNC, 0644); pid1 = getpid(); if (fd1 < 0) { perror("Can't create file"); ksft_exit_fail(); } if (pipe(pipefd)) { perror("Can't create pipe"); ksft_exit_fail(); } epollfd = epoll_create1(0); if (epollfd < 0) { perror("epoll_create1 failed"); ksft_exit_fail(); } memset(&ev, 0xff, sizeof(ev)); ev.events = EPOLLIN | EPOLLOUT; if (epoll_ctl(epollfd, EPOLL_CTL_ADD, pipefd[0], &ev)) { perror("epoll_ctl failed"); ksft_exit_fail(); } fddup = dup2(pipefd[1], duped_num); if (fddup < 0) { perror("dup2 failed"); ksft_exit_fail(); } if (epoll_ctl(epollfd, EPOLL_CTL_ADD, fddup, &ev)) { perror("epoll_ctl failed"); ksft_exit_fail(); } close(fddup); pid2 = fork(); if (pid2 < 0) { perror("fork failed"); ksft_exit_fail(); } if (!pid2) { int pid2 = getpid(); int ret; ksft_print_header(); ksft_set_plan(3); fd2 = open(kpath, O_RDWR, 0644); if (fd2 < 0) { perror("Can't open file"); ksft_exit_fail(); } /* An example of output and arguments */ printf("pid1: %6d pid2: %6d FD: %2ld FILES: %2ld VM: %2ld " "FS: %2ld SIGHAND: %2ld IO: %2ld SYSVSEM: %2ld " "INV: %2ld\n", pid1, pid2, sys_kcmp(pid1, pid2, KCMP_FILE, fd1, fd2), sys_kcmp(pid1, pid2, KCMP_FILES, 0, 0), sys_kcmp(pid1, pid2, KCMP_VM, 0, 0), sys_kcmp(pid1, pid2, KCMP_FS, 0, 0), sys_kcmp(pid1, pid2, KCMP_SIGHAND, 0, 0), sys_kcmp(pid1, pid2, KCMP_IO, 0, 0), sys_kcmp(pid1, pid2, KCMP_SYSVSEM, 0, 0), /* This one should fail */ sys_kcmp(pid1, pid2, KCMP_TYPES + 1, 0, 0)); /* This one should return same fd */ ret = sys_kcmp(pid1, pid2, KCMP_FILE, fd1, fd1); if (ret) { printf("FAIL: 0 expected but %d returned (%s)\n", ret, strerror(errno)); ksft_inc_fail_cnt(); ret = -1; } else { printf("PASS: 0 returned as expected\n"); ksft_inc_pass_cnt(); } /* Compare with self */ ret = sys_kcmp(pid1, pid1, KCMP_VM, 0, 0); if (ret) { printf("FAIL: 0 expected but %d returned (%s)\n", ret, strerror(errno)); ksft_inc_fail_cnt(); ret = -1; } else { printf("PASS: 0 returned as expected\n"); ksft_inc_pass_cnt(); } /* Compare epoll target */ epoll_slot = (struct kcmp_epoll_slot) { .efd = epollfd, .tfd = duped_num, .toff = 0, }; ret = sys_kcmp(pid1, pid1, KCMP_EPOLL_TFD, pipefd[1], (unsigned long)(void *)&epoll_slot); if (ret) { printf("FAIL: 0 expected but %d returned (%s)\n", ret, strerror(errno)); ksft_inc_fail_cnt(); ret = -1; } else { printf("PASS: 0 returned as expected\n"); ksft_inc_pass_cnt(); } if (ret) ksft_exit_fail(); else ksft_exit_pass(); } waitpid(pid2, &status, P_ALL); return 0; } |