kcmp_test.c 3.5 KB

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