From d43fa1d3ae1c9bcfe2b9a4c2eb1b72406ea3b935 Mon Sep 17 00:00:00 2001 From: Bahadir Balban Date: Mon, 9 Nov 2009 23:50:03 +0200 Subject: [PATCH] Simplified cap id finding and destroying it. It is not very straightforward to reach a capabilities list. We now use a single function to find out a capability by its id and its list, since the two are used frequently together (i.e. cap removal and destruction) --- include/l4/generic/capability.h | 4 +-- src/api/cap.c | 25 +++++++++------ src/generic/capability.c | 56 ++++++--------------------------- 3 files changed, 27 insertions(+), 58 deletions(-) diff --git a/include/l4/generic/capability.h b/include/l4/generic/capability.h index 9bc5623..d905e8c 100644 --- a/include/l4/generic/capability.h +++ b/include/l4/generic/capability.h @@ -146,9 +146,7 @@ struct capability *capability_find_by_rtype(struct ktcb *task, struct capability *cap_list_find_by_rtype(struct cap_list *clist, unsigned int rtype); -struct capability *cap_find_byid(l4id_t capid); - -int cap_find_destroy(l4id_t capid); +struct capability *cap_find_by_capid(l4id_t capid, struct cap_list **clist); /* Capability checking on system calls */ int cap_map_check(struct ktcb *task, unsigned long phys, unsigned long virt, diff --git a/src/api/cap.c b/src/api/cap.c index 152ab59..512c31a 100644 --- a/src/api/cap.c +++ b/src/api/cap.c @@ -61,15 +61,16 @@ int cap_read_all(struct capability *caparray) int cap_share_single(l4id_t capid) { struct capability *cap; + struct cap_list *clist; - if (!(cap = cap_find_byid(capid))) + if (!(cap = cap_find_by_capid(capid, &clist))) return -EEXIST; if (cap->owner != current->tid) return -EPERM; /* First remove it from its list */ - list_remove(&cap->list); + cap_list_remove(cap, clist); /* Place it where it is shared */ cap_list_insert(cap, &curcont->cap_list); @@ -145,9 +146,10 @@ out_err: int cap_grant_single(struct capability *req, unsigned int flags) { struct capability *cap; + struct cap_list *clist; struct ktcb *target; - if (!(cap = cap_find_byid(req->capid))) + if (!(cap = cap_find_by_capid(req->capid, &clist))) return -EEXIST; if (!(target = tcb_find(req->owner))) @@ -161,7 +163,7 @@ int cap_grant_single(struct capability *req, unsigned int flags) return -EPERM; /* First remove it from its list */ - list_remove(&cap->list); + cap_list_remove(cap, clist); /* Change ownership */ cap->owner = target->tid; @@ -272,10 +274,11 @@ int cap_deduce_rtype(struct capability *orig, struct capability *new) int cap_deduce(struct capability *new) { struct capability *orig; + struct cap_list *clist; int ret; /* Find original capability */ - if (!(orig = cap_find_byid(new->capid))) + if (!(orig = cap_find_by_capid(new->capid, &clist))) return -EEXIST; /* Check that caller is owner */ @@ -353,9 +356,10 @@ int cap_deduce(struct capability *new) int cap_destroy(struct capability *cap) { struct capability *orig; + struct cap_list *clist; /* Find original capability */ - if (!(orig = cap_find_byid(cap->capid))) + if (!(orig = cap_find_by_capid(cap->capid, &clist))) return -EEXIST; /* Check that caller is owner */ @@ -366,7 +370,8 @@ int cap_destroy(struct capability *cap) if (!(cap_generic_perms(orig) & CAP_CHANGEABLE)) return -ENOCAP; - cap_find_destroy(cap->capid); + cap_list_remove(orig, clist); + free_capability(orig); return 0; } @@ -399,10 +404,11 @@ static inline int cap_has_range(struct capability *c) int cap_split(struct capability *diff, unsigned int flags) { struct capability *orig, *new; + struct cap_list *clist; int ret; /* Find original capability */ - if (!(orig = cap_find_byid(diff->capid))) + if (!(orig = cap_find_by_capid(diff->capid, &clist))) return -EEXIST; /* Check target type/resid/owner is the same */ @@ -576,9 +582,10 @@ out_err: int cap_replicate(struct capability *dupl) { struct capability *new, *orig; + struct cap_list *clist; /* Find original capability */ - if (!(orig = cap_find_byid(dupl->capid))) + if (!(orig = cap_find_by_capid(dupl->capid, &clist))) return -EEXIST; /* Check that caller is owner */ diff --git a/src/generic/capability.c b/src/generic/capability.c index 00e95ad..2cabacb 100644 --- a/src/generic/capability.c +++ b/src/generic/capability.c @@ -128,70 +128,35 @@ struct capability *capability_find_by_rtype(struct ktcb *task, return 0; } -/* - * FIXME: Make these functions pass a match function to cap_find() - * and remove all duplication. Same goes for find_rtype. - */ -struct capability *cap_find_byid(l4id_t capid) +struct capability *cap_find_by_capid(l4id_t capid, struct cap_list **cap_list) { struct capability *cap; struct ktcb *task = current; /* Search task's own list */ list_foreach_struct(cap, &task->cap_list.caps, list) - if (cap->capid == capid) + if (cap->capid == capid) { + *cap_list = &task->cap_list; return cap; + } /* Search space list */ list_foreach_struct(cap, &task->space->cap_list.caps, list) - if (cap->capid == capid) + if (cap->capid == capid) { + *cap_list = &task->space->cap_list; return cap; + } /* Search container list */ list_foreach_struct(cap, &task->container->cap_list.caps, list) - if (cap->capid == capid) + if (cap->capid == capid) { + *cap_list = &task->container->cap_list; return cap; + } return 0; } -/* - * TODO: Instead of destroying, use cap_find_byid match function's - * match_args to pass a pointer to the capability list, so the - * caller may destroy it - */ -int cap_find_destroy(l4id_t capid) -{ - struct capability *cap; - struct ktcb *task = current; - - /* Search task's own list */ - list_foreach_struct(cap, &task->cap_list.caps, list) - if (cap->capid == capid) { - cap_list_remove(cap, &task->cap_list); - free_capability(cap); - return 0; - } - - /* Search space list */ - list_foreach_struct(cap, &task->space->cap_list.caps, list) - if (cap->capid == capid) { - cap_list_remove(cap, &task->space->cap_list); - free_capability(cap); - return 0; - } - - /* Search container list */ - list_foreach_struct(cap, &task->container->cap_list.caps, list) - if (cap->capid == capid) { - cap_list_remove(cap, &task->container->cap_list); - free_capability(cap); - return 0; - } - - return -EEXIST; -} - typedef struct capability *(*cap_match_func_t) \ (struct capability *cap, void *match_args); @@ -543,7 +508,6 @@ struct capability *cap_match_thread(struct capability *cap, if (!(cap->access & CAP_TCTRL_WAIT)) return 0; break; - default: /* We refuse to accept anything else */ return 0;