1 // SPDX-License-Identifier: GPL-2.0
2 /*
3 * Landlock tests - Common user space base
4 *
5 * Copyright © 2017-2020 Mickaël Salaün <mic@digikod.net>
6 * Copyright © 2019-2020 ANSSI
7 */
8
9 #define _GNU_SOURCE
10 #include <errno.h>
11 #include <fcntl.h>
12 #include <linux/keyctl.h>
13 #include <linux/landlock.h>
14 #include <string.h>
15 #include <sys/prctl.h>
16 #include <sys/socket.h>
17 #include <sys/types.h>
18
19 #include "common.h"
20
21 #ifndef O_PATH
22 #define O_PATH 010000000
23 #endif
24
TEST(inconsistent_attr)25 TEST(inconsistent_attr)
26 {
27 const long page_size = sysconf(_SC_PAGESIZE);
28 char *const buf = malloc(page_size + 1);
29 struct landlock_ruleset_attr *const ruleset_attr = (void *)buf;
30
31 ASSERT_NE(NULL, buf);
32
33 /* Checks copy_from_user(). */
34 ASSERT_EQ(-1, landlock_create_ruleset(ruleset_attr, 0, 0));
35 /* The size if less than sizeof(struct landlock_attr_enforce). */
36 ASSERT_EQ(EINVAL, errno);
37 ASSERT_EQ(-1, landlock_create_ruleset(ruleset_attr, 1, 0));
38 ASSERT_EQ(EINVAL, errno);
39 ASSERT_EQ(-1, landlock_create_ruleset(ruleset_attr, 7, 0));
40 ASSERT_EQ(EINVAL, errno);
41
42 ASSERT_EQ(-1, landlock_create_ruleset(NULL, 1, 0));
43 /* The size if less than sizeof(struct landlock_attr_enforce). */
44 ASSERT_EQ(EFAULT, errno);
45
46 ASSERT_EQ(-1, landlock_create_ruleset(
47 NULL, sizeof(struct landlock_ruleset_attr), 0));
48 ASSERT_EQ(EFAULT, errno);
49
50 ASSERT_EQ(-1, landlock_create_ruleset(ruleset_attr, page_size + 1, 0));
51 ASSERT_EQ(E2BIG, errno);
52
53 /* Checks minimal valid attribute size. */
54 ASSERT_EQ(-1, landlock_create_ruleset(ruleset_attr, 8, 0));
55 ASSERT_EQ(ENOMSG, errno);
56 ASSERT_EQ(-1, landlock_create_ruleset(
57 ruleset_attr,
58 sizeof(struct landlock_ruleset_attr), 0));
59 ASSERT_EQ(ENOMSG, errno);
60 ASSERT_EQ(-1, landlock_create_ruleset(ruleset_attr, page_size, 0));
61 ASSERT_EQ(ENOMSG, errno);
62
63 /* Checks non-zero value. */
64 buf[page_size - 2] = '.';
65 ASSERT_EQ(-1, landlock_create_ruleset(ruleset_attr, page_size, 0));
66 ASSERT_EQ(E2BIG, errno);
67
68 ASSERT_EQ(-1, landlock_create_ruleset(ruleset_attr, page_size + 1, 0));
69 ASSERT_EQ(E2BIG, errno);
70
71 free(buf);
72 }
73
TEST(abi_version)74 TEST(abi_version)
75 {
76 const struct landlock_ruleset_attr ruleset_attr = {
77 .handled_access_fs = LANDLOCK_ACCESS_FS_READ_FILE,
78 };
79 ASSERT_EQ(7, landlock_create_ruleset(NULL, 0,
80 LANDLOCK_CREATE_RULESET_VERSION));
81
82 ASSERT_EQ(-1, landlock_create_ruleset(&ruleset_attr, 0,
83 LANDLOCK_CREATE_RULESET_VERSION));
84 ASSERT_EQ(EINVAL, errno);
85
86 ASSERT_EQ(-1, landlock_create_ruleset(NULL, sizeof(ruleset_attr),
87 LANDLOCK_CREATE_RULESET_VERSION));
88 ASSERT_EQ(EINVAL, errno);
89
90 ASSERT_EQ(-1,
91 landlock_create_ruleset(&ruleset_attr, sizeof(ruleset_attr),
92 LANDLOCK_CREATE_RULESET_VERSION));
93 ASSERT_EQ(EINVAL, errno);
94
95 ASSERT_EQ(-1, landlock_create_ruleset(NULL, 0,
96 LANDLOCK_CREATE_RULESET_VERSION |
97 1 << 31));
98 ASSERT_EQ(EINVAL, errno);
99 }
100
101 /*
102 * Old source trees might not have the set of Kselftest fixes related to kernel
103 * UAPI headers.
104 */
105 #ifndef LANDLOCK_CREATE_RULESET_ERRATA
106 #define LANDLOCK_CREATE_RULESET_ERRATA (1U << 1)
107 #endif
108
TEST(errata)109 TEST(errata)
110 {
111 const struct landlock_ruleset_attr ruleset_attr = {
112 .handled_access_fs = LANDLOCK_ACCESS_FS_READ_FILE,
113 };
114 int errata;
115
116 errata = landlock_create_ruleset(NULL, 0,
117 LANDLOCK_CREATE_RULESET_ERRATA);
118 /* The errata bitmask will not be backported to tests. */
119 ASSERT_LE(0, errata);
120 TH_LOG("errata: 0x%x", errata);
121
122 ASSERT_EQ(-1, landlock_create_ruleset(&ruleset_attr, 0,
123 LANDLOCK_CREATE_RULESET_ERRATA));
124 ASSERT_EQ(EINVAL, errno);
125
126 ASSERT_EQ(-1, landlock_create_ruleset(NULL, sizeof(ruleset_attr),
127 LANDLOCK_CREATE_RULESET_ERRATA));
128 ASSERT_EQ(EINVAL, errno);
129
130 ASSERT_EQ(-1,
131 landlock_create_ruleset(&ruleset_attr, sizeof(ruleset_attr),
132 LANDLOCK_CREATE_RULESET_ERRATA));
133 ASSERT_EQ(EINVAL, errno);
134
135 ASSERT_EQ(-1, landlock_create_ruleset(
136 NULL, 0,
137 LANDLOCK_CREATE_RULESET_VERSION |
138 LANDLOCK_CREATE_RULESET_ERRATA));
139 ASSERT_EQ(-1, landlock_create_ruleset(NULL, 0,
140 LANDLOCK_CREATE_RULESET_ERRATA |
141 1 << 31));
142 ASSERT_EQ(EINVAL, errno);
143 }
144
145 /* Tests ordering of syscall argument checks. */
TEST(create_ruleset_checks_ordering)146 TEST(create_ruleset_checks_ordering)
147 {
148 const int last_flag = LANDLOCK_CREATE_RULESET_ERRATA;
149 const int invalid_flag = last_flag << 1;
150 int ruleset_fd;
151 const struct landlock_ruleset_attr ruleset_attr = {
152 .handled_access_fs = LANDLOCK_ACCESS_FS_READ_FILE,
153 };
154
155 /* Checks priority for invalid flags. */
156 ASSERT_EQ(-1, landlock_create_ruleset(NULL, 0, invalid_flag));
157 ASSERT_EQ(EINVAL, errno);
158
159 ASSERT_EQ(-1, landlock_create_ruleset(&ruleset_attr, 0, invalid_flag));
160 ASSERT_EQ(EINVAL, errno);
161
162 ASSERT_EQ(-1, landlock_create_ruleset(NULL, sizeof(ruleset_attr),
163 invalid_flag));
164 ASSERT_EQ(EINVAL, errno);
165
166 ASSERT_EQ(-1,
167 landlock_create_ruleset(&ruleset_attr, sizeof(ruleset_attr),
168 invalid_flag));
169 ASSERT_EQ(EINVAL, errno);
170
171 /* Checks too big ruleset_attr size. */
172 ASSERT_EQ(-1, landlock_create_ruleset(&ruleset_attr, -1, 0));
173 ASSERT_EQ(E2BIG, errno);
174
175 /* Checks too small ruleset_attr size. */
176 ASSERT_EQ(-1, landlock_create_ruleset(&ruleset_attr, 0, 0));
177 ASSERT_EQ(EINVAL, errno);
178 ASSERT_EQ(-1, landlock_create_ruleset(&ruleset_attr, 1, 0));
179 ASSERT_EQ(EINVAL, errno);
180
181 /* Checks valid call. */
182 ruleset_fd =
183 landlock_create_ruleset(&ruleset_attr, sizeof(ruleset_attr), 0);
184 ASSERT_LE(0, ruleset_fd);
185 ASSERT_EQ(0, close(ruleset_fd));
186 }
187
188 /* Tests ordering of syscall argument checks. */
TEST(add_rule_checks_ordering)189 TEST(add_rule_checks_ordering)
190 {
191 const struct landlock_ruleset_attr ruleset_attr = {
192 .handled_access_fs = LANDLOCK_ACCESS_FS_EXECUTE,
193 };
194 struct landlock_path_beneath_attr path_beneath_attr = {
195 .allowed_access = LANDLOCK_ACCESS_FS_EXECUTE,
196 .parent_fd = -1,
197 };
198 const int ruleset_fd =
199 landlock_create_ruleset(&ruleset_attr, sizeof(ruleset_attr), 0);
200
201 ASSERT_LE(0, ruleset_fd);
202
203 /* Checks invalid flags. */
204 ASSERT_EQ(-1, landlock_add_rule(-1, 0, NULL, 1));
205 ASSERT_EQ(EINVAL, errno);
206
207 /* Checks invalid ruleset FD. */
208 ASSERT_EQ(-1, landlock_add_rule(-1, 0, NULL, 0));
209 ASSERT_EQ(EBADF, errno);
210
211 /* Checks invalid rule type. */
212 ASSERT_EQ(-1, landlock_add_rule(ruleset_fd, 0, NULL, 0));
213 ASSERT_EQ(EINVAL, errno);
214
215 /* Checks invalid rule attr. */
216 ASSERT_EQ(-1, landlock_add_rule(ruleset_fd, LANDLOCK_RULE_PATH_BENEATH,
217 NULL, 0));
218 ASSERT_EQ(EFAULT, errno);
219
220 /* Checks invalid path_beneath.parent_fd. */
221 ASSERT_EQ(-1, landlock_add_rule(ruleset_fd, LANDLOCK_RULE_PATH_BENEATH,
222 &path_beneath_attr, 0));
223 ASSERT_EQ(EBADF, errno);
224
225 /* Checks valid call. */
226 path_beneath_attr.parent_fd =
227 open("/tmp", O_PATH | O_NOFOLLOW | O_DIRECTORY | O_CLOEXEC);
228 ASSERT_LE(0, path_beneath_attr.parent_fd);
229 ASSERT_EQ(0, landlock_add_rule(ruleset_fd, LANDLOCK_RULE_PATH_BENEATH,
230 &path_beneath_attr, 0));
231 ASSERT_EQ(0, close(path_beneath_attr.parent_fd));
232 ASSERT_EQ(0, close(ruleset_fd));
233 }
234
235 /* Tests ordering of syscall argument and permission checks. */
TEST(restrict_self_checks_ordering)236 TEST(restrict_self_checks_ordering)
237 {
238 const struct landlock_ruleset_attr ruleset_attr = {
239 .handled_access_fs = LANDLOCK_ACCESS_FS_EXECUTE,
240 };
241 struct landlock_path_beneath_attr path_beneath_attr = {
242 .allowed_access = LANDLOCK_ACCESS_FS_EXECUTE,
243 .parent_fd = -1,
244 };
245 const int ruleset_fd =
246 landlock_create_ruleset(&ruleset_attr, sizeof(ruleset_attr), 0);
247
248 ASSERT_LE(0, ruleset_fd);
249 path_beneath_attr.parent_fd =
250 open("/tmp", O_PATH | O_NOFOLLOW | O_DIRECTORY | O_CLOEXEC);
251 ASSERT_LE(0, path_beneath_attr.parent_fd);
252 ASSERT_EQ(0, landlock_add_rule(ruleset_fd, LANDLOCK_RULE_PATH_BENEATH,
253 &path_beneath_attr, 0));
254 ASSERT_EQ(0, close(path_beneath_attr.parent_fd));
255
256 /* Checks unprivileged enforcement without no_new_privs. */
257 drop_caps(_metadata);
258 ASSERT_EQ(-1, landlock_restrict_self(-1, -1));
259 ASSERT_EQ(EPERM, errno);
260 ASSERT_EQ(-1, landlock_restrict_self(-1, 0));
261 ASSERT_EQ(EPERM, errno);
262 ASSERT_EQ(-1, landlock_restrict_self(ruleset_fd, 0));
263 ASSERT_EQ(EPERM, errno);
264
265 ASSERT_EQ(0, prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0));
266
267 /* Checks invalid flags. */
268 ASSERT_EQ(-1, landlock_restrict_self(-1, -1));
269 ASSERT_EQ(EINVAL, errno);
270
271 /* Checks invalid ruleset FD. */
272 ASSERT_EQ(-1, landlock_restrict_self(-1, 0));
273 ASSERT_EQ(EBADF, errno);
274
275 /* Checks valid call. */
276 ASSERT_EQ(0, landlock_restrict_self(ruleset_fd, 0));
277 ASSERT_EQ(0, close(ruleset_fd));
278 }
279
TEST(restrict_self_fd)280 TEST(restrict_self_fd)
281 {
282 int fd;
283
284 fd = open("/dev/null", O_RDONLY | O_CLOEXEC);
285 ASSERT_LE(0, fd);
286
287 EXPECT_EQ(-1, landlock_restrict_self(fd, 0));
288 EXPECT_EQ(EBADFD, errno);
289 }
290
TEST(restrict_self_fd_flags)291 TEST(restrict_self_fd_flags)
292 {
293 int fd;
294
295 fd = open("/dev/null", O_RDONLY | O_CLOEXEC);
296 ASSERT_LE(0, fd);
297
298 /*
299 * LANDLOCK_RESTRICT_SELF_LOG_SUBDOMAINS_OFF accepts -1 but not any file
300 * descriptor.
301 */
302 EXPECT_EQ(-1, landlock_restrict_self(
303 fd, LANDLOCK_RESTRICT_SELF_LOG_SUBDOMAINS_OFF));
304 EXPECT_EQ(EBADFD, errno);
305 }
306
TEST(restrict_self_flags)307 TEST(restrict_self_flags)
308 {
309 const __u32 last_flag = LANDLOCK_RESTRICT_SELF_LOG_SUBDOMAINS_OFF;
310
311 /* Tests invalid flag combinations. */
312
313 EXPECT_EQ(-1, landlock_restrict_self(-1, last_flag << 1));
314 EXPECT_EQ(EINVAL, errno);
315
316 EXPECT_EQ(-1, landlock_restrict_self(-1, -1));
317 EXPECT_EQ(EINVAL, errno);
318
319 /* Tests valid flag combinations. */
320
321 EXPECT_EQ(-1, landlock_restrict_self(-1, 0));
322 EXPECT_EQ(EBADF, errno);
323
324 EXPECT_EQ(-1, landlock_restrict_self(
325 -1, LANDLOCK_RESTRICT_SELF_LOG_SAME_EXEC_OFF));
326 EXPECT_EQ(EBADF, errno);
327
328 EXPECT_EQ(-1,
329 landlock_restrict_self(
330 -1,
331 LANDLOCK_RESTRICT_SELF_LOG_SAME_EXEC_OFF |
332 LANDLOCK_RESTRICT_SELF_LOG_SUBDOMAINS_OFF));
333 EXPECT_EQ(EBADF, errno);
334
335 EXPECT_EQ(-1,
336 landlock_restrict_self(
337 -1,
338 LANDLOCK_RESTRICT_SELF_LOG_NEW_EXEC_ON |
339 LANDLOCK_RESTRICT_SELF_LOG_SUBDOMAINS_OFF));
340 EXPECT_EQ(EBADF, errno);
341
342 EXPECT_EQ(-1, landlock_restrict_self(
343 -1, LANDLOCK_RESTRICT_SELF_LOG_NEW_EXEC_ON));
344 EXPECT_EQ(EBADF, errno);
345
346 EXPECT_EQ(-1,
347 landlock_restrict_self(
348 -1, LANDLOCK_RESTRICT_SELF_LOG_SAME_EXEC_OFF |
349 LANDLOCK_RESTRICT_SELF_LOG_NEW_EXEC_ON));
350 EXPECT_EQ(EBADF, errno);
351
352 /* Tests with an invalid ruleset_fd. */
353
354 EXPECT_EQ(-1, landlock_restrict_self(
355 -2, LANDLOCK_RESTRICT_SELF_LOG_SUBDOMAINS_OFF));
356 EXPECT_EQ(EBADF, errno);
357
358 EXPECT_EQ(0, landlock_restrict_self(
359 -1, LANDLOCK_RESTRICT_SELF_LOG_SUBDOMAINS_OFF));
360 }
361
TEST(ruleset_fd_io)362 TEST(ruleset_fd_io)
363 {
364 struct landlock_ruleset_attr ruleset_attr = {
365 .handled_access_fs = LANDLOCK_ACCESS_FS_READ_FILE,
366 };
367 int ruleset_fd;
368 char buf;
369
370 drop_caps(_metadata);
371 ruleset_fd =
372 landlock_create_ruleset(&ruleset_attr, sizeof(ruleset_attr), 0);
373 ASSERT_LE(0, ruleset_fd);
374
375 ASSERT_EQ(-1, write(ruleset_fd, ".", 1));
376 ASSERT_EQ(EINVAL, errno);
377 ASSERT_EQ(-1, read(ruleset_fd, &buf, 1));
378 ASSERT_EQ(EINVAL, errno);
379
380 ASSERT_EQ(0, close(ruleset_fd));
381 }
382
383 /* Tests enforcement of a ruleset FD transferred through a UNIX socket. */
TEST(ruleset_fd_transfer)384 TEST(ruleset_fd_transfer)
385 {
386 struct landlock_ruleset_attr ruleset_attr = {
387 .handled_access_fs = LANDLOCK_ACCESS_FS_READ_DIR,
388 };
389 struct landlock_path_beneath_attr path_beneath_attr = {
390 .allowed_access = LANDLOCK_ACCESS_FS_READ_DIR,
391 };
392 int ruleset_fd_tx, dir_fd;
393 int socket_fds[2];
394 pid_t child;
395 int status;
396
397 drop_caps(_metadata);
398
399 /* Creates a test ruleset with a simple rule. */
400 ruleset_fd_tx =
401 landlock_create_ruleset(&ruleset_attr, sizeof(ruleset_attr), 0);
402 ASSERT_LE(0, ruleset_fd_tx);
403 path_beneath_attr.parent_fd =
404 open("/tmp", O_PATH | O_NOFOLLOW | O_DIRECTORY | O_CLOEXEC);
405 ASSERT_LE(0, path_beneath_attr.parent_fd);
406 ASSERT_EQ(0,
407 landlock_add_rule(ruleset_fd_tx, LANDLOCK_RULE_PATH_BENEATH,
408 &path_beneath_attr, 0));
409 ASSERT_EQ(0, close(path_beneath_attr.parent_fd));
410
411 /* Sends the ruleset FD over a socketpair and then close it. */
412 ASSERT_EQ(0, socketpair(AF_UNIX, SOCK_STREAM | SOCK_CLOEXEC, 0,
413 socket_fds));
414 ASSERT_EQ(0, send_fd(socket_fds[0], ruleset_fd_tx));
415 ASSERT_EQ(0, close(socket_fds[0]));
416 ASSERT_EQ(0, close(ruleset_fd_tx));
417
418 child = fork();
419 ASSERT_LE(0, child);
420 if (child == 0) {
421 const int ruleset_fd_rx = recv_fd(socket_fds[1]);
422
423 ASSERT_LE(0, ruleset_fd_rx);
424 ASSERT_EQ(0, close(socket_fds[1]));
425
426 /* Enforces the received ruleset on the child. */
427 ASSERT_EQ(0, prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0));
428 ASSERT_EQ(0, landlock_restrict_self(ruleset_fd_rx, 0));
429 ASSERT_EQ(0, close(ruleset_fd_rx));
430
431 /* Checks that the ruleset enforcement. */
432 ASSERT_EQ(-1, open("/", O_RDONLY | O_DIRECTORY | O_CLOEXEC));
433 ASSERT_EQ(EACCES, errno);
434 dir_fd = open("/tmp", O_RDONLY | O_DIRECTORY | O_CLOEXEC);
435 ASSERT_LE(0, dir_fd);
436 ASSERT_EQ(0, close(dir_fd));
437 _exit(_metadata->exit_code);
438 return;
439 }
440
441 ASSERT_EQ(0, close(socket_fds[1]));
442
443 /* Checks that the parent is unrestricted. */
444 dir_fd = open("/", O_RDONLY | O_DIRECTORY | O_CLOEXEC);
445 ASSERT_LE(0, dir_fd);
446 ASSERT_EQ(0, close(dir_fd));
447 dir_fd = open("/tmp", O_RDONLY | O_DIRECTORY | O_CLOEXEC);
448 ASSERT_LE(0, dir_fd);
449 ASSERT_EQ(0, close(dir_fd));
450
451 ASSERT_EQ(child, waitpid(child, &status, 0));
452 ASSERT_EQ(1, WIFEXITED(status));
453 ASSERT_EQ(EXIT_SUCCESS, WEXITSTATUS(status));
454 }
455
TEST(cred_transfer)456 TEST(cred_transfer)
457 {
458 struct landlock_ruleset_attr ruleset_attr = {
459 .handled_access_fs = LANDLOCK_ACCESS_FS_READ_DIR,
460 };
461 int ruleset_fd, dir_fd;
462 pid_t child;
463 int status;
464
465 drop_caps(_metadata);
466
467 dir_fd = open("/", O_RDONLY | O_DIRECTORY | O_CLOEXEC);
468 EXPECT_LE(0, dir_fd);
469 EXPECT_EQ(0, close(dir_fd));
470
471 /* Denies opening directories. */
472 ruleset_fd =
473 landlock_create_ruleset(&ruleset_attr, sizeof(ruleset_attr), 0);
474 ASSERT_LE(0, ruleset_fd);
475 EXPECT_EQ(0, prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0));
476 ASSERT_EQ(0, landlock_restrict_self(ruleset_fd, 0));
477 EXPECT_EQ(0, close(ruleset_fd));
478
479 /* Checks ruleset enforcement. */
480 EXPECT_EQ(-1, open("/", O_RDONLY | O_DIRECTORY | O_CLOEXEC));
481 EXPECT_EQ(EACCES, errno);
482
483 /* Needed for KEYCTL_SESSION_TO_PARENT permission checks */
484 EXPECT_NE(-1, syscall(__NR_keyctl, KEYCTL_JOIN_SESSION_KEYRING, NULL, 0,
485 0, 0))
486 {
487 TH_LOG("Failed to join session keyring: %s", strerror(errno));
488 }
489
490 child = fork();
491 ASSERT_LE(0, child);
492 if (child == 0) {
493 /* Checks ruleset enforcement. */
494 EXPECT_EQ(-1, open("/", O_RDONLY | O_DIRECTORY | O_CLOEXEC));
495 EXPECT_EQ(EACCES, errno);
496
497 /*
498 * KEYCTL_SESSION_TO_PARENT is a no-op unless we have a
499 * different session keyring in the child, so make that happen.
500 */
501 EXPECT_NE(-1, syscall(__NR_keyctl, KEYCTL_JOIN_SESSION_KEYRING,
502 NULL, 0, 0, 0));
503
504 /*
505 * KEYCTL_SESSION_TO_PARENT installs credentials on the parent
506 * that never go through the cred_prepare hook, this path uses
507 * cred_transfer instead.
508 */
509 EXPECT_EQ(0, syscall(__NR_keyctl, KEYCTL_SESSION_TO_PARENT, 0,
510 0, 0, 0));
511
512 /* Re-checks ruleset enforcement. */
513 EXPECT_EQ(-1, open("/", O_RDONLY | O_DIRECTORY | O_CLOEXEC));
514 EXPECT_EQ(EACCES, errno);
515
516 _exit(_metadata->exit_code);
517 return;
518 }
519
520 EXPECT_EQ(child, waitpid(child, &status, 0));
521 EXPECT_EQ(1, WIFEXITED(status));
522 EXPECT_EQ(EXIT_SUCCESS, WEXITSTATUS(status));
523
524 /* Re-checks ruleset enforcement. */
525 EXPECT_EQ(-1, open("/", O_RDONLY | O_DIRECTORY | O_CLOEXEC));
526 EXPECT_EQ(EACCES, errno);
527 }
528
529 TEST_HARNESS_MAIN
530