Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

Merge tag 'caps-pr-20260213' of git://git.kernel.org/pub/scm/linux/kernel/git/sergeh/linux

Pull capabilities updates from Serge Hallyn:

- add KUnit tests for some core capabilities helpers

- avoid emitting IPC audit messages when there's not
actually a permission being denied

* tag 'caps-pr-20260213' of git://git.kernel.org/pub/scm/linux/kernel/git/sergeh/linux:
ipc: don't audit capability check in ipc_permissions()
security: Add KUnit tests for kuid_root_in_ns and vfsuid_root_in_currentns

+310
+1
MAINTAINERS
··· 5734 5734 F: include/uapi/linux/capability.h 5735 5735 F: kernel/capability.c 5736 5736 F: security/commoncap.c 5737 + F: security/commoncap_test.c 5737 5738 5738 5739 CAPELLA MICROSYSTEMS LIGHT SENSOR DRIVER 5739 5740 M: Kevin Tsai <ktsai@capellamicro.com>
+17
security/Kconfig
··· 284 284 285 285 If unsure, leave this as the default. 286 286 287 + config SECURITY_COMMONCAP_KUNIT_TEST 288 + bool "Build KUnit tests for commoncap" if !KUNIT_ALL_TESTS 289 + depends on KUNIT=y && USER_NS 290 + default KUNIT_ALL_TESTS 291 + help 292 + This builds the commoncap KUnit tests. 293 + 294 + KUnit tests run during boot and output the results to the debug log 295 + in TAP format (https://testanything.org/). Only useful for kernel devs 296 + running KUnit test harness and are not for inclusion into a 297 + production build. 298 + 299 + For more information on KUnit and unit tests in general please refer 300 + to the KUnit documentation in Documentation/dev-tools/kunit/. 301 + 302 + If unsure, say N. 303 + 287 304 source "security/Kconfig.hardening" 288 305 289 306 endmenu
+4
security/commoncap.c
··· 1521 1521 }; 1522 1522 1523 1523 #endif /* CONFIG_SECURITY */ 1524 + 1525 + #ifdef CONFIG_SECURITY_COMMONCAP_KUNIT_TEST 1526 + #include "commoncap_test.c" 1527 + #endif
+288
security/commoncap_test.c
··· 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 + 9 + #include <kunit/test.h> 10 + #include <linux/user_namespace.h> 11 + #include <linux/uidgid.h> 12 + #include <linux/cred.h> 13 + #include <linux/mnt_idmapping.h> 14 + #include <linux/module.h> 15 + #include <linux/slab.h> 16 + #include <linux/refcount.h> 17 + 18 + #ifdef CONFIG_SECURITY_COMMONCAP_KUNIT_TEST 19 + 20 + /* Functions are static in commoncap.c, but we can call them since we're 21 + * included in the same compilation unit when tests are enabled. 22 + */ 23 + 24 + /** 25 + * test_vfsuid_root_in_currentns_init_ns - Test vfsuid_root_in_currentns with init ns 26 + * 27 + * Verifies that UID 0 in the init namespace correctly owns the current 28 + * namespace when running in init_user_ns. 29 + * 30 + * @test: KUnit test context 31 + */ 32 + static void test_vfsuid_root_in_currentns_init_ns(struct kunit *test) 33 + { 34 + vfsuid_t vfsuid; 35 + kuid_t kuid; 36 + 37 + /* Create UID 0 in init namespace */ 38 + kuid = KUIDT_INIT(0); 39 + vfsuid = VFSUIDT_INIT(kuid); 40 + 41 + /* In init namespace, UID 0 should own current namespace */ 42 + KUNIT_EXPECT_TRUE(test, vfsuid_root_in_currentns(vfsuid)); 43 + } 44 + 45 + /** 46 + * test_vfsuid_root_in_currentns_invalid - Test vfsuid_root_in_currentns with invalid vfsuid 47 + * 48 + * Verifies that an invalid vfsuid correctly returns false. 49 + * 50 + * @test: KUnit test context 51 + */ 52 + static void test_vfsuid_root_in_currentns_invalid(struct kunit *test) 53 + { 54 + vfsuid_t invalid_vfsuid; 55 + 56 + /* Use the predefined invalid vfsuid */ 57 + invalid_vfsuid = INVALID_VFSUID; 58 + 59 + /* Invalid vfsuid should return false */ 60 + KUNIT_EXPECT_FALSE(test, vfsuid_root_in_currentns(invalid_vfsuid)); 61 + } 62 + 63 + /** 64 + * test_vfsuid_root_in_currentns_nonzero - Test vfsuid_root_in_currentns with non-zero UID 65 + * 66 + * Verifies that a non-zero UID correctly returns false. 67 + * 68 + * @test: KUnit test context 69 + */ 70 + static void test_vfsuid_root_in_currentns_nonzero(struct kunit *test) 71 + { 72 + vfsuid_t vfsuid; 73 + kuid_t kuid; 74 + 75 + /* Create a non-zero UID */ 76 + kuid = KUIDT_INIT(1000); 77 + vfsuid = VFSUIDT_INIT(kuid); 78 + 79 + /* Non-zero UID should return false */ 80 + KUNIT_EXPECT_FALSE(test, vfsuid_root_in_currentns(vfsuid)); 81 + } 82 + 83 + /** 84 + * test_kuid_root_in_ns_init_ns_uid0 - Test kuid_root_in_ns with init namespace and UID 0 85 + * 86 + * Verifies that kuid_root_in_ns correctly identifies UID 0 in init namespace. 87 + * This tests the core namespace traversal logic. In init namespace, UID 0 88 + * maps to itself, so it should own the namespace. 89 + * 90 + * @test: KUnit test context 91 + */ 92 + static void test_kuid_root_in_ns_init_ns_uid0(struct kunit *test) 93 + { 94 + kuid_t kuid; 95 + struct user_namespace *init_ns; 96 + 97 + kuid = KUIDT_INIT(0); 98 + init_ns = &init_user_ns; 99 + 100 + /* UID 0 should own init namespace */ 101 + KUNIT_EXPECT_TRUE(test, kuid_root_in_ns(kuid, init_ns)); 102 + } 103 + 104 + /** 105 + * test_kuid_root_in_ns_init_ns_nonzero - Test kuid_root_in_ns with init namespace and non-zero UID 106 + * 107 + * Verifies that kuid_root_in_ns correctly rejects non-zero UIDs in init namespace. 108 + * Only UID 0 should own a namespace. 109 + * 110 + * @test: KUnit test context 111 + */ 112 + static void test_kuid_root_in_ns_init_ns_nonzero(struct kunit *test) 113 + { 114 + kuid_t kuid; 115 + struct user_namespace *init_ns; 116 + 117 + kuid = KUIDT_INIT(1000); 118 + init_ns = &init_user_ns; 119 + 120 + /* Non-zero UID should not own namespace */ 121 + KUNIT_EXPECT_FALSE(test, kuid_root_in_ns(kuid, init_ns)); 122 + } 123 + 124 + /** 125 + * create_test_user_ns_with_mapping - Create a mock user namespace with UID mapping 126 + * 127 + * Creates a minimal user namespace structure for testing where uid 0 in the 128 + * namespace maps to a specific kuid in the parent namespace. 129 + * 130 + * @test: KUnit test context 131 + * @parent_ns: Parent namespace (typically init_user_ns) 132 + * @mapped_kuid: The kuid that uid 0 in this namespace maps to in parent 133 + * 134 + * Returns: Pointer to allocated namespace, or NULL on failure 135 + */ 136 + static struct user_namespace *create_test_user_ns_with_mapping(struct kunit *test, 137 + struct user_namespace *parent_ns, 138 + kuid_t mapped_kuid) 139 + { 140 + struct user_namespace *ns; 141 + struct uid_gid_extent extent; 142 + 143 + /* Allocate a test namespace - use kzalloc to zero all fields */ 144 + ns = kunit_kzalloc(test, sizeof(*ns), GFP_KERNEL); 145 + if (!ns) 146 + return NULL; 147 + 148 + /* Initialize basic namespace structure fields */ 149 + ns->parent = parent_ns; 150 + ns->level = parent_ns ? parent_ns->level + 1 : 0; 151 + ns->owner = mapped_kuid; 152 + ns->group = KGIDT_INIT(0); 153 + 154 + /* Initialize ns_common structure */ 155 + refcount_set(&ns->ns.__ns_ref, 1); 156 + ns->ns.inum = 0; /* Mock inum */ 157 + 158 + /* Set up uid mapping: uid 0 in this namespace maps to mapped_kuid in parent 159 + * Format: first (uid in ns) : lower_first (kuid in parent) : count 160 + * So: uid 0 in ns -> kuid mapped_kuid in parent 161 + * This means from_kuid(ns, mapped_kuid) returns 0 162 + */ 163 + extent.first = 0; /* uid 0 in this namespace */ 164 + extent.lower_first = __kuid_val(mapped_kuid); /* maps to this kuid in parent */ 165 + extent.count = 1; 166 + 167 + ns->uid_map.extent[0] = extent; 168 + ns->uid_map.nr_extents = 1; 169 + 170 + /* Set up gid mapping: gid 0 maps to gid 0 in parent (simplified) */ 171 + extent.first = 0; 172 + extent.lower_first = 0; 173 + extent.count = 1; 174 + 175 + ns->gid_map.extent[0] = extent; 176 + ns->gid_map.nr_extents = 1; 177 + 178 + return ns; 179 + } 180 + 181 + /** 182 + * test_kuid_root_in_ns_with_mapping - Test kuid_root_in_ns with namespace where uid 0 183 + * maps to different kuid 184 + * 185 + * Creates a user namespace where uid 0 maps to kuid 1000 in the parent namespace. 186 + * Verifies that kuid_root_in_ns correctly identifies kuid 1000 as owning the namespace. 187 + * 188 + * Note: kuid_root_in_ns walks up the namespace hierarchy, so it checks the current 189 + * namespace first, then parent, then parent's parent, etc. So: 190 + * - kuid 1000 owns test_ns because from_kuid(test_ns, 1000) == 0 191 + * - kuid 0 also owns test_ns because from_kuid(init_user_ns, 0) == 0 192 + * (checked in parent) 193 + * 194 + * This tests the actual functionality as requested: creating namespaces with 195 + * different values for the namespace's uid 0. 196 + * 197 + * @test: KUnit test context 198 + */ 199 + static void test_kuid_root_in_ns_with_mapping(struct kunit *test) 200 + { 201 + struct user_namespace *test_ns; 202 + struct user_namespace *parent_ns; 203 + kuid_t mapped_kuid, other_kuid; 204 + 205 + parent_ns = &init_user_ns; 206 + mapped_kuid = KUIDT_INIT(1000); 207 + other_kuid = KUIDT_INIT(2000); 208 + 209 + test_ns = create_test_user_ns_with_mapping(test, parent_ns, mapped_kuid); 210 + KUNIT_ASSERT_NOT_ERR_OR_NULL(test, test_ns); 211 + 212 + /* kuid 1000 should own test_ns because it maps to uid 0 in test_ns */ 213 + KUNIT_EXPECT_TRUE(test, kuid_root_in_ns(mapped_kuid, test_ns)); 214 + 215 + /* kuid 0 should also own test_ns (checked via parent init_user_ns) */ 216 + KUNIT_EXPECT_TRUE(test, kuid_root_in_ns(KUIDT_INIT(0), test_ns)); 217 + 218 + /* Other kuids should not own test_ns */ 219 + KUNIT_EXPECT_FALSE(test, kuid_root_in_ns(other_kuid, test_ns)); 220 + KUNIT_EXPECT_FALSE(test, kuid_root_in_ns(KUIDT_INIT(500), test_ns)); 221 + } 222 + 223 + /** 224 + * test_kuid_root_in_ns_with_different_mappings - Test with multiple namespaces 225 + * 226 + * Creates multiple user namespaces with different UID mappings to verify 227 + * that kuid_root_in_ns correctly distinguishes between namespaces. 228 + * 229 + * Each namespace maps uid 0 to a different kuid, and we verify that each 230 + * kuid only owns its corresponding namespace (plus kuid 0 owns all via 231 + * init_user_ns parent). 232 + * 233 + * @test: KUnit test context 234 + */ 235 + static void test_kuid_root_in_ns_with_different_mappings(struct kunit *test) 236 + { 237 + struct user_namespace *ns1, *ns2, *ns3; 238 + 239 + /* Create three independent namespaces, each mapping uid 0 to different kuids */ 240 + ns1 = create_test_user_ns_with_mapping(test, &init_user_ns, KUIDT_INIT(1000)); 241 + KUNIT_ASSERT_NOT_ERR_OR_NULL(test, ns1); 242 + 243 + ns2 = create_test_user_ns_with_mapping(test, &init_user_ns, KUIDT_INIT(2000)); 244 + KUNIT_ASSERT_NOT_ERR_OR_NULL(test, ns2); 245 + 246 + ns3 = create_test_user_ns_with_mapping(test, &init_user_ns, KUIDT_INIT(3000)); 247 + KUNIT_ASSERT_NOT_ERR_OR_NULL(test, ns3); 248 + 249 + /* Test ns1: kuid 1000 owns it, kuid 0 owns it (via parent), others do not */ 250 + KUNIT_EXPECT_TRUE(test, kuid_root_in_ns(KUIDT_INIT(1000), ns1)); 251 + KUNIT_EXPECT_TRUE(test, kuid_root_in_ns(KUIDT_INIT(0), ns1)); 252 + KUNIT_EXPECT_FALSE(test, kuid_root_in_ns(KUIDT_INIT(2000), ns1)); 253 + KUNIT_EXPECT_FALSE(test, kuid_root_in_ns(KUIDT_INIT(3000), ns1)); 254 + 255 + /* Test ns2: kuid 2000 owns it, kuid 0 owns it (via parent), others do not */ 256 + KUNIT_EXPECT_TRUE(test, kuid_root_in_ns(KUIDT_INIT(2000), ns2)); 257 + KUNIT_EXPECT_TRUE(test, kuid_root_in_ns(KUIDT_INIT(0), ns2)); 258 + KUNIT_EXPECT_FALSE(test, kuid_root_in_ns(KUIDT_INIT(1000), ns2)); 259 + KUNIT_EXPECT_FALSE(test, kuid_root_in_ns(KUIDT_INIT(3000), ns2)); 260 + 261 + /* Test ns3: kuid 3000 owns it, kuid 0 owns it (via parent), others do not */ 262 + KUNIT_EXPECT_TRUE(test, kuid_root_in_ns(KUIDT_INIT(3000), ns3)); 263 + KUNIT_EXPECT_TRUE(test, kuid_root_in_ns(KUIDT_INIT(0), ns3)); 264 + KUNIT_EXPECT_FALSE(test, kuid_root_in_ns(KUIDT_INIT(1000), ns3)); 265 + KUNIT_EXPECT_FALSE(test, kuid_root_in_ns(KUIDT_INIT(2000), ns3)); 266 + } 267 + 268 + static struct kunit_case commoncap_test_cases[] = { 269 + KUNIT_CASE(test_vfsuid_root_in_currentns_init_ns), 270 + KUNIT_CASE(test_vfsuid_root_in_currentns_invalid), 271 + KUNIT_CASE(test_vfsuid_root_in_currentns_nonzero), 272 + KUNIT_CASE(test_kuid_root_in_ns_init_ns_uid0), 273 + KUNIT_CASE(test_kuid_root_in_ns_init_ns_nonzero), 274 + KUNIT_CASE(test_kuid_root_in_ns_with_mapping), 275 + KUNIT_CASE(test_kuid_root_in_ns_with_different_mappings), 276 + {} 277 + }; 278 + 279 + static struct kunit_suite commoncap_test_suite = { 280 + .name = "commoncap", 281 + .test_cases = commoncap_test_cases, 282 + }; 283 + 284 + kunit_test_suite(commoncap_test_suite); 285 + 286 + MODULE_LICENSE("GPL"); 287 + 288 + #endif /* CONFIG_SECURITY_COMMONCAP_KUNIT_TEST */