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