non-regular.c 3.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196
  1. // SPDX-License-Identifier: GPL-2.0+
  2. #include <errno.h>
  3. #include <fcntl.h>
  4. #include <stdio.h>
  5. #include <string.h>
  6. #include <unistd.h>
  7. #include <sys/socket.h>
  8. #include <sys/stat.h>
  9. #include <sys/sysmacros.h>
  10. #include <sys/types.h>
  11. #include "kselftest_harness.h"
  12. /* Remove a file, ignoring the result if it didn't exist. */
  13. void rm(struct __test_metadata *_metadata, const char *pathname,
  14. int is_dir)
  15. {
  16. int rc;
  17. if (is_dir)
  18. rc = rmdir(pathname);
  19. else
  20. rc = unlink(pathname);
  21. if (rc < 0) {
  22. ASSERT_EQ(errno, ENOENT) {
  23. TH_LOG("Not ENOENT: %s", pathname);
  24. }
  25. } else {
  26. ASSERT_EQ(rc, 0) {
  27. TH_LOG("Failed to remove: %s", pathname);
  28. }
  29. }
  30. }
  31. FIXTURE(file) {
  32. char *pathname;
  33. int is_dir;
  34. };
  35. FIXTURE_VARIANT(file)
  36. {
  37. const char *name;
  38. int expected;
  39. int is_dir;
  40. void (*setup)(struct __test_metadata *_metadata,
  41. FIXTURE_DATA(file) *self,
  42. const FIXTURE_VARIANT(file) *variant);
  43. int major, minor, mode; /* for mknod() */
  44. };
  45. void setup_link(struct __test_metadata *_metadata,
  46. FIXTURE_DATA(file) *self,
  47. const FIXTURE_VARIANT(file) *variant)
  48. {
  49. const char * const paths[] = {
  50. "/bin/true",
  51. "/usr/bin/true",
  52. };
  53. int i;
  54. for (i = 0; i < ARRAY_SIZE(paths); i++) {
  55. if (access(paths[i], X_OK) == 0) {
  56. ASSERT_EQ(symlink(paths[i], self->pathname), 0);
  57. return;
  58. }
  59. }
  60. ASSERT_EQ(1, 0) {
  61. TH_LOG("Could not find viable 'true' binary");
  62. }
  63. }
  64. FIXTURE_VARIANT_ADD(file, S_IFLNK)
  65. {
  66. .name = "S_IFLNK",
  67. .expected = ELOOP,
  68. .setup = setup_link,
  69. };
  70. void setup_dir(struct __test_metadata *_metadata,
  71. FIXTURE_DATA(file) *self,
  72. const FIXTURE_VARIANT(file) *variant)
  73. {
  74. ASSERT_EQ(mkdir(self->pathname, 0755), 0);
  75. }
  76. FIXTURE_VARIANT_ADD(file, S_IFDIR)
  77. {
  78. .name = "S_IFDIR",
  79. .is_dir = 1,
  80. .expected = EACCES,
  81. .setup = setup_dir,
  82. };
  83. void setup_node(struct __test_metadata *_metadata,
  84. FIXTURE_DATA(file) *self,
  85. const FIXTURE_VARIANT(file) *variant)
  86. {
  87. dev_t dev;
  88. int rc;
  89. dev = makedev(variant->major, variant->minor);
  90. rc = mknod(self->pathname, 0755 | variant->mode, dev);
  91. ASSERT_EQ(rc, 0) {
  92. if (errno == EPERM)
  93. SKIP(return, "Please run as root; cannot mknod(%s)",
  94. variant->name);
  95. }
  96. }
  97. FIXTURE_VARIANT_ADD(file, S_IFBLK)
  98. {
  99. .name = "S_IFBLK",
  100. .expected = EACCES,
  101. .setup = setup_node,
  102. /* /dev/loop0 */
  103. .major = 7,
  104. .minor = 0,
  105. .mode = S_IFBLK,
  106. };
  107. FIXTURE_VARIANT_ADD(file, S_IFCHR)
  108. {
  109. .name = "S_IFCHR",
  110. .expected = EACCES,
  111. .setup = setup_node,
  112. /* /dev/zero */
  113. .major = 1,
  114. .minor = 5,
  115. .mode = S_IFCHR,
  116. };
  117. void setup_fifo(struct __test_metadata *_metadata,
  118. FIXTURE_DATA(file) *self,
  119. const FIXTURE_VARIANT(file) *variant)
  120. {
  121. ASSERT_EQ(mkfifo(self->pathname, 0755), 0);
  122. }
  123. FIXTURE_VARIANT_ADD(file, S_IFIFO)
  124. {
  125. .name = "S_IFIFO",
  126. .expected = EACCES,
  127. .setup = setup_fifo,
  128. };
  129. FIXTURE_SETUP(file)
  130. {
  131. ASSERT_GT(asprintf(&self->pathname, "%s.test", variant->name), 6);
  132. self->is_dir = variant->is_dir;
  133. rm(_metadata, self->pathname, variant->is_dir);
  134. variant->setup(_metadata, self, variant);
  135. }
  136. FIXTURE_TEARDOWN(file)
  137. {
  138. rm(_metadata, self->pathname, self->is_dir);
  139. }
  140. TEST_F(file, exec_errno)
  141. {
  142. char * const argv[2] = { (char * const)self->pathname, NULL };
  143. EXPECT_LT(execv(argv[0], argv), 0);
  144. EXPECT_EQ(errno, variant->expected);
  145. }
  146. /* S_IFSOCK */
  147. FIXTURE(sock)
  148. {
  149. int fd;
  150. };
  151. FIXTURE_SETUP(sock)
  152. {
  153. self->fd = socket(AF_INET, SOCK_STREAM, 0);
  154. ASSERT_GE(self->fd, 0);
  155. }
  156. FIXTURE_TEARDOWN(sock)
  157. {
  158. if (self->fd >= 0)
  159. ASSERT_EQ(close(self->fd), 0);
  160. }
  161. TEST_F(sock, exec_errno)
  162. {
  163. char * const argv[2] = { " magic socket ", NULL };
  164. char * const envp[1] = { NULL };
  165. EXPECT_LT(fexecve(self->fd, argv, envp), 0);
  166. EXPECT_EQ(errno, EACCES);
  167. }
  168. TEST_HARNESS_MAIN