mirror of
https://github.com/RGBCube/serenity
synced 2025-07-27 15:37:46 +00:00
Kernel+LibELF: Validate PT_LOAD and PT_TLS offsets before memcpy()'ing
Before this, you could make the kernel copy memory from anywhere by setting up an ELF executable with a program header specifying file offsets outside the file. Since ELFImage didn't even know how large it was, we had no clue that we were copying things from outside the ELF. Fix this by adding a size field to ELFImage and validating program header ranges before memcpy()'ing to them. The ELF code is definitely going to need more validation and checking.
This commit is contained in:
parent
9bf1fe9439
commit
78a63930cc
6 changed files with 37 additions and 9 deletions
|
@ -56,7 +56,7 @@ void* ELFDynamicLoader::symbol_for_name(const char* name)
|
|||
|
||||
bool ELFDynamicLoader::load_from_image(unsigned flags)
|
||||
{
|
||||
ELFImage elf_image((u8*)m_file_mapping);
|
||||
ELFImage elf_image((u8*)m_file_mapping, m_file_size);
|
||||
|
||||
m_valid = elf_image.is_valid() && elf_image.is_dynamic();
|
||||
|
||||
|
|
|
@ -2,8 +2,9 @@
|
|||
#include <AK/kstdio.h>
|
||||
#include <LibELF/ELFImage.h>
|
||||
|
||||
ELFImage::ELFImage(const u8* buffer)
|
||||
ELFImage::ELFImage(const u8* buffer, size_t size)
|
||||
: m_buffer(buffer)
|
||||
, m_size(size)
|
||||
{
|
||||
m_valid = parse();
|
||||
}
|
||||
|
@ -59,6 +60,8 @@ void ELFImage::dump() const
|
|||
dbgprintf(" entry: %x\n", header().e_entry);
|
||||
dbgprintf(" shoff: %u\n", header().e_shoff);
|
||||
dbgprintf(" shnum: %u\n", header().e_shnum);
|
||||
dbgprintf(" phoff: %u\n", header().e_phoff);
|
||||
dbgprintf(" phnum: %u\n", header().e_phnum);
|
||||
dbgprintf(" shstrndx: %u\n", header().e_shstrndx);
|
||||
|
||||
for (unsigned i = 0; i < header().e_shnum; ++i) {
|
||||
|
|
|
@ -8,12 +8,21 @@
|
|||
|
||||
class ELFImage {
|
||||
public:
|
||||
explicit ELFImage(const u8*);
|
||||
explicit ELFImage(const u8*, size_t);
|
||||
~ELFImage();
|
||||
void dump() const;
|
||||
bool is_valid() const { return m_valid; }
|
||||
bool parse();
|
||||
|
||||
bool is_within_image(const void* address, size_t size)
|
||||
{
|
||||
if (address < m_buffer)
|
||||
return false;
|
||||
if (((const u8*)address + size) > m_buffer + m_size)
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
class Section;
|
||||
class RelocationSection;
|
||||
class Symbol;
|
||||
|
@ -190,6 +199,7 @@ private:
|
|||
const char* section_index_to_string(unsigned index) const;
|
||||
|
||||
const u8* m_buffer { nullptr };
|
||||
size_t m_size { 0 };
|
||||
HashMap<String, unsigned> m_sections;
|
||||
bool m_valid { false };
|
||||
unsigned m_symbol_table_section_index { 0 };
|
||||
|
|
|
@ -9,8 +9,8 @@
|
|||
|
||||
//#define ELFLOADER_DEBUG
|
||||
|
||||
ELFLoader::ELFLoader(const u8* buffer)
|
||||
: m_image(buffer)
|
||||
ELFLoader::ELFLoader(const u8* buffer, size_t size)
|
||||
: m_image(buffer, size)
|
||||
{
|
||||
}
|
||||
|
||||
|
@ -43,6 +43,11 @@ bool ELFLoader::layout()
|
|||
failed = true;
|
||||
return;
|
||||
}
|
||||
if (!m_image.is_within_image(program_header.raw_data(), program_header.size_in_image())) {
|
||||
dbg() << "Shenanigans! ELF PT_TLS header sneaks outside of executable.";
|
||||
failed = true;
|
||||
return;
|
||||
}
|
||||
memcpy(tls_image, program_header.raw_data(), program_header.size_in_image());
|
||||
#endif
|
||||
return;
|
||||
|
@ -65,6 +70,11 @@ bool ELFLoader::layout()
|
|||
failed = true;
|
||||
return;
|
||||
}
|
||||
if (!m_image.is_within_image(program_header.raw_data(), program_header.size_in_image())) {
|
||||
dbg() << "Shenanigans! Writable ELF PT_LOAD header sneaks outside of executable.";
|
||||
failed = true;
|
||||
return;
|
||||
}
|
||||
memcpy(program_header.vaddr().as_ptr(), program_header.raw_data(), program_header.size_in_image());
|
||||
} else {
|
||||
auto* mapped_section = map_section_hook(
|
||||
|
|
|
@ -13,7 +13,7 @@ class Region;
|
|||
|
||||
class ELFLoader {
|
||||
public:
|
||||
explicit ELFLoader(const u8*);
|
||||
explicit ELFLoader(const u8*, size_t);
|
||||
~ELFLoader();
|
||||
|
||||
bool load();
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue