Merge pull request #1259 from Kijewski/x86-heap-check
x86: add read-before-write check at runtime
This commit is contained in:
commit
fde1c106ab
@ -107,6 +107,10 @@ typedef uint64_t pae_page_table_t[512] __attribute__((aligned(0x1000)));
|
||||
#define PT_XD (1ull << 63) /**< 1 = no execute */
|
||||
#define PT_ADDR_MASK (((1ull << 48) - 1) & ~((1ull << 12) - 1))
|
||||
|
||||
#ifdef DEBUG_READ_BEFORE_WRITE
|
||||
# define PT_HEAP_BIT PT_USR9
|
||||
#endif
|
||||
|
||||
#define PF_EC_P (1u << 0) /**< 1 = page protection violation; 0 = page not present */
|
||||
#define PF_EC_W (1u << 1) /**< 1 = accessed writingly; 0 = readingly */
|
||||
#define PF_EC_U (1u << 2) /**< 1 = ring 3 */
|
||||
|
||||
@ -46,7 +46,12 @@
|
||||
#define PT_CR3_BITS (0)
|
||||
#define PT_PDPT_BITS (PT_P)
|
||||
#define PT_PD_BITS (PT_P | PT_RW | PT_US)
|
||||
#define PT_HEAP_BITS (PT_P | PT_RW | PT_US | pt_xd)
|
||||
|
||||
#ifndef DEBUG_READ_BEFORE_WRITE
|
||||
# define PT_HEAP_BITS (PT_P | PT_RW | PT_US | pt_xd)
|
||||
#else
|
||||
# define PT_HEAP_BITS (PT_HEAP_BIT | PT_RW | PT_US | pt_xd)
|
||||
#endif
|
||||
|
||||
static uint64_t pt_xd = PT_XD;
|
||||
|
||||
@ -330,12 +335,41 @@ static void pagefault_handler(uint8_t intr_num, struct x86_pushad *orig_ctx, uns
|
||||
x86_hlt();
|
||||
}
|
||||
|
||||
#ifdef DEBUG_READ_BEFORE_WRITE
|
||||
uint32_t virtual_addr = cr2_read();
|
||||
uint64_t pte = x86_get_pte(virtual_addr);
|
||||
#endif
|
||||
|
||||
if (error_code & PF_EC_I) {
|
||||
puts("Page fault while fetching instruction.");
|
||||
x86_print_registers(orig_ctx, error_code);
|
||||
puts("Halting.");
|
||||
x86_hlt();
|
||||
}
|
||||
#ifdef DEBUG_READ_BEFORE_WRITE
|
||||
else if ((pte != NO_PTE) && !(pte & PT_P) && (pte & PT_HEAP_BIT)) {
|
||||
/* mark as present */
|
||||
TEMP_PAGE.indices[(virtual_addr >> 12) % 512] |= PT_P;
|
||||
asm volatile ("invlpg (%0)" :: "r"(virtual_addr));
|
||||
|
||||
/* initialize for easier debugging */
|
||||
uint32_t *p = (uint32_t *) (virtual_addr & ~0xfff);
|
||||
for (unsigned i = 0; i < 0x1000 / 4; ++i) {
|
||||
const union {
|
||||
char str_value[4];
|
||||
uint32_t int_value;
|
||||
} debug_init = { .str_value = "RIOT" };
|
||||
*p++ = debug_init.int_value;
|
||||
}
|
||||
|
||||
/* print a warning if the page was read before written */
|
||||
if (!(error_code & PF_EC_W)) {
|
||||
unsigned long *sp = (void *) orig_ctx->sp; /* ip, cs, flags */
|
||||
printf("DEBUG: Read before write on heap address 0x%08x (physical: 0x%016llx) at 0x%08x.\n",
|
||||
virtual_addr, pte & PT_ADDR_MASK, sp[0]);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
else if (error_code & PF_EC_P) {
|
||||
printf("Page fault: access violation while %s present page.\n", error_code & PF_EC_W ? "writing to" : "reading from");
|
||||
x86_print_registers(orig_ctx, error_code);
|
||||
@ -362,8 +396,8 @@ void x86_init_memory(void)
|
||||
check_requirements();
|
||||
|
||||
init_pagetable();
|
||||
init_free_pages();
|
||||
init_pagefault_handler();
|
||||
init_free_pages();
|
||||
|
||||
puts("Virtual memory initialized");
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user