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.
This commit is contained in:
Bahadir Balban
2009-11-10 16:15:14 +02:00
parent d43fa1d3ae
commit 2ba4736a8b
5 changed files with 73 additions and 92 deletions

View File

@@ -176,7 +176,7 @@ found:
* to use this pool of mutexes. * to use this pool of mutexes.
*/ */
if ((err = l4_capability_control(CAP_CONTROL_SHARE, CAP_SHARE_SINGLE, 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 " printf("l4_capability_control() sharing of "
"capabilities failed.\n Could not " "capabilities failed.\n Could not "
"complete CAP_CONTROL_SHARE request.\n"); "complete CAP_CONTROL_SHARE request.\n");
@@ -204,7 +204,7 @@ found2:
* to use this pool of mutexes. * to use this pool of mutexes.
*/ */
if ((err = l4_capability_control(CAP_CONTROL_SHARE, CAP_SHARE_SINGLE, 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 " printf("l4_capability_control() sharing of "
"capabilities failed.\n Could not " "capabilities failed.\n Could not "
"complete CAP_CONTROL_SHARE request.\n"); "complete CAP_CONTROL_SHARE request.\n");
@@ -296,7 +296,7 @@ found:
* to communicate to us only, and be able to do nothing else. * to communicate to us only, and be able to do nothing else.
*/ */
if ((err = l4_capability_control(CAP_CONTROL_SHARE, CAP_SHARE_SINGLE, 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 " printf("l4_capability_control() sharing of "
"capabilities failed.\n Could not " "capabilities failed.\n Could not "
"complete CAP_CONTROL_SHARE request.\n"); "complete CAP_CONTROL_SHARE request.\n");

View File

@@ -30,8 +30,4 @@
#define CAP_SPLIT_ACCESS 0x00000002 #define CAP_SPLIT_ACCESS 0x00000002
#define CAP_SPLIT_RANGE 0x00000003 /* Returns -EPERM */ #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__ */ #endif /* __API_CAPABILITY_H__ */

View File

@@ -143,7 +143,7 @@ int capability_consume(struct capability *cap, int quantity);
int capability_free(struct capability *cap, int quantity); int capability_free(struct capability *cap, int quantity);
struct capability *capability_find_by_rtype(struct ktcb *task, struct capability *capability_find_by_rtype(struct ktcb *task,
unsigned int rtype); unsigned int rtype);
int cap_count(struct ktcb *task);
struct capability *cap_list_find_by_rtype(struct cap_list *clist, struct capability *cap_list_find_by_rtype(struct cap_list *clist,
unsigned int rtype); unsigned int rtype);
struct capability *cap_find_by_capid(l4id_t capid, struct cap_list **clist); struct capability *cap_find_by_capid(l4id_t capid, struct cap_list **clist);

View File

@@ -15,37 +15,28 @@
#include INC_API(syscall.h) #include INC_API(syscall.h)
/* /*
* FIXME: This is reading only a single list * Read all capabilitites of the current process.
* there may be more than one. * 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) int cap_read_all(struct capability *caparray)
{ {
struct capability *cap; struct capability *cap;
int total_size, capidx = 0; int capidx = 0;
int err;
/* /* Copy all capabilities from lists to buffer */
* Determine size of pager capabilities list_foreach_struct(cap, &current->cap_list.caps, list) {
* (FIXME: partial!) memcpy(&caparray[capidx], cap, sizeof(*cap));
*/ capidx++;
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;
/* list_foreach_struct(cap, &current->space->cap_list.caps, list) {
* Currently only pagers can memcpy(&caparray[capidx], cap, sizeof(*cap));
* read their own capabilities capidx++;
*/ }
if (current->tid != current->pagerid)
return -EPERM;
/* Copy capabilities from list to buffer */ list_foreach_struct(cap, &curcont->cap_list.caps, list) {
list_foreach_struct(cap,
&TASK_CAP_LIST(current)->caps,
list) {
memcpy(&caparray[capidx], cap, sizeof(*cap)); memcpy(&caparray[capidx], cap, sizeof(*cap));
capidx++; capidx++;
} }
@@ -58,12 +49,12 @@ int cap_read_all(struct capability *caparray)
* only one target that makes sense, that is your * only one target that makes sense, that is your
* own container. * own container.
*/ */
int cap_share_single(l4id_t capid) int cap_share_single(struct capability *user)
{ {
struct capability *cap; struct capability *cap;
struct cap_list *clist; struct cap_list *clist;
if (!(cap = cap_find_by_capid(capid, &clist))) if (!(cap = cap_find_by_capid(user->capid, &clist)))
return -EEXIST; return -EEXIST;
if (cap->owner != current->tid) if (cap->owner != current->tid)
@@ -82,14 +73,14 @@ int cap_share_single(l4id_t capid)
int cap_share_all(void) int cap_share_all(void)
{ {
cap_list_move(&curcont->cap_list, cap_list_move(&curcont->cap_list,
TASK_CAP_LIST(current)); &current->space->cap_list);
return 0; 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) if (flags & CAP_SHARE_SINGLE)
cap_share_single(capid); cap_share_single(cap);
else if (flags & CAP_SHARE_ALL) else if (flags & CAP_SHARE_ALL)
cap_share_all(); cap_share_all();
else else
@@ -109,7 +100,7 @@ int cap_grant_all(struct capability *req, unsigned int flags)
return -ESRCH; return -ESRCH;
/* Detach all caps */ /* Detach all caps */
cap_head = cap_list_detach(TASK_CAP_LIST(current)); cap_head = cap_list_detach(&current->space->cap_list);
list_foreach_struct(cap, &cap_head->list, list) { list_foreach_struct(cap, &cap_head->list, list) {
/* Change ownership */ /* Change ownership */
@@ -134,12 +125,12 @@ int cap_grant_all(struct capability *req, unsigned int flags)
} }
/* Attach all to target */ /* Attach all to target */
cap_list_attach(cap_head, TASK_CAP_LIST(target)); cap_list_attach(cap_head, &target->space->cap_list);
return 0; return 0;
out_err: out_err:
/* Attach it back to original */ /* Attach it back to original */
cap_list_attach(cap_head, TASK_CAP_LIST(current)); cap_list_attach(cap_head, &current->space->cap_list);
return err; return err;
} }
@@ -176,7 +167,7 @@ int cap_grant_single(struct capability *req, unsigned int flags)
} }
/* Place it where it is granted */ /* Place it where it is granted */
cap_list_insert(cap, TASK_CAP_LIST(target)); cap_list_insert(cap, &target->space->cap_list);
return 0; return 0;
} }
@@ -550,7 +541,7 @@ int cap_split(struct capability *diff, unsigned int flags)
new->owner = orig->owner; new->owner = orig->owner;
/* Add the new capability to the most private list */ /* Add the new capability to the most private list */
cap_list_insert(new, TASK_CAP_LIST(current)); cap_list_insert(new, &current->space->cap_list);
/* Check fields that must be identical */ /* Check fields that must be identical */
BUG_ON(new->resid != diff->resid); BUG_ON(new->resid != diff->resid);
@@ -623,7 +614,7 @@ int cap_replicate(struct capability *dupl)
dupl->capid = new->capid; dupl->capid = new->capid;
/* Add it to most private list */ /* Add it to most private list */
cap_list_insert(new, TASK_CAP_LIST(current)); cap_list_insert(new, &current->space->cap_list);
return 0; 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) if ((err = cap_cap_check(current, req, flags)) < 0)
return err; return err;
/* /* Check access for each request */
* FIXME: Create a case statement to collect check_access
* calls to one place.
*/
switch(req) { switch(req) {
case CAP_CONTROL_NCAPS: case CAP_CONTROL_NCAPS:
/* Return number of caps */
if (current->tid != current->pagerid)
return -EPERM;
if ((err = check_access((unsigned long)userbuf, if ((err = check_access((unsigned long)userbuf,
sizeof(int), sizeof(int),
MAP_USR_RW_FLAGS, 1)) < 0) MAP_USR_RW_FLAGS, 1)) < 0)
return err; return err;
/* Copy ncaps value. FIXME: This is only a partial list */
*((int *)userbuf) = TASK_CAP_LIST(current)->ncaps;
break; break;
case CAP_CONTROL_READ: { case CAP_CONTROL_READ:
/* Return all capabilities as an array of capabilities */ if ((err = check_access((unsigned long)userbuf,
err = cap_read_all((struct capability *)userbuf); cap_count(current) *
sizeof(struct capability),
MAP_USR_RW_FLAGS, 1)) < 0)
return err;
break; break;
}
case CAP_CONTROL_SHARE: case CAP_CONTROL_SHARE:
err = cap_share(capid, flags);
break;
case CAP_CONTROL_GRANT: 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: 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: 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: 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: case CAP_CONTROL_DESTROY:
if ((err = check_access((unsigned long)userbuf, if ((err = check_access((unsigned long)userbuf,
sizeof(struct capability), sizeof(struct capability),
MAP_USR_RW_FLAGS, 1)) < 0) MAP_USR_RW_FLAGS, 1)) < 0)
return err; 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); err = cap_destroy((struct capability *)userbuf);
break; break;
default: default:
/* Invalid request id */
return -EINVAL; return -EINVAL;
} }

View File

@@ -157,8 +157,15 @@ struct capability *cap_find_by_capid(l4id_t capid, struct cap_list **cap_list)
return 0; 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) \ 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 * This is used by every system call to match each