mirror of
https://github.com/drasko/codezero.git
synced 2026-02-27 09:13:13 +01:00
Capability replicate/deduce/share tested with mm0.
This commit is contained in:
@@ -35,6 +35,48 @@ struct capability {
|
|||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
static inline void cap_list_init(struct cap_list *clist)
|
||||||
|
{
|
||||||
|
clist->ncaps = 0;
|
||||||
|
link_init(&clist->caps);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void cap_list_insert(struct capability *cap,
|
||||||
|
struct cap_list *clist)
|
||||||
|
{
|
||||||
|
list_insert(&cap->list, &clist->caps);
|
||||||
|
clist->ncaps++;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Detach a whole list of capabilities from list head */
|
||||||
|
static inline struct capability *
|
||||||
|
cap_list_detach(struct cap_list *clist)
|
||||||
|
{
|
||||||
|
struct link *list = list_detach(&clist->caps);
|
||||||
|
clist->ncaps = 0;
|
||||||
|
return link_to_struct(list, struct capability, list);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Attach a whole list of capabilities to list head */
|
||||||
|
static inline void cap_list_attach(struct capability *cap,
|
||||||
|
struct cap_list *clist)
|
||||||
|
{
|
||||||
|
/* Attach as if cap is the list and clist is the element */
|
||||||
|
list_insert(&clist->caps, &cap->list);
|
||||||
|
|
||||||
|
/* Count the number of caps attached */
|
||||||
|
list_foreach_struct(cap, &clist->caps, list)
|
||||||
|
clist->ncaps++;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void cap_list_move(struct cap_list *to,
|
||||||
|
struct cap_list *from)
|
||||||
|
{
|
||||||
|
struct capability *cap_head = cap_list_detach(from);
|
||||||
|
cap_list_attach(cap_head, to);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
extern struct cap_list capability_list;
|
extern struct cap_list capability_list;
|
||||||
|
|
||||||
struct initdata;
|
struct initdata;
|
||||||
|
|||||||
@@ -163,7 +163,9 @@ void copy_boot_capabilities(int ncaps)
|
|||||||
{
|
{
|
||||||
struct capability *cap;
|
struct capability *cap;
|
||||||
|
|
||||||
|
capability_list.ncaps = 0;
|
||||||
link_init(&capability_list.caps);
|
link_init(&capability_list.caps);
|
||||||
|
|
||||||
for (int i = 0; i < total_caps; i++) {
|
for (int i = 0; i < total_caps; i++) {
|
||||||
cap = kzalloc(sizeof(struct capability));
|
cap = kzalloc(sizeof(struct capability));
|
||||||
|
|
||||||
@@ -174,9 +176,8 @@ void copy_boot_capabilities(int ncaps)
|
|||||||
link_init(&cap->list);
|
link_init(&cap->list);
|
||||||
|
|
||||||
/* Add capability to global cap list */
|
/* Add capability to global cap list */
|
||||||
list_insert(&cap->list, &capability_list.caps);
|
cap_list_insert(cap, &capability_list);
|
||||||
}
|
}
|
||||||
capability_list.ncaps = ncaps;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#if 0
|
#if 0
|
||||||
@@ -305,8 +306,13 @@ void cap_print(struct capability *cap)
|
|||||||
void cap_list_print(struct cap_list *cap_list)
|
void cap_list_print(struct cap_list *cap_list)
|
||||||
{
|
{
|
||||||
struct capability *cap;
|
struct capability *cap;
|
||||||
|
printf("Capabilities\n"
|
||||||
|
"~~~~~~~~~~~~\n");
|
||||||
|
|
||||||
list_foreach_struct(cap, &cap_list->caps, list)
|
list_foreach_struct(cap, &cap_list->caps, list)
|
||||||
cap_print(cap);
|
cap_print(cap);
|
||||||
|
|
||||||
|
printf("\n");
|
||||||
}
|
}
|
||||||
/*
|
/*
|
||||||
* Replicate, deduce and grant to children the capability to
|
* Replicate, deduce and grant to children the capability to
|
||||||
@@ -320,18 +326,18 @@ void cap_list_print(struct cap_list *cap_list)
|
|||||||
* into a capability to only talk to our current space. Our space is a
|
* into a capability to only talk to our current space. Our space is a
|
||||||
* reduced target, since it is a subset contained in our container.
|
* reduced target, since it is a subset contained in our container.
|
||||||
*/
|
*/
|
||||||
int setup_children_caps(int total_caps, struct cap_list *capability_list)
|
int setup_children_caps(int total_caps, struct cap_list *cap_list)
|
||||||
{
|
{
|
||||||
struct capability ipc_cap, *cap;
|
struct capability *ipc_cap, *cap;
|
||||||
struct task_ids ids;
|
struct task_ids ids;
|
||||||
int err;
|
int err;
|
||||||
|
|
||||||
l4_getid(&ids);
|
l4_getid(&ids);
|
||||||
|
|
||||||
cap_list_print(capability_list);
|
cap_list_print(cap_list);
|
||||||
|
|
||||||
/* Find out our own ipc capability on our own container */
|
/* Find out our own ipc capability on our own container */
|
||||||
list_foreach_struct(cap, &capability_list->caps, list) {
|
list_foreach_struct(cap, &cap_list->caps, list) {
|
||||||
if (cap_type(cap) == CAP_TYPE_IPC &&
|
if (cap_type(cap) == CAP_TYPE_IPC &&
|
||||||
cap_rtype(cap) == CAP_RTYPE_CONTAINER &&
|
cap_rtype(cap) == CAP_RTYPE_CONTAINER &&
|
||||||
cap->resid == __cid(ids.tid))
|
cap->resid == __cid(ids.tid))
|
||||||
@@ -343,20 +349,25 @@ int setup_children_caps(int total_caps, struct cap_list *capability_list)
|
|||||||
BUG();
|
BUG();
|
||||||
|
|
||||||
found:
|
found:
|
||||||
|
/* Create a new capability */
|
||||||
|
BUG_ON(!(ipc_cap = kzalloc(sizeof(*ipc_cap))));
|
||||||
|
|
||||||
/* Copy it over to new ipc cap buffer */
|
/* Copy it over to new ipc cap buffer */
|
||||||
memcpy(&ipc_cap, cap, sizeof (*cap));
|
memcpy(ipc_cap, cap, sizeof (*cap));
|
||||||
|
|
||||||
/* Replicate the ipc capability, giving original as reference */
|
/* Replicate the ipc capability, giving original as reference */
|
||||||
if ((err = l4_capability_control(CAP_CONTROL_REPLICATE,
|
if ((err = l4_capability_control(CAP_CONTROL_REPLICATE,
|
||||||
0, 0, 0, &ipc_cap)) < 0) {
|
0, 0, 0, ipc_cap)) < 0) {
|
||||||
printf("l4_capability_control() replication of "
|
printf("l4_capability_control() replication of "
|
||||||
"ipc capability failed.\n Could not "
|
"ipc capability failed.\n Could not "
|
||||||
"complete CAP_CONTROL_REPLICATE request on cap (%d), "
|
"complete CAP_CONTROL_REPLICATE request on cap (%d), "
|
||||||
"err = %d.\n", ipc_cap.capid, err);
|
"err = %d.\n", ipc_cap->capid, err);
|
||||||
BUG();
|
BUG();
|
||||||
}
|
}
|
||||||
|
|
||||||
cap_list_print(capability_list);
|
/* Add it to list */
|
||||||
|
cap_list_insert(ipc_cap, cap_list);
|
||||||
|
cap_list_print(cap_list);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* The returned capability is a replica.
|
* The returned capability is a replica.
|
||||||
@@ -364,18 +375,18 @@ found:
|
|||||||
* Now deduce it such that it applies to talking only to us,
|
* Now deduce it such that it applies to talking only to us,
|
||||||
* instead of to the whole container as original.
|
* instead of to the whole container as original.
|
||||||
*/
|
*/
|
||||||
cap_set_rtype(&ipc_cap, CAP_RTYPE_SPACE);
|
cap_set_rtype(ipc_cap, CAP_RTYPE_SPACE);
|
||||||
ipc_cap.resid = __cid(ids.spid); /* This space is target resource */
|
ipc_cap->resid = ids.spid; /* This space is target resource */
|
||||||
if ((err = l4_capability_control(CAP_CONTROL_DEDUCE,
|
if ((err = l4_capability_control(CAP_CONTROL_DEDUCE,
|
||||||
0, 0, 0, &ipc_cap)) < 0) {
|
0, 0, 0, ipc_cap)) < 0) {
|
||||||
printf("l4_capability_control() deduction of "
|
printf("l4_capability_control() deduction of "
|
||||||
"ipc capability failed.\n Could not "
|
"ipc capability failed.\n Could not "
|
||||||
"complete CAP_CONTROL_DEDUCE request on cap (%d), "
|
"complete CAP_CONTROL_DEDUCE request on cap (%d), "
|
||||||
"err = %d.\n", ipc_cap.capid, err);
|
"err = %d.\n", ipc_cap->capid, err);
|
||||||
BUG();
|
BUG();
|
||||||
}
|
}
|
||||||
|
|
||||||
cap_list_print(capability_list);
|
cap_list_print(cap_list);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Share it with our container.
|
* Share it with our container.
|
||||||
@@ -384,13 +395,14 @@ 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) {
|
ipc_cap->capid, 0, 0)) < 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");
|
||||||
BUG();
|
BUG();
|
||||||
}
|
}
|
||||||
cap_list_print(capability_list);
|
cap_list_print(cap_list);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -37,7 +37,7 @@
|
|||||||
|
|
||||||
#define cap_rtype(c) ((c)->type & CAP_RTYPE_MASK)
|
#define cap_rtype(c) ((c)->type & CAP_RTYPE_MASK)
|
||||||
#define cap_set_rtype(c, rtype) \
|
#define cap_set_rtype(c, rtype) \
|
||||||
{(c)->type &= CAP_RTYPE_MASK; \
|
{(c)->type &= ~CAP_RTYPE_MASK; \
|
||||||
(c)->type |= CAP_RTYPE_MASK & rtype;}
|
(c)->type |= CAP_RTYPE_MASK & rtype;}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|||||||
@@ -306,13 +306,13 @@ int cap_deduce(struct capability *new)
|
|||||||
* orig = orig - diff;
|
* orig = orig - diff;
|
||||||
* new = diff;
|
* new = diff;
|
||||||
*/
|
*/
|
||||||
int cap_split(l4id_t capid, struct capability *diff)
|
int cap_split(struct capability *diff)
|
||||||
{
|
{
|
||||||
struct capability *orig, *new;
|
struct capability *orig, *new;
|
||||||
|
|
||||||
/* Find original capability */
|
/* Find original capability */
|
||||||
if (!(orig = cap_find_byid(capid)))
|
if (!(orig = cap_find_byid(diff->capid)))
|
||||||
return -ENOCAP;
|
return -EEXIST;
|
||||||
|
|
||||||
/* Check target type/resid/owner is the same */
|
/* Check target type/resid/owner is the same */
|
||||||
if (orig->type != diff->type ||
|
if (orig->type != diff->type ||
|
||||||
@@ -421,12 +421,13 @@ int cap_split(l4id_t capid, struct capability *diff)
|
|||||||
* system, but as it is not a quantity, this does not increase
|
* system, but as it is not a quantity, this does not increase
|
||||||
* the capabilities of the caller in any way.
|
* the capabilities of the caller in any way.
|
||||||
*/
|
*/
|
||||||
int cap_replicate(l4id_t capid, struct capability *dupl)
|
int cap_replicate(struct capability *dupl)
|
||||||
{
|
{
|
||||||
struct capability *new, *orig;
|
struct capability *new, *orig;
|
||||||
|
|
||||||
/* Find original capability */
|
/* Find original capability */
|
||||||
orig = cap_find_byid(capid);
|
if (!(orig = cap_find_byid(dupl->capid)))
|
||||||
|
return -EEXIST;
|
||||||
|
|
||||||
/* Check that caller is owner */
|
/* Check that caller is owner */
|
||||||
if (orig->owner != current->tid)
|
if (orig->owner != current->tid)
|
||||||
@@ -450,21 +451,21 @@ int cap_replicate(l4id_t capid, struct capability *dupl)
|
|||||||
return -ENOCAP;
|
return -ENOCAP;
|
||||||
|
|
||||||
/* Copy all except capid & listptrs */
|
/* Copy all except capid & listptrs */
|
||||||
new->resid = orig->resid;
|
dupl->resid = new->resid = orig->resid;
|
||||||
new->owner = orig->owner;
|
dupl->owner = new->owner = orig->owner;
|
||||||
new->type = orig->type;
|
dupl->type = new->type = orig->type;
|
||||||
new->access = orig->access;
|
dupl->access = new->access = orig->access;
|
||||||
new->start = orig->start;
|
dupl->start = new->start = orig->start;
|
||||||
new->end = orig->end;
|
dupl->end = new->end = orig->end;
|
||||||
new->size = orig->size;
|
dupl->size = new->size = orig->size;
|
||||||
new->used = orig->used;
|
dupl->used = new->used = orig->used;
|
||||||
|
|
||||||
|
/* Copy new fields */
|
||||||
|
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, TASK_CAP_LIST(current));
|
||||||
|
|
||||||
/* Return new capability to user */
|
|
||||||
memcpy(dupl, new, sizeof(*new));
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -474,7 +475,7 @@ int cap_replicate(l4id_t capid, struct capability *dupl)
|
|||||||
int sys_capability_control(unsigned int req, unsigned int flags,
|
int sys_capability_control(unsigned int req, unsigned int flags,
|
||||||
l4id_t capid, l4id_t target, void *userbuf)
|
l4id_t capid, l4id_t target, void *userbuf)
|
||||||
{
|
{
|
||||||
int err;
|
int err = 0;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Check capability to do a capability operation.
|
* Check capability to do a capability operation.
|
||||||
@@ -509,7 +510,7 @@ int sys_capability_control(unsigned int req, unsigned int flags,
|
|||||||
err = cap_grant(flags, capid, target);
|
err = cap_grant(flags, capid, target);
|
||||||
break;
|
break;
|
||||||
case CAP_CONTROL_SPLIT:
|
case CAP_CONTROL_SPLIT:
|
||||||
err = cap_split(capid, (struct capability *)userbuf);
|
err = cap_split((struct capability *)userbuf);
|
||||||
break;
|
break;
|
||||||
case CAP_CONTROL_REPLICATE:
|
case CAP_CONTROL_REPLICATE:
|
||||||
if ((err = check_access((unsigned long)userbuf,
|
if ((err = check_access((unsigned long)userbuf,
|
||||||
@@ -517,7 +518,7 @@ int sys_capability_control(unsigned int req, unsigned int flags,
|
|||||||
MAP_USR_RW_FLAGS, 1)) < 0)
|
MAP_USR_RW_FLAGS, 1)) < 0)
|
||||||
return err;
|
return err;
|
||||||
|
|
||||||
err = cap_replicate(capid, (struct capability *)userbuf);
|
err = cap_replicate((struct capability *)userbuf);
|
||||||
break;
|
break;
|
||||||
case CAP_CONTROL_DEDUCE:
|
case CAP_CONTROL_DEDUCE:
|
||||||
if ((err = check_access((unsigned long)userbuf,
|
if ((err = check_access((unsigned long)userbuf,
|
||||||
@@ -527,12 +528,11 @@ int sys_capability_control(unsigned int req, unsigned int flags,
|
|||||||
|
|
||||||
err = cap_deduce((struct capability *)userbuf);
|
err = cap_deduce((struct capability *)userbuf);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
/* Invalid request id */
|
/* Invalid request id */
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -537,6 +537,7 @@ int sys_ipc(l4id_t to, l4id_t from, unsigned int flags)
|
|||||||
{
|
{
|
||||||
unsigned int ipc_type = 0;
|
unsigned int ipc_type = 0;
|
||||||
int ret = 0;
|
int ret = 0;
|
||||||
|
struct ktcb *t = current; if (!t);
|
||||||
|
|
||||||
/* Check arguments */
|
/* Check arguments */
|
||||||
if (task_id_special(from) &&
|
if (task_id_special(from) &&
|
||||||
|
|||||||
Reference in New Issue
Block a user