void capops_revoke(struct domcapref cap, revoke_result_handler_t result_handler, void *st) { errval_t err; DEBUG_CAPOPS("%s ## start revocation protocol\n", __FUNCTION__); distcap_state_t state; err = dom_cnode_get_state(cap, &state); GOTO_IF_ERR(err, report_error); if (distcap_state_is_busy(state)) { err = MON_ERR_REMOTE_CAP_RETRY; goto report_error; } struct revoke_master_st *rst; err = calloce(1, sizeof(*rst), &rst); GOTO_IF_ERR(err, report_error); rst->cap = cap; err = monitor_domains_cap_identify(cap.croot, cap.cptr, cap.bits, &rst->rawcap); GOTO_IF_ERR(err, free_st); rst->result_handler = result_handler; rst->st = st; if (distcap_state_is_foreign(state)) { // need to retrieve ownership DEBUG_CAPOPS("%s getting cap ownership\n", __FUNCTION__); capops_retrieve(rst->cap, revoke_retrieve__rx, rst); } else { if (num_monitors_online() == 1) { DEBUG_CAPOPS("%s: only one monitor: do simpler revoke\n", __FUNCTION__); // no remote monitors exist; do simplified revocation process revoke_no_remote(rst); // return here return; } // have ownership, initiate revoke revoke_local(rst); } return; free_st: free(rst); report_error: result_handler(err, st); }
void capops_retrieve(struct domcapref cap, move_result_handler_t result_handler, void *st) { errval_t err; distcap_state_t state; err = dom_cnode_get_state(cap, &state); GOTO_IF_ERR(err, report_error); if (distcap_state_is_busy(state)) { err = MON_ERR_REMOTE_CAP_RETRY; } if (distcap_state_is_foreign(state)) { err = MON_ERR_CAP_FOREIGN; } GOTO_IF_ERR(err, report_error); err = monitor_lock_cap(cap.croot, cap.cptr, cap.bits); GOTO_IF_ERR(err, report_error); struct retrieve_rpc_st *rst = NULL; err = calloce(1, sizeof(*rst), &rst); GOTO_IF_ERR(err, unlock_cap); rst->cap = cap; rst->result_handler = result_handler; rst->st = st; err = monitor_get_domcap_owner(cap, &rst->prev_owner); GOTO_IF_ERR(err, free_st); if (rst->prev_owner == my_core_id) { err = SYS_ERR_OK; goto free_st; } retrieve_owner__enq(rst); return; free_st: free(rst); unlock_cap: caplock_unlock(cap); report_error: result_handler(err, st); }
static void revoke_retrieve__rx(errval_t result, void *st_) { struct revoke_master_st *st = (struct revoke_master_st*)st_; if (err_is_fail(result)) { revoke_result__rx(result, st, false); } else { #ifndef NDEBUG distcap_state_t state; errval_t err = dom_cnode_get_state(st->cap, &state); PANIC_IF_ERR(err, "dom_cnode_get_state"); assert(!distcap_state_is_foreign(state)); #endif revoke_local(st); } }
void retrieve_request__rx(struct intermon_binding *b, intermon_caprep_t caprep, genvaddr_t st) { errval_t err, err2; struct intermon_state *inter_st = (struct intermon_state*)b->st; struct retrieve_response_st *rst; err = calloce(1, sizeof(*rst), &rst); PANIC_IF_ERR(err, "allocating retrieve respones state"); rst->st = st; rst->from = inter_st->core_id; struct capability rawcap; caprep_to_capability(&caprep, &rawcap); struct capref cap; err = slot_alloc(&cap); GOTO_IF_ERR(err, respond_err); err = monitor_copy_if_exists(&rawcap, cap); GOTO_IF_ERR(err, free_slot); distcap_state_t state; err = dom_cnode_get_state(get_cap_domref(cap), &state); GOTO_IF_ERR(err, delete_cap); if (distcap_state_is_busy(state)) { err = MON_ERR_REMOTE_CAP_RETRY; goto delete_cap; } if (distcap_state_is_foreign(state)) { err = MON_ERR_CAP_FOREIGN; goto delete_cap; } uint8_t relations, remote_relations; err = monitor_cap_has_relations(cap, 0xFF, &relations); GOTO_IF_ERR(err, delete_cap); err = monitor_remote_relations(cap, 0, 0, &remote_relations); GOTO_IF_ERR(err, delete_cap); rst->relations = relations | remote_relations | RRELS_COPY_BIT; err = monitor_set_cap_owner(cap_root, get_cap_addr(cap), get_cap_valid_bits(cap), rst->from); delete_cap: err2 = cap_delete(cap); DEBUG_IF_ERR(err2, "while deleting temp cap for retrieve"); free_slot: err2 = slot_free(cap); DEBUG_IF_ERR(err2, "freeing temp cap slot for retrieve"); respond_err: retrieve_result__enq(err, rst); }