1 // SPDX-License-Identifier: GPL-2.0
2 /*
3  * Landlock tests - Common user space base
4  *
5  * Copyright © 2017-2020 Mickaël Salaün <[email protected]>
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(6, 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(ruleset_fd_io)280 TEST(ruleset_fd_io)
281 {
282 	struct landlock_ruleset_attr ruleset_attr = {
283 		.handled_access_fs = LANDLOCK_ACCESS_FS_READ_FILE,
284 	};
285 	int ruleset_fd;
286 	char buf;
287 
288 	drop_caps(_metadata);
289 	ruleset_fd =
290 		landlock_create_ruleset(&ruleset_attr, sizeof(ruleset_attr), 0);
291 	ASSERT_LE(0, ruleset_fd);
292 
293 	ASSERT_EQ(-1, write(ruleset_fd, ".", 1));
294 	ASSERT_EQ(EINVAL, errno);
295 	ASSERT_EQ(-1, read(ruleset_fd, &buf, 1));
296 	ASSERT_EQ(EINVAL, errno);
297 
298 	ASSERT_EQ(0, close(ruleset_fd));
299 }
300 
301 /* Tests enforcement of a ruleset FD transferred through a UNIX socket. */
TEST(ruleset_fd_transfer)302 TEST(ruleset_fd_transfer)
303 {
304 	struct landlock_ruleset_attr ruleset_attr = {
305 		.handled_access_fs = LANDLOCK_ACCESS_FS_READ_DIR,
306 	};
307 	struct landlock_path_beneath_attr path_beneath_attr = {
308 		.allowed_access = LANDLOCK_ACCESS_FS_READ_DIR,
309 	};
310 	int ruleset_fd_tx, dir_fd;
311 	int socket_fds[2];
312 	pid_t child;
313 	int status;
314 
315 	drop_caps(_metadata);
316 
317 	/* Creates a test ruleset with a simple rule. */
318 	ruleset_fd_tx =
319 		landlock_create_ruleset(&ruleset_attr, sizeof(ruleset_attr), 0);
320 	ASSERT_LE(0, ruleset_fd_tx);
321 	path_beneath_attr.parent_fd =
322 		open("/tmp", O_PATH | O_NOFOLLOW | O_DIRECTORY | O_CLOEXEC);
323 	ASSERT_LE(0, path_beneath_attr.parent_fd);
324 	ASSERT_EQ(0,
325 		  landlock_add_rule(ruleset_fd_tx, LANDLOCK_RULE_PATH_BENEATH,
326 				    &path_beneath_attr, 0));
327 	ASSERT_EQ(0, close(path_beneath_attr.parent_fd));
328 
329 	/* Sends the ruleset FD over a socketpair and then close it. */
330 	ASSERT_EQ(0, socketpair(AF_UNIX, SOCK_STREAM | SOCK_CLOEXEC, 0,
331 				socket_fds));
332 	ASSERT_EQ(0, send_fd(socket_fds[0], ruleset_fd_tx));
333 	ASSERT_EQ(0, close(socket_fds[0]));
334 	ASSERT_EQ(0, close(ruleset_fd_tx));
335 
336 	child = fork();
337 	ASSERT_LE(0, child);
338 	if (child == 0) {
339 		const int ruleset_fd_rx = recv_fd(socket_fds[1]);
340 
341 		ASSERT_LE(0, ruleset_fd_rx);
342 		ASSERT_EQ(0, close(socket_fds[1]));
343 
344 		/* Enforces the received ruleset on the child. */
345 		ASSERT_EQ(0, prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0));
346 		ASSERT_EQ(0, landlock_restrict_self(ruleset_fd_rx, 0));
347 		ASSERT_EQ(0, close(ruleset_fd_rx));
348 
349 		/* Checks that the ruleset enforcement. */
350 		ASSERT_EQ(-1, open("/", O_RDONLY | O_DIRECTORY | O_CLOEXEC));
351 		ASSERT_EQ(EACCES, errno);
352 		dir_fd = open("/tmp", O_RDONLY | O_DIRECTORY | O_CLOEXEC);
353 		ASSERT_LE(0, dir_fd);
354 		ASSERT_EQ(0, close(dir_fd));
355 		_exit(_metadata->exit_code);
356 		return;
357 	}
358 
359 	ASSERT_EQ(0, close(socket_fds[1]));
360 
361 	/* Checks that the parent is unrestricted. */
362 	dir_fd = open("/", O_RDONLY | O_DIRECTORY | O_CLOEXEC);
363 	ASSERT_LE(0, dir_fd);
364 	ASSERT_EQ(0, close(dir_fd));
365 	dir_fd = open("/tmp", O_RDONLY | O_DIRECTORY | O_CLOEXEC);
366 	ASSERT_LE(0, dir_fd);
367 	ASSERT_EQ(0, close(dir_fd));
368 
369 	ASSERT_EQ(child, waitpid(child, &status, 0));
370 	ASSERT_EQ(1, WIFEXITED(status));
371 	ASSERT_EQ(EXIT_SUCCESS, WEXITSTATUS(status));
372 }
373 
TEST(cred_transfer)374 TEST(cred_transfer)
375 {
376 	struct landlock_ruleset_attr ruleset_attr = {
377 		.handled_access_fs = LANDLOCK_ACCESS_FS_READ_DIR,
378 	};
379 	int ruleset_fd, dir_fd;
380 	pid_t child;
381 	int status;
382 
383 	drop_caps(_metadata);
384 
385 	dir_fd = open("/", O_RDONLY | O_DIRECTORY | O_CLOEXEC);
386 	EXPECT_LE(0, dir_fd);
387 	EXPECT_EQ(0, close(dir_fd));
388 
389 	/* Denies opening directories. */
390 	ruleset_fd =
391 		landlock_create_ruleset(&ruleset_attr, sizeof(ruleset_attr), 0);
392 	ASSERT_LE(0, ruleset_fd);
393 	EXPECT_EQ(0, prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0));
394 	ASSERT_EQ(0, landlock_restrict_self(ruleset_fd, 0));
395 	EXPECT_EQ(0, close(ruleset_fd));
396 
397 	/* Checks ruleset enforcement. */
398 	EXPECT_EQ(-1, open("/", O_RDONLY | O_DIRECTORY | O_CLOEXEC));
399 	EXPECT_EQ(EACCES, errno);
400 
401 	/* Needed for KEYCTL_SESSION_TO_PARENT permission checks */
402 	EXPECT_NE(-1, syscall(__NR_keyctl, KEYCTL_JOIN_SESSION_KEYRING, NULL, 0,
403 			      0, 0))
404 	{
405 		TH_LOG("Failed to join session keyring: %s", strerror(errno));
406 	}
407 
408 	child = fork();
409 	ASSERT_LE(0, child);
410 	if (child == 0) {
411 		/* Checks ruleset enforcement. */
412 		EXPECT_EQ(-1, open("/", O_RDONLY | O_DIRECTORY | O_CLOEXEC));
413 		EXPECT_EQ(EACCES, errno);
414 
415 		/*
416 		 * KEYCTL_SESSION_TO_PARENT is a no-op unless we have a
417 		 * different session keyring in the child, so make that happen.
418 		 */
419 		EXPECT_NE(-1, syscall(__NR_keyctl, KEYCTL_JOIN_SESSION_KEYRING,
420 				      NULL, 0, 0, 0));
421 
422 		/*
423 		 * KEYCTL_SESSION_TO_PARENT installs credentials on the parent
424 		 * that never go through the cred_prepare hook, this path uses
425 		 * cred_transfer instead.
426 		 */
427 		EXPECT_EQ(0, syscall(__NR_keyctl, KEYCTL_SESSION_TO_PARENT, 0,
428 				     0, 0, 0));
429 
430 		/* Re-checks ruleset enforcement. */
431 		EXPECT_EQ(-1, open("/", O_RDONLY | O_DIRECTORY | O_CLOEXEC));
432 		EXPECT_EQ(EACCES, errno);
433 
434 		_exit(_metadata->exit_code);
435 		return;
436 	}
437 
438 	EXPECT_EQ(child, waitpid(child, &status, 0));
439 	EXPECT_EQ(1, WIFEXITED(status));
440 	EXPECT_EQ(EXIT_SUCCESS, WEXITSTATUS(status));
441 
442 	/* Re-checks ruleset enforcement. */
443 	EXPECT_EQ(-1, open("/", O_RDONLY | O_DIRECTORY | O_CLOEXEC));
444 	EXPECT_EQ(EACCES, errno);
445 }
446 
447 TEST_HARNESS_MAIN
448