summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorAndrei Vagin <avagin@google.com>2021-02-08 19:15:45 -0800
committergVisor bot <gvisor-bot@google.com>2021-02-08 19:18:03 -0800
commitbf4968e17d7d08299493835a34af1a6d8551c375 (patch)
tree6c5e9228abf2ee41a058c69528f2876ea7934129
parent39251f31cb92d6c2b053416d04e195e290b106f2 (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.go6
-rw-r--r--test/syscalls/linux/exec_binary.cc28
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();