1/** 2 * \file 3 * \brief remote revoke test 4 */ 5 6/* 7 * Copyright (c) 2016, 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, Universitaetstr 6, CH-8092 Zurich. Attn: Systems Group. 13 */ 14 15#include <barrelfish/barrelfish.h> 16#include <barrelfish_kpi/capbits.h> 17#include <if/test_defs.h> 18 19#include "test.h" 20 21__attribute__((unused)) 22static void debug_capref(const char *prefix, struct capref cap) 23{ 24 char buf[128]; 25 debug_print_capref(buf, 128, cap); 26 printf("%s capref = %s\n", prefix, buf); 27} 28 29enum server_op { 30 // Try to retype ram (should fail) then revoke RAM cap 31 SERVER_OP_RETYPE_THEN_REVOKE, 32 // After checking that caps were deleted on client do another retype on 33 // server that should succeed 34 SERVER_OP_RETYPE, 35}; 36 37enum client_op { 38 // Check that caps that we were holding were deleted by revoke() on server 39 // side 40 CLIENT_OP_CHECK_DELETED, 41}; 42 43//{{{1 Server-side cap operations 44 45struct server_state { 46 struct capref ram; 47}; 48 49void init_server(struct test_binding *b) 50{ 51 b->st = malloc(sizeof(struct server_state)); 52 assert(b->st); 53 if (!b->st) { 54 USER_PANIC("state malloc() in server"); 55 } 56} 57 58void server_do_test(struct test_binding *b, uint32_t test, struct capref cap) 59{ 60 errval_t err; 61 struct server_state *st = b->st; 62 63 switch(test) { 64 case SERVER_OP_RETYPE_THEN_REVOKE: 65 // Remember RAM capref 66 st->ram = cap; 67 68 // Try retype; expect SYS_ERR_REVOKE_FIRST 69 printf("server: try retype on already retyped RAM cap\n"); 70 server_test_retype(st->ram, NULL, 0, BASE_PAGE_SIZE, 1, SYS_ERR_REVOKE_FIRST); 71 72 printf("server: revoke RAM cap\n"); 73 err = cap_revoke(st->ram); 74 if (err_is_fail(err)) { 75 printf("distops_revoke: revoke: expected OK, got %s\n", err_getcode(err)); 76 } 77 78 err = test_basic__tx(b, NOP_CONT, CLIENT_OP_CHECK_DELETED); 79 PANIC_IF_ERR(err, "server: triggering check_deleted on client"); 80 break; 81 82 case SERVER_OP_RETYPE: 83 printf("server: try retype on revoked cap\n"); 84 server_test_retype(st->ram, NULL, 0, BASE_PAGE_SIZE, 1, SYS_ERR_OK); 85 86 printf("distops_revoke: test done\n"); 87 exit(0); 88 89 default: 90 USER_PANIC("server: Unknown test %"PRIu32"\n", test); 91 } 92} 93 94//{{{1 Client-side cap operations 95 96struct client_state { 97 struct capref ram; ///< Large RAM cap 98 struct capref cnode; ///< CNode that contains all the small Frames 99 struct capref frame; ///< First slot in cnode 100}; 101 102void init_client(struct test_binding *b) 103{ 104 errval_t err; 105 106 // Allocate client state struct 107 b->st = malloc(sizeof(struct client_state)); 108 assert(b->st); 109 if (!b->st) { 110 USER_PANIC("state malloc() in client"); 111 } 112 struct client_state *cst = b->st; 113 114 // Allocate RAM cap 115 err = ram_alloc(&cst->ram, RAM_BITS); 116 PANIC_IF_ERR(err, "in client: ram_alloc()"); 117 118 err = cnode_create_l2(&cst->cnode, &cst->frame.cnode); 119 PANIC_IF_ERR(err, "in client: cnode_create_l2"); 120 121 err = cap_retype(cst->frame, cst->ram, 0, ObjType_Frame, BASE_PAGE_SIZE, L2_CNODE_SLOTS); 122 PANIC_IF_ERR(err, "in client: cap_retype"); 123 124 // Trigger Server 125 err = test_caps__tx(b, NOP_CONT, SERVER_OP_RETYPE_THEN_REVOKE, cst->ram, NULL_CAP); 126 PANIC_IF_ERR(err, "in client: sending ram to server"); 127} 128 129void client_do_test(struct test_binding *b, uint32_t test, struct capref cap) 130{ 131 errval_t err; 132 struct capability c; 133 struct client_state *st = b->st; 134 assert(st); 135 136 switch(test) { 137 // Check that revoke on server deleted our Frame caps and our RAM cap 138 case CLIENT_OP_CHECK_DELETED: 139 err = debug_cap_identify(st->ram, &c); 140 if (err_no(err) == SYS_ERR_LMP_CAPTRANSFER_SRC_LOOKUP) { 141 // RAM is empty -> cap got deleted by revoke 142 } else { 143 PANIC_IF_ERR(err, "debug_cap_identify(RAM)"); 144 if (c.type != ObjType_Null) { 145 printf("client: RAM: expected ObjType_Null, got %d\n", c.type); 146 } 147 } 148 149 cap = st->frame; 150 for (cap.slot = 0; cap.slot < L2_CNODE_SLOTS; cap.slot++) { 151 err = debug_cap_identify(cap, &c); 152 if (err_no(err) == SYS_ERR_LMP_CAPTRANSFER_SRC_LOOKUP) { 153 // slot is empty -> cap got deleted by revoke 154 continue; 155 } 156 PANIC_IF_ERR(err, "debug_cap_identify(Frame %"PRIuCSLOT")", cap.slot); 157 if (c.type != ObjType_Null) { 158 printf("client: Frame %"PRIuCSLOT": expected ObjType_Null, got %d\n", 159 cap.slot, c.type); 160 } 161 } 162 163 err = test_basic__tx(b, NOP_CONT, SERVER_OP_RETYPE); 164 PANIC_IF_ERR(err, "in client: triggering server retype #2"); 165 printf("client: exit\n"); 166 exit(0); 167 break; 168 169 default: 170 USER_PANIC("client: Unknown test %"PRIu32"\n", test); 171 } 172} 173