diff --git a/conts/posix/mm0/include/capability.h b/conts/posix/mm0/include/capability.h index 317a78d..49517f5 100644 --- a/conts/posix/mm0/include/capability.h +++ b/conts/posix/mm0/include/capability.h @@ -35,6 +35,48 @@ struct capability { }; +static inline void cap_list_init(struct cap_list *clist) +{ + clist->ncaps = 0; + link_init(&clist->caps); +} + +static inline void cap_list_insert(struct capability *cap, + struct cap_list *clist) +{ + list_insert(&cap->list, &clist->caps); + clist->ncaps++; +} + +/* Detach a whole list of capabilities from list head */ +static inline struct capability * +cap_list_detach(struct cap_list *clist) +{ + struct link *list = list_detach(&clist->caps); + clist->ncaps = 0; + return link_to_struct(list, struct capability, list); +} + +/* Attach a whole list of capabilities to list head */ +static inline void cap_list_attach(struct capability *cap, + struct cap_list *clist) +{ + /* Attach as if cap is the list and clist is the element */ + list_insert(&clist->caps, &cap->list); + + /* Count the number of caps attached */ + list_foreach_struct(cap, &clist->caps, list) + clist->ncaps++; +} + +static inline void cap_list_move(struct cap_list *to, + struct cap_list *from) +{ + struct capability *cap_head = cap_list_detach(from); + cap_list_attach(cap_head, to); +} + + extern struct cap_list capability_list; struct initdata; diff --git a/conts/posix/mm0/mm/init.c b/conts/posix/mm0/mm/init.c index 714e374..f706cdf 100644 --- a/conts/posix/mm0/mm/init.c +++ b/conts/posix/mm0/mm/init.c @@ -163,7 +163,9 @@ void copy_boot_capabilities(int ncaps) { struct capability *cap; + capability_list.ncaps = 0; link_init(&capability_list.caps); + for (int i = 0; i < total_caps; i++) { cap = kzalloc(sizeof(struct capability)); @@ -174,9 +176,8 @@ void copy_boot_capabilities(int ncaps) link_init(&cap->list); /* Add capability to global cap list */ - list_insert(&cap->list, &capability_list.caps); + cap_list_insert(cap, &capability_list); } - capability_list.ncaps = ncaps; } #if 0 @@ -305,8 +306,13 @@ void cap_print(struct capability *cap) void cap_list_print(struct cap_list *cap_list) { struct capability *cap; + printf("Capabilities\n" + "~~~~~~~~~~~~\n"); + list_foreach_struct(cap, &cap_list->caps, list) cap_print(cap); + + printf("\n"); } /* * Replicate, deduce and grant to children the capability to @@ -320,18 +326,18 @@ void cap_list_print(struct cap_list *cap_list) * into a capability to only talk to our current space. Our space is a * reduced target, since it is a subset contained in our container. */ -int setup_children_caps(int total_caps, struct cap_list *capability_list) +int setup_children_caps(int total_caps, struct cap_list *cap_list) { - struct capability ipc_cap, *cap; + struct capability *ipc_cap, *cap; struct task_ids ids; int err; l4_getid(&ids); - cap_list_print(capability_list); + cap_list_print(cap_list); /* Find out our own ipc capability on our own container */ - list_foreach_struct(cap, &capability_list->caps, list) { + list_foreach_struct(cap, &cap_list->caps, list) { if (cap_type(cap) == CAP_TYPE_IPC && cap_rtype(cap) == CAP_RTYPE_CONTAINER && cap->resid == __cid(ids.tid)) @@ -343,20 +349,25 @@ int setup_children_caps(int total_caps, struct cap_list *capability_list) BUG(); found: + /* Create a new capability */ + BUG_ON(!(ipc_cap = kzalloc(sizeof(*ipc_cap)))); + /* Copy it over to new ipc cap buffer */ - memcpy(&ipc_cap, cap, sizeof (*cap)); + memcpy(ipc_cap, cap, sizeof (*cap)); /* Replicate the ipc capability, giving original as reference */ if ((err = l4_capability_control(CAP_CONTROL_REPLICATE, - 0, 0, 0, &ipc_cap)) < 0) { + 0, 0, 0, ipc_cap)) < 0) { printf("l4_capability_control() replication of " "ipc capability failed.\n Could not " "complete CAP_CONTROL_REPLICATE request on cap (%d), " - "err = %d.\n", ipc_cap.capid, err); + "err = %d.\n", ipc_cap->capid, err); BUG(); } - cap_list_print(capability_list); + /* Add it to list */ + cap_list_insert(ipc_cap, cap_list); + cap_list_print(cap_list); /* * The returned capability is a replica. @@ -364,18 +375,18 @@ found: * Now deduce it such that it applies to talking only to us, * instead of to the whole container as original. */ - cap_set_rtype(&ipc_cap, CAP_RTYPE_SPACE); - ipc_cap.resid = __cid(ids.spid); /* This space is target resource */ + cap_set_rtype(ipc_cap, CAP_RTYPE_SPACE); + ipc_cap->resid = ids.spid; /* This space is target resource */ if ((err = l4_capability_control(CAP_CONTROL_DEDUCE, - 0, 0, 0, &ipc_cap)) < 0) { + 0, 0, 0, ipc_cap)) < 0) { printf("l4_capability_control() deduction of " "ipc capability failed.\n Could not " "complete CAP_CONTROL_DEDUCE request on cap (%d), " - "err = %d.\n", ipc_cap.capid, err); + "err = %d.\n", ipc_cap->capid, err); BUG(); } - cap_list_print(capability_list); + cap_list_print(cap_list); /* * Share it with our container. @@ -384,13 +395,14 @@ found: * to communicate to us only, and be able to do nothing else. */ if ((err = l4_capability_control(CAP_CONTROL_SHARE, CAP_SHARE_SINGLE, - ipc_cap.capid, 0, 0)) < 0) { + ipc_cap->capid, 0, 0)) < 0) { printf("l4_capability_control() sharing of " "capabilities failed.\n Could not " "complete CAP_CONTROL_SHARE request.\n"); BUG(); } - cap_list_print(capability_list); + cap_list_print(cap_list); + return 0; } diff --git a/include/l4/generic/cap-types.h b/include/l4/generic/cap-types.h index 88dcaff..5df4e33 100644 --- a/include/l4/generic/cap-types.h +++ b/include/l4/generic/cap-types.h @@ -37,7 +37,7 @@ #define cap_rtype(c) ((c)->type & CAP_RTYPE_MASK) #define cap_set_rtype(c, rtype) \ - {(c)->type &= CAP_RTYPE_MASK; \ + {(c)->type &= ~CAP_RTYPE_MASK; \ (c)->type |= CAP_RTYPE_MASK & rtype;} /* diff --git a/src/api/cap.c b/src/api/cap.c index 4ed4a28..4ade8ae 100644 --- a/src/api/cap.c +++ b/src/api/cap.c @@ -306,13 +306,13 @@ int cap_deduce(struct capability *new) * orig = orig - diff; * new = diff; */ -int cap_split(l4id_t capid, struct capability *diff) +int cap_split(struct capability *diff) { struct capability *orig, *new; /* Find original capability */ - if (!(orig = cap_find_byid(capid))) - return -ENOCAP; + if (!(orig = cap_find_byid(diff->capid))) + return -EEXIST; /* Check target type/resid/owner is the same */ if (orig->type != diff->type || @@ -421,12 +421,13 @@ int cap_split(l4id_t capid, struct capability *diff) * system, but as it is not a quantity, this does not increase * the capabilities of the caller in any way. */ -int cap_replicate(l4id_t capid, struct capability *dupl) +int cap_replicate(struct capability *dupl) { struct capability *new, *orig; /* Find original capability */ - orig = cap_find_byid(capid); + if (!(orig = cap_find_byid(dupl->capid))) + return -EEXIST; /* Check that caller is owner */ if (orig->owner != current->tid) @@ -450,21 +451,21 @@ int cap_replicate(l4id_t capid, struct capability *dupl) return -ENOCAP; /* Copy all except capid & listptrs */ - new->resid = orig->resid; - new->owner = orig->owner; - new->type = orig->type; - new->access = orig->access; - new->start = orig->start; - new->end = orig->end; - new->size = orig->size; - new->used = orig->used; + dupl->resid = new->resid = orig->resid; + dupl->owner = new->owner = orig->owner; + dupl->type = new->type = orig->type; + dupl->access = new->access = orig->access; + dupl->start = new->start = orig->start; + dupl->end = new->end = orig->end; + dupl->size = new->size = orig->size; + dupl->used = new->used = orig->used; + + /* Copy new fields */ + dupl->capid = new->capid; /* Add it to most private list */ cap_list_insert(new, TASK_CAP_LIST(current)); - /* Return new capability to user */ - memcpy(dupl, new, sizeof(*new)); - return 0; } @@ -474,7 +475,7 @@ int cap_replicate(l4id_t capid, struct capability *dupl) int sys_capability_control(unsigned int req, unsigned int flags, l4id_t capid, l4id_t target, void *userbuf) { - int err; + int err = 0; /* * Check capability to do a capability operation. @@ -509,7 +510,7 @@ int sys_capability_control(unsigned int req, unsigned int flags, err = cap_grant(flags, capid, target); break; case CAP_CONTROL_SPLIT: - err = cap_split(capid, (struct capability *)userbuf); + err = cap_split((struct capability *)userbuf); break; case CAP_CONTROL_REPLICATE: if ((err = check_access((unsigned long)userbuf, @@ -517,7 +518,7 @@ int sys_capability_control(unsigned int req, unsigned int flags, MAP_USR_RW_FLAGS, 1)) < 0) return err; - err = cap_replicate(capid, (struct capability *)userbuf); + err = cap_replicate((struct capability *)userbuf); break; case CAP_CONTROL_DEDUCE: if ((err = check_access((unsigned long)userbuf, @@ -527,12 +528,11 @@ int sys_capability_control(unsigned int req, unsigned int flags, err = cap_deduce((struct capability *)userbuf); break; - default: /* Invalid request id */ return -EINVAL; } - return 0; + return err; } diff --git a/src/api/ipc.c b/src/api/ipc.c index 020ee14..95c39d9 100644 --- a/src/api/ipc.c +++ b/src/api/ipc.c @@ -537,6 +537,7 @@ int sys_ipc(l4id_t to, l4id_t from, unsigned int flags) { unsigned int ipc_type = 0; int ret = 0; + struct ktcb *t = current; if (!t); /* Check arguments */ if (task_id_special(from) &&