Path: blob/master/tools/testing/selftests/kcmp/kcmp_test.c
26285 views
// SPDX-License-Identifier: GPL-2.01#define _GNU_SOURCE23#include <stdio.h>4#include <stdlib.h>5#include <signal.h>6#include <limits.h>7#include <unistd.h>8#include <errno.h>9#include <string.h>10#include <fcntl.h>11#include <linux/unistd.h>12#include <linux/kcmp.h>1314#include <sys/syscall.h>15#include <sys/types.h>16#include <sys/stat.h>17#include <sys/wait.h>18#include <sys/epoll.h>1920#include "../kselftest.h"2122static long sys_kcmp(int pid1, int pid2, int type, unsigned long fd1, unsigned long fd2)23{24return syscall(__NR_kcmp, pid1, pid2, type, fd1, fd2);25}2627static const unsigned int duped_num = 64;2829int main(int argc, char **argv)30{31const char kpath[] = "kcmp-test-file";32struct kcmp_epoll_slot epoll_slot;33struct epoll_event ev;34int pid1, pid2;35int pipefd[2];36int fd1, fd2;37int epollfd;38int status;39int fddup;4041fd1 = open(kpath, O_RDWR | O_CREAT | O_TRUNC, 0644);42pid1 = getpid();4344if (fd1 < 0) {45perror("Can't create file");46ksft_exit_fail();47}4849if (pipe(pipefd)) {50perror("Can't create pipe");51ksft_exit_fail();52}5354epollfd = epoll_create1(0);55if (epollfd < 0) {56perror("epoll_create1 failed");57ksft_exit_fail();58}5960memset(&ev, 0xff, sizeof(ev));61ev.events = EPOLLIN | EPOLLOUT;6263if (epoll_ctl(epollfd, EPOLL_CTL_ADD, pipefd[0], &ev)) {64perror("epoll_ctl failed");65ksft_exit_fail();66}6768fddup = dup2(pipefd[1], duped_num);69if (fddup < 0) {70perror("dup2 failed");71ksft_exit_fail();72}7374if (epoll_ctl(epollfd, EPOLL_CTL_ADD, fddup, &ev)) {75perror("epoll_ctl failed");76ksft_exit_fail();77}78close(fddup);7980pid2 = fork();81if (pid2 < 0) {82perror("fork failed");83ksft_exit_fail();84}8586if (!pid2) {87int pid2 = getpid();88int ret;8990ksft_print_header();91ksft_set_plan(3);9293fd2 = open(kpath, O_RDWR);94if (fd2 < 0) {95perror("Can't open file");96ksft_exit_fail();97}9899/* An example of output and arguments */100printf("pid1: %6d pid2: %6d FD: %2ld FILES: %2ld VM: %2ld "101"FS: %2ld SIGHAND: %2ld IO: %2ld SYSVSEM: %2ld "102"INV: %2ld\n",103pid1, pid2,104sys_kcmp(pid1, pid2, KCMP_FILE, fd1, fd2),105sys_kcmp(pid1, pid2, KCMP_FILES, 0, 0),106sys_kcmp(pid1, pid2, KCMP_VM, 0, 0),107sys_kcmp(pid1, pid2, KCMP_FS, 0, 0),108sys_kcmp(pid1, pid2, KCMP_SIGHAND, 0, 0),109sys_kcmp(pid1, pid2, KCMP_IO, 0, 0),110sys_kcmp(pid1, pid2, KCMP_SYSVSEM, 0, 0),111112/* This one should fail */113sys_kcmp(pid1, pid2, KCMP_TYPES + 1, 0, 0));114115/* This one should return same fd */116ret = sys_kcmp(pid1, pid2, KCMP_FILE, fd1, fd1);117if (ret) {118printf("FAIL: 0 expected but %d returned (%s)\n",119ret, strerror(errno));120ksft_inc_fail_cnt();121ret = -1;122} else {123printf("PASS: 0 returned as expected\n");124ksft_inc_pass_cnt();125}126127/* Compare with self */128ret = sys_kcmp(pid1, pid1, KCMP_VM, 0, 0);129if (ret) {130printf("FAIL: 0 expected but %d returned (%s)\n",131ret, strerror(errno));132ksft_inc_fail_cnt();133ret = -1;134} else {135printf("PASS: 0 returned as expected\n");136ksft_inc_pass_cnt();137}138139/* Compare epoll target */140epoll_slot = (struct kcmp_epoll_slot) {141.efd = epollfd,142.tfd = duped_num,143.toff = 0,144};145ret = sys_kcmp(pid1, pid1, KCMP_EPOLL_TFD, pipefd[1],146(unsigned long)(void *)&epoll_slot);147if (ret) {148printf("FAIL: 0 expected but %d returned (%s)\n",149ret, strerror(errno));150ksft_inc_fail_cnt();151ret = -1;152} else {153printf("PASS: 0 returned as expected\n");154ksft_inc_pass_cnt();155}156157158if (ret)159ksft_exit_fail();160else161ksft_exit_pass();162}163164waitpid(pid2, &status, P_ALL);165166return 0;167}168169170