xref: /linux/tools/testing/selftests/landlock/base_test.c (revision e178b404ea0c909c51d22bddb2cfbb2124028c84)
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 
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 
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 
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. */
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. */
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. */
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 
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 
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 
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 
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. */
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 
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