Skip to content

Commit

Permalink
Kernel ASLR
Browse files Browse the repository at this point in the history
  • Loading branch information
djphoenix committed May 23, 2019
1 parent bcb17c1 commit 25b35cd
Show file tree
Hide file tree
Showing 6 changed files with 140 additions and 43 deletions.
1 change: 0 additions & 1 deletion src/boot/bootstrap.s
Expand Up @@ -217,7 +217,6 @@ x64_entry:
call _ZN3SMP4initEv
call _ZN13ModuleManager4initEv
call _ZN7Syscall5setupEv
mov %rsp, %rbp
jmp _ZN14ProcessManager12process_loopEv

reloc_vtables:
Expand Down
5 changes: 2 additions & 3 deletions src/boot/efiboot.cpp
Expand Up @@ -9,14 +9,14 @@ namespace EFI {
const void *ImageHandle = nullptr;
const void *acpi1 = nullptr, *acpi2 = nullptr;
void load();
Framebuffer fb, *fbPtr = nullptr;
Framebuffer fb;
}
const struct EFI::SystemTable *EFI::getSystemTable() { load(); return SystemTable; }
const void *EFI::getImageHandle() { return ImageHandle; }

const void *EFI::getACPI1Addr() { return acpi1; }
const void *EFI::getACPI2Addr() { return acpi2; }
const struct EFI::Framebuffer *EFI::getFramebuffer() { return fbPtr; }
const struct EFI::Framebuffer *EFI::getFramebuffer() { return fb.base ? &fb : nullptr; }

void EFI::load() {
static bool loaded = false;
Expand All @@ -38,7 +38,6 @@ void EFI::load() {
fb.width = graphics_output->Mode->Info->HorizontalResolution;
fb.height = graphics_output->Mode->Info->VerticalResolution;
fb.pixelFormat = graphics_output->Mode->Info->PixelFormat;
fbPtr = &fb;
}
loaded = true;
}
1 change: 0 additions & 1 deletion src/platform/include/pagetable.hpp
Expand Up @@ -59,7 +59,6 @@ class Pagetable {
} PACKED;

private:
static Entry *pagetable;
static Mutex page_mutex;
static uint64_t last_page;
static void* _alloc(uint8_t avl = 0, bool nolow = false);
Expand Down
6 changes: 3 additions & 3 deletions src/platform/interrupts.cpp
Expand Up @@ -312,7 +312,7 @@ void Interrupts::init() {
ent->iomap_base = sizeof(TSS64_ENT);

gdt->sys_ents[idx] = GDT::SystemEntry(
uintptr_t(tss[idx]), sizeof(TSS64_ENT) + 0x2000,
uintptr_t(tss[idx]), sizeof(TSS64_ENT) + 0x2000 - 1,
0x9, 0, 0, 1, 0, 1, 0, 0);
}

Expand All @@ -326,14 +326,14 @@ void Interrupts::init() {
"pushq $8;"
"lea 1f(%%rip), %%rcx;"
"pushq %%rcx;"
"lgdtq (%q0);"
"lgdtq %0;"
"iretq;"
"1:"
"mov %%ss, %%ax;"
"mov %%ax, %%ds;"
"mov %%ax, %%es;"
"mov %%ax, %%gs;"
::"r"(&gdtreg):"rax", "rcx");
::"m"(gdtreg):"rax", "rcx");

uintptr_t addr;
char *lapic_eoi =
Expand Down
161 changes: 130 additions & 31 deletions src/platform/pagetable.cpp
Expand Up @@ -8,7 +8,6 @@

using PTE = Pagetable::Entry;

PTE *Pagetable::pagetable;
Mutex Pagetable::page_mutex;
uintptr_t Pagetable::last_page = 1;

Expand Down Expand Up @@ -76,21 +75,74 @@ static void efiMapPage(PTE *pagetable, const void *page,
*pml4e = PTE(page, flags);
}

void Pagetable::init() {
static const size_t stack_size = 0x1000;
static void fillPagesEfi(uintptr_t low, uintptr_t top, PTE *pagetable,
const struct EFI::SystemTable *ST, uint8_t flags = 3) {
low &= 0xFFFFFFFFFFFFF000;
top = klib::__align(top, 0x1000);
for (; low < top; low += 0x1000) {
printf("SET: %#lx %d\n", low, flags);
efiMapPage(pagetable, reinterpret_cast<void*>(low), ST, flags);
}
}

static inline void fillPagesEfi(const void *low, const void *top, PTE *pagetable,
const struct EFI::SystemTable *ST, uint8_t flags = 3) {
fillPagesEfi(uintptr_t(low), uintptr_t(top), pagetable, ST, flags);
}

static inline __attribute__((always_inline)) void newkern_reloc(uintptr_t kernbase) {
const char *__text_start__, *__bss_end__;
asm volatile(
"lea __text_start__(%%rip), %q0;"
"lea __bss_end__(%%rip), %q1;"
:"=r"(__text_start__), "=r"(__bss_end__));
uintptr_t *__VTABLE_START__, *__VTABLE_END__;
asm volatile(
"lea __VTABLE_START__(%%rip), %q0;"
"lea __VTABLE_END__(%%rip), %q1;"
:"=r"(__VTABLE_START__), "=r"(__VTABLE_END__));

ptrdiff_t kernreloc = ptrdiff_t(kernbase) - ptrdiff_t(__text_start__);
for (uintptr_t *p = __VTABLE_START__; p < __VTABLE_END__; p++) {
if (*p < uintptr_t(__text_start__)) continue;
if (*p > uintptr_t(__bss_end__)) continue;
uintptr_t *np = p + kernreloc / 8;
*np = (*p + uintptr_t(kernreloc));
}
}

extern const char __stack_end__[];
const char *__stack_start__ = __stack_end__ - stack_size;
static inline __attribute__((always_inline)) void newkern_relocstack(ptrdiff_t kernreloc) {
struct stackframe {
struct stackframe* rbp;
uintptr_t rip;
} __attribute__((packed));
struct stackframe *frame;
asm volatile("mov %%rbp, %q0":"=r"(frame)::);
while (frame != nullptr) {
frame->rip += uintptr_t(kernreloc);
frame = frame->rbp;
}
}

static inline __attribute__((always_inline)) void newkern_reinit() {
uintptr_t *__CTOR_LIST__; asm volatile("leaq __CTOR_LIST__(%%rip), %q0":"=r"(__CTOR_LIST__));
for (uintptr_t *p = __CTOR_LIST__ + 1; *p != 0; p++) {
void (*func)(void) = reinterpret_cast<void(*)(void)>(*p);
func();
}
}

void Pagetable::init() {
extern const char __text_start__[], __text_end__[];
extern const char __modules_start__[], __modules_end__[];
extern const char __data_start__[], __data_end__[];
extern const char __bss_start__[], __bss_end__[];

const size_t kernsz = size_t(__bss_end__ - __text_start__);

const struct EFI::SystemTable *ST = EFI::getSystemTable();
Multiboot::Payload *multiboot = Multiboot::getPayload();

asm volatile("mov %%cr3, %q0":"=r"(pagetable));

// Initialization of pagetables

if (ST) {
Expand All @@ -99,33 +151,59 @@ void Pagetable::init() {
EFI::getImageHandle(), &EFI::GUID_LoadedImageProtocol,
reinterpret_cast<void**>(&loaded_image));

uintptr_t ptbase = RAND::get<uintptr_t>(0x800, 0x10000) << 12;
uintptr_t ptbase = RAND::get<uintptr_t>(0x800, 0x8000) << 12;

char *base; asm volatile("lea __text_start__(%%rip), %q0":"=r"(base));

pagetable = static_cast<PTE*>(efiAllocatePage(ptbase, ST));
PTE *pagetable = static_cast<PTE*>(efiAllocatePage(ptbase, ST));
efiMapPage(pagetable, nullptr, ST, 0);
efiMapPage(pagetable, pagetable, ST);

size_t mapSize = 0, entSize = 0;
uint64_t mapKey = 0;
uint32_t entVer = 0;
EFI::MemoryDescriptor *map = nullptr, *ent;

EFI::MemoryDescriptor *map = nullptr;
ST->BootServices->GetMemoryMap(&mapSize, map, &mapKey, &entSize, &entVer);
map = static_cast<EFI::MemoryDescriptor*>(alloca(mapSize));
ST->BootServices->GetMemoryMap(&mapSize, map, &mapKey, &entSize, &entVer);
for (ent = map;
ent < reinterpret_cast<EFI::MemoryDescriptor*>(uintptr_t(map) + mapSize);
ent = reinterpret_cast<EFI::MemoryDescriptor*>(uintptr_t(ent) + entSize)) {
if (ent->Type == EFI::MEMORY_TYPE_CONVENTIONAL) continue;
for (uintptr_t ptr = ent->PhysicalStart;
ptr < ent->PhysicalStart + ent->NumberOfPages * 0x1000;
ptr += 0x1000) {
efiMapPage(pagetable, reinterpret_cast<void*>(ptr), ST);
}
}

const char *rsp; asm volatile("mov %%rsp, %q0":"=r"(rsp));
efiMapPage(pagetable, rsp, ST);
efiMapPage(pagetable, rsp - 0x1000, ST);

void *newbase = reinterpret_cast<void*>(RAND::get<uintptr_t>(0x8000, 0x10000 - ((kernsz + 0xFFF) / 0x1000)) << 12);
ST->BootServices->AllocatePages(EFI::ALLOCATE_TYPE_ADDR, EFI::MEMORY_TYPE_LOADER,
(kernsz + 0xFFF) >> 12, &newbase);
printf("New base: %p => %p\n", base, newbase);

ptrdiff_t kernreloc = ptrdiff_t(newbase) - ptrdiff_t(__text_start__);
Memory::copy(newbase, base, kernsz);

newkern_reloc(uintptr_t(newbase));

fillPagesEfi(__text_start__ + kernreloc, __text_end__ + kernreloc, pagetable, ST, 3);
fillPagesEfi(__modules_start__ + kernreloc, __modules_end__ + kernreloc, pagetable, ST, 1);
fillPagesEfi(__data_start__ + kernreloc, __data_end__ + kernreloc, pagetable, ST);
fillPagesEfi(__bss_start__ + kernreloc, __bss_end__ + kernreloc, pagetable, ST);

DTREG gdtreg = { 0, nullptr };
asm volatile("sgdtq (%q0)"::"r"(&gdtreg));
efiMapPage(pagetable, gdtreg.addr, ST);

ST->BootServices->ExitBootServices(EFI::getImageHandle(), mapKey);
asm volatile("mov %q0, %%cr3"::"r"(pagetable));

asm volatile(
"movq %q1, %%rax;"
"addq $1f, %%rax;"
"jmpq *%%rax;1:"
"mov %q0, %%cr3;"
::"r"(pagetable), "r"(kernreloc) : "rax");

kernreloc = reinterpret_cast<char*>(newbase) - base;
newkern_relocstack(kernreloc);
newkern_reinit();
} else {
PTE *pagetable; asm volatile("mov %%cr3, %q0":"=r"(pagetable));
PTE::find(nullptr, pagetable)->present = 0;
fillPages(0x1000, 0x3FFFF000, pagetable);

Expand All @@ -150,20 +228,38 @@ void Pagetable::init() {
fillPages(0x0C8000, 0x0F0000, newpt); // Reserved for many systems
fillPages(0x0F0000, 0x100000, newpt); // BIOS Code

fillPages(__stack_start__, __stack_end__, newpt); // PXOS Stack
fillPages(__text_start__, __text_end__, newpt, 1); // PXOS Code
fillPages(__modules_start__, __modules_end__, newpt, 1); // PXOS Built-in modules
fillPages(__data_start__, __data_end__, newpt); // PXOS Data
fillPages(__bss_start__, __bss_end__, newpt); // PXOS BSS
static const size_t stack_size = 0x1000;
extern const char __stack_end__[];
const char *__stack_start__ = __stack_end__ - stack_size;
fillPages(__stack_start__, __stack_end__, newpt);

uintptr_t kernbase = RAND::get<uintptr_t>(
((ptbase + (3 + pdpe_num)) >> 12),
0x8000 - (kernsz + 0xFFF) / 0x1000) << 12;

ptrdiff_t kernreloc = ptrdiff_t(kernbase) - ptrdiff_t(__text_start__);
Memory::copy(reinterpret_cast<char*>(kernbase), __text_start__, kernsz);

newkern_reloc(kernbase);

fillPages(__text_start__ + kernreloc, __text_end__ + kernreloc, newpt, 3);
fillPages(__modules_start__ + kernreloc, __modules_end__ + kernreloc, newpt, 1);
fillPages(__data_start__ + kernreloc, __data_end__ + kernreloc, newpt);
fillPages(__bss_start__ + kernreloc, __bss_end__ + kernreloc, newpt);

if (multiboot)
*PTE::find(multiboot, newpt) = PTE { multiboot, 3 };
asm volatile(
"movq %q1, %%rax;"
"addq $1f, %%rax;"
"jmpq *%%rax;1:"
"mov %q0, %%cr3;"
::"r"(newpt), "r"(kernreloc) : "rax");

pagetable = newpt;
asm volatile("mov %q0, %%cr3"::"r"(pagetable));
newkern_relocstack(kernreloc);
newkern_reinit();
}

if (multiboot) {
map(multiboot);
if (multiboot->flags & Multiboot::MB_FLAG_CMDLINE) {
if (multiboot->pcmdline < 0x80000)
multiboot->pcmdline += uintptr_t(__bss_end__);
Expand Down Expand Up @@ -215,6 +311,7 @@ void Pagetable::init() {
}

void* Pagetable::map(const void* mem) {
PTE *pagetable; asm volatile("mov %%cr3, %q0":"=r"(pagetable));
uint64_t t = EnterCritical();
page_mutex.lock();
uintptr_t i = uintptr_t(mem) >> 12;
Expand All @@ -241,6 +338,7 @@ void* Pagetable::map(const void* mem) {
}

void* Pagetable::_alloc(uint8_t avl, bool nolow) {
PTE *pagetable; asm volatile("mov %%cr3, %q0":"=r"(pagetable));
start:
void *addr = nullptr;
PTE *page;
Expand Down Expand Up @@ -290,6 +388,7 @@ void* Pagetable::alloc(uint8_t avl) {
}

void Pagetable::free(void* page) {
PTE *pagetable; asm volatile("mov %%cr3, %q0":"=r"(pagetable));
uint64_t t = EnterCritical();
page_mutex.lock();
PTE *pdata = PTE::find(page, pagetable);
Expand Down
9 changes: 5 additions & 4 deletions src/process/process.cpp
Expand Up @@ -290,18 +290,19 @@ void Process::startup() {
while (gdt_ent < gdt_top) {
uintptr_t base = gdt_ent->getBase();
size_t limit = gdt_ent->getLimit();
if (((gdt_ent->type != 0x9) && (gdt_ent->type != 0xB)) || (limit != sizeof(TSS64_ENT) + 0x2000)) {
if (((gdt_ent->type != 0x9) && (gdt_ent->type != 0xB)) || (limit != sizeof(TSS64_ENT) + 0x2000 - 1)) {
gdt_ent++;
continue;
}

GDT::SystemEntry *sysent = reinterpret_cast<GDT::SystemEntry*>(gdt_ent);
base = sysent->getBase();

uintptr_t page = base & KB4;
addPage(page, reinterpret_cast<void*>(page), 5);
addPage(page + 0x1000, iomap[0], 5);
addPage(page + 0x2000, iomap[1], 5);

GDT::SystemEntry *sysent = reinterpret_cast<GDT::SystemEntry*>(gdt_ent);
base = sysent->getBase();

TSS64_ENT *tss = reinterpret_cast<TSS64_ENT*>(base);
uintptr_t stack = tss->ist[0];
page = stack - 0x1000;
Expand Down

0 comments on commit 25b35cd

Please sign in to comment.