mirror of
https://github.com/LadybirdBrowser/ladybird.git
synced 2024-11-25 09:00:22 +00:00
Tests: Add LibELF tests
This commit is contained in:
parent
07850ccf51
commit
0629b4e170
Notes:
sideshowbarker
2024-07-18 22:57:59 +09:00
Author: https://github.com/bcoles Commit: https://github.com/SerenityOS/serenity/commit/0629b4e170e Pull-request: https://github.com/SerenityOS/serenity/pull/7128 Reviewed-by: https://github.com/linusg
3 changed files with 297 additions and 0 deletions
|
@ -3,6 +3,7 @@ add_subdirectory(Kernel)
|
|||
add_subdirectory(LibC)
|
||||
add_subdirectory(LibCore)
|
||||
add_subdirectory(LibCompress)
|
||||
add_subdirectory(LibELF)
|
||||
add_subdirectory(LibGfx)
|
||||
add_subdirectory(LibJS)
|
||||
add_subdirectory(LibM)
|
||||
|
|
5
Tests/LibELF/CMakeLists.txt
Normal file
5
Tests/LibELF/CMakeLists.txt
Normal file
|
@ -0,0 +1,5 @@
|
|||
file(GLOB CMD_SOURCES CONFIGURE_DEPENDS "*.cpp")
|
||||
|
||||
foreach(CMD_SRC ${CMD_SOURCES})
|
||||
serenity_test(${CMD_SRC} LibELF)
|
||||
endforeach()
|
291
Tests/LibELF/test-elf.cpp
Normal file
291
Tests/LibELF/test-elf.cpp
Normal file
|
@ -0,0 +1,291 @@
|
|||
/*
|
||||
* Copyright (c) 2021, the SerenityOS developers.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-2-Clause
|
||||
*/
|
||||
|
||||
#include <LibC/elf.h>
|
||||
#include <LibCore/File.h>
|
||||
#include <LibTest/TestCase.h>
|
||||
#include <fcntl.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
|
||||
TEST_CASE(test_interp_header_tiny_p_filesz)
|
||||
{
|
||||
char buffer[0x2000];
|
||||
|
||||
auto& header = *(Elf32_Ehdr*)buffer;
|
||||
header.e_ident[EI_MAG0] = ELFMAG0;
|
||||
header.e_ident[EI_MAG1] = ELFMAG1;
|
||||
header.e_ident[EI_MAG2] = ELFMAG2;
|
||||
header.e_ident[EI_MAG3] = ELFMAG3;
|
||||
header.e_ident[EI_CLASS] = ELFCLASS32;
|
||||
header.e_ident[EI_DATA] = ELFDATA2LSB;
|
||||
header.e_ident[EI_VERSION] = EV_CURRENT;
|
||||
header.e_ident[EI_OSABI] = ELFOSABI_SYSV;
|
||||
header.e_ident[EI_ABIVERSION] = 0;
|
||||
header.e_type = ET_REL;
|
||||
header.e_version = EV_CURRENT;
|
||||
header.e_ehsize = sizeof(Elf32_Ehdr);
|
||||
header.e_machine = EM_386;
|
||||
header.e_shentsize = sizeof(Elf32_Shdr);
|
||||
header.e_phnum = 1;
|
||||
header.e_phoff = 52; // inaccurate
|
||||
header.e_phentsize = sizeof(Elf32_Phdr); // inaccurate
|
||||
header.e_shnum = 3; // inaccurate
|
||||
header.e_shoff = 1024; // inaccurate
|
||||
header.e_shstrndx = 2; // inaccurate
|
||||
header.e_entry = 1024; // inaccurate
|
||||
|
||||
auto* ph = (Elf32_Phdr*)(&buffer[header.e_phoff]);
|
||||
ph[0].p_flags = PF_R | PF_X;
|
||||
ph[0].p_vaddr = 0x00d4;
|
||||
ph[0].p_align = PAGE_SIZE;
|
||||
ph[0].p_type = PT_INTERP;
|
||||
ph[0].p_memsz = 0xffff0000;
|
||||
ph[0].p_offset = 0x100;
|
||||
|
||||
// p_filesz (1 or less) to trigger crash
|
||||
ph[0].p_filesz = 1;
|
||||
|
||||
char path[] = "/tmp/test-elf.XXXXXX";
|
||||
auto fd = mkstemp(path);
|
||||
EXPECT_NE(fd, -1);
|
||||
EXPECT_EQ(fchmod(fd, 0700), 0);
|
||||
|
||||
int nwritten = write(fd, buffer, sizeof(buffer));
|
||||
EXPECT(nwritten);
|
||||
|
||||
auto elf_path = Core::File::read_link(String::formatted("/proc/{}/fd/{}", getpid(), fd));
|
||||
EXPECT(elf_path.characters());
|
||||
|
||||
int rc = execl(elf_path.characters(), "test-elf", nullptr);
|
||||
EXPECT_EQ(rc, -1);
|
||||
EXPECT_EQ(errno, 8);
|
||||
|
||||
EXPECT_EQ(unlink(path), 0);
|
||||
}
|
||||
|
||||
TEST_CASE(test_interp_header_p_filesz_larger_than_p_memsz)
|
||||
{
|
||||
char buffer[0x2000];
|
||||
|
||||
auto& header = *(Elf32_Ehdr*)buffer;
|
||||
header.e_ident[EI_MAG0] = ELFMAG0;
|
||||
header.e_ident[EI_MAG1] = ELFMAG1;
|
||||
header.e_ident[EI_MAG2] = ELFMAG2;
|
||||
header.e_ident[EI_MAG3] = ELFMAG3;
|
||||
header.e_ident[EI_CLASS] = ELFCLASS32;
|
||||
header.e_ident[EI_DATA] = ELFDATA2LSB;
|
||||
header.e_ident[EI_VERSION] = EV_CURRENT;
|
||||
header.e_ident[EI_OSABI] = ELFOSABI_SYSV;
|
||||
header.e_ident[EI_ABIVERSION] = 0;
|
||||
header.e_type = ET_REL;
|
||||
header.e_version = EV_CURRENT;
|
||||
header.e_ehsize = sizeof(Elf32_Ehdr);
|
||||
header.e_machine = EM_386;
|
||||
header.e_shentsize = sizeof(Elf32_Shdr);
|
||||
header.e_phnum = 1;
|
||||
header.e_phoff = 52; // inaccurate
|
||||
header.e_phentsize = sizeof(Elf32_Phdr); // inaccurate
|
||||
header.e_shnum = 3; // inaccurate
|
||||
header.e_shoff = 1024; // inaccurate
|
||||
header.e_shstrndx = 2; // inaccurate
|
||||
header.e_entry = 1024; // inaccurate
|
||||
|
||||
auto* ph = (Elf32_Phdr*)(&buffer[header.e_phoff]);
|
||||
ph[0].p_flags = PF_R | PF_X;
|
||||
ph[0].p_vaddr = 0x00d4;
|
||||
ph[0].p_align = PAGE_SIZE;
|
||||
ph[0].p_type = PT_INTERP;
|
||||
ph[0].p_memsz = 0xffff0000;
|
||||
ph[0].p_offset = 0x1000;
|
||||
ph[0].p_filesz = 0x1000;
|
||||
|
||||
char path[] = "/tmp/test-elf.XXXXXX";
|
||||
auto fd = mkstemp(path);
|
||||
EXPECT_NE(fd, -1);
|
||||
EXPECT_EQ(fchmod(fd, 0700), 0);
|
||||
|
||||
int nwritten = write(fd, buffer, sizeof(buffer));
|
||||
EXPECT(nwritten);
|
||||
|
||||
auto elf_path = Core::File::read_link(String::formatted("/proc/{}/fd/{}", getpid(), fd));
|
||||
EXPECT(elf_path.characters());
|
||||
|
||||
int rc = execl(elf_path.characters(), "test-elf", nullptr);
|
||||
EXPECT_EQ(rc, -1);
|
||||
EXPECT_EQ(errno, 8);
|
||||
|
||||
EXPECT_EQ(unlink(path), 0);
|
||||
}
|
||||
|
||||
TEST_CASE(test_interp_header_p_filesz_plus_p_offset_overflow_p_memsz)
|
||||
{
|
||||
char buffer[0x2000];
|
||||
|
||||
auto& header = *(Elf32_Ehdr*)buffer;
|
||||
header.e_ident[EI_MAG0] = ELFMAG0;
|
||||
header.e_ident[EI_MAG1] = ELFMAG1;
|
||||
header.e_ident[EI_MAG2] = ELFMAG2;
|
||||
header.e_ident[EI_MAG3] = ELFMAG3;
|
||||
header.e_ident[EI_CLASS] = ELFCLASS32;
|
||||
header.e_ident[EI_DATA] = ELFDATA2LSB;
|
||||
header.e_ident[EI_VERSION] = EV_CURRENT;
|
||||
header.e_ident[EI_OSABI] = ELFOSABI_SYSV;
|
||||
header.e_ident[EI_ABIVERSION] = 0;
|
||||
header.e_type = ET_REL;
|
||||
header.e_version = EV_CURRENT;
|
||||
header.e_ehsize = sizeof(Elf32_Ehdr);
|
||||
header.e_machine = EM_386;
|
||||
header.e_shentsize = sizeof(Elf32_Shdr);
|
||||
header.e_phoff = 52; // inaccurate
|
||||
header.e_phentsize = sizeof(Elf32_Phdr); // inaccurate
|
||||
header.e_shnum = 3; // inaccurate
|
||||
header.e_shoff = 1024; // inaccurate
|
||||
header.e_shstrndx = 2; // inaccurate
|
||||
header.e_entry = 1024; // inaccurate
|
||||
|
||||
auto* ph = (Elf32_Phdr*)(&buffer[header.e_phoff]);
|
||||
ph[0].p_flags = PF_R | PF_X;
|
||||
ph[0].p_vaddr = 0x00d4;
|
||||
ph[0].p_align = PAGE_SIZE;
|
||||
ph[0].p_type = PT_INTERP;
|
||||
|
||||
// p_memsz must be of sufficient size to hold maxint - 0x1000
|
||||
ph[0].p_memsz = 0xfffff000;
|
||||
|
||||
// p_offset + p_filesz must not exceed buffer size in order to pass buffer size check in ELF::validate_program_headers().
|
||||
// p_memsz + p_offset must be sufficiently large to overflow maxint.
|
||||
ph[0].p_offset = 0x1234;
|
||||
ph[0].p_filesz = -0x1000;
|
||||
|
||||
char path[] = "/tmp/test-elf.XXXXXX";
|
||||
auto fd = mkstemp(path);
|
||||
EXPECT_NE(fd, -1);
|
||||
EXPECT_EQ(fchmod(fd, 0700), 0);
|
||||
|
||||
int nwritten = write(fd, buffer, sizeof(buffer));
|
||||
EXPECT(nwritten);
|
||||
|
||||
auto elf_path = Core::File::read_link(String::formatted("/proc/{}/fd/{}", getpid(), fd));
|
||||
EXPECT(elf_path.characters());
|
||||
|
||||
int rc = execl(elf_path.characters(), "test-elf", nullptr);
|
||||
EXPECT_EQ(rc, -1);
|
||||
EXPECT_EQ(errno, 8);
|
||||
|
||||
EXPECT_EQ(unlink(path), 0);
|
||||
}
|
||||
|
||||
TEST_CASE(test_load_header_p_memsz_zero)
|
||||
{
|
||||
char buffer[0x2000];
|
||||
|
||||
auto& header = *(Elf32_Ehdr*)buffer;
|
||||
header.e_ident[EI_MAG0] = ELFMAG0;
|
||||
header.e_ident[EI_MAG1] = ELFMAG1;
|
||||
header.e_ident[EI_MAG2] = ELFMAG2;
|
||||
header.e_ident[EI_MAG3] = ELFMAG3;
|
||||
header.e_ident[EI_CLASS] = ELFCLASS32;
|
||||
header.e_ident[EI_DATA] = ELFDATA2LSB;
|
||||
header.e_ident[EI_VERSION] = EV_CURRENT;
|
||||
header.e_ident[EI_OSABI] = ELFOSABI_SYSV;
|
||||
header.e_ident[EI_ABIVERSION] = 0;
|
||||
header.e_type = ET_REL;
|
||||
header.e_version = EV_CURRENT;
|
||||
header.e_ehsize = sizeof(Elf32_Ehdr);
|
||||
header.e_machine = EM_386;
|
||||
header.e_shentsize = sizeof(Elf32_Shdr);
|
||||
header.e_phoff = 52; // inaccurate
|
||||
header.e_phentsize = sizeof(Elf32_Phdr); // inaccurate
|
||||
header.e_shnum = 3; // inaccurate
|
||||
header.e_shoff = 1024; // inaccurate
|
||||
header.e_shstrndx = 2; // inaccurate
|
||||
header.e_entry = 1024; // inaccurate
|
||||
|
||||
auto* ph = (Elf32_Phdr*)(&buffer[header.e_phoff]);
|
||||
ph[0].p_flags = PF_R | PF_X;
|
||||
ph[0].p_vaddr = 0x00d4;
|
||||
ph[0].p_align = PAGE_SIZE;
|
||||
ph[0].p_type = PT_LOAD;
|
||||
ph[0].p_offset = 0;
|
||||
ph[0].p_filesz = 0;
|
||||
|
||||
// p_memsz zero to trigger crash
|
||||
ph[0].p_memsz = 0;
|
||||
|
||||
char path[] = "/tmp/test-elf.XXXXXX";
|
||||
auto fd = mkstemp(path);
|
||||
EXPECT_NE(fd, -1);
|
||||
EXPECT_EQ(fchmod(fd, 0700), 0);
|
||||
|
||||
int nwritten = write(fd, buffer, sizeof(buffer));
|
||||
EXPECT(nwritten);
|
||||
|
||||
auto elf_path = Core::File::read_link(String::formatted("/proc/{}/fd/{}", getpid(), fd));
|
||||
EXPECT(elf_path.characters());
|
||||
|
||||
int rc = execl(elf_path.characters(), "test-elf", nullptr);
|
||||
EXPECT_EQ(rc, -1);
|
||||
EXPECT_EQ(errno, 8);
|
||||
|
||||
EXPECT_EQ(unlink(path), 0);
|
||||
}
|
||||
|
||||
TEST_CASE(test_load_header_p_memsz_not_equal_to_p_align)
|
||||
{
|
||||
char buffer[0x2000];
|
||||
|
||||
auto& header = *(Elf32_Ehdr*)buffer;
|
||||
header.e_ident[EI_MAG0] = ELFMAG0;
|
||||
header.e_ident[EI_MAG1] = ELFMAG1;
|
||||
header.e_ident[EI_MAG2] = ELFMAG2;
|
||||
header.e_ident[EI_MAG3] = ELFMAG3;
|
||||
header.e_ident[EI_CLASS] = ELFCLASS32;
|
||||
header.e_ident[EI_DATA] = ELFDATA2LSB;
|
||||
header.e_ident[EI_VERSION] = EV_CURRENT;
|
||||
header.e_ident[EI_OSABI] = ELFOSABI_SYSV;
|
||||
header.e_ident[EI_ABIVERSION] = 0;
|
||||
header.e_type = ET_REL;
|
||||
header.e_version = EV_CURRENT;
|
||||
header.e_ehsize = sizeof(Elf32_Ehdr);
|
||||
header.e_machine = EM_386;
|
||||
header.e_shentsize = sizeof(Elf32_Shdr);
|
||||
header.e_phoff = 52; // inaccurate
|
||||
header.e_phentsize = sizeof(Elf32_Phdr); // inaccurate
|
||||
header.e_shnum = 3; // inaccurate
|
||||
header.e_shoff = 1024; // inaccurate
|
||||
header.e_shstrndx = 2; // inaccurate
|
||||
header.e_entry = 1024; // inaccurate
|
||||
|
||||
auto* ph = (Elf32_Phdr*)(&buffer[header.e_phoff]);
|
||||
ph[0].p_flags = PF_R | PF_X;
|
||||
ph[0].p_vaddr = 0x00d4;
|
||||
ph[0].p_type = PT_LOAD;
|
||||
ph[0].p_memsz = 0xffff0000;
|
||||
ph[0].p_offset = 0x1000;
|
||||
ph[0].p_filesz = 0x1000;
|
||||
|
||||
// p_align not equal to PAGE_SIZE to trigger crash
|
||||
ph[0].p_align = PAGE_SIZE / 2;
|
||||
|
||||
char path[] = "/tmp/test-elf.XXXXXX";
|
||||
auto fd = mkstemp(path);
|
||||
EXPECT_NE(fd, -1);
|
||||
EXPECT_EQ(fchmod(fd, 0700), 0);
|
||||
|
||||
int nwritten = write(fd, buffer, sizeof(buffer));
|
||||
EXPECT(nwritten);
|
||||
|
||||
auto elf_path = Core::File::read_link(String::formatted("/proc/{}/fd/{}", getpid(), fd));
|
||||
EXPECT(elf_path.characters());
|
||||
|
||||
int rc = execl(elf_path.characters(), "test-elf", nullptr);
|
||||
EXPECT_EQ(rc, -1);
|
||||
EXPECT_EQ(errno, 8);
|
||||
|
||||
EXPECT_EQ(unlink(path), 0);
|
||||
}
|
Loading…
Reference in a new issue