gvisor.dev/gvisor@v0.0.0-20240520182842-f9d4d51c7e0f/test/syscalls/linux/exec_binary.cc (about) 1 // Copyright 2018 The gVisor Authors. 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 15 #include <elf.h> 16 #include <errno.h> 17 #include <signal.h> 18 #include <sys/ptrace.h> 19 #include <sys/syscall.h> 20 #include <sys/types.h> 21 #include <sys/user.h> 22 #include <unistd.h> 23 24 #include <algorithm> 25 #include <functional> 26 #include <iterator> 27 #include <tuple> 28 #include <utility> 29 #include <vector> 30 31 #include "gmock/gmock.h" 32 #include "gtest/gtest.h" 33 #include "absl/strings/str_cat.h" 34 #include "absl/strings/string_view.h" 35 #include "test/util/cleanup.h" 36 #include "test/util/file_descriptor.h" 37 #include "test/util/fs_util.h" 38 #include "test/util/multiprocess_util.h" 39 #include "test/util/posix_error.h" 40 #include "test/util/proc_util.h" 41 #include "test/util/temp_path.h" 42 #include "test/util/test_util.h" 43 44 namespace gvisor { 45 namespace testing { 46 namespace { 47 48 using ::testing::AnyOf; 49 using ::testing::Eq; 50 51 #if !defined(__x86_64__) && !defined(__aarch64__) 52 // The assembly stub and ELF internal details must be ported to other arches. 53 #error "Test only supported on x86-64/arm64" 54 #endif // __x86_64__ || __aarch64__ 55 56 #if defined(__x86_64__) 57 #define EM_TYPE EM_X86_64 58 #define IP_REG(p) ((p).rip) 59 #define RAX_REG(p) ((p).rax) 60 #define RDI_REG(p) ((p).rdi) 61 #define RETURN_REG(p) ((p).rax) 62 63 // amd64 stub that calls PTRACE_TRACEME and sends itself SIGSTOP. 64 const char kPtraceCode[] = { 65 // movq $101, %rax /* ptrace */ 66 '\x48', 67 '\xc7', 68 '\xc0', 69 '\x65', 70 '\x00', 71 '\x00', 72 '\x00', 73 // movq $0, %rsi /* PTRACE_TRACEME */ 74 '\x48', 75 '\xc7', 76 '\xc6', 77 '\x00', 78 '\x00', 79 '\x00', 80 '\x00', 81 // movq $0, %rdi 82 '\x48', 83 '\xc7', 84 '\xc7', 85 '\x00', 86 '\x00', 87 '\x00', 88 '\x00', 89 // movq $0, %rdx 90 '\x48', 91 '\xc7', 92 '\xc2', 93 '\x00', 94 '\x00', 95 '\x00', 96 '\x00', 97 // movq $0, %r10 98 '\x49', 99 '\xc7', 100 '\xc2', 101 '\x00', 102 '\x00', 103 '\x00', 104 '\x00', 105 // syscall 106 '\x0f', 107 '\x05', 108 109 // movq $39, %rax /* getpid */ 110 '\x48', 111 '\xc7', 112 '\xc0', 113 '\x27', 114 '\x00', 115 '\x00', 116 '\x00', 117 // syscall 118 '\x0f', 119 '\x05', 120 121 // movq %rax, %rdi /* pid */ 122 '\x48', 123 '\x89', 124 '\xc7', 125 // movq $62, %rax /* kill */ 126 '\x48', 127 '\xc7', 128 '\xc0', 129 '\x3e', 130 '\x00', 131 '\x00', 132 '\x00', 133 // movq $19, %rsi /* SIGSTOP */ 134 '\x48', 135 '\xc7', 136 '\xc6', 137 '\x13', 138 '\x00', 139 '\x00', 140 '\x00', 141 // syscall 142 '\x0f', 143 '\x05', 144 }; 145 146 // Size of a syscall instruction. 147 constexpr int kSyscallSize = 2; 148 149 #elif defined(__aarch64__) 150 #define EM_TYPE EM_AARCH64 151 #define IP_REG(p) ((p).pc) 152 #define RAX_REG(p) ((p).regs[8]) 153 #define RDI_REG(p) ((p).regs[0]) 154 #define RETURN_REG(p) ((p).regs[0]) 155 156 const char kPtraceCode[] = { 157 // MOVD $117, R8 /* ptrace */ 158 '\xa8', 159 '\x0e', 160 '\x80', 161 '\xd2', 162 // MOVD $0, R0 /* PTRACE_TRACEME */ 163 '\x00', 164 '\x00', 165 '\x80', 166 '\xd2', 167 // MOVD $0, R1 /* pid */ 168 '\x01', 169 '\x00', 170 '\x80', 171 '\xd2', 172 // MOVD $0, R2 /* addr */ 173 '\x02', 174 '\x00', 175 '\x80', 176 '\xd2', 177 // MOVD $0, R3 /* data */ 178 '\x03', 179 '\x00', 180 '\x80', 181 '\xd2', 182 // SVC 183 '\x01', 184 '\x00', 185 '\x00', 186 '\xd4', 187 // MOVD $172, R8 /* getpid */ 188 '\x88', 189 '\x15', 190 '\x80', 191 '\xd2', 192 // SVC 193 '\x01', 194 '\x00', 195 '\x00', 196 '\xd4', 197 // MOVD $129, R8 /* kill, R0=pid */ 198 '\x28', 199 '\x10', 200 '\x80', 201 '\xd2', 202 // MOVD $19, R1 /* SIGSTOP */ 203 '\x61', 204 '\x02', 205 '\x80', 206 '\xd2', 207 // SVC 208 '\x01', 209 '\x00', 210 '\x00', 211 '\xd4', 212 }; 213 // Size of a syscall instruction. 214 constexpr int kSyscallSize = 4; 215 #else 216 #error "Unknown architecture" 217 #endif 218 219 // This test suite tests executable loading in the kernel (ELF and interpreter 220 // scripts). 221 222 // Parameterized ELF types for 64 and 32 bit. 223 template <int Size> 224 struct ElfTypes; 225 226 template <> 227 struct ElfTypes<64> { 228 typedef Elf64_Ehdr ElfEhdr; 229 typedef Elf64_Phdr ElfPhdr; 230 }; 231 232 template <> 233 struct ElfTypes<32> { 234 typedef Elf32_Ehdr ElfEhdr; 235 typedef Elf32_Phdr ElfPhdr; 236 }; 237 238 template <int Size> 239 struct ElfBinary { 240 using ElfEhdr = typename ElfTypes<Size>::ElfEhdr; 241 using ElfPhdr = typename ElfTypes<Size>::ElfPhdr; 242 243 ElfEhdr header = {}; 244 std::vector<ElfPhdr> phdrs; 245 std::vector<char> data; 246 247 // UpdateOffsets updates p_offset, p_vaddr in all phdrs to account for the 248 // space taken by the header and phdrs. 249 // 250 // It also updates header.e_phnum and adds the offset to header.e_entry to 251 // account for the headers residing in the first PT_LOAD segment. 252 // 253 // Before calling UpdateOffsets each of those fields should be the appropriate 254 // offset into data. 255 void UpdateOffsets() { 256 size_t offset = sizeof(header) + phdrs.size() * sizeof(ElfPhdr); 257 header.e_entry += offset; 258 header.e_phnum = phdrs.size(); 259 for (auto& p : phdrs) { 260 p.p_offset += offset; 261 p.p_vaddr += offset; 262 } 263 } 264 265 // AddInterpreter adds a PT_INTERP segment with the passed contents. 266 // 267 // A later call to UpdateOffsets is required to make the new phdr valid. 268 void AddInterpreter(std::vector<char> contents) { 269 const int start = data.size(); 270 data.insert(data.end(), contents.begin(), contents.end()); 271 const int size = data.size() - start; 272 273 ElfPhdr phdr = {}; 274 phdr.p_type = PT_INTERP; 275 phdr.p_offset = start; 276 phdr.p_filesz = size; 277 phdr.p_memsz = size; 278 // "If [PT_INTERP] is present, it must precede any loadable segment entry." 279 phdrs.insert(phdrs.begin(), phdr); 280 } 281 282 // Writes the header, phdrs, and data to fd. 283 PosixError Write(int fd) const { 284 int ret = WriteFd(fd, &header, sizeof(header)); 285 if (ret < 0) { 286 return PosixError(errno, "failed to write header"); 287 } else if (ret != sizeof(header)) { 288 return PosixError(EIO, absl::StrCat("short write of header: ", ret)); 289 } 290 291 for (auto const& p : phdrs) { 292 ret = WriteFd(fd, &p, sizeof(p)); 293 if (ret < 0) { 294 return PosixError(errno, "failed to write phdr"); 295 } else if (ret != sizeof(p)) { 296 return PosixError(EIO, absl::StrCat("short write of phdr: ", ret)); 297 } 298 } 299 300 ret = WriteFd(fd, data.data(), data.size()); 301 if (ret < 0) { 302 return PosixError(errno, "failed to write data"); 303 } else if (ret != static_cast<int>(data.size())) { 304 return PosixError(EIO, absl::StrCat("short write of data: ", ret)); 305 } 306 307 return NoError(); 308 } 309 }; 310 311 // Creates a new temporary executable ELF file in parent with elf as the 312 // contents. 313 template <int Size> 314 PosixErrorOr<TempPath> CreateElfWith(absl::string_view parent, 315 ElfBinary<Size> const& elf) { 316 ASSIGN_OR_RETURN_ERRNO( 317 auto file, TempPath::CreateFileWith(parent, absl::string_view(), 0755)); 318 ASSIGN_OR_RETURN_ERRNO(auto fd, Open(file.path(), O_RDWR)); 319 RETURN_IF_ERRNO(elf.Write(fd.get())); 320 return std::move(file); 321 } 322 323 // Creates a new temporary executable ELF file with elf as the contents. 324 template <int Size> 325 PosixErrorOr<TempPath> CreateElfWith(ElfBinary<Size> const& elf) { 326 return CreateElfWith(GetAbsoluteTestTmpdir(), elf); 327 } 328 329 // Wait for pid to stop, and assert that it stopped via SIGSTOP. 330 PosixError WaitStopped(pid_t pid) { 331 int status; 332 int ret = RetryEINTR(waitpid)(pid, &status, 0); 333 MaybeSave(); 334 if (ret < 0) { 335 return PosixError(errno, "wait failed"); 336 } else if (ret != pid) { 337 return PosixError(ESRCH, absl::StrCat("wait got ", ret, " want ", pid)); 338 } 339 340 if (!WIFSTOPPED(status) || WSTOPSIG(status) != SIGSTOP) { 341 return PosixError(EINVAL, 342 absl::StrCat("pid did not SIGSTOP; status = ", status)); 343 } 344 345 return NoError(); 346 } 347 348 // Returns a valid ELF that PTRACE_TRACEME and SIGSTOPs itself. 349 // 350 // UpdateOffsets must be called before writing this ELF. 351 ElfBinary<64> StandardElf() { 352 ElfBinary<64> elf; 353 elf.header.e_ident[EI_MAG0] = ELFMAG0; 354 elf.header.e_ident[EI_MAG1] = ELFMAG1; 355 elf.header.e_ident[EI_MAG2] = ELFMAG2; 356 elf.header.e_ident[EI_MAG3] = ELFMAG3; 357 elf.header.e_ident[EI_CLASS] = ELFCLASS64; 358 elf.header.e_ident[EI_DATA] = ELFDATA2LSB; 359 elf.header.e_ident[EI_VERSION] = EV_CURRENT; 360 elf.header.e_type = ET_EXEC; 361 elf.header.e_machine = EM_TYPE; 362 elf.header.e_version = EV_CURRENT; 363 elf.header.e_phoff = sizeof(elf.header); 364 elf.header.e_phentsize = sizeof(decltype(elf)::ElfPhdr); 365 366 // TODO(gvisor.dev/issue/153): Always include a PT_GNU_STACK segment to 367 // disable executable stacks. With this omitted the stack (and all PROT_READ) 368 // mappings should be executable, but gVisor doesn't support that. 369 decltype(elf)::ElfPhdr phdr = {}; 370 phdr.p_type = PT_GNU_STACK; 371 phdr.p_flags = PF_R | PF_W; 372 elf.phdrs.push_back(phdr); 373 374 phdr = {}; 375 phdr.p_type = PT_LOAD; 376 phdr.p_flags = PF_R | PF_X; 377 phdr.p_offset = 0; 378 phdr.p_vaddr = 0x40000; 379 phdr.p_filesz = sizeof(kPtraceCode); 380 phdr.p_memsz = phdr.p_filesz; 381 elf.phdrs.push_back(phdr); 382 383 elf.header.e_entry = phdr.p_vaddr; 384 385 elf.data.assign(kPtraceCode, kPtraceCode + sizeof(kPtraceCode)); 386 387 return elf; 388 } 389 390 // Test that a trivial binary executes. 391 TEST(ElfTest, Execute) { 392 ElfBinary<64> elf = StandardElf(); 393 elf.UpdateOffsets(); 394 395 TempPath file = ASSERT_NO_ERRNO_AND_VALUE(CreateElfWith(elf)); 396 397 pid_t child; 398 int execve_errno; 399 auto cleanup = ASSERT_NO_ERRNO_AND_VALUE( 400 ForkAndExec(file.path(), {file.path()}, {}, &child, &execve_errno)); 401 ASSERT_EQ(execve_errno, 0); 402 403 // Ensure it made it to SIGSTOP. 404 ASSERT_NO_ERRNO(WaitStopped(child)); 405 406 struct user_regs_struct regs; 407 struct iovec iov; 408 iov.iov_base = ®s; 409 iov.iov_len = sizeof(regs); 410 EXPECT_THAT(ptrace(PTRACE_GETREGSET, child, NT_PRSTATUS, &iov), 411 SyscallSucceeds()); 412 // Read exactly the full register set. 413 EXPECT_EQ(iov.iov_len, sizeof(regs)); 414 // RIP/PC is just beyond the final syscall instruction. 415 EXPECT_EQ(IP_REG(regs), elf.header.e_entry + sizeof(kPtraceCode)); 416 417 EXPECT_THAT(child, ContainsMappings(std::vector<ProcMapsEntry>({ 418 {0x40000, 0x41000, true, false, true, true, 0, 0, 0, 0, 419 file.path().c_str()}, 420 }))); 421 } 422 423 // StandardElf without data completes execve, but faults once running. 424 TEST(ElfTest, MissingText) { 425 ElfBinary<64> elf = StandardElf(); 426 elf.data.clear(); 427 elf.UpdateOffsets(); 428 429 TempPath file = ASSERT_NO_ERRNO_AND_VALUE(CreateElfWith(elf)); 430 431 pid_t child; 432 int execve_errno; 433 auto cleanup = ASSERT_NO_ERRNO_AND_VALUE( 434 ForkAndExec(file.path(), {file.path()}, {}, &child, &execve_errno)); 435 ASSERT_EQ(execve_errno, 0); 436 437 int status; 438 ASSERT_THAT(RetryEINTR(waitpid)(child, &status, 0), 439 SyscallSucceedsWithValue(child)); 440 // It runs off the end of the zeroes filling the end of the page. 441 #if defined(__x86_64__) 442 EXPECT_TRUE(WIFSIGNALED(status) && WTERMSIG(status) == SIGSEGV) << status; 443 #elif defined(__aarch64__) 444 // 0 is an invalid instruction opcode on arm64. 445 EXPECT_TRUE(WIFSIGNALED(status) && WTERMSIG(status) == SIGILL) << status; 446 #endif 447 } 448 449 // Typical ELF with a data + bss segment 450 TEST(ElfTest, DataSegment) { 451 ElfBinary<64> elf = StandardElf(); 452 453 // Create a standard ELF, but extend to 1.5 pages. The second page will be the 454 // beginning of a multi-page data + bss segment. 455 elf.data.resize(kPageSize + kPageSize / 2); 456 457 decltype(elf)::ElfPhdr phdr = {}; 458 phdr.p_type = PT_LOAD; 459 phdr.p_flags = PF_R | PF_W; 460 phdr.p_offset = kPageSize; 461 phdr.p_vaddr = 0x41000; 462 phdr.p_filesz = kPageSize / 2; 463 // The header is going to push vaddr up by a few hundred bytes. Keep p_memsz a 464 // bit less than 2 pages so this mapping doesn't extend beyond 0x43000. 465 phdr.p_memsz = 2 * kPageSize - kPageSize / 2; 466 elf.phdrs.push_back(phdr); 467 468 elf.UpdateOffsets(); 469 470 TempPath file = ASSERT_NO_ERRNO_AND_VALUE(CreateElfWith(elf)); 471 472 pid_t child; 473 int execve_errno; 474 auto cleanup = ASSERT_NO_ERRNO_AND_VALUE( 475 ForkAndExec(file.path(), {file.path()}, {}, &child, &execve_errno)); 476 ASSERT_EQ(execve_errno, 0); 477 478 ASSERT_NO_ERRNO(WaitStopped(child)); 479 480 EXPECT_THAT( 481 child, ContainsMappings(std::vector<ProcMapsEntry>({ 482 // text page. 483 {0x40000, 0x41000, true, false, true, true, 0, 0, 0, 0, 484 file.path().c_str()}, 485 // data + bss page from file. 486 {0x41000, 0x42000, true, true, false, true, kPageSize, 0, 0, 0, 487 file.path().c_str()}, 488 // bss page from anon. 489 {0x42000, 0x43000, true, true, false, true, 0, 0, 0, 0, ""}, 490 }))); 491 } 492 493 // Additonal pages beyond filesz honor (only) execute protections. 494 // 495 // N.B. Linux changed this in 4.11 (16e72e9b30986 "powerpc: do not make the 496 // entire heap executable"). Previously, extra pages were always RW. 497 TEST(ElfTest, ExtraMemPages) { 498 // gVisor has the newer behavior. 499 if (!IsRunningOnGvisor()) { 500 auto version = ASSERT_NO_ERRNO_AND_VALUE(GetKernelVersion()); 501 SKIP_IF(version.major < 4 || (version.major == 4 && version.minor < 11)); 502 } 503 504 ElfBinary<64> elf = StandardElf(); 505 506 // Create a standard ELF, but extend to 1.5 pages. The second page will be the 507 // beginning of a multi-page data + bss segment. 508 elf.data.resize(kPageSize + kPageSize / 2); 509 510 decltype(elf)::ElfPhdr phdr = {}; 511 phdr.p_type = PT_LOAD; 512 // RWX segment. The extra anon page will also be RWX. 513 // 514 // N.B. Linux uses clear_user to clear the end of the file-mapped page, which 515 // respects the mapping protections. Thus if we map this RO with memsz > 516 // (unaligned) filesz, then execve will fail with EFAULT. See padzero(elf_bss) 517 // in fs/binfmt_elf.c:load_elf_binary. 518 // 519 // N.N.B.B. The above only applies to the last segment. For earlier segments, 520 // the clear_user error is ignored. 521 phdr.p_flags = PF_R | PF_W | PF_X; 522 phdr.p_offset = kPageSize; 523 phdr.p_vaddr = 0x41000; 524 phdr.p_filesz = kPageSize / 2; 525 // The header is going to push vaddr up by a few hundred bytes. Keep p_memsz a 526 // bit less than 2 pages so this mapping doesn't extend beyond 0x43000. 527 phdr.p_memsz = 2 * kPageSize - kPageSize / 2; 528 elf.phdrs.push_back(phdr); 529 530 elf.UpdateOffsets(); 531 532 TempPath file = ASSERT_NO_ERRNO_AND_VALUE(CreateElfWith(elf)); 533 534 pid_t child; 535 int execve_errno; 536 auto cleanup = ASSERT_NO_ERRNO_AND_VALUE( 537 ForkAndExec(file.path(), {file.path()}, {}, &child, &execve_errno)); 538 ASSERT_EQ(execve_errno, 0); 539 540 ASSERT_NO_ERRNO(WaitStopped(child)); 541 542 EXPECT_THAT(child, 543 ContainsMappings(std::vector<ProcMapsEntry>({ 544 // text page. 545 {0x40000, 0x41000, true, false, true, true, 0, 0, 0, 0, 546 file.path().c_str()}, 547 // data + bss page from file. 548 {0x41000, 0x42000, true, true, true, true, kPageSize, 0, 0, 0, 549 file.path().c_str()}, 550 // extra page from anon. 551 {0x42000, 0x43000, true, true, true, true, 0, 0, 0, 0, ""}, 552 }))); 553 } 554 555 // An aligned segment with filesz == 0, memsz > 0 is anon-only. 556 TEST(ElfTest, AnonOnlySegment) { 557 ElfBinary<64> elf = StandardElf(); 558 559 decltype(elf)::ElfPhdr phdr = {}; 560 phdr.p_type = PT_LOAD; 561 // RO segment. The extra anon page will be RW anyways. 562 phdr.p_flags = PF_R; 563 phdr.p_offset = 0; 564 phdr.p_vaddr = 0x41000; 565 phdr.p_filesz = 0; 566 phdr.p_memsz = kPageSize; 567 elf.phdrs.push_back(phdr); 568 569 elf.UpdateOffsets(); 570 571 // UpdateOffsets adjusts p_vaddr and p_offset by the header size, but we need 572 // a page-aligned p_vaddr to get a truly anon-only page. 573 elf.phdrs[2].p_vaddr = 0x41000; 574 // N.B. p_offset is now unaligned, but Linux doesn't care since this is 575 // anon-only. 576 577 TempPath file = ASSERT_NO_ERRNO_AND_VALUE(CreateElfWith(elf)); 578 579 pid_t child; 580 int execve_errno; 581 auto cleanup = ASSERT_NO_ERRNO_AND_VALUE( 582 ForkAndExec(file.path(), {file.path()}, {}, &child, &execve_errno)); 583 ASSERT_EQ(execve_errno, 0); 584 585 ASSERT_NO_ERRNO(WaitStopped(child)); 586 587 EXPECT_THAT(child, 588 ContainsMappings(std::vector<ProcMapsEntry>({ 589 // text page. 590 {0x40000, 0x41000, true, false, true, true, 0, 0, 0, 0, 591 file.path().c_str()}, 592 // anon page. 593 {0x41000, 0x42000, true, true, false, true, 0, 0, 0, 0, ""}, 594 }))); 595 } 596 597 // p_offset must have the same alignment as p_vaddr. 598 TEST(ElfTest, UnalignedOffset) { 599 ElfBinary<64> elf = StandardElf(); 600 601 // Unaligned offset. 602 elf.phdrs[1].p_offset += 1; 603 604 elf.UpdateOffsets(); 605 606 TempPath file = ASSERT_NO_ERRNO_AND_VALUE(CreateElfWith(elf)); 607 608 pid_t child; 609 int execve_errno; 610 auto cleanup = ASSERT_NO_ERRNO_AND_VALUE( 611 ForkAndExec(file.path(), {file.path()}, {}, &child, &execve_errno)); 612 613 // execve(2) return EINVAL, but behavior varies between Linux and gVisor. 614 // 615 // On Linux, the new mm is committed before attempting to map into it. By the 616 // time we hit EINVAL in the segment mmap, the old mm is gone. Linux returns 617 // to an empty mm, which immediately segfaults. 618 // 619 // OTOH, gVisor maps into the new mm before committing it. Thus when it hits 620 // failure, the caller is still intact to receive the error. 621 if (IsRunningOnGvisor()) { 622 ASSERT_EQ(execve_errno, EINVAL); 623 } else { 624 ASSERT_EQ(execve_errno, 0); 625 626 int status; 627 ASSERT_THAT(RetryEINTR(waitpid)(child, &status, 0), 628 SyscallSucceedsWithValue(child)); 629 EXPECT_TRUE(WIFSIGNALED(status) && WTERMSIG(status) == SIGSEGV) << status; 630 } 631 } 632 633 // Linux will allow PT_LOAD segments to overlap. 634 TEST(ElfTest, DirectlyOverlappingSegments) { 635 // NOTE(b/37289926): see PIEOutOfOrderSegments. 636 SKIP_IF(IsRunningOnGvisor()); 637 638 ElfBinary<64> elf = StandardElf(); 639 640 // Same as the StandardElf mapping. 641 decltype(elf)::ElfPhdr phdr = {}; 642 phdr.p_type = PT_LOAD; 643 // Add PF_W so we can differentiate this mapping from the first. 644 phdr.p_flags = PF_R | PF_W | PF_X; 645 phdr.p_offset = 0; 646 phdr.p_vaddr = 0x40000; 647 phdr.p_filesz = sizeof(kPtraceCode); 648 phdr.p_memsz = phdr.p_filesz; 649 elf.phdrs.push_back(phdr); 650 651 elf.UpdateOffsets(); 652 653 TempPath file = ASSERT_NO_ERRNO_AND_VALUE(CreateElfWith(elf)); 654 655 pid_t child; 656 int execve_errno; 657 auto cleanup = ASSERT_NO_ERRNO_AND_VALUE( 658 ForkAndExec(file.path(), {file.path()}, {}, &child, &execve_errno)); 659 ASSERT_EQ(execve_errno, 0); 660 661 ASSERT_NO_ERRNO(WaitStopped(child)); 662 663 EXPECT_THAT(child, ContainsMappings(std::vector<ProcMapsEntry>({ 664 {0x40000, 0x41000, true, true, true, true, 0, 0, 0, 0, 665 file.path().c_str()}, 666 }))); 667 } 668 669 // Linux allows out-of-order PT_LOAD segments. 670 TEST(ElfTest, OutOfOrderSegments) { 671 // NOTE(b/37289926): see PIEOutOfOrderSegments. 672 SKIP_IF(IsRunningOnGvisor()); 673 674 ElfBinary<64> elf = StandardElf(); 675 676 decltype(elf)::ElfPhdr phdr = {}; 677 phdr.p_type = PT_LOAD; 678 phdr.p_flags = PF_R | PF_X; 679 phdr.p_offset = 0; 680 phdr.p_vaddr = 0x20000; 681 phdr.p_filesz = sizeof(kPtraceCode); 682 phdr.p_memsz = phdr.p_filesz; 683 elf.phdrs.push_back(phdr); 684 685 elf.UpdateOffsets(); 686 687 TempPath file = ASSERT_NO_ERRNO_AND_VALUE(CreateElfWith(elf)); 688 689 pid_t child; 690 int execve_errno; 691 auto cleanup = ASSERT_NO_ERRNO_AND_VALUE( 692 ForkAndExec(file.path(), {file.path()}, {}, &child, &execve_errno)); 693 ASSERT_EQ(execve_errno, 0); 694 695 ASSERT_NO_ERRNO(WaitStopped(child)); 696 697 EXPECT_THAT(child, ContainsMappings(std::vector<ProcMapsEntry>({ 698 {0x20000, 0x21000, true, false, true, true, 0, 0, 0, 0, 699 file.path().c_str()}, 700 {0x40000, 0x41000, true, false, true, true, 0, 0, 0, 0, 701 file.path().c_str()}, 702 }))); 703 } 704 705 // header.e_phoff is bound the end of the file. 706 TEST(ElfTest, OutOfBoundsPhdrs) { 707 ElfBinary<64> elf = StandardElf(); 708 elf.header.e_phoff = 0x100000; 709 elf.UpdateOffsets(); 710 711 TempPath file = ASSERT_NO_ERRNO_AND_VALUE(CreateElfWith(elf)); 712 713 pid_t child; 714 int execve_errno; 715 auto cleanup = ASSERT_NO_ERRNO_AND_VALUE( 716 ForkAndExec(file.path(), {file.path()}, {}, &child, &execve_errno)); 717 // On Linux 3.11, this caused EIO. On newer Linux, it causes ENOEXEC. 718 EXPECT_THAT(execve_errno, AnyOf(Eq(ENOEXEC), Eq(EIO))); 719 } 720 721 // Claim there is a phdr beyond the end of the file, but don't include it. 722 TEST(ElfTest, MissingPhdr) { 723 ElfBinary<64> elf = StandardElf(); 724 725 // Clear data so the file ends immediately after the phdrs. 726 // N.B. Per ElfTest.MissingData, StandardElf without data completes execve 727 // without error. 728 elf.data.clear(); 729 elf.UpdateOffsets(); 730 731 // Claim that there is another phdr just beyond the end of the file. Of 732 // course, it isn't accessible. 733 elf.header.e_phnum++; 734 735 TempPath file = ASSERT_NO_ERRNO_AND_VALUE(CreateElfWith(elf)); 736 737 pid_t child; 738 int execve_errno; 739 auto cleanup = ASSERT_NO_ERRNO_AND_VALUE( 740 ForkAndExec(file.path(), {file.path()}, {}, &child, &execve_errno)); 741 // On Linux 3.11, this caused EIO. On newer Linux, it causes ENOEXEC. 742 EXPECT_THAT(execve_errno, AnyOf(Eq(ENOEXEC), Eq(EIO))); 743 } 744 745 // No headers at all, just the ELF magic. 746 TEST(ElfTest, MissingHeader) { 747 TempPath file = ASSERT_NO_ERRNO_AND_VALUE(TempPath::CreateFileMode(0755)); 748 FileDescriptor fd = ASSERT_NO_ERRNO_AND_VALUE(Open(file.path(), O_RDWR)); 749 750 const char kElfMagic[] = {0x7f, 'E', 'L', 'F'}; 751 752 ASSERT_THAT(WriteFd(fd.get(), &kElfMagic, sizeof(kElfMagic)), 753 SyscallSucceeds()); 754 fd.reset(); 755 756 pid_t child; 757 int execve_errno; 758 auto cleanup = ASSERT_NO_ERRNO_AND_VALUE( 759 ForkAndExec(file.path(), {file.path()}, {}, &child, &execve_errno)); 760 EXPECT_EQ(execve_errno, ENOEXEC); 761 } 762 763 // Load a PIE ELF with a data + bss segment. 764 TEST(ElfTest, PIE) { 765 ElfBinary<64> elf = StandardElf(); 766 767 elf.header.e_type = ET_DYN; 768 769 // Create a standard ELF, but extend to 1.5 pages. The second page will be the 770 // beginning of a multi-page data + bss segment. 771 elf.data.resize(kPageSize + kPageSize / 2); 772 773 elf.header.e_entry = 0x0; 774 775 decltype(elf)::ElfPhdr phdr = {}; 776 phdr.p_type = PT_LOAD; 777 phdr.p_flags = PF_R | PF_W; 778 phdr.p_offset = kPageSize; 779 // Put the data segment at a bit of an offset. 780 phdr.p_vaddr = 0x20000; 781 phdr.p_filesz = kPageSize / 2; 782 // The header is going to push vaddr up by a few hundred bytes. Keep p_memsz a 783 // bit less than 2 pages so this mapping doesn't extend beyond 0x43000. 784 phdr.p_memsz = 2 * kPageSize - kPageSize / 2; 785 elf.phdrs.push_back(phdr); 786 787 elf.UpdateOffsets(); 788 789 // The first segment really needs to start at 0 for a normal PIE binary, and 790 // thus includes the headers. 791 const uint64_t offset = elf.phdrs[1].p_offset; 792 elf.phdrs[1].p_offset = 0x0; 793 elf.phdrs[1].p_vaddr = 0x0; 794 elf.phdrs[1].p_filesz += offset; 795 elf.phdrs[1].p_memsz += offset; 796 797 TempPath file = ASSERT_NO_ERRNO_AND_VALUE(CreateElfWith(elf)); 798 799 pid_t child; 800 int execve_errno; 801 auto cleanup = ASSERT_NO_ERRNO_AND_VALUE( 802 ForkAndExec(file.path(), {file.path()}, {}, &child, &execve_errno)); 803 ASSERT_EQ(execve_errno, 0); 804 805 ASSERT_NO_ERRNO(WaitStopped(child)); 806 807 // RIP tells us which page the first segment was loaded into. 808 struct user_regs_struct regs; 809 struct iovec iov; 810 iov.iov_base = ®s; 811 iov.iov_len = sizeof(regs); 812 813 EXPECT_THAT(ptrace(PTRACE_GETREGSET, child, NT_PRSTATUS, &iov), 814 SyscallSucceeds()); 815 // Read exactly the full register set. 816 EXPECT_EQ(iov.iov_len, sizeof(regs)); 817 818 const uint64_t load_addr = IP_REG(regs) & ~(kPageSize - 1); 819 820 EXPECT_THAT(child, ContainsMappings(std::vector<ProcMapsEntry>({ 821 // text page. 822 {load_addr, load_addr + 0x1000, true, false, true, 823 true, 0, 0, 0, 0, file.path().c_str()}, 824 // data + bss page from file. 825 {load_addr + 0x20000, load_addr + 0x21000, true, true, 826 false, true, kPageSize, 0, 0, 0, file.path().c_str()}, 827 // bss page from anon. 828 {load_addr + 0x21000, load_addr + 0x22000, true, true, 829 false, true, 0, 0, 0, 0, ""}, 830 }))); 831 } 832 833 // PIE binary with a non-zero start address. 834 // 835 // This is non-standard for a PIE binary, but valid. The binary is still loaded 836 // at an arbitrary address, not the first PT_LOAD vaddr. 837 // 838 // N.B. Linux changed this behavior in d1fd836dcf00d2028c700c7e44d2c23404062c90. 839 // Previously, with "randomization" enabled, PIE binaries with a non-zero start 840 // address would be be loaded at the address they specified because mmap was 841 // passed the load address, which wasn't 0 as expected. 842 // 843 // This change is present in kernel v4.1+. 844 TEST(ElfTest, PIENonZeroStart) { 845 // gVisor has the newer behavior. 846 if (!IsRunningOnGvisor()) { 847 auto version = ASSERT_NO_ERRNO_AND_VALUE(GetKernelVersion()); 848 SKIP_IF(version.major < 4 || (version.major == 4 && version.minor < 1)); 849 } 850 851 ElfBinary<64> elf = StandardElf(); 852 853 elf.header.e_type = ET_DYN; 854 855 // Create a standard ELF, but extend to 1.5 pages. The second page will be the 856 // beginning of a multi-page data + bss segment. 857 elf.data.resize(kPageSize + kPageSize / 2); 858 859 decltype(elf)::ElfPhdr phdr = {}; 860 phdr.p_type = PT_LOAD; 861 phdr.p_flags = PF_R | PF_W; 862 phdr.p_offset = kPageSize; 863 // Put the data segment at a bit of an offset. 864 phdr.p_vaddr = 0x60000; 865 phdr.p_filesz = kPageSize / 2; 866 // The header is going to push vaddr up by a few hundred bytes. Keep p_memsz a 867 // bit less than 2 pages so this mapping doesn't extend beyond 0x43000. 868 phdr.p_memsz = 2 * kPageSize - kPageSize / 2; 869 elf.phdrs.push_back(phdr); 870 871 elf.UpdateOffsets(); 872 873 TempPath file = ASSERT_NO_ERRNO_AND_VALUE(CreateElfWith(elf)); 874 875 pid_t child; 876 int execve_errno; 877 auto cleanup = ASSERT_NO_ERRNO_AND_VALUE( 878 ForkAndExec(file.path(), {file.path()}, {}, &child, &execve_errno)); 879 ASSERT_EQ(execve_errno, 0); 880 881 ASSERT_NO_ERRNO(WaitStopped(child)); 882 883 // RIP tells us which page the first segment was loaded into. 884 struct user_regs_struct regs; 885 struct iovec iov; 886 iov.iov_base = ®s; 887 iov.iov_len = sizeof(regs); 888 EXPECT_THAT(ptrace(PTRACE_GETREGSET, child, NT_PRSTATUS, &iov), 889 SyscallSucceeds()); 890 // Read exactly the full register set. 891 EXPECT_EQ(iov.iov_len, sizeof(regs)); 892 893 const uint64_t load_addr = IP_REG(regs) & ~(kPageSize - 1); 894 895 // The ELF is loaded at an arbitrary address, not the first PT_LOAD vaddr. 896 // 897 // N.B. this is technically flaky, but Linux is *extremely* unlikely to pick 898 // this as the start address, as it searches from the top down. 899 EXPECT_NE(load_addr, 0x40000); 900 901 EXPECT_THAT(child, ContainsMappings(std::vector<ProcMapsEntry>({ 902 // text page. 903 {load_addr, load_addr + 0x1000, true, false, true, 904 true, 0, 0, 0, 0, file.path().c_str()}, 905 // data + bss page from file. 906 {load_addr + 0x20000, load_addr + 0x21000, true, true, 907 false, true, kPageSize, 0, 0, 0, file.path().c_str()}, 908 // bss page from anon. 909 {load_addr + 0x21000, load_addr + 0x22000, true, true, 910 false, true, 0, 0, 0, 0, ""}, 911 }))); 912 } 913 914 TEST(ElfTest, PIEOutOfOrderSegments) { 915 // TODO(b/37289926): This triggers a bug in Linux where it computes the size 916 // of the binary as 0x20000 - 0x40000 = 0xfffffffffffe0000, which obviously 917 // fails to map. 918 // 919 // We test gVisor's behavior (of rejecting the binary) because I assert that 920 // Linux is wrong and needs to be fixed. 921 SKIP_IF(!IsRunningOnGvisor()); 922 923 ElfBinary<64> elf = StandardElf(); 924 925 elf.header.e_type = ET_DYN; 926 927 // Create a standard ELF, but extend to 1.5 pages. The second page will be the 928 // beginning of a multi-page data + bss segment. 929 elf.data.resize(kPageSize + kPageSize / 2); 930 931 decltype(elf)::ElfPhdr phdr = {}; 932 phdr.p_type = PT_LOAD; 933 phdr.p_flags = PF_R | PF_W; 934 phdr.p_offset = kPageSize; 935 // Put the data segment *before* the first segment. 936 phdr.p_vaddr = 0x20000; 937 phdr.p_filesz = kPageSize / 2; 938 // The header is going to push vaddr up by a few hundred bytes. Keep p_memsz a 939 // bit less than 2 pages so this mapping doesn't extend beyond 0x43000. 940 phdr.p_memsz = 2 * kPageSize - kPageSize / 2; 941 elf.phdrs.push_back(phdr); 942 943 elf.UpdateOffsets(); 944 945 TempPath file = ASSERT_NO_ERRNO_AND_VALUE(CreateElfWith(elf)); 946 947 pid_t child; 948 int execve_errno; 949 auto cleanup = ASSERT_NO_ERRNO_AND_VALUE( 950 ForkAndExec(file.path(), {file.path()}, {}, &child, &execve_errno)); 951 EXPECT_EQ(execve_errno, ENOEXEC); 952 } 953 954 TEST(ElfTest, PIEOverflow) { 955 ElfBinary<64> elf = StandardElf(); 956 957 elf.header.e_type = ET_DYN; 958 959 // Choose vaddr of the first segment so that the end address overflows if the 960 // segment is mapped with a non-zero offset. 961 elf.phdrs[1].p_vaddr = 0xfffffffffffff000UL - elf.phdrs[1].p_memsz; 962 963 elf.UpdateOffsets(); 964 965 TempPath file = ASSERT_NO_ERRNO_AND_VALUE(CreateElfWith(elf)); 966 967 pid_t child; 968 int execve_errno; 969 auto cleanup = ASSERT_NO_ERRNO_AND_VALUE( 970 ForkAndExec(file.path(), {file.path()}, {}, &child, &execve_errno)); 971 if (IsRunningOnGvisor()) { 972 ASSERT_EQ(execve_errno, EINVAL); 973 } else { 974 ASSERT_EQ(execve_errno, 0); 975 int status; 976 ASSERT_THAT(RetryEINTR(waitpid)(child, &status, 0), 977 SyscallSucceedsWithValue(child)); 978 EXPECT_TRUE(WIFSIGNALED(status) && WTERMSIG(status) == SIGSEGV) << status; 979 } 980 } 981 982 // Standard dynamically linked binary with an ELF interpreter. 983 TEST(ElfTest, ELFInterpreter) { 984 ElfBinary<64> interpreter = StandardElf(); 985 interpreter.header.e_type = ET_DYN; 986 interpreter.header.e_entry = 0x0; 987 interpreter.UpdateOffsets(); 988 989 // The first segment really needs to start at 0 for a normal PIE binary, and 990 // thus includes the headers. 991 uint64_t const offset = interpreter.phdrs[1].p_offset; 992 // N.B. Since Linux 4.10 (0036d1f7eb95b "binfmt_elf: fix calculations for bss 993 // padding"), Linux unconditionally zeroes the remainder of the highest mapped 994 // page in an interpreter, failing if the protections don't allow write. Thus 995 // we must mark this writeable. 996 interpreter.phdrs[1].p_flags = PF_R | PF_W | PF_X; 997 interpreter.phdrs[1].p_offset = 0x0; 998 interpreter.phdrs[1].p_vaddr = 0x0; 999 interpreter.phdrs[1].p_filesz += offset; 1000 interpreter.phdrs[1].p_memsz += offset; 1001 1002 TempPath interpreter_file = 1003 ASSERT_NO_ERRNO_AND_VALUE(CreateElfWith(interpreter)); 1004 1005 ElfBinary<64> binary = StandardElf(); 1006 1007 // Append the interpreter path. 1008 int const interp_data_start = binary.data.size(); 1009 for (char const c : interpreter_file.path()) { 1010 binary.data.push_back(c); 1011 } 1012 // NUL-terminate. 1013 binary.data.push_back(0); 1014 int const interp_data_size = binary.data.size() - interp_data_start; 1015 1016 decltype(binary)::ElfPhdr phdr = {}; 1017 phdr.p_type = PT_INTERP; 1018 phdr.p_offset = interp_data_start; 1019 phdr.p_filesz = interp_data_size; 1020 phdr.p_memsz = interp_data_size; 1021 // "If [PT_INTERP] is present, it must precede any loadable segment entry." 1022 // 1023 // However, Linux allows it anywhere, so we just stick it at the end to make 1024 // sure out-of-order PT_INTERP is OK. 1025 binary.phdrs.push_back(phdr); 1026 1027 binary.UpdateOffsets(); 1028 1029 TempPath binary_file = ASSERT_NO_ERRNO_AND_VALUE(CreateElfWith(binary)); 1030 1031 pid_t child; 1032 int execve_errno; 1033 auto cleanup = ASSERT_NO_ERRNO_AND_VALUE(ForkAndExec( 1034 binary_file.path(), {binary_file.path()}, {}, &child, &execve_errno)); 1035 ASSERT_EQ(execve_errno, 0); 1036 1037 ASSERT_NO_ERRNO(WaitStopped(child)); 1038 1039 // RIP tells us which page the first segment of the interpreter was loaded 1040 // into. 1041 struct user_regs_struct regs; 1042 struct iovec iov; 1043 iov.iov_base = ®s; 1044 iov.iov_len = sizeof(regs); 1045 EXPECT_THAT(ptrace(PTRACE_GETREGSET, child, NT_PRSTATUS, &iov), 1046 SyscallSucceeds()); 1047 // Read exactly the full register set. 1048 EXPECT_EQ(iov.iov_len, sizeof(regs)); 1049 1050 const uint64_t interp_load_addr = IP_REG(regs) & ~(kPageSize - 1); 1051 1052 EXPECT_THAT( 1053 child, ContainsMappings(std::vector<ProcMapsEntry>({ 1054 // Main binary 1055 {0x40000, 0x41000, true, false, true, true, 0, 0, 0, 0, 1056 binary_file.path().c_str()}, 1057 // Interpreter 1058 {interp_load_addr, interp_load_addr + 0x1000, true, true, true, 1059 true, 0, 0, 0, 0, interpreter_file.path().c_str()}, 1060 }))); 1061 } 1062 1063 // Test parameter to ElfInterpterStaticTest cases. The first item is a suffix to 1064 // add to the end of the interpreter path in the PT_INTERP segment and the 1065 // second is the expected execve(2) errno. 1066 using ElfInterpreterStaticParam = std::tuple<std::vector<char>, int>; 1067 1068 class ElfInterpreterStaticTest 1069 : public ::testing::TestWithParam<ElfInterpreterStaticParam> {}; 1070 1071 // Statically linked ELF with a statically linked ELF interpreter. 1072 TEST_P(ElfInterpreterStaticTest, Test) { 1073 // TODO(gvisor.dev/issue/3721): Test has been observed to segfault on 5.X 1074 // kernels. 1075 if (!IsRunningOnGvisor()) { 1076 auto version = ASSERT_NO_ERRNO_AND_VALUE(GetKernelVersion()); 1077 SKIP_IF(version.major > 4); 1078 } 1079 1080 const std::vector<char> segment_suffix = std::get<0>(GetParam()); 1081 const int expected_errno = std::get<1>(GetParam()); 1082 1083 ElfBinary<64> interpreter = StandardElf(); 1084 // See comment in ElfTest.ELFInterpreter. 1085 interpreter.phdrs[1].p_flags = PF_R | PF_W | PF_X; 1086 interpreter.UpdateOffsets(); 1087 TempPath interpreter_file = 1088 ASSERT_NO_ERRNO_AND_VALUE(CreateElfWith(interpreter)); 1089 1090 ElfBinary<64> binary = StandardElf(); 1091 // The PT_LOAD segment conflicts with the interpreter's PT_LOAD segment. The 1092 // interpreter's will be mapped directly over the binary's. 1093 1094 // Interpreter path plus the parameterized suffix in the PT_INTERP segment. 1095 const std::string path = interpreter_file.path(); 1096 std::vector<char> segment(path.begin(), path.end()); 1097 segment.insert(segment.end(), segment_suffix.begin(), segment_suffix.end()); 1098 binary.AddInterpreter(segment); 1099 1100 binary.UpdateOffsets(); 1101 1102 TempPath binary_file = ASSERT_NO_ERRNO_AND_VALUE(CreateElfWith(binary)); 1103 1104 pid_t child; 1105 int execve_errno; 1106 auto cleanup = ASSERT_NO_ERRNO_AND_VALUE(ForkAndExec( 1107 binary_file.path(), {binary_file.path()}, {}, &child, &execve_errno)); 1108 ASSERT_EQ(execve_errno, expected_errno); 1109 1110 if (expected_errno == 0) { 1111 ASSERT_NO_ERRNO(WaitStopped(child)); 1112 1113 EXPECT_THAT(child, ContainsMappings(std::vector<ProcMapsEntry>({ 1114 // Interpreter. 1115 {0x40000, 0x41000, true, true, true, true, 0, 0, 0, 1116 0, interpreter_file.path().c_str()}, 1117 }))); 1118 } 1119 } 1120 1121 INSTANTIATE_TEST_SUITE_P( 1122 Cases, ElfInterpreterStaticTest, 1123 ::testing::ValuesIn({ 1124 // Simple NUL-terminator to run the interpreter as normal. 1125 std::make_tuple(std::vector<char>({'\0'}), 0), 1126 // Add some garbage to the segment followed by a NUL-terminator. This is 1127 // ignored. 1128 std::make_tuple(std::vector<char>({'\0', 'b', '\0'}), 0), 1129 // Add some garbage to the segment without a NUL-terminator. Linux will 1130 // reject 1131 // this. 1132 std::make_tuple(std::vector<char>({'\0', 'b'}), ENOEXEC), 1133 })); 1134 1135 // Test parameter to ElfInterpterBadPathTest cases. The first item is the 1136 // contents of the PT_INTERP segment and the second is the expected execve(2) 1137 // errno. 1138 using ElfInterpreterBadPathParam = std::tuple<std::vector<char>, int>; 1139 1140 class ElfInterpreterBadPathTest 1141 : public ::testing::TestWithParam<ElfInterpreterBadPathParam> {}; 1142 1143 TEST_P(ElfInterpreterBadPathTest, Test) { 1144 const std::vector<char> segment = std::get<0>(GetParam()); 1145 const int expected_errno = std::get<1>(GetParam()); 1146 1147 ElfBinary<64> binary = StandardElf(); 1148 binary.AddInterpreter(segment); 1149 binary.UpdateOffsets(); 1150 1151 TempPath binary_file = ASSERT_NO_ERRNO_AND_VALUE(CreateElfWith(binary)); 1152 1153 int execve_errno; 1154 auto cleanup = ASSERT_NO_ERRNO_AND_VALUE(ForkAndExec( 1155 binary_file.path(), {binary_file.path()}, {}, nullptr, &execve_errno)); 1156 EXPECT_EQ(execve_errno, expected_errno); 1157 } 1158 1159 INSTANTIATE_TEST_SUITE_P( 1160 Cases, ElfInterpreterBadPathTest, 1161 ::testing::ValuesIn({ 1162 // NUL-terminated fake path in the PT_INTERP segment. 1163 std::make_tuple(std::vector<char>({'/', 'f', '/', 'b', '\0'}), ENOENT), 1164 // ELF interpreter not NUL-terminated. 1165 std::make_tuple(std::vector<char>({'/', 'f', '/', 'b'}), ENOEXEC), 1166 // ELF interpreter path omitted entirely. 1167 // 1168 // fs/binfmt_elf.c:load_elf_binary returns ENOEXEC if p_filesz is < 2 1169 // bytes. 1170 std::make_tuple(std::vector<char>({'\0'}), ENOEXEC), 1171 // ELF interpreter path = "\0". 1172 // 1173 // fs/binfmt_elf.c:load_elf_binary returns ENOEXEC if p_filesz is < 2 1174 // bytes, so add an extra byte to pass that check. 1175 // 1176 // load_elf_binary -> open_exec -> do_open_execat fails to check that 1177 // name != '\0' before calling do_filp_open, which thus opens the 1178 // working directory. do_open_execat returns EACCES because the 1179 // directory is not a regular file. 1180 std::make_tuple(std::vector<char>({'\0', '\0'}), EACCES), 1181 })); 1182 1183 // Relative path to ELF interpreter. 1184 TEST(ElfTest, ELFInterpreterRelative) { 1185 ElfBinary<64> interpreter = StandardElf(); 1186 interpreter.header.e_type = ET_DYN; 1187 interpreter.header.e_entry = 0x0; 1188 interpreter.UpdateOffsets(); 1189 1190 // The first segment really needs to start at 0 for a normal PIE binary, and 1191 // thus includes the headers. 1192 uint64_t const offset = interpreter.phdrs[1].p_offset; 1193 // See comment in ElfTest.ELFInterpreter. 1194 interpreter.phdrs[1].p_flags = PF_R | PF_W | PF_X; 1195 interpreter.phdrs[1].p_offset = 0x0; 1196 interpreter.phdrs[1].p_vaddr = 0x0; 1197 interpreter.phdrs[1].p_filesz += offset; 1198 interpreter.phdrs[1].p_memsz += offset; 1199 1200 TempPath interpreter_file = 1201 ASSERT_NO_ERRNO_AND_VALUE(CreateElfWith(interpreter)); 1202 auto cwd = ASSERT_NO_ERRNO_AND_VALUE(GetCWD()); 1203 auto interpreter_relative = 1204 ASSERT_NO_ERRNO_AND_VALUE(GetRelativePath(cwd, interpreter_file.path())); 1205 1206 ElfBinary<64> binary = StandardElf(); 1207 1208 // NUL-terminated path in the PT_INTERP segment. 1209 std::vector<char> segment(interpreter_relative.begin(), 1210 interpreter_relative.end()); 1211 segment.push_back(0); 1212 binary.AddInterpreter(segment); 1213 1214 binary.UpdateOffsets(); 1215 1216 TempPath binary_file = ASSERT_NO_ERRNO_AND_VALUE(CreateElfWith(binary)); 1217 1218 pid_t child; 1219 int execve_errno; 1220 auto cleanup = ASSERT_NO_ERRNO_AND_VALUE(ForkAndExec( 1221 binary_file.path(), {binary_file.path()}, {}, &child, &execve_errno)); 1222 ASSERT_EQ(execve_errno, 0); 1223 1224 ASSERT_NO_ERRNO(WaitStopped(child)); 1225 1226 // RIP tells us which page the first segment of the interpreter was loaded 1227 // into. 1228 struct user_regs_struct regs; 1229 struct iovec iov; 1230 iov.iov_base = ®s; 1231 iov.iov_len = sizeof(regs); 1232 EXPECT_THAT(ptrace(PTRACE_GETREGSET, child, NT_PRSTATUS, &iov), 1233 SyscallSucceeds()); 1234 // Read exactly the full register set. 1235 EXPECT_EQ(iov.iov_len, sizeof(regs)); 1236 1237 const uint64_t interp_load_addr = IP_REG(regs) & ~(kPageSize - 1); 1238 1239 EXPECT_THAT( 1240 child, ContainsMappings(std::vector<ProcMapsEntry>({ 1241 // Main binary 1242 {0x40000, 0x41000, true, false, true, true, 0, 0, 0, 0, 1243 binary_file.path().c_str()}, 1244 // Interpreter 1245 {interp_load_addr, interp_load_addr + 0x1000, true, true, true, 1246 true, 0, 0, 0, 0, interpreter_file.path().c_str()}, 1247 }))); 1248 } 1249 1250 // ELF interpreter architecture doesn't match the binary. 1251 TEST(ElfTest, ELFInterpreterWrongArch) { 1252 ElfBinary<64> interpreter = StandardElf(); 1253 interpreter.header.e_machine = EM_PPC64; 1254 interpreter.header.e_type = ET_DYN; 1255 interpreter.header.e_entry = 0x0; 1256 interpreter.UpdateOffsets(); 1257 1258 // The first segment really needs to start at 0 for a normal PIE binary, and 1259 // thus includes the headers. 1260 uint64_t const offset = interpreter.phdrs[1].p_offset; 1261 // See comment in ElfTest.ELFInterpreter. 1262 interpreter.phdrs[1].p_flags = PF_R | PF_W | PF_X; 1263 interpreter.phdrs[1].p_offset = 0x0; 1264 interpreter.phdrs[1].p_vaddr = 0x0; 1265 interpreter.phdrs[1].p_filesz += offset; 1266 interpreter.phdrs[1].p_memsz += offset; 1267 1268 TempPath interpreter_file = 1269 ASSERT_NO_ERRNO_AND_VALUE(CreateElfWith(interpreter)); 1270 1271 ElfBinary<64> binary = StandardElf(); 1272 1273 // NUL-terminated path in the PT_INTERP segment. 1274 const std::string path = interpreter_file.path(); 1275 std::vector<char> segment(path.begin(), path.end()); 1276 segment.push_back(0); 1277 binary.AddInterpreter(segment); 1278 1279 binary.UpdateOffsets(); 1280 1281 TempPath binary_file = ASSERT_NO_ERRNO_AND_VALUE(CreateElfWith(binary)); 1282 1283 pid_t child; 1284 int execve_errno; 1285 auto cleanup = ASSERT_NO_ERRNO_AND_VALUE(ForkAndExec( 1286 binary_file.path(), {binary_file.path()}, {}, &child, &execve_errno)); 1287 ASSERT_EQ(execve_errno, ELIBBAD); 1288 } 1289 1290 // No execute permissions on the binary. 1291 TEST(ElfTest, NoExecute) { 1292 ElfBinary<64> elf = StandardElf(); 1293 elf.UpdateOffsets(); 1294 1295 TempPath file = ASSERT_NO_ERRNO_AND_VALUE(CreateElfWith(elf)); 1296 1297 ASSERT_THAT(chmod(file.path().c_str(), 0644), SyscallSucceeds()); 1298 1299 pid_t child; 1300 int execve_errno; 1301 auto cleanup = ASSERT_NO_ERRNO_AND_VALUE( 1302 ForkAndExec(file.path(), {file.path()}, {}, &child, &execve_errno)); 1303 EXPECT_EQ(execve_errno, EACCES); 1304 } 1305 1306 // Execute, but no read permissions on the binary works just fine. 1307 TEST(ElfTest, NoRead) { 1308 // TODO(gvisor.dev/issue/160): gVisor's backing filesystem may prevent the 1309 // sentry from reading the executable. 1310 SKIP_IF(IsRunningOnGvisor()); 1311 1312 ElfBinary<64> elf = StandardElf(); 1313 elf.UpdateOffsets(); 1314 1315 TempPath file = ASSERT_NO_ERRNO_AND_VALUE(CreateElfWith(elf)); 1316 1317 ASSERT_THAT(chmod(file.path().c_str(), 0111), SyscallSucceeds()); 1318 1319 pid_t child; 1320 int execve_errno; 1321 auto cleanup = ASSERT_NO_ERRNO_AND_VALUE( 1322 ForkAndExec(file.path(), {file.path()}, {}, &child, &execve_errno)); 1323 ASSERT_EQ(execve_errno, 0); 1324 1325 ASSERT_NO_ERRNO(WaitStopped(child)); 1326 1327 // TODO(gvisor.dev/issue/160): A task with a non-readable executable is marked 1328 // non-dumpable, preventing access to proc files. gVisor does not implement 1329 // this behavior. 1330 } 1331 1332 // No execute permissions on the ELF interpreter. 1333 TEST(ElfTest, ElfInterpreterNoExecute) { 1334 ElfBinary<64> interpreter = StandardElf(); 1335 interpreter.header.e_type = ET_DYN; 1336 interpreter.header.e_entry = 0x0; 1337 interpreter.UpdateOffsets(); 1338 1339 // The first segment really needs to start at 0 for a normal PIE binary, and 1340 // thus includes the headers. 1341 uint64_t const offset = interpreter.phdrs[1].p_offset; 1342 // See comment in ElfTest.ELFInterpreter. 1343 interpreter.phdrs[1].p_flags = PF_R | PF_W | PF_X; 1344 interpreter.phdrs[1].p_offset = 0x0; 1345 interpreter.phdrs[1].p_vaddr = 0x0; 1346 interpreter.phdrs[1].p_filesz += offset; 1347 interpreter.phdrs[1].p_memsz += offset; 1348 1349 TempPath interpreter_file = 1350 ASSERT_NO_ERRNO_AND_VALUE(CreateElfWith(interpreter)); 1351 1352 ElfBinary<64> binary = StandardElf(); 1353 1354 // NUL-terminated path in the PT_INTERP segment. 1355 const std::string path = interpreter_file.path(); 1356 std::vector<char> segment(path.begin(), path.end()); 1357 segment.push_back(0); 1358 binary.AddInterpreter(segment); 1359 1360 binary.UpdateOffsets(); 1361 1362 TempPath binary_file = ASSERT_NO_ERRNO_AND_VALUE(CreateElfWith(binary)); 1363 1364 ASSERT_THAT(chmod(interpreter_file.path().c_str(), 0644), SyscallSucceeds()); 1365 1366 pid_t child; 1367 int execve_errno; 1368 auto cleanup = ASSERT_NO_ERRNO_AND_VALUE( 1369 ForkAndExec(interpreter_file.path(), {interpreter_file.path()}, {}, 1370 &child, &execve_errno)); 1371 EXPECT_EQ(execve_errno, EACCES); 1372 } 1373 1374 // Execute a basic interpreter script. 1375 TEST(InterpreterScriptTest, Execute) { 1376 ElfBinary<64> elf = StandardElf(); 1377 elf.UpdateOffsets(); 1378 // Use /tmp explicitly to ensure the path is short enough. 1379 TempPath binary = ASSERT_NO_ERRNO_AND_VALUE(CreateElfWith("/tmp", elf)); 1380 1381 TempPath script = ASSERT_NO_ERRNO_AND_VALUE(TempPath::CreateFileWith( 1382 GetAbsoluteTestTmpdir(), absl::StrCat("#!", binary.path()), 0755)); 1383 1384 pid_t child; 1385 int execve_errno; 1386 auto cleanup = ASSERT_NO_ERRNO_AND_VALUE( 1387 ForkAndExec(script.path(), {script.path()}, {}, &child, &execve_errno)); 1388 ASSERT_EQ(execve_errno, 0); 1389 1390 EXPECT_NO_ERRNO(WaitStopped(child)); 1391 } 1392 1393 // Whitespace after #!. 1394 TEST(InterpreterScriptTest, Whitespace) { 1395 ElfBinary<64> elf = StandardElf(); 1396 elf.UpdateOffsets(); 1397 // Use /tmp explicitly to ensure the path is short enough. 1398 TempPath binary = ASSERT_NO_ERRNO_AND_VALUE(CreateElfWith("/tmp", elf)); 1399 1400 TempPath script = ASSERT_NO_ERRNO_AND_VALUE(TempPath::CreateFileWith( 1401 GetAbsoluteTestTmpdir(), absl::StrCat("#! \t \t", binary.path()), 0755)); 1402 1403 pid_t child; 1404 int execve_errno; 1405 auto cleanup = ASSERT_NO_ERRNO_AND_VALUE( 1406 ForkAndExec(script.path(), {script.path()}, {}, &child, &execve_errno)); 1407 ASSERT_EQ(execve_errno, 0); 1408 1409 EXPECT_NO_ERRNO(WaitStopped(child)); 1410 } 1411 1412 // Interpreter script is missing execute permission. 1413 TEST(InterpreterScriptTest, InterpreterScriptNoExecute) { 1414 ElfBinary<64> elf = StandardElf(); 1415 elf.UpdateOffsets(); 1416 // Use /tmp explicitly to ensure the path is short enough. 1417 TempPath binary = ASSERT_NO_ERRNO_AND_VALUE(CreateElfWith("/tmp", elf)); 1418 1419 TempPath script = ASSERT_NO_ERRNO_AND_VALUE(TempPath::CreateFileWith( 1420 GetAbsoluteTestTmpdir(), absl::StrCat("#!", binary.path()), 0644)); 1421 1422 pid_t child; 1423 int execve_errno; 1424 auto cleanup = ASSERT_NO_ERRNO_AND_VALUE( 1425 ForkAndExec(script.path(), {script.path()}, {}, &child, &execve_errno)); 1426 ASSERT_EQ(execve_errno, EACCES); 1427 } 1428 1429 // Binary interpreter script refers to is missing execute permission. 1430 TEST(InterpreterScriptTest, BinaryNoExecute) { 1431 ElfBinary<64> elf = StandardElf(); 1432 elf.UpdateOffsets(); 1433 // Use /tmp explicitly to ensure the path is short enough. 1434 TempPath binary = ASSERT_NO_ERRNO_AND_VALUE(CreateElfWith("/tmp", elf)); 1435 1436 ASSERT_THAT(chmod(binary.path().c_str(), 0644), SyscallSucceeds()); 1437 1438 TempPath script = ASSERT_NO_ERRNO_AND_VALUE(TempPath::CreateFileWith( 1439 GetAbsoluteTestTmpdir(), absl::StrCat("#!", binary.path()), 0755)); 1440 1441 pid_t child; 1442 int execve_errno; 1443 auto cleanup = ASSERT_NO_ERRNO_AND_VALUE( 1444 ForkAndExec(script.path(), {script.path()}, {}, &child, &execve_errno)); 1445 ASSERT_EQ(execve_errno, EACCES); 1446 } 1447 1448 // Linux will load interpreter scripts five levels deep, but no more. 1449 TEST(InterpreterScriptTest, MaxRecursion) { 1450 ElfBinary<64> elf = StandardElf(); 1451 elf.UpdateOffsets(); 1452 // Use /tmp explicitly to ensure the path is short enough. 1453 TempPath binary = ASSERT_NO_ERRNO_AND_VALUE(CreateElfWith("/tmp", elf)); 1454 1455 TempPath script1 = ASSERT_NO_ERRNO_AND_VALUE(TempPath::CreateFileWith( 1456 "/tmp", absl::StrCat("#!", binary.path()), 0755)); 1457 TempPath script2 = ASSERT_NO_ERRNO_AND_VALUE(TempPath::CreateFileWith( 1458 "/tmp", absl::StrCat("#!", script1.path()), 0755)); 1459 TempPath script3 = ASSERT_NO_ERRNO_AND_VALUE(TempPath::CreateFileWith( 1460 "/tmp", absl::StrCat("#!", script2.path()), 0755)); 1461 TempPath script4 = ASSERT_NO_ERRNO_AND_VALUE(TempPath::CreateFileWith( 1462 "/tmp", absl::StrCat("#!", script3.path()), 0755)); 1463 TempPath script5 = ASSERT_NO_ERRNO_AND_VALUE(TempPath::CreateFileWith( 1464 "/tmp", absl::StrCat("#!", script4.path()), 0755)); 1465 TempPath script6 = ASSERT_NO_ERRNO_AND_VALUE(TempPath::CreateFileWith( 1466 "/tmp", absl::StrCat("#!", script5.path()), 0755)); 1467 1468 pid_t child; 1469 int execve_errno; 1470 auto cleanup = ASSERT_NO_ERRNO_AND_VALUE( 1471 ForkAndExec(script6.path(), {script6.path()}, {}, &child, &execve_errno)); 1472 // Too many levels of recursion. 1473 EXPECT_EQ(execve_errno, ELOOP); 1474 1475 // The next level up is OK. 1476 auto cleanup2 = ASSERT_NO_ERRNO_AND_VALUE( 1477 ForkAndExec(script5.path(), {script5.path()}, {}, &child, &execve_errno)); 1478 ASSERT_EQ(execve_errno, 0); 1479 1480 EXPECT_NO_ERRNO(WaitStopped(child)); 1481 } 1482 1483 // Interpreter script with a relative path. 1484 TEST(InterpreterScriptTest, RelativePath) { 1485 ElfBinary<64> elf = StandardElf(); 1486 elf.UpdateOffsets(); 1487 TempPath binary = ASSERT_NO_ERRNO_AND_VALUE(CreateElfWith("/tmp", elf)); 1488 1489 auto cwd = ASSERT_NO_ERRNO_AND_VALUE(GetCWD()); 1490 auto binary_relative = 1491 ASSERT_NO_ERRNO_AND_VALUE(GetRelativePath(cwd, binary.path())); 1492 1493 TempPath script = ASSERT_NO_ERRNO_AND_VALUE(TempPath::CreateFileWith( 1494 GetAbsoluteTestTmpdir(), absl::StrCat("#!", binary_relative), 0755)); 1495 1496 pid_t child; 1497 int execve_errno; 1498 auto cleanup = ASSERT_NO_ERRNO_AND_VALUE( 1499 ForkAndExec(script.path(), {script.path()}, {}, &child, &execve_errno)); 1500 ASSERT_EQ(execve_errno, 0); 1501 1502 EXPECT_NO_ERRNO(WaitStopped(child)); 1503 } 1504 1505 // Interpreter script with .. in a path component. 1506 TEST(InterpreterScriptTest, UncleanPath) { 1507 ElfBinary<64> elf = StandardElf(); 1508 elf.UpdateOffsets(); 1509 // Use /tmp explicitly to ensure the path is short enough. 1510 TempPath binary = ASSERT_NO_ERRNO_AND_VALUE(CreateElfWith("/tmp", elf)); 1511 1512 TempPath script = ASSERT_NO_ERRNO_AND_VALUE(TempPath::CreateFileWith( 1513 GetAbsoluteTestTmpdir(), absl::StrCat("#!/tmp/../", binary.path()), 1514 0755)); 1515 1516 pid_t child; 1517 int execve_errno; 1518 auto cleanup = ASSERT_NO_ERRNO_AND_VALUE( 1519 ForkAndExec(script.path(), {script.path()}, {}, &child, &execve_errno)); 1520 ASSERT_EQ(execve_errno, 0); 1521 1522 EXPECT_NO_ERRNO(WaitStopped(child)); 1523 } 1524 1525 // Passed interpreter script is a symlink. 1526 TEST(InterpreterScriptTest, Symlink) { 1527 ElfBinary<64> elf = StandardElf(); 1528 elf.UpdateOffsets(); 1529 // Use /tmp explicitly to ensure the path is short enough. 1530 TempPath binary = ASSERT_NO_ERRNO_AND_VALUE(CreateElfWith("/tmp", elf)); 1531 1532 TempPath script = ASSERT_NO_ERRNO_AND_VALUE(TempPath::CreateFileWith( 1533 GetAbsoluteTestTmpdir(), absl::StrCat("#!", binary.path()), 0755)); 1534 1535 TempPath link = ASSERT_NO_ERRNO_AND_VALUE( 1536 TempPath::CreateSymlinkTo(GetAbsoluteTestTmpdir(), script.path())); 1537 1538 pid_t child; 1539 int execve_errno; 1540 auto cleanup = ASSERT_NO_ERRNO_AND_VALUE( 1541 ForkAndExec(link.path(), {link.path()}, {}, &child, &execve_errno)); 1542 ASSERT_EQ(execve_errno, 0); 1543 1544 EXPECT_NO_ERRNO(WaitStopped(child)); 1545 } 1546 1547 // Interpreter script points to a symlink loop. 1548 TEST(InterpreterScriptTest, SymlinkLoop) { 1549 std::string const link1 = NewTempAbsPathInDir("/tmp"); 1550 std::string const link2 = NewTempAbsPathInDir("/tmp"); 1551 1552 ASSERT_THAT(symlink(link2.c_str(), link1.c_str()), SyscallSucceeds()); 1553 auto remove_link1 = Cleanup( 1554 [&link1] { EXPECT_THAT(unlink(link1.c_str()), SyscallSucceeds()); }); 1555 1556 ASSERT_THAT(symlink(link1.c_str(), link2.c_str()), SyscallSucceeds()); 1557 auto remove_link2 = Cleanup( 1558 [&link2] { EXPECT_THAT(unlink(link2.c_str()), SyscallSucceeds()); }); 1559 1560 TempPath script = ASSERT_NO_ERRNO_AND_VALUE(TempPath::CreateFileWith( 1561 GetAbsoluteTestTmpdir(), absl::StrCat("#!", link1), 0755)); 1562 1563 pid_t child; 1564 int execve_errno; 1565 auto cleanup = ASSERT_NO_ERRNO_AND_VALUE( 1566 ForkAndExec(script.path(), {script.path()}, {}, &child, &execve_errno)); 1567 EXPECT_EQ(execve_errno, ELOOP); 1568 } 1569 1570 // Binary is a symlink loop. 1571 TEST(ExecveTest, SymlinkLoop) { 1572 std::string const link1 = NewTempAbsPathInDir("/tmp"); 1573 std::string const link2 = NewTempAbsPathInDir("/tmp"); 1574 1575 ASSERT_THAT(symlink(link2.c_str(), link1.c_str()), SyscallSucceeds()); 1576 auto remove_link = Cleanup( 1577 [&link1] { EXPECT_THAT(unlink(link1.c_str()), SyscallSucceeds()); }); 1578 1579 ASSERT_THAT(symlink(link1.c_str(), link2.c_str()), SyscallSucceeds()); 1580 auto remove_link2 = Cleanup( 1581 [&link2] { EXPECT_THAT(unlink(link2.c_str()), SyscallSucceeds()); }); 1582 1583 pid_t child; 1584 int execve_errno; 1585 auto cleanup = ASSERT_NO_ERRNO_AND_VALUE( 1586 ForkAndExec(link1, {link1}, {}, &child, &execve_errno)); 1587 EXPECT_EQ(execve_errno, ELOOP); 1588 } 1589 1590 // Binary is a directory. 1591 TEST(ExecveTest, Directory) { 1592 pid_t child; 1593 int execve_errno; 1594 auto cleanup = ASSERT_NO_ERRNO_AND_VALUE( 1595 ForkAndExec("/tmp", {"/tmp"}, {}, &child, &execve_errno)); 1596 EXPECT_EQ(execve_errno, EACCES); 1597 } 1598 1599 // Pass a valid binary as a directory (extra / on the end). 1600 TEST(ExecveTest, BinaryAsDirectory) { 1601 ElfBinary<64> elf = StandardElf(); 1602 elf.UpdateOffsets(); 1603 TempPath file = ASSERT_NO_ERRNO_AND_VALUE(CreateElfWith(elf)); 1604 1605 std::string const path = absl::StrCat(file.path(), "/"); 1606 1607 pid_t child; 1608 int execve_errno; 1609 auto cleanup = ASSERT_NO_ERRNO_AND_VALUE( 1610 ForkAndExec(path, {path}, {}, &child, &execve_errno)); 1611 EXPECT_EQ(execve_errno, ENOTDIR); 1612 } 1613 1614 // The initial brk value is after the page at the end of the binary. 1615 TEST(ExecveTest, BrkAfterBinary) { 1616 ElfBinary<64> elf = StandardElf(); 1617 elf.UpdateOffsets(); 1618 1619 TempPath file = ASSERT_NO_ERRNO_AND_VALUE(CreateElfWith(elf)); 1620 1621 pid_t child; 1622 int execve_errno; 1623 auto cleanup = ASSERT_NO_ERRNO_AND_VALUE( 1624 ForkAndExec(file.path(), {file.path()}, {}, &child, &execve_errno)); 1625 ASSERT_EQ(execve_errno, 0); 1626 1627 // Ensure it made it to SIGSTOP. 1628 ASSERT_NO_ERRNO(WaitStopped(child)); 1629 1630 struct user_regs_struct regs; 1631 struct iovec iov; 1632 iov.iov_base = ®s; 1633 iov.iov_len = sizeof(regs); 1634 EXPECT_THAT(ptrace(PTRACE_GETREGSET, child, NT_PRSTATUS, &iov), 1635 SyscallSucceeds()); 1636 // Read exactly the full register set. 1637 EXPECT_EQ(iov.iov_len, sizeof(regs)); 1638 1639 // RIP is just beyond the final syscall instruction. Rewind to execute a brk 1640 // syscall. 1641 IP_REG(regs) -= kSyscallSize; 1642 RAX_REG(regs) = __NR_brk; 1643 RDI_REG(regs) = 0; 1644 ASSERT_THAT(ptrace(PTRACE_SETREGSET, child, NT_PRSTATUS, &iov), 1645 SyscallSucceeds()); 1646 1647 // Resume the child, waiting for syscall entry. 1648 ASSERT_THAT(ptrace(PTRACE_SYSCALL, child, 0, 0), SyscallSucceeds()); 1649 int status; 1650 ASSERT_THAT(RetryEINTR(waitpid)(child, &status, 0), 1651 SyscallSucceedsWithValue(child)); 1652 ASSERT_TRUE(WIFSTOPPED(status) && WSTOPSIG(status) == SIGTRAP) 1653 << "status = " << status; 1654 1655 // Execute the syscall. 1656 ASSERT_THAT(ptrace(PTRACE_SYSCALL, child, 0, 0), SyscallSucceeds()); 1657 ASSERT_THAT(RetryEINTR(waitpid)(child, &status, 0), 1658 SyscallSucceedsWithValue(child)); 1659 ASSERT_TRUE(WIFSTOPPED(status) && WSTOPSIG(status) == SIGTRAP) 1660 << "status = " << status; 1661 1662 iov.iov_base = ®s; 1663 iov.iov_len = sizeof(regs); 1664 EXPECT_THAT(ptrace(PTRACE_GETREGSET, child, NT_PRSTATUS, &iov), 1665 SyscallSucceeds()); 1666 // Read exactly the full register set. 1667 EXPECT_EQ(iov.iov_len, sizeof(regs)); 1668 1669 // brk is after the text page. 1670 // 1671 // The kernel does brk randomization, so we can't be sure what the exact 1672 // address will be, but it is always beyond the final page in the binary. 1673 // i.e., it does not start immediately after memsz in the middle of a page. 1674 // Userspace may expect to use that space. 1675 EXPECT_GE(RETURN_REG(regs), 0x41000); 1676 } 1677 1678 } // namespace 1679 1680 } // namespace testing 1681 } // namespace gvisor