Commit 19b3c971 authored by Josh Kunz's avatar Josh Kunz

Makes rp0s part of the node's secret c-space explicitly

Previously, the cn_node_new would put the rp0 in the node's
actual c-space, and the reset operation would put it in the node's
secret c-space. Which meant that if the rp0 was fetched *after* the node
was reset, it wouldn't function properly (since the capability would not
be valid in the node's real principal).

This commit fixes the implementation of rp0 to always put the rp0 in
the secret c-space. This is probably a good idea to ensure that CapNet
can always safely revoke the rp0 when the node is reset, but I believe
the previous implementation was still safe. So now, when the node calls
the `rp0` rpc, the node is explicitly granted its own rp0 from its secret
principal.

This commit also fixes an improper-free bug after a principal is
cleared. When the principal is cleared its refcount would be set to zero
(due to a cal to _obj_init) instead of keeping the same refcount it had
before the clear operation.
parent d82aab8f
......@@ -1068,6 +1068,8 @@ fail1:
int cn_dispatch_rp0(cn_principal_t * as, cn_dispatch_result_t *result) {
// XXX: Assumes that A) principals do not have rp0s, and B) all invoking
// principals are nodes. This may need to change at some point.
int ret = -1;
cn_dispatch_result_item_t * ritem = cn_dispatch_result_item_alloc();
if (ritem == NULL) {
......@@ -1079,14 +1081,27 @@ int cn_dispatch_rp0(cn_principal_t * as, cn_dispatch_result_t *result) {
cn_obj_lock(node);
c_log_debug("got node: %0#lx", (unsigned long) node);
cn_dispatch_result_item_init_cptr(ritem, node->rp0, CN_RP);
cn_obj_lock(node->secret);
cptr_t rp0;
if (cn_grant(node->secret, node->rp0, as, NULL, &rp0) != 0) {
ret = cn_dispatch_result_fail(result, "couldn't grant rp0 from secret");
goto end;
}
cn_dispatch_result_item_init_cptr(ritem, rp0, CN_RP);
cn_dispatch_result_push_item(result, ritem);
result->status = SUCCESS;
result->msg = strdup("success");
ret = 0;
end:
cn_obj_unlock(node->secret);
cn_obj_unlock(node);
cn_obj_unlock(as);
return 0;
return ret;
}
/* Generate the appropriate cn_dispatch_result_t items according to the output
......
......@@ -125,7 +125,6 @@ int cn_principal_init(cn_principal_t *p) {
p->cspace = cspace;
cap_cspace_set_owner(p->cspace, (void *) p);
_obj_init(&p->obj, CN_PRINCIPAL, _cn_principal_free);
p->owner = NULL;
......@@ -139,6 +138,8 @@ int cn_principal_new(cn_principal_t **out) {
cn_principal_t *principal = calloc(1,sizeof(*principal));
if (principal == NULL) { goto fail; }
_obj_init(&principal->obj, CN_PRINCIPAL, _cn_principal_free);
if (cn_principal_init(principal) != 0) { goto fail; }
*out = principal;
......@@ -316,7 +317,7 @@ int cn_node_new(cn_node_t **o_node) {
/* Create the default rp0 and insert it into the node's cspace */
cn_rp_t *rp0;
if (cn_rp_new(&rp0) != 0) { goto fail3; }
if (cn_principal_insert(node->principal, (cn_obj_t *) rp0, NULL, &node->rp0) != 0) {
if (cn_principal_insert(node->secret, (cn_obj_t *) rp0, NULL, &node->rp0) != 0) {
goto fail4;
}
......@@ -1604,6 +1605,10 @@ int cn_node_reset(struct cnode * node, cptr_t *o_grant) {
cncinfo("Deleting grant\n");
cn_delete(n->secret, n->grant, NULL);
cncinfo("Revoking rp0 (cap: %#0lx)\n", cptr2ul(n->rp0));
cn_revoke(n->secret, n->rp0, NULL);
cn_delete(n->secret, n->rp0, NULL);
if ((res = cn_principal_clear(n->principal)) != 0) {
cncerr("principal clear failed\n");
goto finish2; }
......@@ -1924,15 +1929,6 @@ static int cn_rp_recv_injected(struct cnode * rp, struct cn_rp_elem * e,
" associated with a node.\n");
return -1;
}
cn_obj_lock(owner);
// This should only ever happen on a node's RP0
if (cptr2ul(cap_cnode_cptr(rp)) != cptr2ul(owner->rp0)) {
cncerr("Trying to recv injected capability on non-rp0 rendezvous point\n");
cn_obj_unlock(owner);
return -1;
}
cn_obj_unlock(owner);
#endif
if (cn_principal_insert(cn_cnode_principal(rp), e->injected.object, NULL, recv_cap) != 0) {
......@@ -2775,7 +2771,7 @@ int cnc_deliver_obj(cn_node_t *node, cn_obj_t *obj) {
int result = -1;
struct cnode * rp0;
cn_obj_lock(node);
if (cn_principal_get(node->principal, node->rp0, &rp0) != 0) {
if (cn_principal_get(node->secret, node->rp0, &rp0) != 0) {
cncerr("Can't get RP0 for node to deliver cptr\n");
goto fail1;
}
......
......@@ -406,7 +406,8 @@ struct cn_node {
cn_obj_t obj;
cn_principal_t *principal;
/* Our RP0, set at initialization. */
/* Our RP0, set at initialization. This capability is owned by the node's
* secret c-space */
cptr_t rp0;
/* the secret cspace for local caps like the grant object */
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment