diff options
author | Andrei Vagin <avagin@google.com> | 2021-02-08 19:15:45 -0800 |
---|---|---|
committer | gVisor bot <gvisor-bot@google.com> | 2021-02-08 19:18:03 -0800 |
commit | bf4968e17d7d08299493835a34af1a6d8551c375 (patch) | |
tree | 6c5e9228abf2ee41a058c69528f2876ea7934129 | |
parent | 39251f31cb92d6c2b053416d04e195e290b106f2 (diff) |
exec: don't panic if an elf file is malformed
Reported-by: syzbot+d54bc27a15aefe52c330@syzkaller.appspotmail.com
PiperOrigin-RevId: 356406975
-rw-r--r-- | pkg/sentry/loader/elf.go | 6 | ||||
-rw-r--r-- | test/syscalls/linux/exec_binary.cc | 28 |
2 files changed, 32 insertions, 2 deletions
diff --git a/pkg/sentry/loader/elf.go b/pkg/sentry/loader/elf.go index 98af2cc38..cd9fa4031 100644 --- a/pkg/sentry/loader/elf.go +++ b/pkg/sentry/loader/elf.go @@ -517,12 +517,14 @@ func loadParsedELF(ctx context.Context, m *mm.MemoryManager, f fsbridge.File, in start, ok = start.AddLength(uint64(offset)) if !ok { - panic(fmt.Sprintf("Start %#x + offset %#x overflows?", start, offset)) + ctx.Infof(fmt.Sprintf("Start %#x + offset %#x overflows?", start, offset)) + return loadedELF{}, syserror.EINVAL } end, ok = end.AddLength(uint64(offset)) if !ok { - panic(fmt.Sprintf("End %#x + offset %#x overflows?", end, offset)) + ctx.Infof(fmt.Sprintf("End %#x + offset %#x overflows?", end, offset)) + return loadedELF{}, syserror.EINVAL } info.entry, ok = info.entry.AddLength(uint64(offset)) diff --git a/test/syscalls/linux/exec_binary.cc b/test/syscalls/linux/exec_binary.cc index 3797fd4c8..b0fb120c6 100644 --- a/test/syscalls/linux/exec_binary.cc +++ b/test/syscalls/linux/exec_binary.cc @@ -951,6 +951,34 @@ TEST(ElfTest, PIEOutOfOrderSegments) { EXPECT_EQ(execve_errno, ENOEXEC); } +TEST(ElfTest, PIEOverflow) { + ElfBinary<64> elf = StandardElf(); + + elf.header.e_type = ET_DYN; + + // Choose vaddr of the first segment so that the end address overflows if the + // segment is mapped with a non-zero offset. + elf.phdrs[1].p_vaddr = 0xfffffffffffff000UL - elf.phdrs[1].p_memsz; + + elf.UpdateOffsets(); + + TempPath file = ASSERT_NO_ERRNO_AND_VALUE(CreateElfWith(elf)); + + pid_t child; + int execve_errno; + auto cleanup = ASSERT_NO_ERRNO_AND_VALUE( + ForkAndExec(file.path(), {file.path()}, {}, &child, &execve_errno)); + if (IsRunningOnGvisor()) { + ASSERT_EQ(execve_errno, EINVAL); + } else { + ASSERT_EQ(execve_errno, 0); + int status; + ASSERT_THAT(RetryEINTR(waitpid)(child, &status, 0), + SyscallSucceedsWithValue(child)); + EXPECT_TRUE(WIFSIGNALED(status) && WTERMSIG(status) == SIGSEGV) << status; + } +} + // Standard dynamically linked binary with an ELF interpreter. TEST(ElfTest, ELFInterpreter) { ElfBinary<64> interpreter = StandardElf(); |