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