implement guard pages for stack
This commit is contained in:
parent
42d51de0b1
commit
f6364278d0
@ -14,6 +14,7 @@
|
|||||||
"extensions": [
|
"extensions": [
|
||||||
"ms-azuretools.vscode-docker",
|
"ms-azuretools.vscode-docker",
|
||||||
"ms-vscode.cpptools-extension-pack",
|
"ms-vscode.cpptools-extension-pack",
|
||||||
|
"eamodio.gitlens",
|
||||||
],
|
],
|
||||||
|
|
||||||
// allow access to the toradex board
|
// allow access to the toradex board
|
||||||
|
|||||||
@ -322,6 +322,7 @@ errors libaos LIB_ERR_ {
|
|||||||
failure PMAP_FRAME_IDENTIFY "Frame could not be identified",
|
failure PMAP_FRAME_IDENTIFY "Frame could not be identified",
|
||||||
failure PMAP_NOT_MAPPED "No mapping in given address range",
|
failure PMAP_NOT_MAPPED "No mapping in given address range",
|
||||||
failure PMAP_ALLOC_CNODE "Failure while allocating Mapping CNode",
|
failure PMAP_ALLOC_CNODE "Failure while allocating Mapping CNode",
|
||||||
|
failure PMAP_ADDR_IS_GUARDED "The requested address is in a guarded range",
|
||||||
|
|
||||||
failure OUT_OF_VIRTUAL_ADDR "Out of virtual address",
|
failure OUT_OF_VIRTUAL_ADDR "Out of virtual address",
|
||||||
|
|
||||||
|
|||||||
@ -25,6 +25,7 @@
|
|||||||
|
|
||||||
struct paging_state;
|
struct paging_state;
|
||||||
|
|
||||||
|
void * paging_malloc(size_t bytes, size_t * retbytes, size_t guarded_region_size);
|
||||||
|
|
||||||
struct thread;
|
struct thread;
|
||||||
errval_t paging_init_state(struct paging_state *st, lvaddr_t start_vaddr,
|
errval_t paging_init_state(struct paging_state *st, lvaddr_t start_vaddr,
|
||||||
@ -39,7 +40,7 @@ errval_t paging_init_onthread(struct thread *t);
|
|||||||
|
|
||||||
|
|
||||||
errval_t paging_alloc_ext(struct paging_state *st, void **buf, size_t bytes,
|
errval_t paging_alloc_ext(struct paging_state *st, void **buf, size_t bytes,
|
||||||
size_t alignment, bool heap);
|
size_t alignment, bool heap, size_t guarded_region_size);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* \brief Find a bit of free virtual address space that is large enough to
|
* \brief Find a bit of free virtual address space that is large enough to
|
||||||
|
|||||||
@ -63,6 +63,7 @@ struct pt_vaddr_reg_t {
|
|||||||
size_t size;
|
size_t size;
|
||||||
uint8_t free:1; // Is the region free?
|
uint8_t free:1; // Is the region free?
|
||||||
uint8_t heap:1; // Is the region part of the heap?
|
uint8_t heap:1; // Is the region part of the heap?
|
||||||
|
size_t guarded_region_size; //the first n bits of this region are guarded and will panic when mapped! (e.g to detect stack overflows)
|
||||||
struct pt_vaddr_reg_t *next;
|
struct pt_vaddr_reg_t *next;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@ -101,18 +101,7 @@ errval_t morecore_reinit(void)
|
|||||||
*/
|
*/
|
||||||
static void *morecore_alloc(size_t bytes, size_t *retbytes)
|
static void *morecore_alloc(size_t bytes, size_t *retbytes)
|
||||||
{
|
{
|
||||||
errval_t err;
|
return paging_malloc(bytes, retbytes, 0);
|
||||||
// struct morecore_state *state = get_morecore_state();
|
|
||||||
|
|
||||||
size_t aligned_bytes = ROUND_UP(bytes, LARGE_PAGE_SIZE);
|
|
||||||
void *ret = NULL;
|
|
||||||
err = paging_alloc_ext(get_current_paging_state(), &ret, aligned_bytes, LARGE_PAGE_SIZE, true);
|
|
||||||
if (err_is_fail(err)) {
|
|
||||||
DEBUG_ERR(err, "in morecore_alloc, size=%"PRIuPTR"\n", aligned_bytes);
|
|
||||||
aligned_bytes = 0;
|
|
||||||
}
|
|
||||||
*retbytes = aligned_bytes;
|
|
||||||
return ret;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void morecore_free(void *base, size_t bytes)
|
static void morecore_free(void *base, size_t bytes)
|
||||||
|
|||||||
@ -134,7 +134,8 @@ static void pt_exception_handler(enum exception_type type, int subtype,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (vaddr_reg == NULL || vaddr_reg->free) {
|
if (vaddr_reg == NULL || vaddr_reg->free) {
|
||||||
USER_PANIC("[ERROR] Page fault ouside allocated address space");
|
debug_printf("[pt_exception_handler] page_addr = %x, base = %x, size = %x\n", page_addr, vaddr_reg->base, vaddr_reg->size);
|
||||||
|
USER_PANIC("[pt_exception_handler][ERROR] Page fault ouside allocated address space");
|
||||||
}
|
}
|
||||||
if (!vaddr_reg->heap) {
|
if (!vaddr_reg->heap) {
|
||||||
USER_PANIC("[ERROR] Page fault in allocated address space but outside heap");
|
USER_PANIC("[ERROR] Page fault in allocated address space but outside heap");
|
||||||
@ -259,6 +260,27 @@ void pt_print_state(struct paging_state *st) {
|
|||||||
PAGING_UNLOCK
|
PAGING_UNLOCK
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void * paging_malloc(size_t bytes, size_t * retbytes, size_t guarded_region_size) {
|
||||||
|
errval_t err;
|
||||||
|
|
||||||
|
assert(guarded_region_size < bytes);
|
||||||
|
|
||||||
|
size_t aligned_bytes = ROUND_UP(bytes, LARGE_PAGE_SIZE);
|
||||||
|
void *ret = NULL;
|
||||||
|
err = paging_alloc_ext(get_current_paging_state(), &ret, aligned_bytes, LARGE_PAGE_SIZE, true, guarded_region_size);
|
||||||
|
if (err_is_fail(err)) {
|
||||||
|
DEBUG_ERR(err, "in paging_malloc, size=%"PRIuPTR"\n", aligned_bytes);
|
||||||
|
aligned_bytes = 0;
|
||||||
|
}
|
||||||
|
*retbytes = aligned_bytes;
|
||||||
|
debug_printf("[paging_malloc]: bytes = %x, aligned_bytes = %x, base = %p\n", bytes, aligned_bytes, ret);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
// void paging_free(void * ptr) {
|
||||||
|
|
||||||
|
// }
|
||||||
|
|
||||||
// refill the slab and hold the paging lock for the slab growing but not before
|
// refill the slab and hold the paging lock for the slab growing but not before
|
||||||
static errval_t pt_slab_refill_locked(struct paging_state *st, struct slab_allocator *slabs, size_t size) {
|
static errval_t pt_slab_refill_locked(struct paging_state *st, struct slab_allocator *slabs, size_t size) {
|
||||||
errval_t err;
|
errval_t err;
|
||||||
@ -480,6 +502,7 @@ errval_t paging_init_state(struct paging_state *st, lvaddr_t start_vaddr,
|
|||||||
st->vaddr_head.free = true;
|
st->vaddr_head.free = true;
|
||||||
st->vaddr_head.heap = false;
|
st->vaddr_head.heap = false;
|
||||||
st->vaddr_head.next = NULL;
|
st->vaddr_head.next = NULL;
|
||||||
|
st->vaddr_head.guarded_region_size = 0;
|
||||||
|
|
||||||
st->slot_alloc = ca;
|
st->slot_alloc = ca;
|
||||||
st->refilling = 0;
|
st->refilling = 0;
|
||||||
@ -608,7 +631,7 @@ errval_t paging_init_onthread(struct thread *t)
|
|||||||
|
|
||||||
static errval_t paging_insert_vaddr_reg(
|
static errval_t paging_insert_vaddr_reg(
|
||||||
struct paging_state *st, struct pt_vaddr_reg_t *target_region,
|
struct paging_state *st, struct pt_vaddr_reg_t *target_region,
|
||||||
size_t prefix_size, size_t alloc_size, bool heap
|
size_t prefix_size, size_t alloc_size, bool heap, size_t guarded_region_size
|
||||||
) {
|
) {
|
||||||
assert(target_region->free);
|
assert(target_region->free);
|
||||||
assert(target_region->size >= prefix_size + alloc_size);
|
assert(target_region->size >= prefix_size + alloc_size);
|
||||||
@ -629,6 +652,7 @@ static errval_t paging_insert_vaddr_reg(
|
|||||||
} else {
|
} else {
|
||||||
main_reg = target_region;
|
main_reg = target_region;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (postfix_size > 0) {
|
if (postfix_size > 0) {
|
||||||
postfix_reg = slab_alloc(&st->pt_slabs);
|
postfix_reg = slab_alloc(&st->pt_slabs);
|
||||||
if (postfix_reg == NULL) {
|
if (postfix_reg == NULL) {
|
||||||
@ -645,6 +669,7 @@ static errval_t paging_insert_vaddr_reg(
|
|||||||
if (prefix_size > 0) {
|
if (prefix_size > 0) {
|
||||||
prefix_reg->base = base;
|
prefix_reg->base = base;
|
||||||
prefix_reg->size = prefix_size;
|
prefix_reg->size = prefix_size;
|
||||||
|
prefix_reg->guarded_region_size = 0;
|
||||||
|
|
||||||
main_reg->next = prefix_reg->next;
|
main_reg->next = prefix_reg->next;
|
||||||
prefix_reg->next = main_reg;
|
prefix_reg->next = main_reg;
|
||||||
@ -656,6 +681,11 @@ static errval_t paging_insert_vaddr_reg(
|
|||||||
main_reg->size = alloc_size;
|
main_reg->size = alloc_size;
|
||||||
main_reg->free = false;
|
main_reg->free = false;
|
||||||
main_reg->heap = heap;
|
main_reg->heap = heap;
|
||||||
|
main_reg->guarded_region_size = guarded_region_size;
|
||||||
|
|
||||||
|
// if (guarded_region_size > 0) {
|
||||||
|
// debug_printf("[paging_insert_vaddr_reg] guarding region: base = %x, size = %x, guarded_region_size = %x\n", main_reg->base, main_reg->size, main_reg->guarded_region_size);
|
||||||
|
// }
|
||||||
|
|
||||||
base += alloc_size;
|
base += alloc_size;
|
||||||
|
|
||||||
@ -664,6 +694,7 @@ static errval_t paging_insert_vaddr_reg(
|
|||||||
postfix_reg->size = postfix_size;
|
postfix_reg->size = postfix_size;
|
||||||
postfix_reg->free = true;
|
postfix_reg->free = true;
|
||||||
postfix_reg->heap = false;
|
postfix_reg->heap = false;
|
||||||
|
postfix_reg->guarded_region_size = 0;
|
||||||
|
|
||||||
postfix_reg->next = main_reg->next;
|
postfix_reg->next = main_reg->next;
|
||||||
main_reg->next = postfix_reg;
|
main_reg->next = postfix_reg;
|
||||||
@ -674,7 +705,7 @@ static errval_t paging_insert_vaddr_reg(
|
|||||||
|
|
||||||
errval_t paging_alloc_ext(
|
errval_t paging_alloc_ext(
|
||||||
struct paging_state *st, void **buf, size_t bytes,
|
struct paging_state *st, void **buf, size_t bytes,
|
||||||
size_t alignment, bool heap
|
size_t alignment, bool heap, size_t guarded_region_size
|
||||||
) {
|
) {
|
||||||
errval_t err;
|
errval_t err;
|
||||||
|
|
||||||
@ -707,7 +738,7 @@ errval_t paging_alloc_ext(
|
|||||||
if (vaddr_reg->free && vaddr_reg->size >= prefix_size + bytes) {
|
if (vaddr_reg->free && vaddr_reg->size >= prefix_size + bytes) {
|
||||||
|
|
||||||
// allocate the new region, potentially splitting off a prefix and postfix from the region
|
// allocate the new region, potentially splitting off a prefix and postfix from the region
|
||||||
err = paging_insert_vaddr_reg(st, vaddr_reg, prefix_size, bytes, heap);
|
err = paging_insert_vaddr_reg(st, vaddr_reg, prefix_size, bytes, heap, guarded_region_size);
|
||||||
if (err_is_fail(err)) {
|
if (err_is_fail(err)) {
|
||||||
PAGING_UNLOCK
|
PAGING_UNLOCK
|
||||||
return err;
|
return err;
|
||||||
@ -738,7 +769,7 @@ errval_t paging_alloc_ext(
|
|||||||
*/
|
*/
|
||||||
errval_t paging_alloc(struct paging_state *st, void **buf, size_t bytes, size_t alignment)
|
errval_t paging_alloc(struct paging_state *st, void **buf, size_t bytes, size_t alignment)
|
||||||
{
|
{
|
||||||
return paging_alloc_ext(st, buf, bytes, alignment, false);
|
return paging_alloc_ext(st, buf, bytes, alignment, false, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -840,9 +871,15 @@ errval_t paging_map_fixed_attr(struct paging_state *st, lvaddr_t vaddr,
|
|||||||
for(;vaddr_reg != NULL; vaddr_reg = vaddr_reg->next) {
|
for(;vaddr_reg != NULL; vaddr_reg = vaddr_reg->next) {
|
||||||
// we have found the region it belongs to
|
// we have found the region it belongs to
|
||||||
if(vaddr_reg->base <= vaddr && end_vaddr <= vaddr_reg->base + vaddr_reg->size) {
|
if(vaddr_reg->base <= vaddr && end_vaddr <= vaddr_reg->base + vaddr_reg->size) {
|
||||||
|
//check if we try to map anything in the guarded region!
|
||||||
|
if (vaddr < vaddr_reg->base + vaddr_reg->guarded_region_size) {
|
||||||
|
debug_printf("[paging_map_fixed_attr] attempt to map guarded region!, vaddr = %p, guarded_region_size = %x\n", vaddr, vaddr_reg->guarded_region_size);
|
||||||
|
return LIB_ERR_PMAP_ADDR_IS_GUARDED;
|
||||||
|
}
|
||||||
|
|
||||||
if (vaddr_reg->free == true) {
|
if (vaddr_reg->free == true) {
|
||||||
// make sure the virtual memory is not used by anyone else
|
// make sure the virtual memory is not used by anyone else
|
||||||
err = paging_insert_vaddr_reg(st, vaddr_reg, vaddr - vaddr_reg->base, bytes, false);
|
err = paging_insert_vaddr_reg(st, vaddr_reg, vaddr - vaddr_reg->base, bytes, false, 0);
|
||||||
if (err_is_fail(err)) {
|
if (err_is_fail(err)) {
|
||||||
PAGING_UNLOCK
|
PAGING_UNLOCK
|
||||||
return err;
|
return err;
|
||||||
|
|||||||
@ -317,7 +317,8 @@ static void free_thread(struct thread *thread)
|
|||||||
ldt_free_segment(thread->thread_seg_selector);
|
ldt_free_segment(thread->thread_seg_selector);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
free(thread->stack);
|
//TODO: afeer: properly free stack again
|
||||||
|
// free(thread->stack);
|
||||||
if (thread->tls_dtv != NULL) {
|
if (thread->tls_dtv != NULL) {
|
||||||
free(thread->tls_dtv);
|
free(thread->tls_dtv);
|
||||||
}
|
}
|
||||||
@ -345,7 +346,9 @@ struct thread *thread_create_unrunnable(thread_func_t start_func, void *arg,
|
|||||||
{
|
{
|
||||||
// allocate stack
|
// allocate stack
|
||||||
assert((stacksize % sizeof(uintptr_t)) == 0);
|
assert((stacksize % sizeof(uintptr_t)) == 0);
|
||||||
void *stack = malloc(stacksize);
|
stacksize += BASE_PAGE_SIZE;
|
||||||
|
size_t bytes_allocated;
|
||||||
|
void *stack = paging_malloc(stacksize, &bytes_allocated, BASE_PAGE_SIZE);
|
||||||
if (stack == NULL) {
|
if (stack == NULL) {
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user