0001
0002 #define _GNU_SOURCE
0003
0004 #include <stdio.h>
0005 #include <stdlib.h>
0006 #include <signal.h>
0007 #include <limits.h>
0008 #include <unistd.h>
0009 #include <errno.h>
0010 #include <string.h>
0011 #include <fcntl.h>
0012 #include <linux/unistd.h>
0013 #include <linux/kcmp.h>
0014
0015 #include <sys/syscall.h>
0016 #include <sys/types.h>
0017 #include <sys/stat.h>
0018 #include <sys/wait.h>
0019 #include <sys/epoll.h>
0020
0021 #include "../kselftest.h"
0022
0023 static long sys_kcmp(int pid1, int pid2, int type, unsigned long fd1, unsigned long fd2)
0024 {
0025 return syscall(__NR_kcmp, pid1, pid2, type, fd1, fd2);
0026 }
0027
0028 static const unsigned int duped_num = 64;
0029
0030 int main(int argc, char **argv)
0031 {
0032 const char kpath[] = "kcmp-test-file";
0033 struct kcmp_epoll_slot epoll_slot;
0034 struct epoll_event ev;
0035 int pid1, pid2;
0036 int pipefd[2];
0037 int fd1, fd2;
0038 int epollfd;
0039 int status;
0040 int fddup;
0041
0042 fd1 = open(kpath, O_RDWR | O_CREAT | O_TRUNC, 0644);
0043 pid1 = getpid();
0044
0045 if (fd1 < 0) {
0046 perror("Can't create file");
0047 ksft_exit_fail();
0048 }
0049
0050 if (pipe(pipefd)) {
0051 perror("Can't create pipe");
0052 ksft_exit_fail();
0053 }
0054
0055 epollfd = epoll_create1(0);
0056 if (epollfd < 0) {
0057 perror("epoll_create1 failed");
0058 ksft_exit_fail();
0059 }
0060
0061 memset(&ev, 0xff, sizeof(ev));
0062 ev.events = EPOLLIN | EPOLLOUT;
0063
0064 if (epoll_ctl(epollfd, EPOLL_CTL_ADD, pipefd[0], &ev)) {
0065 perror("epoll_ctl failed");
0066 ksft_exit_fail();
0067 }
0068
0069 fddup = dup2(pipefd[1], duped_num);
0070 if (fddup < 0) {
0071 perror("dup2 failed");
0072 ksft_exit_fail();
0073 }
0074
0075 if (epoll_ctl(epollfd, EPOLL_CTL_ADD, fddup, &ev)) {
0076 perror("epoll_ctl failed");
0077 ksft_exit_fail();
0078 }
0079 close(fddup);
0080
0081 pid2 = fork();
0082 if (pid2 < 0) {
0083 perror("fork failed");
0084 ksft_exit_fail();
0085 }
0086
0087 if (!pid2) {
0088 int pid2 = getpid();
0089 int ret;
0090
0091 ksft_print_header();
0092 ksft_set_plan(3);
0093
0094 fd2 = open(kpath, O_RDWR, 0644);
0095 if (fd2 < 0) {
0096 perror("Can't open file");
0097 ksft_exit_fail();
0098 }
0099
0100
0101 printf("pid1: %6d pid2: %6d FD: %2ld FILES: %2ld VM: %2ld "
0102 "FS: %2ld SIGHAND: %2ld IO: %2ld SYSVSEM: %2ld "
0103 "INV: %2ld\n",
0104 pid1, pid2,
0105 sys_kcmp(pid1, pid2, KCMP_FILE, fd1, fd2),
0106 sys_kcmp(pid1, pid2, KCMP_FILES, 0, 0),
0107 sys_kcmp(pid1, pid2, KCMP_VM, 0, 0),
0108 sys_kcmp(pid1, pid2, KCMP_FS, 0, 0),
0109 sys_kcmp(pid1, pid2, KCMP_SIGHAND, 0, 0),
0110 sys_kcmp(pid1, pid2, KCMP_IO, 0, 0),
0111 sys_kcmp(pid1, pid2, KCMP_SYSVSEM, 0, 0),
0112
0113
0114 sys_kcmp(pid1, pid2, KCMP_TYPES + 1, 0, 0));
0115
0116
0117 ret = sys_kcmp(pid1, pid2, KCMP_FILE, fd1, fd1);
0118 if (ret) {
0119 printf("FAIL: 0 expected but %d returned (%s)\n",
0120 ret, strerror(errno));
0121 ksft_inc_fail_cnt();
0122 ret = -1;
0123 } else {
0124 printf("PASS: 0 returned as expected\n");
0125 ksft_inc_pass_cnt();
0126 }
0127
0128
0129 ret = sys_kcmp(pid1, pid1, KCMP_VM, 0, 0);
0130 if (ret) {
0131 printf("FAIL: 0 expected but %d returned (%s)\n",
0132 ret, strerror(errno));
0133 ksft_inc_fail_cnt();
0134 ret = -1;
0135 } else {
0136 printf("PASS: 0 returned as expected\n");
0137 ksft_inc_pass_cnt();
0138 }
0139
0140
0141 epoll_slot = (struct kcmp_epoll_slot) {
0142 .efd = epollfd,
0143 .tfd = duped_num,
0144 .toff = 0,
0145 };
0146 ret = sys_kcmp(pid1, pid1, KCMP_EPOLL_TFD, pipefd[1],
0147 (unsigned long)(void *)&epoll_slot);
0148 if (ret) {
0149 printf("FAIL: 0 expected but %d returned (%s)\n",
0150 ret, strerror(errno));
0151 ksft_inc_fail_cnt();
0152 ret = -1;
0153 } else {
0154 printf("PASS: 0 returned as expected\n");
0155 ksft_inc_pass_cnt();
0156 }
0157
0158
0159 if (ret)
0160 ksft_exit_fail();
0161 else
0162 ksft_exit_pass();
0163 }
0164
0165 waitpid(pid2, &status, P_ALL);
0166
0167 return 0;
0168 }