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