1/** 2 * \file 3 * \brief test that vnode_inherit cannot create unrevokable ptes 4 */ 5 6/* 7 * Copyright (c) 2017, ETH Zurich. 8 * All rights reserved. 9 * 10 * This file is distributed under the terms in the attached LICENSE file. 11 * If you do not find this file, copies can be found by writing to: 12 * ETH Zurich D-INFK, Universitaetstrasse 6, CH-8092 Zurich. Attn: Systems Group. 13 */ 14 15#include <stdio.h> 16#include <stdlib.h> 17 18#include <barrelfish/barrelfish.h> 19#include <barrelfish/except.h> 20#include <barrelfish/sys_debug.h> 21 22// Defined in lib/barrelfish/target/x86_64/pmap_target.c 23errval_t get_ptable(struct pmap_x86 *pmap, genvaddr_t base, 24 struct vnode **ptable); 25 26#ifdef DELETE_FRAME 27#define EX_STACK_SIZE 16384 28static char ex_stack[EX_STACK_SIZE]; 29static char *ex_stack_top = ex_stack + EX_STACK_SIZE; 30 31static void exhandler(enum exception_type type, int subtype, void *vaddr, 32 arch_registers_state_t *regs) 33{ 34 debug_printf("Got fault on %p\n", vaddr); 35 debug_printf("Test completed: SUCCESS.\n"); 36 exit(0); 37} 38#endif 39 40int main(int argc, char *argv[]) 41{ 42 errval_t err; 43 44 struct pmap_x86 *x86 = (struct pmap_x86*)get_current_pmap(); 45 46 struct memobj *memobj = NULL; 47 struct vregion *vregion = NULL; 48 49 /* get frame cap */ 50 struct capref frame; 51 size_t rb; 52 err = frame_alloc(&frame, 4096, &rb); 53 assert(err_is_ok(err)); 54 assert(rb == 4096); 55 56 void *vbase; 57 err = vspace_map_one_frame(&vbase, BASE_PAGE_SIZE, frame, &memobj, &vregion); 58 assert(err_is_ok(err)); 59 60 genvaddr_t base = vregion_get_base_addr(vregion); 61 debug_printf("our region is at %#"PRIxGENVADDR"\n", base); 62 63 /* get struct vnode for ptable for our region */ 64 struct vnode *ptable = NULL; 65 err = get_ptable(x86, base, &ptable); 66 assert(err_is_ok(err)); 67 assert(ptable); 68 69 /* allocate a empty ptable */ 70 genvaddr_t cloned_base; 71 err = x86->p.f.determine_addr_raw(&x86->p, LARGE_PAGE_SIZE, 72 LARGE_PAGE_SIZE, &cloned_base); 73 assert(err_is_ok(err)); 74 debug_printf("cloned ptable is at %#"PRIxGENVADDR"\n", cloned_base); 75 76 struct vnode *cloned = NULL; 77 err = get_ptable(x86, cloned_base, &cloned); 78 assert(err_is_ok(err)); 79 assert(cloned); 80 81 /* clone ptable */ 82 debug_printf("calling vnode inherit\n"); 83 err = vnode_inherit(cloned->v.u.vnode.invokable, ptable->v.u.vnode.invokable, 84 0, PTABLE_SIZE, ptable->u.vnode.mcn, cloned->u.vnode.mcn); 85 assert(err_is_ok(err)); 86 87 size_t ptentry = X86_64_PTABLE_BASE(base); 88 genvaddr_t cloned_addr = cloned_base | (ptentry << BASE_PAGE_BITS); 89 debug_printf("cloned region is at %#"PRIxGENVADDR"\n", cloned_addr); 90 91 debug_printf("Writing to original region\n"); 92 uint8_t *b = vbase; 93 for (int i = 0; i < BASE_PAGE_SIZE; i++) { 94 b[i] = i % UINT8_MAX; 95 } 96 sys_debug_flush_cache(); 97 98 char *exitmsg = NULL; 99 int retval = 0; 100 101#ifdef DELETE_FRAME 102 debug_printf("Deleting Frame cap, check should fault\n"); 103 exitmsg = "FAILURE"; 104 retval = 1; 105 106 /* install exception handler, to gracefully handle expected faults */ 107 err = thread_set_exception_handler(exhandler, NULL, ex_stack, ex_stack_top, 108 NULL, NULL); 109 assert(err_is_ok(err)); 110 111 /* delete frame cap, should unmap region in both page tables */ 112 err = cap_destroy(frame); 113 assert(err_is_ok(err)); 114#else 115 exitmsg = "SUCCESS"; 116#endif 117 118 debug_printf("Checking cloned region\n"); 119 b = (void *)cloned_addr; 120 for (int i = 0; i < BASE_PAGE_SIZE; i++) { 121 if (b[i] != (i % UINT8_MAX)) { 122 debug_printf("Error at byte %d: %hhu, %u\n", i, b[i], i % UINT8_MAX); 123 } 124 } 125 debug_printf("Cloned region checked successfully!\n"); 126 127#if !defined(DELETE_FRAME) 128 129 sys_debug_flush_cache(); 130 debug_printf("Checking original region\n"); 131 b = vbase; 132 for (int i = 0; i < BASE_PAGE_SIZE; i++) { 133 if (b[i] != (i % UINT8_MAX)) { 134 debug_printf("Error at byte %d: %hhu, %u\n", i, b[i], i % UINT8_MAX); 135 } 136 } 137 debug_printf("Original region checked successfully\n"); 138#endif 139 140 debug_printf("Test completed: %s.\n", exitmsg); 141 142 return retval; 143} 144