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