Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

at master 432 lines 12 kB view raw
1// SPDX-License-Identifier: GPL-2.0 2/* 3 * Landlock tests - Ptrace 4 * 5 * Copyright © 2017-2020 Mickaël Salaün <mic@digikod.net> 6 * Copyright © 2019-2020 ANSSI 7 * Copyright © 2024-2025 Microsoft Corporation 8 */ 9 10#define _GNU_SOURCE 11#include <errno.h> 12#include <fcntl.h> 13#include <linux/landlock.h> 14#include <signal.h> 15#include <sys/prctl.h> 16#include <sys/ptrace.h> 17#include <sys/types.h> 18#include <sys/wait.h> 19#include <unistd.h> 20 21#include "audit.h" 22#include "common.h" 23 24/* Copied from security/yama/yama_lsm.c */ 25#define YAMA_SCOPE_DISABLED 0 26#define YAMA_SCOPE_RELATIONAL 1 27 28static void create_domain(struct __test_metadata *const _metadata) 29{ 30 int ruleset_fd; 31 struct landlock_ruleset_attr ruleset_attr = { 32 .handled_access_fs = LANDLOCK_ACCESS_FS_MAKE_BLOCK, 33 }; 34 35 ruleset_fd = 36 landlock_create_ruleset(&ruleset_attr, sizeof(ruleset_attr), 0); 37 EXPECT_LE(0, ruleset_fd) 38 { 39 TH_LOG("Failed to create a ruleset: %s", strerror(errno)); 40 } 41 EXPECT_EQ(0, prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0)); 42 EXPECT_EQ(0, landlock_restrict_self(ruleset_fd, 0)); 43 EXPECT_EQ(0, close(ruleset_fd)); 44} 45 46static int test_ptrace_read(const pid_t pid) 47{ 48 static const char path_template[] = "/proc/%d/environ"; 49 char procenv_path[sizeof(path_template) + 10]; 50 int procenv_path_size, fd; 51 52 procenv_path_size = snprintf(procenv_path, sizeof(procenv_path), 53 path_template, pid); 54 if (procenv_path_size >= sizeof(procenv_path)) 55 return E2BIG; 56 57 fd = open(procenv_path, O_RDONLY | O_CLOEXEC); 58 if (fd < 0) 59 return errno; 60 /* 61 * Mixing error codes from close(2) and open(2) should not lead to any 62 * (access type) confusion for this test. 63 */ 64 if (close(fd) != 0) 65 return errno; 66 return 0; 67} 68 69static int get_yama_ptrace_scope(void) 70{ 71 int ret; 72 char buf[2] = {}; 73 const int fd = open("/proc/sys/kernel/yama/ptrace_scope", O_RDONLY); 74 75 if (fd < 0) 76 return 0; 77 78 if (read(fd, buf, 1) < 0) { 79 close(fd); 80 return -1; 81 } 82 83 ret = atoi(buf); 84 close(fd); 85 return ret; 86} 87 88/* clang-format off */ 89FIXTURE(scoped_domains) {}; 90/* clang-format on */ 91 92/* 93 * Test multiple tracing combinations between a parent process P1 and a child 94 * process P2. 95 * 96 * Yama's scoped ptrace is presumed disabled. If enabled, this optional 97 * restriction is enforced in addition to any Landlock check, which means that 98 * all P2 requests to trace P1 would be denied. 99 */ 100#include "scoped_base_variants.h" 101 102FIXTURE_SETUP(scoped_domains) 103{ 104} 105 106FIXTURE_TEARDOWN(scoped_domains) 107{ 108} 109 110/* Test PTRACE_TRACEME and PTRACE_ATTACH for parent and child. */ 111TEST_F(scoped_domains, trace) 112{ 113 pid_t child, parent; 114 int status, err_proc_read; 115 int pipe_child[2], pipe_parent[2]; 116 int yama_ptrace_scope; 117 char buf_parent; 118 long ret; 119 bool can_read_child, can_trace_child, can_read_parent, can_trace_parent; 120 121 yama_ptrace_scope = get_yama_ptrace_scope(); 122 ASSERT_LE(0, yama_ptrace_scope); 123 124 if (yama_ptrace_scope > YAMA_SCOPE_DISABLED) 125 TH_LOG("Incomplete tests due to Yama restrictions (scope %d)", 126 yama_ptrace_scope); 127 128 /* 129 * can_read_child is true if a parent process can read its child 130 * process, which is only the case when the parent process is not 131 * isolated from the child with a dedicated Landlock domain. 132 */ 133 can_read_child = !variant->domain_parent; 134 135 /* 136 * can_trace_child is true if a parent process can trace its child 137 * process. This depends on two conditions: 138 * - The parent process is not isolated from the child with a dedicated 139 * Landlock domain. 140 * - Yama allows tracing children (up to YAMA_SCOPE_RELATIONAL). 141 */ 142 can_trace_child = can_read_child && 143 yama_ptrace_scope <= YAMA_SCOPE_RELATIONAL; 144 145 /* 146 * can_read_parent is true if a child process can read its parent 147 * process, which is only the case when the child process is not 148 * isolated from the parent with a dedicated Landlock domain. 149 */ 150 can_read_parent = !variant->domain_child; 151 152 /* 153 * can_trace_parent is true if a child process can trace its parent 154 * process. This depends on two conditions: 155 * - The child process is not isolated from the parent with a dedicated 156 * Landlock domain. 157 * - Yama is disabled (YAMA_SCOPE_DISABLED). 158 */ 159 can_trace_parent = can_read_parent && 160 yama_ptrace_scope <= YAMA_SCOPE_DISABLED; 161 162 /* 163 * Removes all effective and permitted capabilities to not interfere 164 * with cap_ptrace_access_check() in case of PTRACE_MODE_FSCREDS. 165 */ 166 drop_caps(_metadata); 167 168 parent = getpid(); 169 ASSERT_EQ(0, pipe2(pipe_child, O_CLOEXEC)); 170 ASSERT_EQ(0, pipe2(pipe_parent, O_CLOEXEC)); 171 if (variant->domain_both) { 172 create_domain(_metadata); 173 if (!__test_passed(_metadata)) 174 /* Aborts before forking. */ 175 return; 176 } 177 178 child = fork(); 179 ASSERT_LE(0, child); 180 if (child == 0) { 181 char buf_child; 182 183 ASSERT_EQ(0, close(pipe_parent[1])); 184 ASSERT_EQ(0, close(pipe_child[0])); 185 if (variant->domain_child) 186 create_domain(_metadata); 187 188 /* Waits for the parent to be in a domain, if any. */ 189 ASSERT_EQ(1, read(pipe_parent[0], &buf_child, 1)); 190 191 /* Tests PTRACE_MODE_READ on the parent. */ 192 err_proc_read = test_ptrace_read(parent); 193 if (can_read_parent) { 194 EXPECT_EQ(0, err_proc_read); 195 } else { 196 EXPECT_EQ(EACCES, err_proc_read); 197 } 198 199 /* Tests PTRACE_ATTACH on the parent. */ 200 ret = ptrace(PTRACE_ATTACH, parent, NULL, 0); 201 if (can_trace_parent) { 202 EXPECT_EQ(0, ret); 203 } else { 204 EXPECT_EQ(-1, ret); 205 EXPECT_EQ(EPERM, errno); 206 } 207 if (ret == 0) { 208 ASSERT_EQ(parent, waitpid(parent, &status, 0)); 209 ASSERT_EQ(1, WIFSTOPPED(status)); 210 ASSERT_EQ(0, ptrace(PTRACE_DETACH, parent, NULL, 0)); 211 } 212 213 /* Tests child PTRACE_TRACEME. */ 214 ret = ptrace(PTRACE_TRACEME); 215 if (can_trace_child) { 216 EXPECT_EQ(0, ret); 217 } else { 218 EXPECT_EQ(-1, ret); 219 EXPECT_EQ(EPERM, errno); 220 } 221 222 /* 223 * Signals that the PTRACE_ATTACH test is done and the 224 * PTRACE_TRACEME test is ongoing. 225 */ 226 ASSERT_EQ(1, write(pipe_child[1], ".", 1)); 227 228 if (can_trace_child) { 229 ASSERT_EQ(0, raise(SIGSTOP)); 230 } 231 232 /* Waits for the parent PTRACE_ATTACH test. */ 233 ASSERT_EQ(1, read(pipe_parent[0], &buf_child, 1)); 234 _exit(_metadata->exit_code); 235 return; 236 } 237 238 ASSERT_EQ(0, close(pipe_child[1])); 239 ASSERT_EQ(0, close(pipe_parent[0])); 240 if (variant->domain_parent) 241 create_domain(_metadata); 242 243 /* Signals that the parent is in a domain, if any. */ 244 ASSERT_EQ(1, write(pipe_parent[1], ".", 1)); 245 246 /* 247 * Waits for the child to test PTRACE_ATTACH on the parent and start 248 * testing PTRACE_TRACEME. 249 */ 250 ASSERT_EQ(1, read(pipe_child[0], &buf_parent, 1)); 251 252 /* Tests child PTRACE_TRACEME. */ 253 if (can_trace_child) { 254 ASSERT_EQ(child, waitpid(child, &status, 0)); 255 ASSERT_EQ(1, WIFSTOPPED(status)); 256 ASSERT_EQ(0, ptrace(PTRACE_DETACH, child, NULL, 0)); 257 } else { 258 /* The child should not be traced by the parent. */ 259 EXPECT_EQ(-1, ptrace(PTRACE_DETACH, child, NULL, 0)); 260 EXPECT_EQ(ESRCH, errno); 261 } 262 263 /* Tests PTRACE_MODE_READ on the child. */ 264 err_proc_read = test_ptrace_read(child); 265 if (can_read_child) { 266 EXPECT_EQ(0, err_proc_read); 267 } else { 268 EXPECT_EQ(EACCES, err_proc_read); 269 } 270 271 /* Tests PTRACE_ATTACH on the child. */ 272 ret = ptrace(PTRACE_ATTACH, child, NULL, 0); 273 if (can_trace_child) { 274 EXPECT_EQ(0, ret); 275 } else { 276 EXPECT_EQ(-1, ret); 277 EXPECT_EQ(EPERM, errno); 278 } 279 280 if (ret == 0) { 281 ASSERT_EQ(child, waitpid(child, &status, 0)); 282 ASSERT_EQ(1, WIFSTOPPED(status)); 283 ASSERT_EQ(0, ptrace(PTRACE_DETACH, child, NULL, 0)); 284 } 285 286 /* Signals that the parent PTRACE_ATTACH test is done. */ 287 ASSERT_EQ(1, write(pipe_parent[1], ".", 1)); 288 ASSERT_EQ(child, waitpid(child, &status, 0)); 289 290 if (WIFSIGNALED(status) || !WIFEXITED(status) || 291 WEXITSTATUS(status) != EXIT_SUCCESS) 292 _metadata->exit_code = KSFT_FAIL; 293} 294 295static int matches_log_ptrace(struct __test_metadata *const _metadata, 296 int audit_fd, const pid_t opid) 297{ 298 static const char log_template[] = REGEX_LANDLOCK_PREFIX 299 " blockers=ptrace opid=%d ocomm=\"ptrace_test\"$"; 300 char log_match[sizeof(log_template) + 10]; 301 int log_match_len; 302 303 log_match_len = 304 snprintf(log_match, sizeof(log_match), log_template, opid); 305 if (log_match_len > sizeof(log_match)) 306 return -E2BIG; 307 308 return audit_match_record(audit_fd, AUDIT_LANDLOCK_ACCESS, log_match, 309 NULL); 310} 311 312FIXTURE(audit) 313{ 314 struct audit_filter audit_filter; 315 int audit_fd; 316}; 317 318FIXTURE_SETUP(audit) 319{ 320 disable_caps(_metadata); 321 set_cap(_metadata, CAP_AUDIT_CONTROL); 322 self->audit_fd = audit_init_with_exe_filter(&self->audit_filter); 323 EXPECT_LE(0, self->audit_fd); 324 clear_cap(_metadata, CAP_AUDIT_CONTROL); 325} 326 327FIXTURE_TEARDOWN_PARENT(audit) 328{ 329 EXPECT_EQ(0, audit_cleanup(-1, NULL)); 330} 331 332/* Test PTRACE_TRACEME and PTRACE_ATTACH for parent and child. */ 333TEST_F(audit, trace) 334{ 335 pid_t child; 336 int status; 337 int pipe_child[2], pipe_parent[2]; 338 int yama_ptrace_scope; 339 char buf_parent; 340 struct audit_records records; 341 342 /* Makes sure there is no superfluous logged records. */ 343 EXPECT_EQ(0, audit_count_records(self->audit_fd, &records)); 344 EXPECT_EQ(0, records.access); 345 346 yama_ptrace_scope = get_yama_ptrace_scope(); 347 ASSERT_LE(0, yama_ptrace_scope); 348 349 if (yama_ptrace_scope > YAMA_SCOPE_DISABLED) 350 TH_LOG("Incomplete tests due to Yama restrictions (scope %d)", 351 yama_ptrace_scope); 352 353 /* 354 * Removes all effective and permitted capabilities to not interfere 355 * with cap_ptrace_access_check() in case of PTRACE_MODE_FSCREDS. 356 */ 357 drop_caps(_metadata); 358 359 ASSERT_EQ(0, pipe2(pipe_child, O_CLOEXEC)); 360 ASSERT_EQ(0, pipe2(pipe_parent, O_CLOEXEC)); 361 362 child = fork(); 363 ASSERT_LE(0, child); 364 if (child == 0) { 365 char buf_child; 366 367 ASSERT_EQ(0, close(pipe_parent[1])); 368 ASSERT_EQ(0, close(pipe_child[0])); 369 370 /* Waits for the parent to be in a domain, if any. */ 371 ASSERT_EQ(1, read(pipe_parent[0], &buf_child, 1)); 372 373 /* Tests child PTRACE_TRACEME. */ 374 EXPECT_EQ(-1, ptrace(PTRACE_TRACEME)); 375 EXPECT_EQ(EPERM, errno); 376 /* We should see the child process. */ 377 EXPECT_EQ(0, matches_log_ptrace(_metadata, self->audit_fd, 378 getpid())); 379 380 EXPECT_EQ(0, audit_count_records(self->audit_fd, &records)); 381 EXPECT_EQ(0, records.access); 382 /* Checks for a domain creation. */ 383 EXPECT_EQ(1, records.domain); 384 385 /* 386 * Signals that the PTRACE_ATTACH test is done and the 387 * PTRACE_TRACEME test is ongoing. 388 */ 389 ASSERT_EQ(1, write(pipe_child[1], ".", 1)); 390 391 /* Waits for the parent PTRACE_ATTACH test. */ 392 ASSERT_EQ(1, read(pipe_parent[0], &buf_child, 1)); 393 _exit(_metadata->exit_code); 394 return; 395 } 396 397 ASSERT_EQ(0, close(pipe_child[1])); 398 ASSERT_EQ(0, close(pipe_parent[0])); 399 create_domain(_metadata); 400 401 /* Signals that the parent is in a domain. */ 402 ASSERT_EQ(1, write(pipe_parent[1], ".", 1)); 403 404 /* 405 * Waits for the child to test PTRACE_ATTACH on the parent and start 406 * testing PTRACE_TRACEME. 407 */ 408 ASSERT_EQ(1, read(pipe_child[0], &buf_parent, 1)); 409 410 /* The child should not be traced by the parent. */ 411 EXPECT_EQ(-1, ptrace(PTRACE_DETACH, child, NULL, 0)); 412 EXPECT_EQ(ESRCH, errno); 413 414 /* Tests PTRACE_ATTACH on the child. */ 415 EXPECT_EQ(-1, ptrace(PTRACE_ATTACH, child, NULL, 0)); 416 EXPECT_EQ(EPERM, errno); 417 EXPECT_EQ(0, matches_log_ptrace(_metadata, self->audit_fd, child)); 418 419 /* Signals that the parent PTRACE_ATTACH test is done. */ 420 ASSERT_EQ(1, write(pipe_parent[1], ".", 1)); 421 ASSERT_EQ(child, waitpid(child, &status, 0)); 422 if (WIFSIGNALED(status) || !WIFEXITED(status) || 423 WEXITSTATUS(status) != EXIT_SUCCESS) 424 _metadata->exit_code = KSFT_FAIL; 425 426 /* Makes sure there is no superfluous logged records. */ 427 EXPECT_EQ(0, audit_count_records(self->audit_fd, &records)); 428 EXPECT_EQ(0, records.access); 429 EXPECT_EQ(0, records.domain); 430} 431 432TEST_HARNESS_MAIN