static void remote_cap_revoke(struct monitor_blocking_binding *b, struct capref croot, capaddr_t src, uint8_t vbits) { errval_t err; /* Save state for stackripped reply */ struct revoke_st * st = alloc_revoke_st(b, croot, src, vbits); /* Get the raw cap from the kernel */ err = monitor_domains_cap_identify(croot, src, vbits, &(st->rcap_st.capability)); if (err_is_fail(err)) { err_push(err, MON_ERR_CAP_REMOTE); goto reply; } /* request recursive lock on the cap and all of its descendants */ err = rcap_db_acquire_recursive_lock(&(st->rcap_st.capability), (struct rcap_st*)st); if (err_is_fail(err)) { goto reply; } return; // continues in remote_cap_retype_phase_2 reply: free_revoke_st(st); err = b->tx_vtbl.remote_cap_revoke_response(b, NOP_CONT, err); assert(err_is_ok(err)); }
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); }
errval_t capsend_update_owner(struct domcapref capref, struct event_closure completion_continuation) { errval_t err; struct capability cap; err = monitor_domains_cap_identify(capref.croot, capref.cptr, capref.bits, &cap); if (err_is_fail(err)) { return err; } struct update_owner_broadcast_st *bc_st = calloc(1, sizeof(struct update_owner_broadcast_st)); if (!bc_st) { return LIB_ERR_MALLOC_FAIL; } bc_st->completion_continuation = completion_continuation; return capsend_broadcast((struct capsend_mc_st*)bc_st, NULL, &cap, update_owner_broadcast_send_cont); }
static void remote_cap_retype(struct monitor_blocking_binding *b, struct capref croot, capaddr_t src, uint64_t new_type, uint8_t size_bits, capaddr_t to, capaddr_t slot, int32_t dcn_vbits) { errval_t err; bool has_descendants; coremask_t on_cores; /* Save state for stackripped reply */ struct retype_st * st = alloc_retype_st(b, croot, src, new_type, size_bits, to, slot, dcn_vbits); /* Get the raw cap from the kernel */ err = monitor_domains_cap_identify(croot, src, CPTR_BITS, &(st->rcap_st.capability)); if (err_is_fail(err)) { err_push(err, MON_ERR_CAP_REMOTE); goto reply; } /* Check if cap is retyped, if it is there is no point continuing, This will be checked again once we succeed in locking cap */ err = rcap_db_get_info(&st->rcap_st.capability, &has_descendants, &on_cores); assert(err_is_ok(err)); if (has_descendants) { err = MON_ERR_REMOTE_CAP_NEED_REVOKE; goto reply; } /* request lock */ err = rcap_db_acquire_lock(&st->rcap_st.capability, (struct rcap_st*)st); if (err_is_fail(err)) { goto reply; } return; // continues in remote_cap_retype_phase_2 reply: free_retype_st(st); err = b->tx_vtbl.remote_cap_retype_response(b, NOP_CONT, err); assert(err_is_ok(err)); }
errval_t capsend_find_descendants(struct domcapref src, capsend_result_fn result_fn, void *st) { errval_t err; struct capability cap; err = monitor_domains_cap_identify(src.croot, src.cptr, src.bits, &cap); if (err_is_fail(err)) { return err; } struct find_descendants_mc_st *mc_st; mc_st = malloc(sizeof(*mc_st)); if (!mc_st) { return LIB_ERR_MALLOC_FAIL; } mc_st->result_fn = result_fn; mc_st->st = st; mc_st->have_result = false; return capsend_relations(&cap, find_descendants_send_cont, (struct capsend_mc_st*)mc_st, NULL); }