162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0 262306a36Sopenharmony_ci#define _GNU_SOURCE 362306a36Sopenharmony_ci 462306a36Sopenharmony_ci#include <stdio.h> 562306a36Sopenharmony_ci#include <stdlib.h> 662306a36Sopenharmony_ci#include <signal.h> 762306a36Sopenharmony_ci#include <limits.h> 862306a36Sopenharmony_ci#include <unistd.h> 962306a36Sopenharmony_ci#include <errno.h> 1062306a36Sopenharmony_ci#include <string.h> 1162306a36Sopenharmony_ci#include <fcntl.h> 1262306a36Sopenharmony_ci#include <linux/unistd.h> 1362306a36Sopenharmony_ci#include <linux/kcmp.h> 1462306a36Sopenharmony_ci 1562306a36Sopenharmony_ci#include <sys/syscall.h> 1662306a36Sopenharmony_ci#include <sys/types.h> 1762306a36Sopenharmony_ci#include <sys/stat.h> 1862306a36Sopenharmony_ci#include <sys/wait.h> 1962306a36Sopenharmony_ci#include <sys/epoll.h> 2062306a36Sopenharmony_ci 2162306a36Sopenharmony_ci#include "../kselftest.h" 2262306a36Sopenharmony_ci 2362306a36Sopenharmony_cistatic long sys_kcmp(int pid1, int pid2, int type, unsigned long fd1, unsigned long fd2) 2462306a36Sopenharmony_ci{ 2562306a36Sopenharmony_ci return syscall(__NR_kcmp, pid1, pid2, type, fd1, fd2); 2662306a36Sopenharmony_ci} 2762306a36Sopenharmony_ci 2862306a36Sopenharmony_cistatic const unsigned int duped_num = 64; 2962306a36Sopenharmony_ci 3062306a36Sopenharmony_ciint main(int argc, char **argv) 3162306a36Sopenharmony_ci{ 3262306a36Sopenharmony_ci const char kpath[] = "kcmp-test-file"; 3362306a36Sopenharmony_ci struct kcmp_epoll_slot epoll_slot; 3462306a36Sopenharmony_ci struct epoll_event ev; 3562306a36Sopenharmony_ci int pid1, pid2; 3662306a36Sopenharmony_ci int pipefd[2]; 3762306a36Sopenharmony_ci int fd1, fd2; 3862306a36Sopenharmony_ci int epollfd; 3962306a36Sopenharmony_ci int status; 4062306a36Sopenharmony_ci int fddup; 4162306a36Sopenharmony_ci 4262306a36Sopenharmony_ci fd1 = open(kpath, O_RDWR | O_CREAT | O_TRUNC, 0644); 4362306a36Sopenharmony_ci pid1 = getpid(); 4462306a36Sopenharmony_ci 4562306a36Sopenharmony_ci if (fd1 < 0) { 4662306a36Sopenharmony_ci perror("Can't create file"); 4762306a36Sopenharmony_ci ksft_exit_fail(); 4862306a36Sopenharmony_ci } 4962306a36Sopenharmony_ci 5062306a36Sopenharmony_ci if (pipe(pipefd)) { 5162306a36Sopenharmony_ci perror("Can't create pipe"); 5262306a36Sopenharmony_ci ksft_exit_fail(); 5362306a36Sopenharmony_ci } 5462306a36Sopenharmony_ci 5562306a36Sopenharmony_ci epollfd = epoll_create1(0); 5662306a36Sopenharmony_ci if (epollfd < 0) { 5762306a36Sopenharmony_ci perror("epoll_create1 failed"); 5862306a36Sopenharmony_ci ksft_exit_fail(); 5962306a36Sopenharmony_ci } 6062306a36Sopenharmony_ci 6162306a36Sopenharmony_ci memset(&ev, 0xff, sizeof(ev)); 6262306a36Sopenharmony_ci ev.events = EPOLLIN | EPOLLOUT; 6362306a36Sopenharmony_ci 6462306a36Sopenharmony_ci if (epoll_ctl(epollfd, EPOLL_CTL_ADD, pipefd[0], &ev)) { 6562306a36Sopenharmony_ci perror("epoll_ctl failed"); 6662306a36Sopenharmony_ci ksft_exit_fail(); 6762306a36Sopenharmony_ci } 6862306a36Sopenharmony_ci 6962306a36Sopenharmony_ci fddup = dup2(pipefd[1], duped_num); 7062306a36Sopenharmony_ci if (fddup < 0) { 7162306a36Sopenharmony_ci perror("dup2 failed"); 7262306a36Sopenharmony_ci ksft_exit_fail(); 7362306a36Sopenharmony_ci } 7462306a36Sopenharmony_ci 7562306a36Sopenharmony_ci if (epoll_ctl(epollfd, EPOLL_CTL_ADD, fddup, &ev)) { 7662306a36Sopenharmony_ci perror("epoll_ctl failed"); 7762306a36Sopenharmony_ci ksft_exit_fail(); 7862306a36Sopenharmony_ci } 7962306a36Sopenharmony_ci close(fddup); 8062306a36Sopenharmony_ci 8162306a36Sopenharmony_ci pid2 = fork(); 8262306a36Sopenharmony_ci if (pid2 < 0) { 8362306a36Sopenharmony_ci perror("fork failed"); 8462306a36Sopenharmony_ci ksft_exit_fail(); 8562306a36Sopenharmony_ci } 8662306a36Sopenharmony_ci 8762306a36Sopenharmony_ci if (!pid2) { 8862306a36Sopenharmony_ci int pid2 = getpid(); 8962306a36Sopenharmony_ci int ret; 9062306a36Sopenharmony_ci 9162306a36Sopenharmony_ci ksft_print_header(); 9262306a36Sopenharmony_ci ksft_set_plan(3); 9362306a36Sopenharmony_ci 9462306a36Sopenharmony_ci fd2 = open(kpath, O_RDWR, 0644); 9562306a36Sopenharmony_ci if (fd2 < 0) { 9662306a36Sopenharmony_ci perror("Can't open file"); 9762306a36Sopenharmony_ci ksft_exit_fail(); 9862306a36Sopenharmony_ci } 9962306a36Sopenharmony_ci 10062306a36Sopenharmony_ci /* An example of output and arguments */ 10162306a36Sopenharmony_ci printf("pid1: %6d pid2: %6d FD: %2ld FILES: %2ld VM: %2ld " 10262306a36Sopenharmony_ci "FS: %2ld SIGHAND: %2ld IO: %2ld SYSVSEM: %2ld " 10362306a36Sopenharmony_ci "INV: %2ld\n", 10462306a36Sopenharmony_ci pid1, pid2, 10562306a36Sopenharmony_ci sys_kcmp(pid1, pid2, KCMP_FILE, fd1, fd2), 10662306a36Sopenharmony_ci sys_kcmp(pid1, pid2, KCMP_FILES, 0, 0), 10762306a36Sopenharmony_ci sys_kcmp(pid1, pid2, KCMP_VM, 0, 0), 10862306a36Sopenharmony_ci sys_kcmp(pid1, pid2, KCMP_FS, 0, 0), 10962306a36Sopenharmony_ci sys_kcmp(pid1, pid2, KCMP_SIGHAND, 0, 0), 11062306a36Sopenharmony_ci sys_kcmp(pid1, pid2, KCMP_IO, 0, 0), 11162306a36Sopenharmony_ci sys_kcmp(pid1, pid2, KCMP_SYSVSEM, 0, 0), 11262306a36Sopenharmony_ci 11362306a36Sopenharmony_ci /* This one should fail */ 11462306a36Sopenharmony_ci sys_kcmp(pid1, pid2, KCMP_TYPES + 1, 0, 0)); 11562306a36Sopenharmony_ci 11662306a36Sopenharmony_ci /* This one should return same fd */ 11762306a36Sopenharmony_ci ret = sys_kcmp(pid1, pid2, KCMP_FILE, fd1, fd1); 11862306a36Sopenharmony_ci if (ret) { 11962306a36Sopenharmony_ci printf("FAIL: 0 expected but %d returned (%s)\n", 12062306a36Sopenharmony_ci ret, strerror(errno)); 12162306a36Sopenharmony_ci ksft_inc_fail_cnt(); 12262306a36Sopenharmony_ci ret = -1; 12362306a36Sopenharmony_ci } else { 12462306a36Sopenharmony_ci printf("PASS: 0 returned as expected\n"); 12562306a36Sopenharmony_ci ksft_inc_pass_cnt(); 12662306a36Sopenharmony_ci } 12762306a36Sopenharmony_ci 12862306a36Sopenharmony_ci /* Compare with self */ 12962306a36Sopenharmony_ci ret = sys_kcmp(pid1, pid1, KCMP_VM, 0, 0); 13062306a36Sopenharmony_ci if (ret) { 13162306a36Sopenharmony_ci printf("FAIL: 0 expected but %d returned (%s)\n", 13262306a36Sopenharmony_ci ret, strerror(errno)); 13362306a36Sopenharmony_ci ksft_inc_fail_cnt(); 13462306a36Sopenharmony_ci ret = -1; 13562306a36Sopenharmony_ci } else { 13662306a36Sopenharmony_ci printf("PASS: 0 returned as expected\n"); 13762306a36Sopenharmony_ci ksft_inc_pass_cnt(); 13862306a36Sopenharmony_ci } 13962306a36Sopenharmony_ci 14062306a36Sopenharmony_ci /* Compare epoll target */ 14162306a36Sopenharmony_ci epoll_slot = (struct kcmp_epoll_slot) { 14262306a36Sopenharmony_ci .efd = epollfd, 14362306a36Sopenharmony_ci .tfd = duped_num, 14462306a36Sopenharmony_ci .toff = 0, 14562306a36Sopenharmony_ci }; 14662306a36Sopenharmony_ci ret = sys_kcmp(pid1, pid1, KCMP_EPOLL_TFD, pipefd[1], 14762306a36Sopenharmony_ci (unsigned long)(void *)&epoll_slot); 14862306a36Sopenharmony_ci if (ret) { 14962306a36Sopenharmony_ci printf("FAIL: 0 expected but %d returned (%s)\n", 15062306a36Sopenharmony_ci ret, strerror(errno)); 15162306a36Sopenharmony_ci ksft_inc_fail_cnt(); 15262306a36Sopenharmony_ci ret = -1; 15362306a36Sopenharmony_ci } else { 15462306a36Sopenharmony_ci printf("PASS: 0 returned as expected\n"); 15562306a36Sopenharmony_ci ksft_inc_pass_cnt(); 15662306a36Sopenharmony_ci } 15762306a36Sopenharmony_ci 15862306a36Sopenharmony_ci 15962306a36Sopenharmony_ci if (ret) 16062306a36Sopenharmony_ci ksft_exit_fail(); 16162306a36Sopenharmony_ci else 16262306a36Sopenharmony_ci ksft_exit_pass(); 16362306a36Sopenharmony_ci } 16462306a36Sopenharmony_ci 16562306a36Sopenharmony_ci waitpid(pid2, &status, P_ALL); 16662306a36Sopenharmony_ci 16762306a36Sopenharmony_ci return 0; 16862306a36Sopenharmony_ci} 169