Commit 39722811 authored by Josh Kunz's avatar Josh Kunz

Merge branch 'node-reset-fixup'

parents 3996dbac 6e9936f3
Pipeline #1884 passed with stage
in 30 seconds
......@@ -20,11 +20,11 @@ n1 = p.rp0().recv()
# Mint a copy of this node capability
n1_1 = n1.mint()
# Create a new rendezvous point
rp1 = p.create(RP)
# Reset the node, and set its rp0 to rp1
n1.reset(rp1)
grant = n1.reset()
# Get the RP0 of the newly reset node
rp1 = grant.rp0()
# Send it a capability to itself
rp1.send(n1_1)
......@@ -672,16 +672,12 @@ class Node(Capability):
reply = self.protocol._invoke(self, cn_pb.CPOBJMETHOD_NODE_INFO, None)
return reply.item.node_info
def reset(self, rp):
"""Reset this node, and set its RP0 to the given RP.
def reset(self):
"""Reset this node.
Returns a node grant capability.
Returns a node grant capability for this node.
"""
args = cn_pb.CPInvokeNodeResetArgs()
assert rp.__class__ == RP
args.rp_cptr = rp.cptr
reply = self.protocol._invoke(self, cn_pb.CPOBJMETHOD_NODE_RESET,
("node_reset_args", args))
reply = self.protocol._invoke(self, cn_pb.CPOBJMETHOD_NODE_RESET, None)
return reply.item.capability
# Exception raised when there is a protocol violation in the recv_iter protocol
......@@ -917,6 +913,15 @@ class NodeGrant(Capability):
("node_grant_grant_args", args))
assert reply.has_no_items
def rp0(self):
"""Get the RP0 of the node this grant was created from.
Returns a capability to the appropriate RP.
"""
reply = self.protocol._invoke(self, cn_pb.CPOBJMETHOD_NODE_GRANT_RP0, None)
return reply.item.capability
def flow(self, *args):
"""Create a new flow for the node this node grant was obtained from
with the given restrictions.
......
......@@ -17,8 +17,8 @@ def recv_preamble(p):
def recv_nodes(p, rp_iter):
nodes = {}
for node in rp_iter:
node_rp = p.create(capnet.RP)
grant = node.reset(node_rp)
grant = node.reset()
node_rp = grant.rp0()
info = node.info()
flow = grant.flow()
nodes[info.name] = NodeProperties(node, grant, info, node_rp, flow)
......
......@@ -82,6 +82,8 @@ static cn_method_t __cn_method_for_CPObjMethod(Cp__CPObjMethod m) {
return CN_MEMBRANE_RECV_WAIT;
case CP__CPOBJ_METHOD__CPOBJMETHOD_NODE_GRANT_GRANT:
return CN_NODE_GRANT_GRANT;
case CP__CPOBJ_METHOD__CPOBJMETHOD_NODE_GRANT_RP0:
return CN_NODE_GRANT_RP0;
case CP__CPOBJ_METHOD__CPOBJMETHOD_SEALER_UNSEALER_SEAL:
return CN_SEALER_UNSEALER_SEAL;
case CP__CPOBJ_METHOD__CPOBJMETHOD_SEALER_UNSEALER_UNSEAL:
......@@ -627,12 +629,6 @@ static int __cn_handle_invoke_message(cn_principal_t *as,
res = cn_dispatch_invoke(as, result, ul2cptr(msg->cptr), method,
&broker_lookup_wait_args);
break;
case CN_NODE_RESET:
ASSERT_INVOKE_ARGS("node.reset", CP__CPINVOKE__ARGS_NODE_RESET_ARGS)
cn_dispatch_invoke_node_reset_args_t reset_args;
reset_args.rp = ul2cptr(msg->node_reset_args->rp_cptr);
res = cn_dispatch_invoke(as, result, ul2cptr(msg->cptr), method, &reset_args);
break;
case CN_NODE_GRANT_GRANT:
ASSERT_INVOKE_ARGS("node_grant.grant", CP__CPINVOKE__ARGS_NODE_GRANT_GRANT_ARGS)
cn_dispatch_invoke_node_grant_grant_args_t grant_args;
......@@ -859,13 +855,14 @@ static int __cn_dispatch_create_flow(cn_principal_t *as,
}
if (cn_cnode_type(*cnode) != CN_NODE_GRANT) {
res = cn_dispatch_result_fail(result, "Node grant capability is not actually a node grant");
res = cn_dispatch_result_fail(result, "Node grant capability is not actually a node grant, it's a %s",
cn_objtype_name(cn_cnode_type(*cnode)));
goto finish;
}
node = ((cn_node_grant_t *) cn_cnode_object(*cnode))->node;
} else {
node = (cn_node_t *) as->owner;
assert(node && "Triede ot create flow in principal with NULL owner");
assert(node && "Tried to create flow in principal with NULL owner");
assert(((cn_obj_t *) node)->type == CN_NODE
&& "Tried to create flow with nodeless owner");
*cnode = NULL;
......@@ -1008,10 +1005,11 @@ int cn_dispatch_create(cn_principal_t *as, cn_dispatch_result_t *result,
} else {
assert(obj_base == NULL && "valid cnode but no args");
cn_obj_lock(as->owner);
assert(as == ((cn_node_t *) as->owner)->principal
&& "node principal should always be invoker");
node_grant = ((cn_node_t *) as->owner)->grant;
cn_obj_unlock(as->owner);
}
c_log_debug("doing derive!");
if (cn_derive(as, node_grant, as, obj_cptr, NULL) != 0) {
cn_delete(as, obj_cptr, NULL);
res = cn_dispatch_result_fail(result, "Cannot perform derive operation on flow");
......@@ -1213,14 +1211,13 @@ int cn_dispatch_invoke(cn_principal_t *as, cn_dispatch_result_t *result,
}
break;
case CN_NODE_RESET: {
cn_dispatch_invoke_node_reset_args_t * reset_args = args;
assert(obj->type == CN_NODE && "Somehow calling reset on non-node");
//RHOLD_OBJ(obj, DISPATCH_OWNER);
//cap_cnode_put(obj_cnode);
//obj_cnode = NULL; // signal we don't need to put the cnode anymore
c_log_debug("Doing reset!");
cptr_t grant_cptr;
if (cn_node_reset(obj_cnode, as, reset_args->rp, &grant_cptr) != 0) {
if (cn_node_reset(obj_cnode, &grant_cptr) != 0) {
res = fail_invoke(result, "cn_node_reset failed: %d", res);
goto fail1;
}
......@@ -1331,6 +1328,15 @@ int cn_dispatch_invoke(cn_principal_t *as, cn_dispatch_result_t *result,
}
}
break;
case CN_NODE_GRANT_RP0: {
cptr_t rp0;
if (cn_node_grant_rp0(obj_cnode, &rp0) != 0) {
res = fail_invoke(result, "failed to get rp0 from node grant");
goto fail1;
}
push_item_cptr(result, rp0, CN_RP);
}
break;
case CN_SEALER_UNSEALER_SEAL: {
cn_dispatch_invoke_sealer_unsealer_seal_args_t * seal_args = args;
cn_objtype_t type;
......
......@@ -32,6 +32,7 @@ typedef enum {
CN_MEMBRANE_CLEAR,
CN_MEMBRANE_RECV_WAIT,
CN_NODE_GRANT_GRANT,
CN_NODE_GRANT_RP0,
CN_SEALER_UNSEALER_SEAL,
CN_SEALER_UNSEALER_UNSEAL,
CN_SEALER_UNSEALER_RESTRICT_TO_SEAL,
......@@ -53,6 +54,7 @@ static const char * METHOD_NAMES[] = {
"membrane_clear",
"membrane_recv_wait",
"node_grant_grant",
"node_grant_rp0",
"sealer_unsealer_seal",
"sealer_unsealer_unseal",
"sealer_unsealer_restrict_to_seal",
......@@ -210,10 +212,6 @@ typedef struct {
struct cn_rp_elem_message msg;
} cn_dispatch_invoke_rp_send_args_t;
typedef struct {
cptr_t rp;
} cn_dispatch_invoke_node_reset_args_t;
typedef struct {
cptr_t cap;
} cn_dispatch_invoke_membrane_send_args_t;
......
......@@ -880,6 +880,12 @@ int cn_membrane_grant(cn_cnode_meta_t * send_meta,
cn_principal_t *receiver,
cptr_t *o_cap, cn_objtype_t *type) {
/* If there are actually no annotations at play, just do a normal grant. */
if (! cn_cnode_meta_is_annotated(send_meta)
&& ! cn_cnode_meta_is_annotated(recv_meta)) {
return cn_grant_extended(granter, granted, receiver, NULL, o_cap, type);
}
int res = -1;
cn_cnode_meta_t * _allocated_meta = NULL;
......@@ -1190,13 +1196,12 @@ int cn_cnode_meta_copy(cn_cnode_meta_t *m, cn_cnode_meta_t **m_copy) {
/* Returns true if the given meta object is annotated*/
bool cn_cnode_meta_is_annotated(cn_cnode_meta_t *m) {
return g_hash_table_size(m->annotations) > 0;
return m != NULL && g_hash_table_size(m->annotations) > 0;
}
/* Returns true if the given cnode is annotated*/
bool cn_cnode_is_annotated(struct cnode *c) {
cn_cnode_meta_t *m = (cn_cnode_meta_t *) cap_cnode_metadata(c);
if (m == NULL) { return false; }
return cn_cnode_meta_is_annotated(m);
}
......@@ -1365,6 +1370,18 @@ bool cn_method_mask_permission_is_set(method_mask_t * mask, cn_method_t m) {
/* sec: Normal Capability Operations */
char * cn_cnode_string(struct cnode * c) {
cn_obj_t * obj = cn_cnode_object(c);
return g_strdup_printf("(cnode (cptr %p %#lx) (type %s) (obj %p %s))",
cn_cnode_principal(c), cptr2ul(cap_cnode_cptr(c)),
cn_objtype_name(cn_cnode_type(c)),
obj, (obj ? cn_objtype_name(obj->type) : NULL));
}
char * cn_cptr_string(cn_principal_t *p, cptr_t c) {
return g_strdup_printf("(cptr %p %#lx)", p, cptr2ul(c));
}
int cn_grant_cnode_extended(struct cnode * ca,
cn_principal_t *dest, void * payload,
cptr_t *out, cn_objtype_t *o_type) {
......@@ -1508,7 +1525,7 @@ finish:
/* sec: Node Manipulation */
int cn_node_reset(struct cnode * node, cn_principal_t * p, cptr_t rp, cptr_t *o_grant) {
int cn_node_reset(struct cnode * node, cptr_t *o_grant) {
int res = -1;
assert(cn_cnode_type(node) == CN_NODE && "Tried to invoke reset on non-node");
cn_node_t * n = (cn_node_t *) cn_cnode_object(node);
......@@ -1522,56 +1539,77 @@ int cn_node_reset(struct cnode * node, cn_principal_t * p, cptr_t rp, cptr_t *o_
goto finish;
}
RHOLD_OBJ(grant, OBJ_OWNER);
cn_rp_t * rp0;
if (cn_rp_new(&rp0) != 0) {
cncerr("failed to create new rp\n");
res = -1;
goto finish1;
}
RHOLD_OBJ(rp0, OBJ_OWNER);
cncinfo("Revoking grant chain (cap: %#0lx)\n", cptr2ul(n->grant));
cn_revoke(n->secret, n->grant, NULL);
cncinfo("Deleting grant\n");
cn_delete(n->secret, n->grant, NULL);
if ((res = cn_principal_clear(n->principal)) != 0) {
cncerr("principal clear failed\n");
goto finish; }
goto finish2; }
n->principal->owner = n;
if ((res = cn_principal_insert(n->secret, (cn_obj_t *) grant, NULL, &n->grant)) != 0) {
cncerr("Failed to insert grant into node's secret principal\n");
goto finish;
goto finish2;
}
struct cnode * grant_cnode;
if ((res = cn_principal_get(n->secret, n->grant, &grant_cnode)) != 0) {
cncerr("Failed to lookup the grant object we just inserted\n");
goto finish;
goto finish2;
}
/* insert the node grant into the CDT of the node cap from which it was
* derived. */
if ((res = cap_derive_cnode(node, grant_cnode, NULL)) != 0) {
cncerr("Failed to derive the grant cnode from the node cnode\n");
cap_delete_cnode(grant_cnode, NULL);
goto finish;
goto finish2;
}
cap_cnode_put(grant_cnode);
grant_cnode = NULL;
if ((res = cn_grant(n->secret, n->grant, p, NULL, o_grant)) != 0) {
cncerr("Failed to grant grant obj to caller\n");
/* give the node access to its RP0 */
if ((res = cn_principal_insert(n->secret, cn_obj_ref(rp0), NULL, &n->rp0)) != 0) {
cncerr("rp0 insert failed");
cn_delete(n->secret, n->grant, NULL);
goto finish;
goto finish2;
}
// XXX: Need to deal with what to do with the RP0 of wrapped nodes, does
// it turn into a wrapping/uwrapping RP0?
// XXX: Basic outline of a solution below:
// Check if this node is wrapped....
// if so, then wrap the given RP. This rp should turn into an 'internal'
// membrane basically.
// If not, just do a normal RP0 grant.
if ((res = cn_grant(p, rp, n->principal, NULL, &n->rp0)) != 0) {
cncerr("rp0 grant failed\n");
cn_revoke(n->secret, n->grant, NULL);
/* A wrapped node being reset should produce a wrapped node grant. Conceptually,
* if the node capability is wrapped, then the entity performing the reset is
* "outside" of the node with respect to the given wraps. We use the metadata of
* the node as the "recv_meta" because those accurately reflect the position of
* the receiver. The node itself on the other hand is always "internal" with
* respect to its own node grant. */
cn_objtype_t type;
if ((res = cn_membrane_grant(/*send_meta=*/NULL, /*recv_meta=*/cap_cnode_metadata(node),
n->secret, n->grant, cn_cnode_principal(node),
o_grant, &type)) != 0) {
cncerr("Failed to grant grant obj to caller\n");
cn_delete(n->secret, n->grant, NULL);
goto finish;
goto finish2;
}
res = 0;
goto finish;
finish2:
RPUTs_OBJ(rp0, OBJ_OWNER);
finish1:
RPUTs_OBJ(grant, OBJ_OWNER);
finish:
cn_obj_unlock(n);
......@@ -1587,18 +1625,42 @@ int cn_node_grant_grant(struct cnode * grant_cnode,
cn_abort("Tried to grant using non-node_grant");
}
cn_node_grant_t * grant = (cn_node_grant_t *) cn_cnode_object(grant_cnode);
// Do membrane grant if we're annotated
if (cn_cnode_is_annotated(grant_cnode)) {
cn_cnode_meta_t * meta = (cn_cnode_meta_t *) cap_cnode_metadata(grant_cnode);
assert(meta != NULL && "meta cannot be NULL when cnode wrapped");
cn_obj_lock(grant);
cn_obj_lock(grant->node);
int res = cn_membrane_grant(cap_cnode_metadata(grant_cnode), /*recv_meta=*/NULL,
p, cap, grant->node->principal, o_cap, o_type);
return cn_membrane_grant(meta, NULL, p, cap, grant->node->principal,
o_cap, o_type);
if (res != 0) {
cncerr("Failed membrane_grant in cn_node_grant_grant with code: %d\n", res);
}
// Otherwise, just do a normal grant operaion
return cn_grant_extended(p, cap, grant->node->principal, NULL, o_cap, o_type);
cn_obj_unlock(grant->node);
cn_obj_unlock(grant);
return res;
}
int cn_node_grant_rp0(struct cnode * grant_cnode, cptr_t *o_rp_cap) {
assert(cn_cnode_type(grant_cnode) == CN_NODE_GRANT);
cn_node_grant_t * grant = (cn_node_grant_t *) cn_cnode_object(grant_cnode);
cn_obj_lock(grant);
cn_obj_lock(grant->node);
cn_objtype_t type;
int res = cn_membrane_grant(cap_cnode_metadata(grant_cnode), /*recv_meta=*/NULL,
grant->node->secret, grant->node->rp0,
cn_cnode_principal(grant_cnode), o_rp_cap, &type);
if (res != 0) {
cncerr("cn_membrane_grant failed for node_grant_rp0");
}
cn_obj_unlock(grant->node);
cn_obj_unlock(grant);
return res;
}
/* sec: RP Manipulation */
......
......@@ -872,7 +872,7 @@ int cn_delete_flow_cb(struct cnode *flow_cnode, void * payload);
* current grant object for this node (if it exists) and creates a new one. A
* capability to the grant object for the given principal (`p`)
* is stored in `o_grant`. Returns 0 on success, and a negative value on error. */
int cn_node_reset(struct cnode * node, cn_principal_t * p, cptr_t rp, cptr_t *o_grant);
int cn_node_reset(struct cnode * node, cptr_t *o_grant);
/* --------- Node Grant Manipulation --------- */
......@@ -883,6 +883,10 @@ int cn_node_grant_grant(struct cnode * grant_cnode,
cn_principal_t *p, cptr_t cap,
cptr_t *o_cap, cn_objtype_t * o_type);
/* Fetch the RP0 of the node this grant is for. A capability to the node's
* RP0 is stored in `o_rp_cap`. Returns 0 on success. */
int cn_node_grant_rp0(struct cnode * grant_cnode, cptr_t *o_rp_cap);
/* --------- RP Manipulation --------- */
/* Creates a "normal" rp_elem struct that consistes of a principal and a
......
......@@ -24,6 +24,10 @@ static int cn_dispatch_caller_binop(struct cnode * ca, struct cnode *cb,
/* Generic delete callback that just decrefs the object the cnode contains */
int cn_default_delete_cb(struct cnode *cnode, void * payload) {
cncinfo("[delete] (cap (principal %p) (cptr %#0lx) (obj-type %s))\n",
cn_cnode_principal(cnode),
cptr2ul(cap_cnode_cptr(cnode)),
cn_objtype_name(cn_cnode_type(cnode)));
cn_obj_t *obj = (cn_obj_t *) cap_cnode_object(cnode);
cn_obj_lock(obj);
assert(cn_cnode_type(cnode) == obj->type
......@@ -223,7 +227,7 @@ end1:
cn_obj_unlock(flow);
cn_obj_unlock(owner);
end:
c_log_debug("default cb...");
cncinfo("flow doing default delete cb\n");
ret = cn_default_delete_cb(flow_cnode, payload);
cn_obj_unlock(principal);
return ret;
......
......@@ -44,5 +44,9 @@ enum cn_rp_recv_result_flag {
// 0x3 (the low two bits reserved)
};
/* Utilities */
char * cn_cnode_string(struct cnode * c);
char * cn_cptr_string(cn_principal_t *p, cptr_t c);
#endif
......@@ -170,6 +170,7 @@ enum CPObjMethod {
CPOBJMETHOD_BROKER_LOOKUP = 7;
CPOBJMETHOD_BROKER_LOOKUP_WAIT = 17;
CPOBJMETHOD_NODE_GRANT_GRANT = 10;
CPOBJMETHOD_NODE_GRANT_RP0 = 18;
CPOBJMETHOD_SEALER_UNSEALER_SEAL = 13;
CPOBJMETHOD_SEALER_UNSEALER_UNSEAL = 14;
CPOBJMETHOD_SEALER_UNSEALER_RESTRICT_TO_SEAL = 15;
......@@ -185,10 +186,6 @@ message CPInvokeMembraneSendArgs {
required fixed64 cptr = 1;
}
message CPInvokeNodeResetArgs {
required fixed64 rp_cptr = 1;
}
message CPInvokeBrokerRegisterArgs {
required string service_name = 1;
required fixed64 rp_cptr = 2;
......@@ -227,7 +224,6 @@ message CPInvoke {
// Additional arguments (if any)
oneof args {
CPInvokeRPSendArgs rp_send_args = 3;
CPInvokeNodeResetArgs node_reset_args = 4;
CPInvokeMembraneSendArgs membrane_send_args = 5;
CPInvokeBrokerRegisterArgs broker_register_args = 6;
CPInvokeBrokerLookupArgs broker_lookup_args = 7;
......
......@@ -36,6 +36,9 @@ extern struct argp log_argp;
__FUNCTION__, __LINE__, ## __VA_ARGS__)
#define cncwarnc(format,...) fprintf(stdout,format, ## __VA_ARGS__)
#define cncinfo(format,...) fprintf(stdout,"CINFO: %s:%d: "format, \
__FUNCTION__, __LINE__, ## __VA_ARGS__)
#define cncwarnopt(level,area,flags,format,...) _cnc_warn(level,area,flags, \
"CWARNING: %s:%d: "format, \
__FUNCTION__, __LINE__, \
......
This diff is collapsed.
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