
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.
61 lines
1.5 KiB
C++
61 lines
1.5 KiB
C++
#pragma once
|
|
|
|
#include <AK/Function.h>
|
|
#include <AK/HashMap.h>
|
|
#include <AK/OwnPtr.h>
|
|
#include <AK/Vector.h>
|
|
#include <LibELF/ELFImage.h>
|
|
|
|
#ifdef KERNEL
|
|
#include <Kernel/VM/VirtualAddress.h>
|
|
class Region;
|
|
#endif
|
|
|
|
class ELFLoader {
|
|
public:
|
|
explicit ELFLoader(const u8*, size_t);
|
|
~ELFLoader();
|
|
|
|
bool load();
|
|
#if defined(KERNEL)
|
|
Function<void*(VirtualAddress, size_t, size_t, bool, bool, const String&)> alloc_section_hook;
|
|
Function<void*(size_t, size_t)> tls_section_hook;
|
|
Function<void*(VirtualAddress, size_t, size_t, size_t, bool r, bool w, bool x, const String&)> map_section_hook;
|
|
VirtualAddress entry() const { return m_image.entry(); }
|
|
#endif
|
|
char* symbol_ptr(const char* name);
|
|
|
|
bool has_symbols() const { return m_image.symbol_count(); }
|
|
|
|
String symbolicate(u32 address, u32* offset = nullptr) const;
|
|
|
|
private:
|
|
bool layout();
|
|
bool perform_relocations();
|
|
void* lookup(const ELFImage::Symbol&);
|
|
char* area_for_section(const ELFImage::Section&);
|
|
char* area_for_section_name(const char*);
|
|
|
|
struct PtrAndSize {
|
|
PtrAndSize() {}
|
|
PtrAndSize(char* p, unsigned s)
|
|
: ptr(p)
|
|
, size(s)
|
|
{
|
|
}
|
|
|
|
char* ptr { nullptr };
|
|
unsigned size { 0 };
|
|
};
|
|
ELFImage m_image;
|
|
|
|
struct SortedSymbol {
|
|
u32 address;
|
|
const char* name;
|
|
};
|
|
#ifdef KERNEL
|
|
mutable OwnPtr<Region> m_sorted_symbols_region;
|
|
#else
|
|
mutable Vector<SortedSymbol> m_sorted_symbols;
|
|
#endif
|
|
};
|