1
Fork 0
mirror of https://github.com/RGBCube/serenity synced 2025-07-27 16:37:47 +00:00

Kernel+LibELF: Add support for validating and loading ELF64 executables

This commit is contained in:
Gunnar Beutner 2021-06-28 17:24:08 +02:00 committed by Andreas Kling
parent e35b060501
commit 158355e0d7
13 changed files with 109 additions and 78 deletions

View file

@ -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*>(&notes_pheader)), sizeof(Elf32_Phdr));
auto result = m_fd->write(UserOrKernelBuffer::for_kernel_buffer(reinterpret_cast<uint8_t*>(&notes_pheader)), sizeof(ElfW(Phdr)));
if (result.is_error())
return result.error();
return KSuccess;

View file

@ -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);

View file

@ -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);

View file

@ -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))