common.h 4.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189
  1. /* SPDX-License-Identifier: GPL-2.0 */
  2. /*
  3. * Landlock test helpers
  4. *
  5. * Copyright © 2017-2020 Mickaël Salaün <[email protected]>
  6. * Copyright © 2019-2020 ANSSI
  7. * Copyright © 2021 Microsoft Corporation
  8. */
  9. #include <errno.h>
  10. #include <linux/landlock.h>
  11. #include <sys/capability.h>
  12. #include <sys/syscall.h>
  13. #include <sys/types.h>
  14. #include <sys/wait.h>
  15. #include <unistd.h>
  16. #include "../kselftest_harness.h"
  17. /*
  18. * TEST_F_FORK() is useful when a test drop privileges but the corresponding
  19. * FIXTURE_TEARDOWN() requires them (e.g. to remove files from a directory
  20. * where write actions are denied). For convenience, FIXTURE_TEARDOWN() is
  21. * also called when the test failed, but not when FIXTURE_SETUP() failed. For
  22. * this to be possible, we must not call abort() but instead exit smoothly
  23. * (hence the step print).
  24. */
  25. /* clang-format off */
  26. #define TEST_F_FORK(fixture_name, test_name) \
  27. static void fixture_name##_##test_name##_child( \
  28. struct __test_metadata *_metadata, \
  29. FIXTURE_DATA(fixture_name) *self, \
  30. const FIXTURE_VARIANT(fixture_name) *variant); \
  31. TEST_F(fixture_name, test_name) \
  32. { \
  33. int status; \
  34. const pid_t child = fork(); \
  35. if (child < 0) \
  36. abort(); \
  37. if (child == 0) { \
  38. _metadata->no_print = 1; \
  39. fixture_name##_##test_name##_child(_metadata, self, variant); \
  40. if (_metadata->skip) \
  41. _exit(255); \
  42. if (_metadata->passed) \
  43. _exit(0); \
  44. _exit(_metadata->step); \
  45. } \
  46. if (child != waitpid(child, &status, 0)) \
  47. abort(); \
  48. if (WIFSIGNALED(status) || !WIFEXITED(status)) { \
  49. _metadata->passed = 0; \
  50. _metadata->step = 1; \
  51. return; \
  52. } \
  53. switch (WEXITSTATUS(status)) { \
  54. case 0: \
  55. _metadata->passed = 1; \
  56. break; \
  57. case 255: \
  58. _metadata->passed = 1; \
  59. _metadata->skip = 1; \
  60. break; \
  61. default: \
  62. _metadata->passed = 0; \
  63. _metadata->step = WEXITSTATUS(status); \
  64. break; \
  65. } \
  66. } \
  67. static void fixture_name##_##test_name##_child( \
  68. struct __test_metadata __attribute__((unused)) *_metadata, \
  69. FIXTURE_DATA(fixture_name) __attribute__((unused)) *self, \
  70. const FIXTURE_VARIANT(fixture_name) \
  71. __attribute__((unused)) *variant)
  72. /* clang-format on */
  73. #ifndef landlock_create_ruleset
  74. static inline int
  75. landlock_create_ruleset(const struct landlock_ruleset_attr *const attr,
  76. const size_t size, const __u32 flags)
  77. {
  78. return syscall(__NR_landlock_create_ruleset, attr, size, flags);
  79. }
  80. #endif
  81. #ifndef landlock_add_rule
  82. static inline int landlock_add_rule(const int ruleset_fd,
  83. const enum landlock_rule_type rule_type,
  84. const void *const rule_attr,
  85. const __u32 flags)
  86. {
  87. return syscall(__NR_landlock_add_rule, ruleset_fd, rule_type, rule_attr,
  88. flags);
  89. }
  90. #endif
  91. #ifndef landlock_restrict_self
  92. static inline int landlock_restrict_self(const int ruleset_fd,
  93. const __u32 flags)
  94. {
  95. return syscall(__NR_landlock_restrict_self, ruleset_fd, flags);
  96. }
  97. #endif
  98. static void _init_caps(struct __test_metadata *const _metadata, bool drop_all)
  99. {
  100. cap_t cap_p;
  101. /* Only these three capabilities are useful for the tests. */
  102. const cap_value_t caps[] = {
  103. CAP_DAC_OVERRIDE,
  104. CAP_MKNOD,
  105. CAP_SYS_ADMIN,
  106. CAP_SYS_CHROOT,
  107. };
  108. cap_p = cap_get_proc();
  109. EXPECT_NE(NULL, cap_p)
  110. {
  111. TH_LOG("Failed to cap_get_proc: %s", strerror(errno));
  112. }
  113. EXPECT_NE(-1, cap_clear(cap_p))
  114. {
  115. TH_LOG("Failed to cap_clear: %s", strerror(errno));
  116. }
  117. if (!drop_all) {
  118. EXPECT_NE(-1, cap_set_flag(cap_p, CAP_PERMITTED,
  119. ARRAY_SIZE(caps), caps, CAP_SET))
  120. {
  121. TH_LOG("Failed to cap_set_flag: %s", strerror(errno));
  122. }
  123. }
  124. EXPECT_NE(-1, cap_set_proc(cap_p))
  125. {
  126. TH_LOG("Failed to cap_set_proc: %s", strerror(errno));
  127. }
  128. EXPECT_NE(-1, cap_free(cap_p))
  129. {
  130. TH_LOG("Failed to cap_free: %s", strerror(errno));
  131. }
  132. }
  133. /* We cannot put such helpers in a library because of kselftest_harness.h . */
  134. __attribute__((__unused__)) static void
  135. disable_caps(struct __test_metadata *const _metadata)
  136. {
  137. _init_caps(_metadata, false);
  138. }
  139. __attribute__((__unused__)) static void
  140. drop_caps(struct __test_metadata *const _metadata)
  141. {
  142. _init_caps(_metadata, true);
  143. }
  144. static void _effective_cap(struct __test_metadata *const _metadata,
  145. const cap_value_t caps, const cap_flag_value_t value)
  146. {
  147. cap_t cap_p;
  148. cap_p = cap_get_proc();
  149. EXPECT_NE(NULL, cap_p)
  150. {
  151. TH_LOG("Failed to cap_get_proc: %s", strerror(errno));
  152. }
  153. EXPECT_NE(-1, cap_set_flag(cap_p, CAP_EFFECTIVE, 1, &caps, value))
  154. {
  155. TH_LOG("Failed to cap_set_flag: %s", strerror(errno));
  156. }
  157. EXPECT_NE(-1, cap_set_proc(cap_p))
  158. {
  159. TH_LOG("Failed to cap_set_proc: %s", strerror(errno));
  160. }
  161. EXPECT_NE(-1, cap_free(cap_p))
  162. {
  163. TH_LOG("Failed to cap_free: %s", strerror(errno));
  164. }
  165. }
  166. __attribute__((__unused__)) static void
  167. set_cap(struct __test_metadata *const _metadata, const cap_value_t caps)
  168. {
  169. _effective_cap(_metadata, caps, CAP_SET);
  170. }
  171. __attribute__((__unused__)) static void
  172. clear_cap(struct __test_metadata *const _metadata, const cap_value_t caps)
  173. {
  174. _effective_cap(_metadata, caps, CAP_CLEAR);
  175. }