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(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 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(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. */ 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 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