kcmp_test.c 3.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166
  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. fd2 = open(kpath, O_RDWR, 0644);
  75. if (fd2 < 0) {
  76. perror("Can't open file");
  77. ksft_exit_fail();
  78. }
  79. /* An example of output and arguments */
  80. printf("pid1: %6d pid2: %6d FD: %2ld FILES: %2ld VM: %2ld "
  81. "FS: %2ld SIGHAND: %2ld IO: %2ld SYSVSEM: %2ld "
  82. "INV: %2ld\n",
  83. pid1, pid2,
  84. sys_kcmp(pid1, pid2, KCMP_FILE, fd1, fd2),
  85. sys_kcmp(pid1, pid2, KCMP_FILES, 0, 0),
  86. sys_kcmp(pid1, pid2, KCMP_VM, 0, 0),
  87. sys_kcmp(pid1, pid2, KCMP_FS, 0, 0),
  88. sys_kcmp(pid1, pid2, KCMP_SIGHAND, 0, 0),
  89. sys_kcmp(pid1, pid2, KCMP_IO, 0, 0),
  90. sys_kcmp(pid1, pid2, KCMP_SYSVSEM, 0, 0),
  91. /* This one should fail */
  92. sys_kcmp(pid1, pid2, KCMP_TYPES + 1, 0, 0));
  93. /* This one should return same fd */
  94. ret = sys_kcmp(pid1, pid2, KCMP_FILE, fd1, fd1);
  95. if (ret) {
  96. printf("FAIL: 0 expected but %d returned (%s)\n",
  97. ret, strerror(errno));
  98. ksft_inc_fail_cnt();
  99. ret = -1;
  100. } else {
  101. printf("PASS: 0 returned as expected\n");
  102. ksft_inc_pass_cnt();
  103. }
  104. /* Compare with self */
  105. ret = sys_kcmp(pid1, pid1, KCMP_VM, 0, 0);
  106. if (ret) {
  107. printf("FAIL: 0 expected but %d returned (%s)\n",
  108. ret, strerror(errno));
  109. ksft_inc_fail_cnt();
  110. ret = -1;
  111. } else {
  112. printf("PASS: 0 returned as expected\n");
  113. ksft_inc_pass_cnt();
  114. }
  115. /* Compare epoll target */
  116. epoll_slot = (struct kcmp_epoll_slot) {
  117. .efd = epollfd,
  118. .tfd = duped_num,
  119. .toff = 0,
  120. };
  121. ret = sys_kcmp(pid1, pid1, KCMP_EPOLL_TFD, pipefd[1],
  122. (unsigned long)(void *)&epoll_slot);
  123. if (ret) {
  124. printf("FAIL: 0 expected but %d returned (%s)\n",
  125. ret, strerror(errno));
  126. ksft_inc_fail_cnt();
  127. ret = -1;
  128. } else {
  129. printf("PASS: 0 returned as expected\n");
  130. ksft_inc_pass_cnt();
  131. }
  132. ksft_print_cnts();
  133. if (ret)
  134. ksft_exit_fail();
  135. else
  136. ksft_exit_pass();
  137. }
  138. waitpid(pid2, &status, P_ALL);
  139. return ksft_exit_pass();
  140. }