mirror of
https://github.com/drasko/codezero.git
synced 2026-01-12 02:43:15 +01:00
Progress on capabilities
Capabilities will be shared among collection of threads. A pager will have a right to share its own capabilities with its space, its thread group and its container. Currently sharing is possible with only all of the caps. Next, it will be support for cap splitting, granting, and partial sharing and granting.
This commit is contained in:
@@ -10,10 +10,10 @@
|
||||
#include <l4/api/capability.h>
|
||||
#include <l4/generic/capability.h>
|
||||
#include <l4/generic/container.h>
|
||||
#include <l4/generic/tcb.h>
|
||||
#include <l4/api/errno.h>
|
||||
#include INC_API(syscall.h)
|
||||
|
||||
|
||||
int read_task_capabilities(void *userbuf)
|
||||
{
|
||||
int copy_size, copy_offset = 0;
|
||||
@@ -28,24 +28,56 @@ int read_task_capabilities(void *userbuf)
|
||||
return -EPERM;
|
||||
|
||||
/* Determine size of pager capabilities */
|
||||
copy_size = current->cap_list_ptr->ncaps * sizeof(*cap);
|
||||
copy_size = current->cap_list.ncaps * sizeof(*cap);
|
||||
|
||||
/* Validate user buffer for this copy size */
|
||||
if ((err = check_access((unsigned long)userbuf, copy_size,
|
||||
if ((err = check_access((unsigned long)userbuf,
|
||||
copy_size,
|
||||
MAP_USR_RW_FLAGS, 1)) < 0)
|
||||
return err;
|
||||
|
||||
/* Copy capabilities from list to buffer */
|
||||
list_foreach_struct(cap,
|
||||
¤t->cap_list_ptr->caps,
|
||||
list_foreach_struct(cap, ¤t->cap_list.caps,
|
||||
list) {
|
||||
memcpy(userbuf + copy_offset, cap, sizeof(*cap));
|
||||
memcpy(userbuf + copy_offset,
|
||||
cap, sizeof(*cap));
|
||||
copy_offset += sizeof(*cap);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Currently shares _all_ capabilities of a task
|
||||
* with a collection of threads
|
||||
*
|
||||
* FIXME: Check ownership for sharing.
|
||||
*/
|
||||
int capability_share(unsigned int share_flags)
|
||||
{
|
||||
switch (share_flags) {
|
||||
case CAP_SHARE_WITH_SPACE:
|
||||
cap_list_move(¤t->space->cap_list,
|
||||
¤t->cap_list);
|
||||
break;
|
||||
case CAP_SHARE_WITH_CONTAINER:
|
||||
cap_list_move(&curcont->cap_list,
|
||||
¤t->cap_list);
|
||||
break;
|
||||
case CAP_SHARE_WITH_TGROUP: {
|
||||
struct ktcb *tgr_leader;
|
||||
|
||||
BUG_ON(!(tgr_leader = tcb_find(current->tgid)));
|
||||
cap_list_move(&tgr_leader->cap_list,
|
||||
¤t->cap_list);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Read, manipulate capabilities. Currently only capability read support.
|
||||
*/
|
||||
@@ -59,19 +91,22 @@ int sys_capability_control(unsigned int req, unsigned int flags, void *userbuf)
|
||||
if (current != current->pager->tcb)
|
||||
return -EPERM;
|
||||
|
||||
if ((err = check_access((unsigned long)userbuf, sizeof(int),
|
||||
if ((err = check_access((unsigned long)userbuf,
|
||||
sizeof(int),
|
||||
MAP_USR_RW_FLAGS, 1)) < 0)
|
||||
return err;
|
||||
|
||||
/* Copy ncaps value */
|
||||
*((int *)userbuf) = current->cap_list_ptr->ncaps;
|
||||
*((int *)userbuf) = current->cap_list.ncaps;
|
||||
break;
|
||||
|
||||
/* Return all capabilities as an array of capabilities */
|
||||
case CAP_CONTROL_READ_CAPS:
|
||||
case CAP_CONTROL_READ:
|
||||
err = read_task_capabilities(userbuf);
|
||||
break;
|
||||
|
||||
case CAP_CONTROL_SHARE:
|
||||
err = capability_share(flags);
|
||||
break;
|
||||
default:
|
||||
/* Invalid request id */
|
||||
return -EINVAL;
|
||||
@@ -80,7 +115,42 @@ int sys_capability_control(unsigned int req, unsigned int flags, void *userbuf)
|
||||
}
|
||||
|
||||
|
||||
#if 0
|
||||
|
||||
int capability_grant(struct ktcb *recv, struct ktcb *send, struct capability *cap)
|
||||
{
|
||||
list_del(&cap->list);
|
||||
list_add(&cap->list, &recv->cap_list);
|
||||
}
|
||||
|
||||
struct cap_split_desc {
|
||||
unsigned int valid;
|
||||
unsigned int access;
|
||||
unsigned long size;
|
||||
unsigned long start;
|
||||
unsigned long end;
|
||||
};
|
||||
|
||||
struct capability *capability_diff(struct capability *cap, struct cap_split_desc *split)
|
||||
{
|
||||
if (split->valid & FIELD_TO_BIT(struct cap_split_desc, access)) {
|
||||
new->access = orig->access & split->access;
|
||||
orig->access &= ~split->access;
|
||||
}
|
||||
if (split->valid & FIELD_TO_BIT(struct cap_split_desc, size)) {
|
||||
new->size = orig->size - split->size;
|
||||
orig->size -= split->size;
|
||||
}
|
||||
if (split->valid & FIELD_TO_BIT(struct cap_split_desc, start)) {
|
||||
memcap_unmap(cap, split->start, split->end);
|
||||
new->size = orig->size - split->size;
|
||||
orig->size -= split->size;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
int capability_split(struct ktcb *recv, struct ktcb *send, struct capability *cap, struct cap_split_desc *split)
|
||||
{
|
||||
capability_diff(orig, new, split);
|
||||
}
|
||||
#endif
|
||||
|
||||
Reference in New Issue
Block a user