File Index
Files and directories
Sign in
FILE

base_test.c

File preview with syntax highlighting.

linux-6.19.14/tools/testing/selftests/landlock/base_test.c C
  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
 25TEST(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
 74TEST(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
109TEST(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. */
146TEST(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. */
189TEST(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. */
236TEST(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
280TEST(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
291TEST(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
307TEST(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
362TEST(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. */
384TEST(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
456TEST(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
529TEST_HARNESS_MAIN
~/ Read-only file preview.