From 2ba4736a8b0cacfb1f0dae94eb792ae298f490de Mon Sep 17 00:00:00 2001 From: Bahadir Balban Date: Tue, 10 Nov 2009 16:15:14 +0200 Subject: [PATCH] Cleaned up various bits with capability syscalls. Made grant interace same as other calls. Corrected counting and reading of task capabilities by applying it to all cap lists that a task has right. --- conts/posix/mm0/mm/capability.c | 6 +- include/l4/api/capability.h | 4 - include/l4/generic/capability.h | 2 +- src/api/cap.c | 144 ++++++++++++++------------------ src/generic/capability.c | 9 +- 5 files changed, 73 insertions(+), 92 deletions(-) diff --git a/conts/posix/mm0/mm/capability.c b/conts/posix/mm0/mm/capability.c index cdf6f6d..1b36085 100644 --- a/conts/posix/mm0/mm/capability.c +++ b/conts/posix/mm0/mm/capability.c @@ -176,7 +176,7 @@ found: * to use this pool of mutexes. */ if ((err = l4_capability_control(CAP_CONTROL_SHARE, CAP_SHARE_SINGLE, - mutex_cap->capid, 0, 0)) < 0) { + 0, 0, mutex_cap)) < 0) { printf("l4_capability_control() sharing of " "capabilities failed.\n Could not " "complete CAP_CONTROL_SHARE request.\n"); @@ -204,7 +204,7 @@ found2: * to use this pool of mutexes. */ if ((err = l4_capability_control(CAP_CONTROL_SHARE, CAP_SHARE_SINGLE, - mutex_cap->capid, 0, 0)) < 0) { + 0, 0, mutex_cap)) < 0) { printf("l4_capability_control() sharing of " "capabilities failed.\n Could not " "complete CAP_CONTROL_SHARE request.\n"); @@ -296,7 +296,7 @@ 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) { + 0, 0, ipc_cap)) < 0) { printf("l4_capability_control() sharing of " "capabilities failed.\n Could not " "complete CAP_CONTROL_SHARE request.\n"); diff --git a/include/l4/api/capability.h b/include/l4/api/capability.h index 7eab604..df177a4 100644 --- a/include/l4/api/capability.h +++ b/include/l4/api/capability.h @@ -30,8 +30,4 @@ #define CAP_SPLIT_ACCESS 0x00000002 #define CAP_SPLIT_RANGE 0x00000003 /* Returns -EPERM */ -/* Task's primary capability list */ -#define TASK_CAP_LIST(task) \ - (&((task)->space->cap_list)) - #endif /* __API_CAPABILITY_H__ */ diff --git a/include/l4/generic/capability.h b/include/l4/generic/capability.h index d905e8c..1558a74 100644 --- a/include/l4/generic/capability.h +++ b/include/l4/generic/capability.h @@ -143,7 +143,7 @@ int capability_consume(struct capability *cap, int quantity); int capability_free(struct capability *cap, int quantity); struct capability *capability_find_by_rtype(struct ktcb *task, unsigned int rtype); - +int cap_count(struct ktcb *task); struct capability *cap_list_find_by_rtype(struct cap_list *clist, unsigned int rtype); struct capability *cap_find_by_capid(l4id_t capid, struct cap_list **clist); diff --git a/src/api/cap.c b/src/api/cap.c index 512c31a..b3a76d1 100644 --- a/src/api/cap.c +++ b/src/api/cap.c @@ -15,37 +15,28 @@ #include INC_API(syscall.h) /* - * FIXME: This is reading only a single list - * there may be more than one. + * Read all capabilitites of the current process. + * This includes the private ones as well as + * ones shared by other tasks that the task has + * rights to but doesn't own. */ int cap_read_all(struct capability *caparray) { struct capability *cap; - int total_size, capidx = 0; - int err; + int capidx = 0; - /* - * Determine size of pager capabilities - * (FIXME: partial!) - */ - total_size = TASK_CAP_LIST(current)->ncaps - * sizeof(*cap); - if ((err = check_access((unsigned long)caparray, - total_size, - MAP_USR_RW_FLAGS, 1)) < 0) - return err; + /* Copy all capabilities from lists to buffer */ + list_foreach_struct(cap, ¤t->cap_list.caps, list) { + memcpy(&caparray[capidx], cap, sizeof(*cap)); + capidx++; + } - /* - * Currently only pagers can - * read their own capabilities - */ - if (current->tid != current->pagerid) - return -EPERM; + list_foreach_struct(cap, ¤t->space->cap_list.caps, list) { + memcpy(&caparray[capidx], cap, sizeof(*cap)); + capidx++; + } - /* Copy capabilities from list to buffer */ - list_foreach_struct(cap, - &TASK_CAP_LIST(current)->caps, - list) { + list_foreach_struct(cap, &curcont->cap_list.caps, list) { memcpy(&caparray[capidx], cap, sizeof(*cap)); capidx++; } @@ -58,12 +49,12 @@ int cap_read_all(struct capability *caparray) * only one target that makes sense, that is your * own container. */ -int cap_share_single(l4id_t capid) +int cap_share_single(struct capability *user) { struct capability *cap; struct cap_list *clist; - if (!(cap = cap_find_by_capid(capid, &clist))) + if (!(cap = cap_find_by_capid(user->capid, &clist))) return -EEXIST; if (cap->owner != current->tid) @@ -82,14 +73,14 @@ int cap_share_single(l4id_t capid) int cap_share_all(void) { cap_list_move(&curcont->cap_list, - TASK_CAP_LIST(current)); + ¤t->space->cap_list); return 0; } -int cap_share(l4id_t capid, unsigned int flags) +int cap_share(struct capability *cap, unsigned int flags) { if (flags & CAP_SHARE_SINGLE) - cap_share_single(capid); + cap_share_single(cap); else if (flags & CAP_SHARE_ALL) cap_share_all(); else @@ -109,7 +100,7 @@ int cap_grant_all(struct capability *req, unsigned int flags) return -ESRCH; /* Detach all caps */ - cap_head = cap_list_detach(TASK_CAP_LIST(current)); + cap_head = cap_list_detach(¤t->space->cap_list); list_foreach_struct(cap, &cap_head->list, list) { /* Change ownership */ @@ -134,12 +125,12 @@ int cap_grant_all(struct capability *req, unsigned int flags) } /* Attach all to target */ - cap_list_attach(cap_head, TASK_CAP_LIST(target)); + cap_list_attach(cap_head, &target->space->cap_list); return 0; out_err: /* Attach it back to original */ - cap_list_attach(cap_head, TASK_CAP_LIST(current)); + cap_list_attach(cap_head, ¤t->space->cap_list); return err; } @@ -176,7 +167,7 @@ int cap_grant_single(struct capability *req, unsigned int flags) } /* Place it where it is granted */ - cap_list_insert(cap, TASK_CAP_LIST(target)); + cap_list_insert(cap, &target->space->cap_list); return 0; } @@ -550,7 +541,7 @@ int cap_split(struct capability *diff, unsigned int flags) new->owner = orig->owner; /* Add the new capability to the most private list */ - cap_list_insert(new, TASK_CAP_LIST(current)); + cap_list_insert(new, ¤t->space->cap_list); /* Check fields that must be identical */ BUG_ON(new->resid != diff->resid); @@ -623,7 +614,7 @@ int cap_replicate(struct capability *dupl) dupl->capid = new->capid; /* Add it to most private list */ - cap_list_insert(new, TASK_CAP_LIST(current)); + cap_list_insert(new, ¤t->space->cap_list); return 0; } @@ -643,76 +634,63 @@ int sys_capability_control(unsigned int req, unsigned int flags, if ((err = cap_cap_check(current, req, flags)) < 0) return err; - /* - * FIXME: Create a case statement to collect check_access - * calls to one place. - */ - + /* Check access for each request */ switch(req) { case CAP_CONTROL_NCAPS: - /* Return number of caps */ - if (current->tid != current->pagerid) - return -EPERM; - if ((err = check_access((unsigned long)userbuf, sizeof(int), MAP_USR_RW_FLAGS, 1)) < 0) return err; - - /* Copy ncaps value. FIXME: This is only a partial list */ - *((int *)userbuf) = TASK_CAP_LIST(current)->ncaps; break; - case CAP_CONTROL_READ: { - /* Return all capabilities as an array of capabilities */ - err = cap_read_all((struct capability *)userbuf); + case CAP_CONTROL_READ: + if ((err = check_access((unsigned long)userbuf, + cap_count(current) * + sizeof(struct capability), + MAP_USR_RW_FLAGS, 1)) < 0) + return err; break; - } case CAP_CONTROL_SHARE: - err = cap_share(capid, flags); - break; case CAP_CONTROL_GRANT: - if ((err = check_access((unsigned long)userbuf, - sizeof(struct capability), - MAP_USR_RW_FLAGS, 1)) < 0) - return err; - - err = cap_grant((struct capability *)userbuf, flags); - break; case CAP_CONTROL_SPLIT: - if ((err = check_access((unsigned long)userbuf, - sizeof(struct capability), - MAP_USR_RW_FLAGS, 1)) < 0) - return err; - - err = cap_split((struct capability *)userbuf, flags); - break; case CAP_CONTROL_REPLICATE: - if ((err = check_access((unsigned long)userbuf, - sizeof(struct capability), - MAP_USR_RW_FLAGS, 1)) < 0) - return err; - - err = cap_replicate((struct capability *)userbuf); - break; case CAP_CONTROL_DEDUCE: - if ((err = check_access((unsigned long)userbuf, - sizeof(struct capability), - MAP_USR_RW_FLAGS, 1)) < 0) - return err; - - err = cap_deduce((struct capability *)userbuf); - break; case CAP_CONTROL_DESTROY: if ((err = check_access((unsigned long)userbuf, sizeof(struct capability), MAP_USR_RW_FLAGS, 1)) < 0) return err; + break; + default: + return -EINVAL; + } + /* Take action for each request */ + switch(req) { + case CAP_CONTROL_NCAPS: + *((int *)userbuf) = cap_count(current); + break; + case CAP_CONTROL_READ: + err = cap_read_all((struct capability *)userbuf); + break; + case CAP_CONTROL_SHARE: + err = cap_share((struct capability *)userbuf, flags); + break; + case CAP_CONTROL_GRANT: + err = cap_grant((struct capability *)userbuf, flags); + break; + case CAP_CONTROL_SPLIT: + err = cap_split((struct capability *)userbuf, flags); + break; + case CAP_CONTROL_REPLICATE: + err = cap_replicate((struct capability *)userbuf); + break; + case CAP_CONTROL_DEDUCE: + err = cap_deduce((struct capability *)userbuf); + break; + case CAP_CONTROL_DESTROY: err = cap_destroy((struct capability *)userbuf); break; - default: - /* Invalid request id */ return -EINVAL; } diff --git a/src/generic/capability.c b/src/generic/capability.c index 2cabacb..609e588 100644 --- a/src/generic/capability.c +++ b/src/generic/capability.c @@ -157,8 +157,15 @@ struct capability *cap_find_by_capid(l4id_t capid, struct cap_list **cap_list) return 0; } +int cap_count(struct ktcb *task) +{ + return task->cap_list.ncaps + + task->space->cap_list.ncaps + + task->container->cap_list.ncaps; +} + typedef struct capability *(*cap_match_func_t) \ - (struct capability *cap, void *match_args); + (struct capability *cap, void *match_args); /* * This is used by every system call to match each