mirror of
https://github.com/drasko/codezero.git
synced 2026-04-09 21:49:04 +02: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.
|
* 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");
|
||||||
|
|||||||
@@ -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__ */
|
||||||
|
|||||||
@@ -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);
|
||||||
|
|||||||
144
src/api/cap.c
144
src/api/cap.c
@@ -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, ¤t->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, ¤t->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));
|
¤t->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(¤t->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, ¤t->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, ¤t->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, ¤t->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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
Reference in New Issue
Block a user