mirror of
https://github.com/drasko/codezero.git
synced 2026-01-12 02:43:15 +01:00
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:
@@ -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");
|
||||
|
||||
@@ -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__ */
|
||||
|
||||
@@ -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);
|
||||
|
||||
144
src/api/cap.c
144
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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user