Capability replicate/deduce/share tested with mm0.

This commit is contained in:
Bahadir Balban
2009-11-07 23:45:57 +02:00
parent e8f002f879
commit b136b79a2d
5 changed files with 94 additions and 39 deletions

View File

@@ -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;

View File

@@ -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;
} }

View File

@@ -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;}
/* /*

View File

@@ -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;
} }

View File

@@ -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) &&