1/** 2 * \file 3 * \brief Protect test 4 */ 5/* 6 * Copyright (c) 2014, ETH Zurich. 7 * All rights reserved. 8 * 9 * This file is distributed under the terms in the attached LICENSE file. 10 * If you do not find this file, copies can be found by writing to: 11 * ETH Zurich D-INFK, Universitaetstrasse 6, CH-8092 Zurich. Attn: Systems Group. 12 */ 13 14#include <stdlib.h> 15#include <stdio.h> 16#include <string.h> 17#include <assert.h> 18 19#include <barrelfish/barrelfish.h> 20#include <barrelfish/except.h> 21 22#define EX_STACK_SIZE 16384 23static char ex_stack[EX_STACK_SIZE]; 24static char *ex_stack_end = ex_stack + EX_STACK_SIZE; 25 26#define ALL_PRIVILEGES (VREGION_FLAGS_READ | VREGION_FLAGS_WRITE | VREGION_FLAGS_EXECUTE) 27#define NO_PRIVILEGES 0x0 28 29#define PAGES 100 30 31struct bf_mem { 32 struct capref frame; 33 void *vmem; 34 struct memobj *memobj; 35 struct vregion *vregion; 36}; 37 38struct bf_mem BFmem; 39size_t pagesize; 40 41static void 42bf_alloc_pages(struct bf_mem *bfmem, size_t npages) 43{ 44 errval_t err; 45 size_t retfsize; 46 const size_t nbytes = npages*BASE_PAGE_SIZE; 47 // allocate a frame 48 err = frame_alloc(&bfmem->frame, nbytes, &retfsize); 49 if (err_is_fail(err)) { 50 fprintf(stderr, "frame_alloc: %s\n", err_getstring(err)); 51 abort(); 52 } 53 assert(retfsize >= nbytes); 54 // map frame rw 55 err = vspace_map_one_frame_attr(&bfmem->vmem, retfsize, bfmem->frame, 56 VREGION_FLAGS_READ_WRITE, 57 &bfmem->memobj, 58 &bfmem->vregion); 59 if (err_is_fail(err)) { 60 fprintf(stderr, "vspace_map: %s\n", err_getstring(err)); 61 abort(); 62 } 63 genvaddr_t mem = (genvaddr_t) bfmem->vmem; 64 if (X86_64_PDIR_BASE(mem) != X86_64_PDIR_BASE(mem + retfsize - 1)) { 65 debug_printf("WARN: mapping overlaps leaf pt!\n"); 66 } 67} 68 69__attribute__((unused)) 70static paging_x86_64_flags_t vregion_to_pmap_flag(vregion_flags_t vregion_flags) 71{ 72 paging_x86_64_flags_t pmap_flags = 73 PTABLE_USER_SUPERVISOR | PTABLE_EXECUTE_DISABLE; 74 if (!(vregion_flags & VREGION_FLAGS_GUARD)) { 75 if (vregion_flags & VREGION_FLAGS_WRITE) { 76 pmap_flags |= PTABLE_READ_WRITE; 77 } 78 if (vregion_flags & VREGION_FLAGS_EXECUTE) { 79 pmap_flags &= ~PTABLE_EXECUTE_DISABLE; 80 } 81 if (vregion_flags & VREGION_FLAGS_NOCACHE) { 82 pmap_flags |= PTABLE_CACHE_DISABLED; 83 } 84 } 85 return pmap_flags; 86} 87 88//#define DIRECT_INVOKE 89static void 90bf_protect(struct bf_mem *bfm, size_t off, size_t len, 91 vs_prot_flags_t flags) 92{ 93 //debug_printf("%s: off:%zd len:%zd flags:%u\n", __FUNCTION__, off, len, flags); 94 errval_t err; 95#if defined(DIRECT_INVOKE) 96 err = invoke_frame_modify_flags(bfm->frame, off / pagesize, len / pagesize, 97 vregion_to_pmap_flag(flags)); 98#else 99 err = bfm->memobj->f.protect(bfm->memobj, bfm->vregion, off, len, flags); 100#endif 101 if (err_is_fail(err)) { 102 fprintf(stderr, "vmpup: memobj.f.protect: %s\n", err_getstring(err)); 103 abort(); 104 } 105} 106 107 108static void 109bf_handler(enum exception_type type, int subtype, 110 void *vaddr, 111 arch_registers_state_t *regs) 112{ 113 assert(type == EXCEPT_PAGEFAULT); 114 assert(subtype == PAGEFLT_WRITE); 115 debug_printf("got exception %d(%d) on %p\n", type, subtype, vaddr); 116 117 assert((uintptr_t)BFmem.vmem <= (uintptr_t)vaddr); 118 uintptr_t off_unprotect = (uintptr_t)vaddr - (uintptr_t)BFmem.vmem; 119 bf_protect(&BFmem, off_unprotect, pagesize, ALL_PRIVILEGES); 120} 121 122 123int main(int argc, char **argv) 124{ 125 char *mem; 126 pagesize = BASE_PAGE_SIZE; 127 128 bf_alloc_pages(&BFmem, PAGES); 129 mem = BFmem.vmem; 130 thread_set_exception_handler(bf_handler, NULL, ex_stack, ex_stack_end, NULL, NULL); 131 debug_printf("MEM=%p\n", mem); 132 133 bf_protect(&BFmem, 0, PAGES*pagesize, NO_PRIVILEGES); 134 135 for (size_t i = 0; i < PAGES; i++) { 136 mem[i * pagesize] = 20; 137 } 138}