at master 491 lines 14 kB view raw
1// SPDX-License-Identifier: GPL-2.0-only 2/* 3 * Landlock - Audit helpers 4 * 5 * Copyright © 2023-2025 Microsoft Corporation 6 */ 7 8#include <kunit/test.h> 9#include <linux/audit.h> 10#include <linux/bitops.h> 11#include <linux/lsm_audit.h> 12#include <linux/pid.h> 13#include <uapi/linux/landlock.h> 14 15#include "access.h" 16#include "audit.h" 17#include "common.h" 18#include "cred.h" 19#include "domain.h" 20#include "limits.h" 21#include "ruleset.h" 22 23static const char *const fs_access_strings[] = { 24 [BIT_INDEX(LANDLOCK_ACCESS_FS_EXECUTE)] = "fs.execute", 25 [BIT_INDEX(LANDLOCK_ACCESS_FS_WRITE_FILE)] = "fs.write_file", 26 [BIT_INDEX(LANDLOCK_ACCESS_FS_READ_FILE)] = "fs.read_file", 27 [BIT_INDEX(LANDLOCK_ACCESS_FS_READ_DIR)] = "fs.read_dir", 28 [BIT_INDEX(LANDLOCK_ACCESS_FS_REMOVE_DIR)] = "fs.remove_dir", 29 [BIT_INDEX(LANDLOCK_ACCESS_FS_REMOVE_FILE)] = "fs.remove_file", 30 [BIT_INDEX(LANDLOCK_ACCESS_FS_MAKE_CHAR)] = "fs.make_char", 31 [BIT_INDEX(LANDLOCK_ACCESS_FS_MAKE_DIR)] = "fs.make_dir", 32 [BIT_INDEX(LANDLOCK_ACCESS_FS_MAKE_REG)] = "fs.make_reg", 33 [BIT_INDEX(LANDLOCK_ACCESS_FS_MAKE_SOCK)] = "fs.make_sock", 34 [BIT_INDEX(LANDLOCK_ACCESS_FS_MAKE_FIFO)] = "fs.make_fifo", 35 [BIT_INDEX(LANDLOCK_ACCESS_FS_MAKE_BLOCK)] = "fs.make_block", 36 [BIT_INDEX(LANDLOCK_ACCESS_FS_MAKE_SYM)] = "fs.make_sym", 37 [BIT_INDEX(LANDLOCK_ACCESS_FS_REFER)] = "fs.refer", 38 [BIT_INDEX(LANDLOCK_ACCESS_FS_TRUNCATE)] = "fs.truncate", 39 [BIT_INDEX(LANDLOCK_ACCESS_FS_IOCTL_DEV)] = "fs.ioctl_dev", 40}; 41 42static_assert(ARRAY_SIZE(fs_access_strings) == LANDLOCK_NUM_ACCESS_FS); 43 44static const char *const net_access_strings[] = { 45 [BIT_INDEX(LANDLOCK_ACCESS_NET_BIND_TCP)] = "net.bind_tcp", 46 [BIT_INDEX(LANDLOCK_ACCESS_NET_CONNECT_TCP)] = "net.connect_tcp", 47}; 48 49static_assert(ARRAY_SIZE(net_access_strings) == LANDLOCK_NUM_ACCESS_NET); 50 51static __attribute_const__ const char * 52get_blocker(const enum landlock_request_type type, 53 const unsigned long access_bit) 54{ 55 switch (type) { 56 case LANDLOCK_REQUEST_PTRACE: 57 WARN_ON_ONCE(access_bit != -1); 58 return "ptrace"; 59 60 case LANDLOCK_REQUEST_FS_CHANGE_TOPOLOGY: 61 WARN_ON_ONCE(access_bit != -1); 62 return "fs.change_topology"; 63 64 case LANDLOCK_REQUEST_FS_ACCESS: 65 if (WARN_ON_ONCE(access_bit >= ARRAY_SIZE(fs_access_strings))) 66 return "unknown"; 67 return fs_access_strings[access_bit]; 68 69 case LANDLOCK_REQUEST_NET_ACCESS: 70 if (WARN_ON_ONCE(access_bit >= ARRAY_SIZE(net_access_strings))) 71 return "unknown"; 72 return net_access_strings[access_bit]; 73 74 case LANDLOCK_REQUEST_SCOPE_ABSTRACT_UNIX_SOCKET: 75 WARN_ON_ONCE(access_bit != -1); 76 return "scope.abstract_unix_socket"; 77 78 case LANDLOCK_REQUEST_SCOPE_SIGNAL: 79 WARN_ON_ONCE(access_bit != -1); 80 return "scope.signal"; 81 } 82 83 WARN_ON_ONCE(1); 84 return "unknown"; 85} 86 87static void log_blockers(struct audit_buffer *const ab, 88 const enum landlock_request_type type, 89 const access_mask_t access) 90{ 91 const unsigned long access_mask = access; 92 unsigned long access_bit; 93 bool is_first = true; 94 95 for_each_set_bit(access_bit, &access_mask, BITS_PER_TYPE(access)) { 96 audit_log_format(ab, "%s%s", is_first ? "" : ",", 97 get_blocker(type, access_bit)); 98 is_first = false; 99 } 100 if (is_first) 101 audit_log_format(ab, "%s", get_blocker(type, -1)); 102} 103 104static void log_domain(struct landlock_hierarchy *const hierarchy) 105{ 106 struct audit_buffer *ab; 107 108 /* Ignores already logged domains. */ 109 if (READ_ONCE(hierarchy->log_status) == LANDLOCK_LOG_RECORDED) 110 return; 111 112 /* Uses consistent allocation flags wrt common_lsm_audit(). */ 113 ab = audit_log_start(audit_context(), GFP_ATOMIC | __GFP_NOWARN, 114 AUDIT_LANDLOCK_DOMAIN); 115 if (!ab) 116 return; 117 118 WARN_ON_ONCE(hierarchy->id == 0); 119 audit_log_format( 120 ab, 121 "domain=%llx status=allocated mode=enforcing pid=%d uid=%u exe=", 122 hierarchy->id, pid_nr(hierarchy->details->pid), 123 hierarchy->details->uid); 124 audit_log_untrustedstring(ab, hierarchy->details->exe_path); 125 audit_log_format(ab, " comm="); 126 audit_log_untrustedstring(ab, hierarchy->details->comm); 127 audit_log_end(ab); 128 129 /* 130 * There may be race condition leading to logging of the same domain 131 * several times but that is OK. 132 */ 133 WRITE_ONCE(hierarchy->log_status, LANDLOCK_LOG_RECORDED); 134} 135 136static struct landlock_hierarchy * 137get_hierarchy(const struct landlock_ruleset *const domain, const size_t layer) 138{ 139 struct landlock_hierarchy *hierarchy = domain->hierarchy; 140 ssize_t i; 141 142 if (WARN_ON_ONCE(layer >= domain->num_layers)) 143 return hierarchy; 144 145 for (i = domain->num_layers - 1; i > layer; i--) { 146 if (WARN_ON_ONCE(!hierarchy->parent)) 147 break; 148 149 hierarchy = hierarchy->parent; 150 } 151 152 return hierarchy; 153} 154 155#ifdef CONFIG_SECURITY_LANDLOCK_KUNIT_TEST 156 157static void test_get_hierarchy(struct kunit *const test) 158{ 159 struct landlock_hierarchy dom0_hierarchy = { 160 .id = 10, 161 }; 162 struct landlock_hierarchy dom1_hierarchy = { 163 .parent = &dom0_hierarchy, 164 .id = 20, 165 }; 166 struct landlock_hierarchy dom2_hierarchy = { 167 .parent = &dom1_hierarchy, 168 .id = 30, 169 }; 170 struct landlock_ruleset dom2 = { 171 .hierarchy = &dom2_hierarchy, 172 .num_layers = 3, 173 }; 174 175 KUNIT_EXPECT_EQ(test, 10, get_hierarchy(&dom2, 0)->id); 176 KUNIT_EXPECT_EQ(test, 20, get_hierarchy(&dom2, 1)->id); 177 KUNIT_EXPECT_EQ(test, 30, get_hierarchy(&dom2, 2)->id); 178 /* KUNIT_EXPECT_EQ(test, 30, get_hierarchy(&dom2, -1)->id); */ 179} 180 181#endif /* CONFIG_SECURITY_LANDLOCK_KUNIT_TEST */ 182 183/* Get the youngest layer that denied the access_request. */ 184static size_t get_denied_layer(const struct landlock_ruleset *const domain, 185 access_mask_t *const access_request, 186 const struct layer_access_masks *masks) 187{ 188 for (ssize_t i = ARRAY_SIZE(masks->access) - 1; i >= 0; i--) { 189 if (masks->access[i] & *access_request) { 190 *access_request &= masks->access[i]; 191 return i; 192 } 193 } 194 195 /* Not found - fall back to default values */ 196 *access_request = 0; 197 return domain->num_layers - 1; 198} 199 200#ifdef CONFIG_SECURITY_LANDLOCK_KUNIT_TEST 201 202static void test_get_denied_layer(struct kunit *const test) 203{ 204 const struct landlock_ruleset dom = { 205 .num_layers = 5, 206 }; 207 const struct layer_access_masks masks = { 208 .access[0] = LANDLOCK_ACCESS_FS_EXECUTE | 209 LANDLOCK_ACCESS_FS_READ_DIR, 210 .access[1] = LANDLOCK_ACCESS_FS_READ_FILE | 211 LANDLOCK_ACCESS_FS_READ_DIR, 212 .access[2] = LANDLOCK_ACCESS_FS_REMOVE_DIR, 213 }; 214 access_mask_t access; 215 216 access = LANDLOCK_ACCESS_FS_EXECUTE; 217 KUNIT_EXPECT_EQ(test, 0, get_denied_layer(&dom, &access, &masks)); 218 KUNIT_EXPECT_EQ(test, access, LANDLOCK_ACCESS_FS_EXECUTE); 219 220 access = LANDLOCK_ACCESS_FS_READ_FILE; 221 KUNIT_EXPECT_EQ(test, 1, get_denied_layer(&dom, &access, &masks)); 222 KUNIT_EXPECT_EQ(test, access, LANDLOCK_ACCESS_FS_READ_FILE); 223 224 access = LANDLOCK_ACCESS_FS_READ_DIR; 225 KUNIT_EXPECT_EQ(test, 1, get_denied_layer(&dom, &access, &masks)); 226 KUNIT_EXPECT_EQ(test, access, LANDLOCK_ACCESS_FS_READ_DIR); 227 228 access = LANDLOCK_ACCESS_FS_READ_FILE | LANDLOCK_ACCESS_FS_READ_DIR; 229 KUNIT_EXPECT_EQ(test, 1, get_denied_layer(&dom, &access, &masks)); 230 KUNIT_EXPECT_EQ(test, access, 231 LANDLOCK_ACCESS_FS_READ_FILE | 232 LANDLOCK_ACCESS_FS_READ_DIR); 233 234 access = LANDLOCK_ACCESS_FS_EXECUTE | LANDLOCK_ACCESS_FS_READ_DIR; 235 KUNIT_EXPECT_EQ(test, 1, get_denied_layer(&dom, &access, &masks)); 236 KUNIT_EXPECT_EQ(test, access, LANDLOCK_ACCESS_FS_READ_DIR); 237 238 access = LANDLOCK_ACCESS_FS_WRITE_FILE; 239 KUNIT_EXPECT_EQ(test, 4, get_denied_layer(&dom, &access, &masks)); 240 KUNIT_EXPECT_EQ(test, access, 0); 241} 242 243#endif /* CONFIG_SECURITY_LANDLOCK_KUNIT_TEST */ 244 245static size_t 246get_layer_from_deny_masks(access_mask_t *const access_request, 247 const access_mask_t all_existing_optional_access, 248 const deny_masks_t deny_masks) 249{ 250 const unsigned long access_opt = all_existing_optional_access; 251 const unsigned long access_req = *access_request; 252 access_mask_t missing = 0; 253 size_t youngest_layer = 0; 254 size_t access_index = 0; 255 unsigned long access_bit; 256 257 /* This will require change with new object types. */ 258 WARN_ON_ONCE(access_opt != _LANDLOCK_ACCESS_FS_OPTIONAL); 259 260 for_each_set_bit(access_bit, &access_opt, 261 BITS_PER_TYPE(access_mask_t)) { 262 if (access_req & BIT(access_bit)) { 263 const size_t layer = 264 (deny_masks >> (access_index * 4)) & 265 (LANDLOCK_MAX_NUM_LAYERS - 1); 266 267 if (layer > youngest_layer) { 268 youngest_layer = layer; 269 missing = BIT(access_bit); 270 } else if (layer == youngest_layer) { 271 missing |= BIT(access_bit); 272 } 273 } 274 access_index++; 275 } 276 277 *access_request = missing; 278 return youngest_layer; 279} 280 281#ifdef CONFIG_SECURITY_LANDLOCK_KUNIT_TEST 282 283static void test_get_layer_from_deny_masks(struct kunit *const test) 284{ 285 deny_masks_t deny_mask; 286 access_mask_t access; 287 288 /* truncate:0 ioctl_dev:2 */ 289 deny_mask = 0x20; 290 291 access = LANDLOCK_ACCESS_FS_TRUNCATE; 292 KUNIT_EXPECT_EQ(test, 0, 293 get_layer_from_deny_masks(&access, 294 _LANDLOCK_ACCESS_FS_OPTIONAL, 295 deny_mask)); 296 KUNIT_EXPECT_EQ(test, access, LANDLOCK_ACCESS_FS_TRUNCATE); 297 298 access = LANDLOCK_ACCESS_FS_TRUNCATE | LANDLOCK_ACCESS_FS_IOCTL_DEV; 299 KUNIT_EXPECT_EQ(test, 2, 300 get_layer_from_deny_masks(&access, 301 _LANDLOCK_ACCESS_FS_OPTIONAL, 302 deny_mask)); 303 KUNIT_EXPECT_EQ(test, access, LANDLOCK_ACCESS_FS_IOCTL_DEV); 304 305 /* truncate:15 ioctl_dev:15 */ 306 deny_mask = 0xff; 307 308 access = LANDLOCK_ACCESS_FS_TRUNCATE; 309 KUNIT_EXPECT_EQ(test, 15, 310 get_layer_from_deny_masks(&access, 311 _LANDLOCK_ACCESS_FS_OPTIONAL, 312 deny_mask)); 313 KUNIT_EXPECT_EQ(test, access, LANDLOCK_ACCESS_FS_TRUNCATE); 314 315 access = LANDLOCK_ACCESS_FS_TRUNCATE | LANDLOCK_ACCESS_FS_IOCTL_DEV; 316 KUNIT_EXPECT_EQ(test, 15, 317 get_layer_from_deny_masks(&access, 318 _LANDLOCK_ACCESS_FS_OPTIONAL, 319 deny_mask)); 320 KUNIT_EXPECT_EQ(test, access, 321 LANDLOCK_ACCESS_FS_TRUNCATE | 322 LANDLOCK_ACCESS_FS_IOCTL_DEV); 323} 324 325#endif /* CONFIG_SECURITY_LANDLOCK_KUNIT_TEST */ 326 327static bool is_valid_request(const struct landlock_request *const request) 328{ 329 if (WARN_ON_ONCE(request->layer_plus_one > LANDLOCK_MAX_NUM_LAYERS)) 330 return false; 331 332 if (WARN_ON_ONCE(!(!!request->layer_plus_one ^ !!request->access))) 333 return false; 334 335 if (request->access) { 336 if (WARN_ON_ONCE(!(!!request->layer_masks ^ 337 !!request->all_existing_optional_access))) 338 return false; 339 } else { 340 if (WARN_ON_ONCE(request->layer_masks || 341 request->all_existing_optional_access)) 342 return false; 343 } 344 345 if (request->deny_masks) { 346 if (WARN_ON_ONCE(!request->all_existing_optional_access)) 347 return false; 348 } 349 350 return true; 351} 352 353/** 354 * landlock_log_denial - Create audit records related to a denial 355 * 356 * @subject: The Landlock subject's credential denying an action. 357 * @request: Detail of the user space request. 358 */ 359void landlock_log_denial(const struct landlock_cred_security *const subject, 360 const struct landlock_request *const request) 361{ 362 struct audit_buffer *ab; 363 struct landlock_hierarchy *youngest_denied; 364 size_t youngest_layer; 365 access_mask_t missing; 366 367 if (WARN_ON_ONCE(!subject || !subject->domain || 368 !subject->domain->hierarchy || !request)) 369 return; 370 371 if (!is_valid_request(request)) 372 return; 373 374 missing = request->access; 375 if (missing) { 376 /* Gets the nearest domain that denies the request. */ 377 if (request->layer_masks) { 378 youngest_layer = get_denied_layer(subject->domain, 379 &missing, 380 request->layer_masks); 381 } else { 382 youngest_layer = get_layer_from_deny_masks( 383 &missing, _LANDLOCK_ACCESS_FS_OPTIONAL, 384 request->deny_masks); 385 } 386 youngest_denied = 387 get_hierarchy(subject->domain, youngest_layer); 388 } else { 389 youngest_layer = request->layer_plus_one - 1; 390 youngest_denied = 391 get_hierarchy(subject->domain, youngest_layer); 392 } 393 394 if (READ_ONCE(youngest_denied->log_status) == LANDLOCK_LOG_DISABLED) 395 return; 396 397 /* 398 * Consistently keeps track of the number of denied access requests 399 * even if audit is currently disabled, or if audit rules currently 400 * exclude this record type, or if landlock_restrict_self(2)'s flags 401 * quiet logs. 402 */ 403 atomic64_inc(&youngest_denied->num_denials); 404 405 if (!audit_enabled) 406 return; 407 408 /* Checks if the current exec was restricting itself. */ 409 if (subject->domain_exec & BIT(youngest_layer)) { 410 /* Ignores denials for the same execution. */ 411 if (!youngest_denied->log_same_exec) 412 return; 413 } else { 414 /* Ignores denials after a new execution. */ 415 if (!youngest_denied->log_new_exec) 416 return; 417 } 418 419 /* Uses consistent allocation flags wrt common_lsm_audit(). */ 420 ab = audit_log_start(audit_context(), GFP_ATOMIC | __GFP_NOWARN, 421 AUDIT_LANDLOCK_ACCESS); 422 if (!ab) 423 return; 424 425 audit_log_format(ab, "domain=%llx blockers=", youngest_denied->id); 426 log_blockers(ab, request->type, missing); 427 audit_log_lsm_data(ab, &request->audit); 428 audit_log_end(ab); 429 430 /* Logs this domain the first time it shows in log. */ 431 log_domain(youngest_denied); 432} 433 434/** 435 * landlock_log_drop_domain - Create an audit record on domain deallocation 436 * 437 * @hierarchy: The domain's hierarchy being deallocated. 438 * 439 * Only domains which previously appeared in the audit logs are logged again. 440 * This is useful to know when a domain will never show again in the audit log. 441 * 442 * Called in a work queue scheduled by landlock_put_ruleset_deferred() called 443 * by hook_cred_free(). 444 */ 445void landlock_log_drop_domain(const struct landlock_hierarchy *const hierarchy) 446{ 447 struct audit_buffer *ab; 448 449 if (WARN_ON_ONCE(!hierarchy)) 450 return; 451 452 if (!audit_enabled) 453 return; 454 455 /* Ignores domains that were not logged. */ 456 if (READ_ONCE(hierarchy->log_status) != LANDLOCK_LOG_RECORDED) 457 return; 458 459 /* 460 * If logging of domain allocation succeeded, warns about failure to log 461 * domain deallocation to highlight unbalanced domain lifetime logs. 462 */ 463 ab = audit_log_start(audit_context(), GFP_KERNEL, 464 AUDIT_LANDLOCK_DOMAIN); 465 if (!ab) 466 return; 467 468 audit_log_format(ab, "domain=%llx status=deallocated denials=%llu", 469 hierarchy->id, atomic64_read(&hierarchy->num_denials)); 470 audit_log_end(ab); 471} 472 473#ifdef CONFIG_SECURITY_LANDLOCK_KUNIT_TEST 474 475static struct kunit_case test_cases[] = { 476 /* clang-format off */ 477 KUNIT_CASE(test_get_hierarchy), 478 KUNIT_CASE(test_get_denied_layer), 479 KUNIT_CASE(test_get_layer_from_deny_masks), 480 {} 481 /* clang-format on */ 482}; 483 484static struct kunit_suite test_suite = { 485 .name = "landlock_audit", 486 .test_cases = test_cases, 487}; 488 489kunit_test_suite(test_suite); 490 491#endif /* CONFIG_SECURITY_LANDLOCK_KUNIT_TEST */