mirror of
https://github.com/LadybirdBrowser/ladybird.git
synced 2024-12-27 21:21:50 +03:00
Kernel+LibELF: Add support for validating and loading ELF64 executables
This commit is contained in:
parent
e35b060501
commit
158355e0d7
Notes:
sideshowbarker
2024-07-18 11:22:39 +09:00
Author: https://github.com/gunnarbeutner Commit: https://github.com/SerenityOS/serenity/commit/158355e0d77 Pull-request: https://github.com/SerenityOS/serenity/pull/8301
@ -73,7 +73,7 @@ RefPtr<FileDescription> CoreDump::create_target_file(const Process& process, con
|
||||
|
||||
KResult CoreDump::write_elf_header()
|
||||
{
|
||||
Elf32_Ehdr elf_file_header;
|
||||
ElfW(Ehdr) elf_file_header;
|
||||
elf_file_header.e_ident[EI_MAG0] = 0x7f;
|
||||
elf_file_header.e_ident[EI_MAG1] = 'E';
|
||||
elf_file_header.e_ident[EI_MAG2] = 'L';
|
||||
@ -93,17 +93,17 @@ KResult CoreDump::write_elf_header()
|
||||
elf_file_header.e_machine = EM_386;
|
||||
elf_file_header.e_version = 1;
|
||||
elf_file_header.e_entry = 0;
|
||||
elf_file_header.e_phoff = sizeof(Elf32_Ehdr);
|
||||
elf_file_header.e_phoff = sizeof(ElfW(Ehdr));
|
||||
elf_file_header.e_shoff = 0;
|
||||
elf_file_header.e_flags = 0;
|
||||
elf_file_header.e_ehsize = sizeof(Elf32_Ehdr);
|
||||
elf_file_header.e_shentsize = sizeof(Elf32_Shdr);
|
||||
elf_file_header.e_phentsize = sizeof(Elf32_Phdr);
|
||||
elf_file_header.e_ehsize = sizeof(ElfW(Ehdr));
|
||||
elf_file_header.e_shentsize = sizeof(ElfW(Shdr));
|
||||
elf_file_header.e_phentsize = sizeof(ElfW(Phdr));
|
||||
elf_file_header.e_phnum = m_num_program_headers;
|
||||
elf_file_header.e_shnum = 0;
|
||||
elf_file_header.e_shstrndx = SHN_UNDEF;
|
||||
|
||||
auto result = m_fd->write(UserOrKernelBuffer::for_kernel_buffer(reinterpret_cast<uint8_t*>(&elf_file_header)), sizeof(Elf32_Ehdr));
|
||||
auto result = m_fd->write(UserOrKernelBuffer::for_kernel_buffer(reinterpret_cast<uint8_t*>(&elf_file_header)), sizeof(ElfW(Ehdr)));
|
||||
if (result.is_error())
|
||||
return result.error();
|
||||
return KSuccess;
|
||||
@ -111,9 +111,9 @@ KResult CoreDump::write_elf_header()
|
||||
|
||||
KResult CoreDump::write_program_headers(size_t notes_size)
|
||||
{
|
||||
size_t offset = sizeof(Elf32_Ehdr) + m_num_program_headers * sizeof(Elf32_Phdr);
|
||||
size_t offset = sizeof(ElfW(Ehdr)) + m_num_program_headers * sizeof(ElfW(Phdr));
|
||||
for (auto& region : m_process->space().regions()) {
|
||||
Elf32_Phdr phdr {};
|
||||
ElfW(Phdr) phdr {};
|
||||
|
||||
phdr.p_type = PT_LOAD;
|
||||
phdr.p_offset = offset;
|
||||
@ -132,10 +132,10 @@ KResult CoreDump::write_program_headers(size_t notes_size)
|
||||
|
||||
offset += phdr.p_filesz;
|
||||
|
||||
[[maybe_unused]] auto rc = m_fd->write(UserOrKernelBuffer::for_kernel_buffer(reinterpret_cast<uint8_t*>(&phdr)), sizeof(Elf32_Phdr));
|
||||
[[maybe_unused]] auto rc = m_fd->write(UserOrKernelBuffer::for_kernel_buffer(reinterpret_cast<uint8_t*>(&phdr)), sizeof(ElfW(Phdr)));
|
||||
}
|
||||
|
||||
Elf32_Phdr notes_pheader {};
|
||||
ElfW(Phdr) notes_pheader {};
|
||||
notes_pheader.p_type = PT_NOTE;
|
||||
notes_pheader.p_offset = offset;
|
||||
notes_pheader.p_vaddr = 0;
|
||||
@ -145,7 +145,7 @@ KResult CoreDump::write_program_headers(size_t notes_size)
|
||||
notes_pheader.p_align = 0;
|
||||
notes_pheader.p_flags = 0;
|
||||
|
||||
auto result = m_fd->write(UserOrKernelBuffer::for_kernel_buffer(reinterpret_cast<uint8_t*>(¬es_pheader)), sizeof(Elf32_Phdr));
|
||||
auto result = m_fd->write(UserOrKernelBuffer::for_kernel_buffer(reinterpret_cast<uint8_t*>(¬es_pheader)), sizeof(ElfW(Phdr)));
|
||||
if (result.is_error())
|
||||
return result.error();
|
||||
return KSuccess;
|
||||
|
@ -448,7 +448,7 @@ public:
|
||||
|
||||
KResult exec(String path, Vector<String> arguments, Vector<String> environment, int recusion_depth = 0);
|
||||
|
||||
KResultOr<LoadResult> load(NonnullRefPtr<FileDescription> main_program_description, RefPtr<FileDescription> interpreter_description, const Elf32_Ehdr& main_program_header);
|
||||
KResultOr<LoadResult> load(NonnullRefPtr<FileDescription> main_program_description, RefPtr<FileDescription> interpreter_description, const ElfW(Ehdr) & main_program_header);
|
||||
|
||||
bool is_superuser() const { return euid() == 0; }
|
||||
|
||||
@ -531,12 +531,12 @@ private:
|
||||
bool create_perf_events_buffer_if_needed();
|
||||
void delete_perf_events_buffer();
|
||||
|
||||
KResult do_exec(NonnullRefPtr<FileDescription> main_program_description, Vector<String> arguments, Vector<String> environment, RefPtr<FileDescription> interpreter_description, Thread*& new_main_thread, u32& prev_flags, const Elf32_Ehdr& main_program_header);
|
||||
KResult do_exec(NonnullRefPtr<FileDescription> main_program_description, Vector<String> arguments, Vector<String> environment, RefPtr<FileDescription> interpreter_description, Thread*& new_main_thread, u32& prev_flags, const ElfW(Ehdr) & main_program_header);
|
||||
KResultOr<size_t> do_write(FileDescription&, const UserOrKernelBuffer&, size_t);
|
||||
|
||||
KResultOr<int> do_statvfs(String path, statvfs* buf);
|
||||
|
||||
KResultOr<RefPtr<FileDescription>> find_elf_interpreter_for_executable(const String& path, const Elf32_Ehdr& elf_header, int nread, size_t file_size);
|
||||
KResultOr<RefPtr<FileDescription>> find_elf_interpreter_for_executable(const String& path, const ElfW(Ehdr) & elf_header, int nread, size_t file_size);
|
||||
|
||||
int alloc_fd(int first_candidate_fd = 0);
|
||||
|
||||
|
@ -187,7 +187,7 @@ static KResultOr<RequiredLoadRange> get_required_load_range(FileDescription& pro
|
||||
return range;
|
||||
};
|
||||
|
||||
static KResultOr<FlatPtr> get_load_offset(const Elf32_Ehdr& main_program_header, FileDescription& main_program_description, FileDescription* interpreter_description)
|
||||
static KResultOr<FlatPtr> get_load_offset(const ElfW(Ehdr) & main_program_header, FileDescription& main_program_description, FileDescription* interpreter_description)
|
||||
{
|
||||
constexpr FlatPtr load_range_start = 0x08000000;
|
||||
constexpr FlatPtr load_range_size = 65536 * PAGE_SIZE; // 2**16 * PAGE_SIZE = 256MB
|
||||
@ -431,7 +431,8 @@ static KResultOr<LoadResult> load_elf_object(NonnullOwnPtr<Space> new_space, Fil
|
||||
};
|
||||
}
|
||||
|
||||
KResultOr<LoadResult> Process::load(NonnullRefPtr<FileDescription> main_program_description, RefPtr<FileDescription> interpreter_description, const Elf32_Ehdr& main_program_header)
|
||||
KResultOr<LoadResult> Process::load(NonnullRefPtr<FileDescription> main_program_description,
|
||||
RefPtr<FileDescription> interpreter_description, const ElfW(Ehdr) & main_program_header)
|
||||
{
|
||||
auto new_space = Space::create(*this, nullptr);
|
||||
if (!new_space)
|
||||
@ -471,7 +472,8 @@ KResultOr<LoadResult> Process::load(NonnullRefPtr<FileDescription> main_program_
|
||||
return interpreter_load_result;
|
||||
}
|
||||
|
||||
KResult Process::do_exec(NonnullRefPtr<FileDescription> main_program_description, Vector<String> arguments, Vector<String> environment, RefPtr<FileDescription> interpreter_description, Thread*& new_main_thread, u32& prev_flags, const Elf32_Ehdr& main_program_header)
|
||||
KResult Process::do_exec(NonnullRefPtr<FileDescription> main_program_description, Vector<String> arguments, Vector<String> environment,
|
||||
RefPtr<FileDescription> interpreter_description, Thread*& new_main_thread, u32& prev_flags, const ElfW(Ehdr) & main_program_header)
|
||||
{
|
||||
VERIFY(is_user_process());
|
||||
VERIFY(!Processor::current().in_critical());
|
||||
@ -740,7 +742,7 @@ static KResultOr<Vector<String>> find_shebang_interpreter_for_executable(const c
|
||||
return ENOEXEC;
|
||||
}
|
||||
|
||||
KResultOr<RefPtr<FileDescription>> Process::find_elf_interpreter_for_executable(const String& path, const Elf32_Ehdr& main_program_header, int nread, size_t file_size)
|
||||
KResultOr<RefPtr<FileDescription>> Process::find_elf_interpreter_for_executable(const String& path, const ElfW(Ehdr) & main_program_header, int nread, size_t file_size)
|
||||
{
|
||||
// Not using KResultOr here because we'll want to do the same thing in userspace in the RTLD
|
||||
String interpreter_path;
|
||||
@ -763,7 +765,7 @@ KResultOr<RefPtr<FileDescription>> Process::find_elf_interpreter_for_executable(
|
||||
|
||||
// Validate the program interpreter as a valid elf binary.
|
||||
// If your program interpreter is a #! file or something, it's time to stop playing games :)
|
||||
if (interp_metadata.size < (int)sizeof(Elf32_Ehdr))
|
||||
if (interp_metadata.size < (int)sizeof(ElfW(Ehdr)))
|
||||
return ENOEXEC;
|
||||
|
||||
char first_page[PAGE_SIZE] = {};
|
||||
@ -773,10 +775,10 @@ KResultOr<RefPtr<FileDescription>> Process::find_elf_interpreter_for_executable(
|
||||
return ENOEXEC;
|
||||
nread = nread_or_error.value();
|
||||
|
||||
if (nread < (int)sizeof(Elf32_Ehdr))
|
||||
if (nread < (int)sizeof(ElfW(Ehdr)))
|
||||
return ENOEXEC;
|
||||
|
||||
auto elf_header = (Elf32_Ehdr*)first_page;
|
||||
auto elf_header = (ElfW(Ehdr)*)first_page;
|
||||
if (!ELF::validate_elf_header(*elf_header, interp_metadata.size)) {
|
||||
dbgln("exec({}): Interpreter ({}) has invalid ELF header", path, interpreter_description->absolute_path());
|
||||
return ENOEXEC;
|
||||
@ -862,9 +864,9 @@ KResult Process::exec(String path, Vector<String> arguments, Vector<String> envi
|
||||
|
||||
// #2) ELF32 for i386
|
||||
|
||||
if (nread_or_error.value() < (int)sizeof(Elf32_Ehdr))
|
||||
if (nread_or_error.value() < (int)sizeof(ElfW(Ehdr)))
|
||||
return ENOEXEC;
|
||||
auto main_program_header = (Elf32_Ehdr*)first_page;
|
||||
auto main_program_header = (ElfW(Ehdr)*)first_page;
|
||||
|
||||
if (!ELF::validate_elf_header(*main_program_header, metadata.size)) {
|
||||
dbgln("exec({}): File has invalid ELF header", path);
|
||||
|
@ -49,7 +49,7 @@ static bool should_make_executable_exception_for_dynamic_loader(bool make_readab
|
||||
auto& inode_vm = static_cast<const InodeVMObject&>(region.vmobject());
|
||||
auto& inode = inode_vm.inode();
|
||||
|
||||
Elf32_Ehdr header;
|
||||
ElfW(Ehdr) header;
|
||||
auto buffer = UserOrKernelBuffer::for_kernel_buffer((u8*)&header);
|
||||
auto result = inode.read_bytes(0, sizeof(header), buffer, nullptr);
|
||||
if (result.is_error() || result.value() != sizeof(header))
|
||||
|
@ -35,8 +35,8 @@ static void perform_self_relocations(auxv_t* auxvp)
|
||||
}
|
||||
}
|
||||
VERIFY(found_base_address);
|
||||
Elf32_Ehdr* header = (Elf32_Ehdr*)(base_address);
|
||||
Elf32_Phdr* pheader = (Elf32_Phdr*)(base_address + header->e_phoff);
|
||||
ElfW(Ehdr)* header = (ElfW(Ehdr)*)(base_address);
|
||||
ElfW(Phdr)* pheader = (ElfW(Phdr)*)(base_address + header->e_phoff);
|
||||
u32 dynamic_section_addr = 0;
|
||||
for (size_t i = 0; i < (size_t)header->e_phnum; ++i, ++pheader) {
|
||||
if (pheader->p_type != PT_DYNAMIC)
|
||||
|
@ -38,6 +38,12 @@
|
||||
# include <AK/Types.h>
|
||||
#endif
|
||||
|
||||
#ifdef __LP64__
|
||||
# define ElfW(type) Elf64_##type
|
||||
#else
|
||||
# define ElfW(type) Elf32_##type
|
||||
#endif
|
||||
|
||||
typedef uint8_t Elf_Byte;
|
||||
|
||||
typedef uint32_t Elf32_Addr; /* Unsigned program address */
|
||||
|
@ -45,7 +45,7 @@ Result<NonnullRefPtr<DynamicLoader>, DlErrorMessage> DynamicLoader::try_create(i
|
||||
|
||||
VERIFY(stat.st_size >= 0);
|
||||
auto size = static_cast<size_t>(stat.st_size);
|
||||
if (size < sizeof(Elf32_Ehdr))
|
||||
if (size < sizeof(ElfW(Ehdr)))
|
||||
return DlErrorMessage { String::formatted("File {} has invalid ELF header", filename) };
|
||||
|
||||
String file_mmap_name = String::formatted("ELF_DYN: {}", filename);
|
||||
@ -117,7 +117,7 @@ bool DynamicLoader::validate()
|
||||
if (!m_elf_image.is_valid())
|
||||
return false;
|
||||
|
||||
auto* elf_header = (Elf32_Ehdr*)m_file_data;
|
||||
auto* elf_header = (ElfW(Ehdr)*)m_file_data;
|
||||
if (!validate_elf_header(*elf_header, m_file_size))
|
||||
return false;
|
||||
if (!validate_program_headers(*elf_header, m_file_size, (u8*)m_file_data, m_file_size, &m_program_interpreter))
|
||||
|
@ -85,7 +85,7 @@ private:
|
||||
|
||||
class ProgramHeaderRegion {
|
||||
public:
|
||||
void set_program_header(const Elf32_Phdr& header) { m_program_header = header; }
|
||||
void set_program_header(const ElfW(Phdr) & header) { m_program_header = header; }
|
||||
|
||||
// Information from ELF Program header
|
||||
u32 type() const { return m_program_header.p_type; }
|
||||
@ -104,7 +104,7 @@ private:
|
||||
bool is_relro() const { return type() == PT_GNU_RELRO; }
|
||||
|
||||
private:
|
||||
Elf32_Phdr m_program_header; // Explicitly a copy of the PHDR in the image
|
||||
ElfW(Phdr) m_program_header; // Explicitly a copy of the PHDR in the image
|
||||
};
|
||||
|
||||
const DynamicObject& dynamic_object() const;
|
||||
|
@ -35,7 +35,7 @@ Image::~Image()
|
||||
}
|
||||
|
||||
#if ELF_IMAGE_DEBUG
|
||||
static const char* object_file_type_to_string(Elf32_Half type)
|
||||
static const char* object_file_type_to_string(ElfW(Half) type)
|
||||
{
|
||||
switch (type) {
|
||||
case ET_NONE:
|
||||
@ -139,7 +139,7 @@ unsigned Image::program_header_count() const
|
||||
|
||||
bool Image::parse()
|
||||
{
|
||||
if (m_size < sizeof(Elf32_Ehdr) || !validate_elf_header(header(), m_size, m_verbose_logging)) {
|
||||
if (m_size < sizeof(ElfW(Ehdr)) || !validate_elf_header(header(), m_size, m_verbose_logging)) {
|
||||
if (m_verbose_logging)
|
||||
dbgln("ELF::Image::parse(): ELF Header not valid");
|
||||
m_valid = false;
|
||||
@ -209,31 +209,31 @@ const char* Image::raw_data(unsigned offset) const
|
||||
return reinterpret_cast<const char*>(m_buffer) + offset;
|
||||
}
|
||||
|
||||
const Elf32_Ehdr& Image::header() const
|
||||
const ElfW(Ehdr) & Image::header() const
|
||||
{
|
||||
VERIFY(m_size >= sizeof(Elf32_Ehdr));
|
||||
return *reinterpret_cast<const Elf32_Ehdr*>(raw_data(0));
|
||||
VERIFY(m_size >= sizeof(ElfW(Ehdr)));
|
||||
return *reinterpret_cast<const ElfW(Ehdr)*>(raw_data(0));
|
||||
}
|
||||
|
||||
const Elf32_Phdr& Image::program_header_internal(unsigned index) const
|
||||
const ElfW(Phdr) & Image::program_header_internal(unsigned index) const
|
||||
{
|
||||
VERIFY(m_valid);
|
||||
VERIFY(index < header().e_phnum);
|
||||
return *reinterpret_cast<const Elf32_Phdr*>(raw_data(header().e_phoff + (index * sizeof(Elf32_Phdr))));
|
||||
return *reinterpret_cast<const ElfW(Phdr)*>(raw_data(header().e_phoff + (index * sizeof(ElfW(Phdr)))));
|
||||
}
|
||||
|
||||
const Elf32_Shdr& Image::section_header(unsigned index) const
|
||||
const ElfW(Shdr) & Image::section_header(unsigned index) const
|
||||
{
|
||||
VERIFY(m_valid);
|
||||
VERIFY(index < header().e_shnum);
|
||||
return *reinterpret_cast<const Elf32_Shdr*>(raw_data(header().e_shoff + (index * header().e_shentsize)));
|
||||
return *reinterpret_cast<const ElfW(Shdr)*>(raw_data(header().e_shoff + (index * header().e_shentsize)));
|
||||
}
|
||||
|
||||
Image::Symbol Image::symbol(unsigned index) const
|
||||
{
|
||||
VERIFY(m_valid);
|
||||
VERIFY(index < symbol_count());
|
||||
auto* raw_syms = reinterpret_cast<const Elf32_Sym*>(raw_data(section(m_symbol_table_section_index).offset()));
|
||||
auto* raw_syms = reinterpret_cast<const ElfW(Sym)*>(raw_data(section(m_symbol_table_section_index).offset()));
|
||||
return Symbol(*this, index, raw_syms[index]);
|
||||
}
|
||||
|
||||
@ -254,7 +254,7 @@ Image::ProgramHeader Image::program_header(unsigned index) const
|
||||
Image::Relocation Image::RelocationSection::relocation(unsigned index) const
|
||||
{
|
||||
VERIFY(index < relocation_count());
|
||||
auto* rels = reinterpret_cast<const Elf32_Rel*>(m_image.raw_data(offset()));
|
||||
auto* rels = reinterpret_cast<const ElfW(Rel)*>(m_image.raw_data(offset()));
|
||||
return Relocation(m_image, rels[index]);
|
||||
}
|
||||
|
||||
|
@ -40,7 +40,7 @@ public:
|
||||
|
||||
class Symbol {
|
||||
public:
|
||||
Symbol(const Image& image, unsigned index, const Elf32_Sym& sym)
|
||||
Symbol(const Image& image, unsigned index, const ElfW(Sym) & sym)
|
||||
: m_image(image)
|
||||
, m_sym(sym)
|
||||
, m_index(index)
|
||||
@ -62,7 +62,7 @@ public:
|
||||
|
||||
private:
|
||||
const Image& m_image;
|
||||
const Elf32_Sym& m_sym;
|
||||
const ElfW(Sym) & m_sym;
|
||||
const unsigned m_index;
|
||||
};
|
||||
|
||||
@ -88,11 +88,11 @@ public:
|
||||
bool is_writable() const { return flags() & PF_W; }
|
||||
bool is_executable() const { return flags() & PF_X; }
|
||||
const char* raw_data() const { return m_image.raw_data(m_program_header.p_offset); }
|
||||
Elf32_Phdr raw_header() const { return m_program_header; }
|
||||
ElfW(Phdr) raw_header() const { return m_program_header; }
|
||||
|
||||
private:
|
||||
const Image& m_image;
|
||||
const Elf32_Phdr& m_program_header;
|
||||
const ElfW(Phdr) & m_program_header;
|
||||
unsigned m_program_header_index { 0 };
|
||||
};
|
||||
|
||||
@ -123,7 +123,7 @@ public:
|
||||
protected:
|
||||
friend class RelocationSection;
|
||||
const Image& m_image;
|
||||
const Elf32_Shdr& m_section_header;
|
||||
const ElfW(Shdr) & m_section_header;
|
||||
unsigned m_section_index;
|
||||
};
|
||||
|
||||
@ -142,7 +142,7 @@ public:
|
||||
|
||||
class Relocation {
|
||||
public:
|
||||
Relocation(const Image& image, const Elf32_Rel& rel)
|
||||
Relocation(const Image& image, const ElfW(Rel) & rel)
|
||||
: m_image(image)
|
||||
, m_rel(rel)
|
||||
{
|
||||
@ -157,7 +157,7 @@ public:
|
||||
|
||||
private:
|
||||
const Image& m_image;
|
||||
const Elf32_Rel& m_rel;
|
||||
const ElfW(Rel) & m_rel;
|
||||
};
|
||||
|
||||
unsigned symbol_count() const;
|
||||
@ -207,9 +207,9 @@ public:
|
||||
|
||||
private:
|
||||
const char* raw_data(unsigned offset) const;
|
||||
const Elf32_Ehdr& header() const;
|
||||
const Elf32_Shdr& section_header(unsigned) const;
|
||||
const Elf32_Phdr& program_header_internal(unsigned) const;
|
||||
const ElfW(Ehdr) & header() const;
|
||||
const ElfW(Shdr) & section_header(unsigned) const;
|
||||
const ElfW(Phdr) & program_header_internal(unsigned) const;
|
||||
StringView table_string(unsigned offset) const;
|
||||
StringView section_header_table_string(unsigned offset) const;
|
||||
StringView section_index_to_string(unsigned index) const;
|
||||
|
@ -14,7 +14,7 @@
|
||||
|
||||
namespace ELF {
|
||||
|
||||
bool validate_elf_header(const Elf32_Ehdr& elf_header, size_t file_size, bool verbose)
|
||||
bool validate_elf_header(const ElfW(Ehdr) & elf_header, size_t file_size, bool verbose)
|
||||
{
|
||||
if (!IS_ELF(elf_header)) {
|
||||
if (verbose)
|
||||
@ -22,9 +22,16 @@ bool validate_elf_header(const Elf32_Ehdr& elf_header, size_t file_size, bool ve
|
||||
return false;
|
||||
}
|
||||
|
||||
if (ELFCLASS32 != elf_header.e_ident[EI_CLASS]) {
|
||||
#if ARCH(I386)
|
||||
auto expected_class = ELFCLASS32;
|
||||
auto expected_bitness = 32;
|
||||
#else
|
||||
auto expected_class = ELFCLASS64;
|
||||
auto expected_bitness = 64;
|
||||
#endif
|
||||
if (expected_class != elf_header.e_ident[EI_CLASS]) {
|
||||
if (verbose)
|
||||
dbgln("File is not a 32 bit ELF file.");
|
||||
dbgln("File is not a {}-bit ELF file.", expected_bitness);
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -52,9 +59,17 @@ bool validate_elf_header(const Elf32_Ehdr& elf_header, size_t file_size, bool ve
|
||||
return false;
|
||||
}
|
||||
|
||||
if (EM_386 != elf_header.e_machine) {
|
||||
#if ARCH(I386)
|
||||
auto expected_machine = EM_386;
|
||||
auto expected_machine_name = "i386";
|
||||
#else
|
||||
auto expected_machine = EM_X86_64;
|
||||
auto expected_machine_name = "x86-64";
|
||||
#endif
|
||||
|
||||
if (expected_machine != elf_header.e_machine) {
|
||||
if (verbose)
|
||||
dbgln("File has unknown machine ({}), expected i386 (3)!", elf_header.e_machine);
|
||||
dbgln("File has unknown machine ({}), expected {} ({})!", elf_header.e_machine, expected_machine_name, expected_machine);
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -70,9 +85,9 @@ bool validate_elf_header(const Elf32_Ehdr& elf_header, size_t file_size, bool ve
|
||||
return false;
|
||||
}
|
||||
|
||||
if (sizeof(Elf32_Ehdr) != elf_header.e_ehsize) {
|
||||
if (sizeof(ElfW(Ehdr)) != elf_header.e_ehsize) {
|
||||
if (verbose)
|
||||
dbgln("File has incorrect ELF header size..? ({}), expected ({})!", elf_header.e_ehsize, sizeof(Elf32_Ehdr));
|
||||
dbgln("File has incorrect ELF header size..? ({}), expected ({})!", elf_header.e_ehsize, sizeof(ElfW(Ehdr)));
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -112,15 +127,15 @@ bool validate_elf_header(const Elf32_Ehdr& elf_header, size_t file_size, bool ve
|
||||
return false;
|
||||
}
|
||||
|
||||
if (0 != elf_header.e_phnum && sizeof(Elf32_Phdr) != elf_header.e_phentsize) {
|
||||
if (0 != elf_header.e_phnum && sizeof(ElfW(Phdr)) != elf_header.e_phentsize) {
|
||||
if (verbose)
|
||||
dbgln("File has incorrect program header size..? ({}), expected ({}).", elf_header.e_phentsize, sizeof(Elf32_Phdr));
|
||||
dbgln("File has incorrect program header size..? ({}), expected ({}).", elf_header.e_phentsize, sizeof(ElfW(Phdr)));
|
||||
return false;
|
||||
}
|
||||
|
||||
if (sizeof(Elf32_Shdr) != elf_header.e_shentsize) {
|
||||
if (sizeof(ElfW(Shdr)) != elf_header.e_shentsize) {
|
||||
if (verbose)
|
||||
dbgln("File has incorrect section header size..? ({}), expected ({}).", elf_header.e_shentsize, sizeof(Elf32_Shdr));
|
||||
dbgln("File has incorrect section header size..? ({}), expected ({}).", elf_header.e_shentsize, sizeof(ElfW(Shdr)));
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -177,7 +192,7 @@ bool validate_elf_header(const Elf32_Ehdr& elf_header, size_t file_size, bool ve
|
||||
return true;
|
||||
}
|
||||
|
||||
bool validate_program_headers(const Elf32_Ehdr& elf_header, size_t file_size, const u8* buffer, size_t buffer_size, String* interpreter_path, bool verbose)
|
||||
bool validate_program_headers(const ElfW(Ehdr) & elf_header, size_t file_size, const u8* buffer, size_t buffer_size, String* interpreter_path, bool verbose)
|
||||
{
|
||||
Checked<size_t> total_size_of_program_headers = elf_header.e_phnum;
|
||||
total_size_of_program_headers *= elf_header.e_phentsize;
|
||||
@ -204,7 +219,7 @@ bool validate_program_headers(const Elf32_Ehdr& elf_header, size_t file_size, co
|
||||
}
|
||||
|
||||
size_t num_program_headers = elf_header.e_phnum;
|
||||
auto program_header_begin = (const Elf32_Phdr*)&(buffer[elf_header.e_phoff]);
|
||||
auto program_header_begin = (const ElfW(Phdr)*)&(buffer[elf_header.e_phoff]);
|
||||
|
||||
for (size_t header_index = 0; header_index < num_program_headers; ++header_index) {
|
||||
auto& program_header = program_header_begin[header_index];
|
||||
@ -221,10 +236,18 @@ bool validate_program_headers(const Elf32_Ehdr& elf_header, size_t file_size, co
|
||||
return false;
|
||||
}
|
||||
|
||||
if (program_header.p_type == PT_LOAD && program_header.p_align != PAGE_SIZE) {
|
||||
if (program_header.p_type == PT_LOAD && program_header.p_align % (size_t)PAGE_SIZE != 0) {
|
||||
if (elf_header.e_type != ET_CORE) {
|
||||
if (verbose)
|
||||
dbgln("Program header ({}) with p_type PT_LOAD has p_align ({}) not equal to page size ({})", header_index, program_header.p_align, PAGE_SIZE);
|
||||
dbgln("Program header ({}) with p_type PT_LOAD has p_align ({}) not divisible by page size ({})", header_index, program_header.p_align, PAGE_SIZE);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if (program_header.p_type == PT_LOAD && program_header.p_vaddr % program_header.p_align != program_header.p_offset % program_header.p_align) {
|
||||
if (elf_header.e_type != ET_CORE) {
|
||||
if (verbose)
|
||||
dbgln("Program header ({}) with p_type PT_LOAD has mis-aligned p_vaddr ({:x})", header_index, program_header.p_vaddr);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
@ -11,7 +11,7 @@
|
||||
|
||||
namespace ELF {
|
||||
|
||||
bool validate_elf_header(const Elf32_Ehdr& elf_header, size_t file_size, bool verbose = true);
|
||||
bool validate_program_headers(const Elf32_Ehdr& elf_header, size_t file_size, const u8* buffer, size_t buffer_size, String* interpreter_path, bool verbose = true);
|
||||
bool validate_elf_header(const ElfW(Ehdr) & elf_header, size_t file_size, bool verbose = true);
|
||||
bool validate_program_headers(const ElfW(Ehdr) & elf_header, size_t file_size, const u8* buffer, size_t buffer_size, String* interpreter_path, bool verbose = true);
|
||||
|
||||
} // end namespace ELF
|
||||
|
@ -19,7 +19,7 @@
|
||||
#include <stdio.h>
|
||||
#include <unistd.h>
|
||||
|
||||
static const char* object_file_type_to_string(Elf32_Half type)
|
||||
static const char* object_file_type_to_string(ElfW(Half) type)
|
||||
{
|
||||
switch (type) {
|
||||
case ET_NONE:
|
||||
@ -37,7 +37,7 @@ static const char* object_file_type_to_string(Elf32_Half type)
|
||||
}
|
||||
}
|
||||
|
||||
static const char* object_machine_type_to_string(Elf32_Half type)
|
||||
static const char* object_machine_type_to_string(ElfW(Half) type)
|
||||
{
|
||||
switch (type) {
|
||||
case ET_NONE:
|
||||
@ -63,7 +63,7 @@ static const char* object_machine_type_to_string(Elf32_Half type)
|
||||
}
|
||||
}
|
||||
|
||||
static const char* object_program_header_type_to_string(Elf32_Word type)
|
||||
static const char* object_program_header_type_to_string(ElfW(Word) type)
|
||||
{
|
||||
switch (type) {
|
||||
case PT_NULL:
|
||||
@ -107,7 +107,7 @@ static const char* object_program_header_type_to_string(Elf32_Word type)
|
||||
}
|
||||
}
|
||||
|
||||
static const char* object_section_header_type_to_string(Elf32_Word type)
|
||||
static const char* object_section_header_type_to_string(ElfW(Word) type)
|
||||
{
|
||||
switch (type) {
|
||||
case SHT_NULL:
|
||||
@ -177,7 +177,7 @@ static const char* object_section_header_type_to_string(Elf32_Word type)
|
||||
}
|
||||
}
|
||||
|
||||
static const char* object_symbol_type_to_string(Elf32_Word type)
|
||||
static const char* object_symbol_type_to_string(ElfW(Word) type)
|
||||
{
|
||||
switch (type) {
|
||||
case STT_NOTYPE:
|
||||
@ -201,7 +201,7 @@ static const char* object_symbol_type_to_string(Elf32_Word type)
|
||||
}
|
||||
}
|
||||
|
||||
static const char* object_symbol_binding_to_string(Elf32_Word type)
|
||||
static const char* object_symbol_binding_to_string(ElfW(Word) type)
|
||||
{
|
||||
switch (type) {
|
||||
case STB_LOCAL:
|
||||
@ -221,7 +221,7 @@ static const char* object_symbol_binding_to_string(Elf32_Word type)
|
||||
}
|
||||
}
|
||||
|
||||
static const char* object_relocation_type_to_string(Elf32_Word type)
|
||||
static const char* object_relocation_type_to_string(ElfW(Word) type)
|
||||
{
|
||||
switch (type) {
|
||||
case R_386_NONE:
|
||||
@ -251,7 +251,7 @@ static const char* object_relocation_type_to_string(Elf32_Word type)
|
||||
}
|
||||
}
|
||||
|
||||
static const char* object_tag_to_string(Elf32_Sword dt_tag)
|
||||
static const char* object_tag_to_string(ElfW(Sword) dt_tag)
|
||||
{
|
||||
switch (dt_tag) {
|
||||
case DT_NULL:
|
||||
@ -419,12 +419,12 @@ int main(int argc, char** argv)
|
||||
|
||||
String interpreter_path;
|
||||
|
||||
if (!ELF::validate_program_headers(*(const Elf32_Ehdr*)elf_image_data.data(), elf_image_data.size(), (const u8*)elf_image_data.data(), elf_image_data.size(), &interpreter_path)) {
|
||||
if (!ELF::validate_program_headers(*(const ElfW(Ehdr)*)elf_image_data.data(), elf_image_data.size(), (const u8*)elf_image_data.data(), elf_image_data.size(), &interpreter_path)) {
|
||||
warnln("Invalid ELF headers");
|
||||
return -1;
|
||||
}
|
||||
|
||||
auto& header = *reinterpret_cast<const Elf32_Ehdr*>(elf_image_data.data());
|
||||
auto& header = *reinterpret_cast<const ElfW(Ehdr)*>(elf_image_data.data());
|
||||
|
||||
RefPtr<ELF::DynamicObject> object = nullptr;
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user