commoncap_test.c 9.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288
  1. // SPDX-License-Identifier: GPL-2.0-or-later
  2. /*
  3. * KUnit tests for commoncap.c security functions
  4. *
  5. * Tests for security-critical functions in the capability subsystem,
  6. * particularly namespace-related capability checks.
  7. */
  8. #include <kunit/test.h>
  9. #include <linux/user_namespace.h>
  10. #include <linux/uidgid.h>
  11. #include <linux/cred.h>
  12. #include <linux/mnt_idmapping.h>
  13. #include <linux/module.h>
  14. #include <linux/slab.h>
  15. #include <linux/refcount.h>
  16. #ifdef CONFIG_SECURITY_COMMONCAP_KUNIT_TEST
  17. /* Functions are static in commoncap.c, but we can call them since we're
  18. * included in the same compilation unit when tests are enabled.
  19. */
  20. /**
  21. * test_vfsuid_root_in_currentns_init_ns - Test vfsuid_root_in_currentns with init ns
  22. *
  23. * Verifies that UID 0 in the init namespace correctly owns the current
  24. * namespace when running in init_user_ns.
  25. *
  26. * @test: KUnit test context
  27. */
  28. static void test_vfsuid_root_in_currentns_init_ns(struct kunit *test)
  29. {
  30. vfsuid_t vfsuid;
  31. kuid_t kuid;
  32. /* Create UID 0 in init namespace */
  33. kuid = KUIDT_INIT(0);
  34. vfsuid = VFSUIDT_INIT(kuid);
  35. /* In init namespace, UID 0 should own current namespace */
  36. KUNIT_EXPECT_TRUE(test, vfsuid_root_in_currentns(vfsuid));
  37. }
  38. /**
  39. * test_vfsuid_root_in_currentns_invalid - Test vfsuid_root_in_currentns with invalid vfsuid
  40. *
  41. * Verifies that an invalid vfsuid correctly returns false.
  42. *
  43. * @test: KUnit test context
  44. */
  45. static void test_vfsuid_root_in_currentns_invalid(struct kunit *test)
  46. {
  47. vfsuid_t invalid_vfsuid;
  48. /* Use the predefined invalid vfsuid */
  49. invalid_vfsuid = INVALID_VFSUID;
  50. /* Invalid vfsuid should return false */
  51. KUNIT_EXPECT_FALSE(test, vfsuid_root_in_currentns(invalid_vfsuid));
  52. }
  53. /**
  54. * test_vfsuid_root_in_currentns_nonzero - Test vfsuid_root_in_currentns with non-zero UID
  55. *
  56. * Verifies that a non-zero UID correctly returns false.
  57. *
  58. * @test: KUnit test context
  59. */
  60. static void test_vfsuid_root_in_currentns_nonzero(struct kunit *test)
  61. {
  62. vfsuid_t vfsuid;
  63. kuid_t kuid;
  64. /* Create a non-zero UID */
  65. kuid = KUIDT_INIT(1000);
  66. vfsuid = VFSUIDT_INIT(kuid);
  67. /* Non-zero UID should return false */
  68. KUNIT_EXPECT_FALSE(test, vfsuid_root_in_currentns(vfsuid));
  69. }
  70. /**
  71. * test_kuid_root_in_ns_init_ns_uid0 - Test kuid_root_in_ns with init namespace and UID 0
  72. *
  73. * Verifies that kuid_root_in_ns correctly identifies UID 0 in init namespace.
  74. * This tests the core namespace traversal logic. In init namespace, UID 0
  75. * maps to itself, so it should own the namespace.
  76. *
  77. * @test: KUnit test context
  78. */
  79. static void test_kuid_root_in_ns_init_ns_uid0(struct kunit *test)
  80. {
  81. kuid_t kuid;
  82. struct user_namespace *init_ns;
  83. kuid = KUIDT_INIT(0);
  84. init_ns = &init_user_ns;
  85. /* UID 0 should own init namespace */
  86. KUNIT_EXPECT_TRUE(test, kuid_root_in_ns(kuid, init_ns));
  87. }
  88. /**
  89. * test_kuid_root_in_ns_init_ns_nonzero - Test kuid_root_in_ns with init namespace and non-zero UID
  90. *
  91. * Verifies that kuid_root_in_ns correctly rejects non-zero UIDs in init namespace.
  92. * Only UID 0 should own a namespace.
  93. *
  94. * @test: KUnit test context
  95. */
  96. static void test_kuid_root_in_ns_init_ns_nonzero(struct kunit *test)
  97. {
  98. kuid_t kuid;
  99. struct user_namespace *init_ns;
  100. kuid = KUIDT_INIT(1000);
  101. init_ns = &init_user_ns;
  102. /* Non-zero UID should not own namespace */
  103. KUNIT_EXPECT_FALSE(test, kuid_root_in_ns(kuid, init_ns));
  104. }
  105. /**
  106. * create_test_user_ns_with_mapping - Create a mock user namespace with UID mapping
  107. *
  108. * Creates a minimal user namespace structure for testing where uid 0 in the
  109. * namespace maps to a specific kuid in the parent namespace.
  110. *
  111. * @test: KUnit test context
  112. * @parent_ns: Parent namespace (typically init_user_ns)
  113. * @mapped_kuid: The kuid that uid 0 in this namespace maps to in parent
  114. *
  115. * Returns: Pointer to allocated namespace, or NULL on failure
  116. */
  117. static struct user_namespace *create_test_user_ns_with_mapping(struct kunit *test,
  118. struct user_namespace *parent_ns,
  119. kuid_t mapped_kuid)
  120. {
  121. struct user_namespace *ns;
  122. struct uid_gid_extent extent;
  123. /* Allocate a test namespace - use kzalloc to zero all fields */
  124. ns = kunit_kzalloc(test, sizeof(*ns), GFP_KERNEL);
  125. if (!ns)
  126. return NULL;
  127. /* Initialize basic namespace structure fields */
  128. ns->parent = parent_ns;
  129. ns->level = parent_ns ? parent_ns->level + 1 : 0;
  130. ns->owner = mapped_kuid;
  131. ns->group = KGIDT_INIT(0);
  132. /* Initialize ns_common structure */
  133. refcount_set(&ns->ns.__ns_ref, 1);
  134. ns->ns.inum = 0; /* Mock inum */
  135. /* Set up uid mapping: uid 0 in this namespace maps to mapped_kuid in parent
  136. * Format: first (uid in ns) : lower_first (kuid in parent) : count
  137. * So: uid 0 in ns -> kuid mapped_kuid in parent
  138. * This means from_kuid(ns, mapped_kuid) returns 0
  139. */
  140. extent.first = 0; /* uid 0 in this namespace */
  141. extent.lower_first = __kuid_val(mapped_kuid); /* maps to this kuid in parent */
  142. extent.count = 1;
  143. ns->uid_map.extent[0] = extent;
  144. ns->uid_map.nr_extents = 1;
  145. /* Set up gid mapping: gid 0 maps to gid 0 in parent (simplified) */
  146. extent.first = 0;
  147. extent.lower_first = 0;
  148. extent.count = 1;
  149. ns->gid_map.extent[0] = extent;
  150. ns->gid_map.nr_extents = 1;
  151. return ns;
  152. }
  153. /**
  154. * test_kuid_root_in_ns_with_mapping - Test kuid_root_in_ns with namespace where uid 0
  155. * maps to different kuid
  156. *
  157. * Creates a user namespace where uid 0 maps to kuid 1000 in the parent namespace.
  158. * Verifies that kuid_root_in_ns correctly identifies kuid 1000 as owning the namespace.
  159. *
  160. * Note: kuid_root_in_ns walks up the namespace hierarchy, so it checks the current
  161. * namespace first, then parent, then parent's parent, etc. So:
  162. * - kuid 1000 owns test_ns because from_kuid(test_ns, 1000) == 0
  163. * - kuid 0 also owns test_ns because from_kuid(init_user_ns, 0) == 0
  164. * (checked in parent)
  165. *
  166. * This tests the actual functionality as requested: creating namespaces with
  167. * different values for the namespace's uid 0.
  168. *
  169. * @test: KUnit test context
  170. */
  171. static void test_kuid_root_in_ns_with_mapping(struct kunit *test)
  172. {
  173. struct user_namespace *test_ns;
  174. struct user_namespace *parent_ns;
  175. kuid_t mapped_kuid, other_kuid;
  176. parent_ns = &init_user_ns;
  177. mapped_kuid = KUIDT_INIT(1000);
  178. other_kuid = KUIDT_INIT(2000);
  179. test_ns = create_test_user_ns_with_mapping(test, parent_ns, mapped_kuid);
  180. KUNIT_ASSERT_NOT_ERR_OR_NULL(test, test_ns);
  181. /* kuid 1000 should own test_ns because it maps to uid 0 in test_ns */
  182. KUNIT_EXPECT_TRUE(test, kuid_root_in_ns(mapped_kuid, test_ns));
  183. /* kuid 0 should also own test_ns (checked via parent init_user_ns) */
  184. KUNIT_EXPECT_TRUE(test, kuid_root_in_ns(KUIDT_INIT(0), test_ns));
  185. /* Other kuids should not own test_ns */
  186. KUNIT_EXPECT_FALSE(test, kuid_root_in_ns(other_kuid, test_ns));
  187. KUNIT_EXPECT_FALSE(test, kuid_root_in_ns(KUIDT_INIT(500), test_ns));
  188. }
  189. /**
  190. * test_kuid_root_in_ns_with_different_mappings - Test with multiple namespaces
  191. *
  192. * Creates multiple user namespaces with different UID mappings to verify
  193. * that kuid_root_in_ns correctly distinguishes between namespaces.
  194. *
  195. * Each namespace maps uid 0 to a different kuid, and we verify that each
  196. * kuid only owns its corresponding namespace (plus kuid 0 owns all via
  197. * init_user_ns parent).
  198. *
  199. * @test: KUnit test context
  200. */
  201. static void test_kuid_root_in_ns_with_different_mappings(struct kunit *test)
  202. {
  203. struct user_namespace *ns1, *ns2, *ns3;
  204. /* Create three independent namespaces, each mapping uid 0 to different kuids */
  205. ns1 = create_test_user_ns_with_mapping(test, &init_user_ns, KUIDT_INIT(1000));
  206. KUNIT_ASSERT_NOT_ERR_OR_NULL(test, ns1);
  207. ns2 = create_test_user_ns_with_mapping(test, &init_user_ns, KUIDT_INIT(2000));
  208. KUNIT_ASSERT_NOT_ERR_OR_NULL(test, ns2);
  209. ns3 = create_test_user_ns_with_mapping(test, &init_user_ns, KUIDT_INIT(3000));
  210. KUNIT_ASSERT_NOT_ERR_OR_NULL(test, ns3);
  211. /* Test ns1: kuid 1000 owns it, kuid 0 owns it (via parent), others do not */
  212. KUNIT_EXPECT_TRUE(test, kuid_root_in_ns(KUIDT_INIT(1000), ns1));
  213. KUNIT_EXPECT_TRUE(test, kuid_root_in_ns(KUIDT_INIT(0), ns1));
  214. KUNIT_EXPECT_FALSE(test, kuid_root_in_ns(KUIDT_INIT(2000), ns1));
  215. KUNIT_EXPECT_FALSE(test, kuid_root_in_ns(KUIDT_INIT(3000), ns1));
  216. /* Test ns2: kuid 2000 owns it, kuid 0 owns it (via parent), others do not */
  217. KUNIT_EXPECT_TRUE(test, kuid_root_in_ns(KUIDT_INIT(2000), ns2));
  218. KUNIT_EXPECT_TRUE(test, kuid_root_in_ns(KUIDT_INIT(0), ns2));
  219. KUNIT_EXPECT_FALSE(test, kuid_root_in_ns(KUIDT_INIT(1000), ns2));
  220. KUNIT_EXPECT_FALSE(test, kuid_root_in_ns(KUIDT_INIT(3000), ns2));
  221. /* Test ns3: kuid 3000 owns it, kuid 0 owns it (via parent), others do not */
  222. KUNIT_EXPECT_TRUE(test, kuid_root_in_ns(KUIDT_INIT(3000), ns3));
  223. KUNIT_EXPECT_TRUE(test, kuid_root_in_ns(KUIDT_INIT(0), ns3));
  224. KUNIT_EXPECT_FALSE(test, kuid_root_in_ns(KUIDT_INIT(1000), ns3));
  225. KUNIT_EXPECT_FALSE(test, kuid_root_in_ns(KUIDT_INIT(2000), ns3));
  226. }
  227. static struct kunit_case commoncap_test_cases[] = {
  228. KUNIT_CASE(test_vfsuid_root_in_currentns_init_ns),
  229. KUNIT_CASE(test_vfsuid_root_in_currentns_invalid),
  230. KUNIT_CASE(test_vfsuid_root_in_currentns_nonzero),
  231. KUNIT_CASE(test_kuid_root_in_ns_init_ns_uid0),
  232. KUNIT_CASE(test_kuid_root_in_ns_init_ns_nonzero),
  233. KUNIT_CASE(test_kuid_root_in_ns_with_mapping),
  234. KUNIT_CASE(test_kuid_root_in_ns_with_different_mappings),
  235. {}
  236. };
  237. static struct kunit_suite commoncap_test_suite = {
  238. .name = "commoncap",
  239. .test_cases = commoncap_test_cases,
  240. };
  241. kunit_test_suite(commoncap_test_suite);
  242. MODULE_LICENSE("GPL");
  243. #endif /* CONFIG_SECURITY_COMMONCAP_KUNIT_TEST */