mirror of
https://github.com/drasko/codezero.git
synced 2026-02-27 09:13:13 +01:00
Some capability checking progress
This commit is contained in:
@@ -5,10 +5,8 @@
|
|||||||
#include <l4/generic/capability.h>
|
#include <l4/generic/capability.h>
|
||||||
#include <l4/generic/cap-types.h>
|
#include <l4/generic/cap-types.h>
|
||||||
|
|
||||||
void print_capability(struct capability *cap);
|
void capability_print(struct capability *cap);
|
||||||
|
|
||||||
int read_pager_capabilities();
|
|
||||||
|
|
||||||
|
|
||||||
|
int caps_read_all();
|
||||||
|
|
||||||
#endif /* __CAPABILITY_H__ */
|
#endif /* __CAPABILITY_H__ */
|
||||||
|
|||||||
@@ -1,5 +1,7 @@
|
|||||||
/*
|
/*
|
||||||
* Main function for all tests
|
* Main function for all tests
|
||||||
|
*
|
||||||
|
* Copyright (C) 2009 B Labs Ltd.
|
||||||
*/
|
*/
|
||||||
#include <l4/api/errno.h>
|
#include <l4/api/errno.h>
|
||||||
#include <container.h>
|
#include <container.h>
|
||||||
@@ -9,7 +11,6 @@
|
|||||||
|
|
||||||
int main(void)
|
int main(void)
|
||||||
{
|
{
|
||||||
|
|
||||||
printf("%s: Container %s started\n",
|
printf("%s: Container %s started\n",
|
||||||
__CONTAINER__, __CONTAINER_NAME__);
|
__CONTAINER__, __CONTAINER_NAME__);
|
||||||
|
|
||||||
|
|||||||
@@ -1,11 +1,80 @@
|
|||||||
|
/*
|
||||||
|
* Capability-related userspace helpers
|
||||||
|
*
|
||||||
|
* Copyright (C) 2009 B Labs Ltd.
|
||||||
|
*/
|
||||||
#include <capability.h>
|
#include <capability.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <l4lib/arch/syscalls.h>
|
#include <l4lib/arch/syscalls.h>
|
||||||
|
|
||||||
static struct capability cap_array[30];
|
static struct capability cap_array[30];
|
||||||
static int total_caps;
|
|
||||||
|
|
||||||
void print_capability(struct capability *cap)
|
struct cap_group {
|
||||||
|
struct cap_list virtmem;
|
||||||
|
struct cap_list physmem;
|
||||||
|
struct cap_list threadpool;
|
||||||
|
struct cap_list tctrl;
|
||||||
|
struct cap_list exregs;
|
||||||
|
struct cap_list ipc;
|
||||||
|
struct cap_list mutex;
|
||||||
|
struct cap_list sched;
|
||||||
|
struct cap_list mutexpool;
|
||||||
|
struct cap_list spacepool;
|
||||||
|
struct cap_list cappool;
|
||||||
|
};
|
||||||
|
|
||||||
|
static inline struct capability *cap_get_thread()
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline struct capability *cap_get_space()
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline struct capability *cap_get_ipc()
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline struct capability *cap_get_virtmem()
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline struct capability *cap_get_physmem()
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline struct capability *cap_get_physmem(unsigned long phys)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline struct capability *cap_get_virtmem(unsigned long virt)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline struct capability *cap_get_byid(l4id_t id)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void cap_share_single(struct capability *orig, struct capability *share, l4id_t target, unsigned int flags)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void cap_grant_single(struct capability *orig, struct capability *share, l4id_t target, unsigned int flags)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void cap_print(struct capability *cap)
|
||||||
{
|
{
|
||||||
printf("Capability id:\t\t\t%d\n", cap->capid);
|
printf("Capability id:\t\t\t%d\n", cap->capid);
|
||||||
printf("Capability resource id:\t\t%d\n", cap->resid);
|
printf("Capability resource id:\t\t%d\n", cap->resid);
|
||||||
@@ -82,7 +151,7 @@ void print_capability(struct capability *cap)
|
|||||||
printf("\n");
|
printf("\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
int read_pager_capabilities()
|
int cap_read_all(void)
|
||||||
{
|
{
|
||||||
int ncaps;
|
int ncaps;
|
||||||
int err;
|
int err;
|
||||||
@@ -95,7 +164,6 @@ int read_pager_capabilities()
|
|||||||
"complete CAP_CONTROL_NCAPS request.\n");
|
"complete CAP_CONTROL_NCAPS request.\n");
|
||||||
BUG();
|
BUG();
|
||||||
}
|
}
|
||||||
total_caps = ncaps;
|
|
||||||
|
|
||||||
/* Read all capabilities */
|
/* Read all capabilities */
|
||||||
if ((err = l4_capability_control(CAP_CONTROL_READ,
|
if ((err = l4_capability_control(CAP_CONTROL_READ,
|
||||||
@@ -106,8 +174,8 @@ int read_pager_capabilities()
|
|||||||
BUG();
|
BUG();
|
||||||
}
|
}
|
||||||
|
|
||||||
for (int i = 0; i < total_caps; i++)
|
for (int i = 0; i < ncaps; i++)
|
||||||
print_capability(&cap_array[i]);
|
cap_print(&cap_array[i]);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -79,7 +79,7 @@ int capability_test(void)
|
|||||||
int TEST_MUST_SUCCEED = 1;
|
int TEST_MUST_SUCCEED = 1;
|
||||||
|
|
||||||
/* Read pager capabilities */
|
/* Read pager capabilities */
|
||||||
read_pager_capabilities();
|
caps_read_all();
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Create new thread that will attempt
|
* Create new thread that will attempt
|
||||||
|
|||||||
@@ -37,6 +37,7 @@
|
|||||||
#define CAP_RTYPE_MUTEXPOOL (1 << 26)
|
#define CAP_RTYPE_MUTEXPOOL (1 << 26)
|
||||||
#define CAP_RTYPE_MAPPOOL (1 << 27) /* For pmd spending */
|
#define CAP_RTYPE_MAPPOOL (1 << 27) /* For pmd spending */
|
||||||
#define CAP_RTYPE_CAPPOOL (1 << 28) /* For new cap generation */
|
#define CAP_RTYPE_CAPPOOL (1 << 28) /* For new cap generation */
|
||||||
|
#define CAP_RTYPE_PGGROUP (1 << 29) /* Group of paged threads */
|
||||||
|
|
||||||
#define cap_rtype(c) ((c)->type & CAP_RTYPE_MASK)
|
#define cap_rtype(c) ((c)->type & CAP_RTYPE_MASK)
|
||||||
|
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ Import('env')
|
|||||||
Import('symbols')
|
Import('symbols')
|
||||||
|
|
||||||
# The set of source files associated with this SConscript file.
|
# The set of source files associated with this SConscript file.
|
||||||
src_local = ['kip.c', 'syscall.c', 'thread.c', 'ipc.c', 'map.c', 'mutex.c', 'capability.c', 'exregs.c']
|
src_local = ['kip.c', 'syscall.c', 'thread.c', 'ipc.c', 'map.c', 'mutex.c', 'cap.c', 'exregs.c']
|
||||||
|
|
||||||
obj = env.Object(src_local)
|
obj = env.Object(src_local)
|
||||||
|
|
||||||
|
|||||||
@@ -576,6 +576,10 @@ int sys_ipc(l4id_t to, l4id_t from, unsigned int flags)
|
|||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Everything in place, now check capability */
|
||||||
|
if ((err = cap_ipc_check(to, from, flags, ipc_type)) < 0)
|
||||||
|
return -ENOCAP;
|
||||||
|
|
||||||
/* Encode ipc type in task flags */
|
/* Encode ipc type in task flags */
|
||||||
tcb_set_ipc_flags(current, flags);
|
tcb_set_ipc_flags(current, flags);
|
||||||
|
|
||||||
|
|||||||
@@ -10,22 +10,17 @@
|
|||||||
#include <l4/api/space.h>
|
#include <l4/api/space.h>
|
||||||
|
|
||||||
int sys_map(unsigned long phys, unsigned long virt, unsigned long npages,
|
int sys_map(unsigned long phys, unsigned long virt, unsigned long npages,
|
||||||
unsigned long flags, unsigned int tid)
|
unsigned int flags, l4id_t tid)
|
||||||
{
|
{
|
||||||
struct ktcb *target;
|
struct ktcb *target;
|
||||||
|
int err;
|
||||||
|
|
||||||
if (tid == current->tid) { /* The easiest case */
|
if ((err = cap_map_check(phys, virt, npages, flags, tid)) < 0)
|
||||||
target = current;
|
return err;
|
||||||
goto found;
|
|
||||||
} else /* else search the tcb from its hash list */
|
|
||||||
if ((target = tcb_find(tid)))
|
|
||||||
goto found;
|
|
||||||
|
|
||||||
BUG();
|
if (!(target = tcb_find(tid)))
|
||||||
return -EINVAL;
|
return -ESRCH;
|
||||||
|
|
||||||
found:
|
|
||||||
// printk("%s (%d) Mapping from 0x%lx to 0x%lxp, %lu pages\n", __FUNCTION__, tid, phys, virt, npages);
|
|
||||||
add_mapping_pgd(phys, virt, npages << PAGE_BITS, flags, TASK_PGD(target));
|
add_mapping_pgd(phys, virt, npages << PAGE_BITS, flags, TASK_PGD(target));
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|||||||
@@ -464,6 +464,9 @@ int sys_thread_control(unsigned int flags, struct task_ids *ids)
|
|||||||
MAP_USR_RW_FLAGS, 1)) < 0)
|
MAP_USR_RW_FLAGS, 1)) < 0)
|
||||||
return err;
|
return err;
|
||||||
|
|
||||||
|
if ((err = cap_thread_check(flags, ids)) < 0)
|
||||||
|
return err;
|
||||||
|
|
||||||
switch (flags & THREAD_ACTION_MASK) {
|
switch (flags & THREAD_ACTION_MASK) {
|
||||||
case THREAD_CREATE:
|
case THREAD_CREATE:
|
||||||
ret = thread_create(ids, flags);
|
ret = thread_create(ids, flags);
|
||||||
|
|||||||
@@ -93,22 +93,6 @@ struct capability *capability_find_by_rtype(struct ktcb *task,
|
|||||||
if (cap_rtype(cap) == rtype)
|
if (cap_rtype(cap) == rtype)
|
||||||
return cap;
|
return cap;
|
||||||
|
|
||||||
/* Find group leader */
|
|
||||||
BUG_ON(!(tgleader = tcb_find(task->tgid)));
|
|
||||||
|
|
||||||
/* Search thread group list */
|
|
||||||
list_foreach_struct(cap, &tgleader->tgroup_cap_list.caps, list)
|
|
||||||
if (cap_rtype(cap) == rtype)
|
|
||||||
return cap;
|
|
||||||
|
|
||||||
/* Find pager */
|
|
||||||
BUG_ON(!(pager = tcb_find(task->pagerid)));
|
|
||||||
|
|
||||||
/* Search pager's paged-children capability list */
|
|
||||||
list_foreach_struct(cap, &pager->pager_cap_list.caps, list)
|
|
||||||
if (cap_rtype(cap) == rtype)
|
|
||||||
return cap;
|
|
||||||
|
|
||||||
/* Search container list */
|
/* Search container list */
|
||||||
list_foreach_struct(cap, &task->container->cap_list.caps, list)
|
list_foreach_struct(cap, &task->container->cap_list.caps, list)
|
||||||
if (cap_rtype(cap) == rtype)
|
if (cap_rtype(cap) == rtype)
|
||||||
@@ -117,6 +101,359 @@ struct capability *capability_find_by_rtype(struct ktcb *task,
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
typedef struct capability *(cap_match_func *)
|
||||||
|
(struct capability *cap, void *match_args)
|
||||||
|
cap_match_func_t;
|
||||||
|
|
||||||
|
struct capability *cap_find(struct ktcb *task, cap_match_func_t cap_match_func,
|
||||||
|
void *match_args, unsigned int val)
|
||||||
|
{
|
||||||
|
struct capability *cap;
|
||||||
|
struct ktcb *tgleader, *pager;
|
||||||
|
|
||||||
|
/* Search task's own list */
|
||||||
|
list_foreach_struct(cap, &task->cap_list.caps, list)
|
||||||
|
if ((cap = cap_match_func(cap, match_args, val)))
|
||||||
|
return cap;
|
||||||
|
|
||||||
|
/* Search space list */
|
||||||
|
list_foreach_struct(cap, &task->space->cap_list.caps, list)
|
||||||
|
if ((cap = cap_match_func(cap, match_args, val)))
|
||||||
|
return cap;
|
||||||
|
|
||||||
|
/* Search container list */
|
||||||
|
list_foreach_struct(cap, &task->container->cap_list.caps, list)
|
||||||
|
if ((cap = cap_match_func(cap, match_args, val)))
|
||||||
|
return cap;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
struct capability *
|
||||||
|
cap_match_mem(struct capability *cap,
|
||||||
|
void *match_args, unsigned int valid)
|
||||||
|
{
|
||||||
|
struct capability *match = match_args;
|
||||||
|
|
||||||
|
/* Equality-check these fields based on valid vector */
|
||||||
|
if (valid & FIELD_TO_BIT(struct capability, capid))
|
||||||
|
if (cap->capid != match->capid)
|
||||||
|
return 0;
|
||||||
|
if (valid & FIELD_TO_BIT(struct capability, resid))
|
||||||
|
if (cap->resid != match->resid)
|
||||||
|
return 0;
|
||||||
|
if (valid & FIELD_TO_BIT(struct capability, owner))
|
||||||
|
if (cap->owner != match->owner)
|
||||||
|
return 0;
|
||||||
|
if (valid & FIELD_TO_BIT(struct capability, type))
|
||||||
|
if (cap->type != match->type)
|
||||||
|
return 0;
|
||||||
|
if (valid & FIELD_TO_BIT(struct capability, access))
|
||||||
|
if ((cap->access & match->access)
|
||||||
|
!= match->access)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
/* Checked these together as a range */
|
||||||
|
if (valid & FIELD_TO_BIT(struct capability, start) ||
|
||||||
|
valid & FIELD_TO_BIT(struct capability, end))
|
||||||
|
if (!(match->start >= cap->start &&
|
||||||
|
match->end <= cap->end &&
|
||||||
|
match->start < match->end))
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
/* It is a match */
|
||||||
|
return cap;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct ipc_match = {
|
||||||
|
l4id_t tid;
|
||||||
|
l4id_t tgid;
|
||||||
|
l4id_t spid;
|
||||||
|
l4id_t cid;
|
||||||
|
struct capability *cap;
|
||||||
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
* In an ipc, we could look for access bits, resource type and target id
|
||||||
|
*/
|
||||||
|
struct capability *
|
||||||
|
cap_match_ipc(struct capability *cap, void *match_args, unsigned int valid)
|
||||||
|
{
|
||||||
|
struct ipc_match *ipc_match = match_args;
|
||||||
|
struct capability *cap = ipc_match->cap;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Check these for basic equality.
|
||||||
|
*/
|
||||||
|
if (valid & FIELD_TO_BIT(struct capability, capid))
|
||||||
|
if (cap->capid != match->capid)
|
||||||
|
return 0;
|
||||||
|
if (valid & FIELD_TO_BIT(struct capability, owner))
|
||||||
|
if (cap->owner != match->owner)
|
||||||
|
return 0;
|
||||||
|
if (valid & FIELD_TO_BIT(struct capability, access))
|
||||||
|
if ((cap->access & match->access)
|
||||||
|
!= match->access)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Check these optimised/specially.
|
||||||
|
* rtype and target are checked against each
|
||||||
|
* other all at once
|
||||||
|
*/
|
||||||
|
if (valid & FIELD_TO_BIT(struct capability, resid)) {
|
||||||
|
switch (cap_rtype(cap)) {
|
||||||
|
case CAP_RTYPE_THREAD:
|
||||||
|
if (ipc_matcher->tid != resid)
|
||||||
|
return 0;
|
||||||
|
break;
|
||||||
|
case CAP_RTYPE_TGROUP:
|
||||||
|
if (ipc_matcher->tgid != resid)
|
||||||
|
return 0;
|
||||||
|
break;
|
||||||
|
case CAP_RTYPE_SPACE:
|
||||||
|
if (ipc_matcher->spid != resid)
|
||||||
|
return 0;
|
||||||
|
break;
|
||||||
|
case CAP_RTYPE_CONTAINER:
|
||||||
|
if (ipc_matcher->cid != resid)
|
||||||
|
return 0;
|
||||||
|
break;
|
||||||
|
/*
|
||||||
|
* It's simply a bug to
|
||||||
|
* get an unknown resource here
|
||||||
|
*/
|
||||||
|
default:
|
||||||
|
BUG();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return cap;
|
||||||
|
}
|
||||||
|
|
||||||
|
int cap_ipc_check(struct ktcb *target, l4id_t from,
|
||||||
|
unsigned int flags, unsigned int ipc_type)
|
||||||
|
{
|
||||||
|
unsigned int valid = 0;
|
||||||
|
struct capability ipccap = {
|
||||||
|
.access = ipc_flags_type_to_access(flags, ipc_type);
|
||||||
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
* All these ids will get checked at once,
|
||||||
|
* depending on the encountered capability's
|
||||||
|
* rtype field
|
||||||
|
*/
|
||||||
|
struct ipc_matcher ipc_matcher = {
|
||||||
|
.tid = target->tid,
|
||||||
|
.tgid = target->tgid,
|
||||||
|
.spid = target->space->spid,
|
||||||
|
.cid = target->container->cid,
|
||||||
|
.ipccap = ipccap,
|
||||||
|
};
|
||||||
|
|
||||||
|
valid |= FIELD_TO_BIT(struct capability, access);
|
||||||
|
valid |= FIELD_TO_BIT(struct capability, resid);
|
||||||
|
|
||||||
|
if (!(cap_find(task, cap_match_ipc,
|
||||||
|
&ipc_matcher, valid)))
|
||||||
|
return -ENOCAP;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct exregs_match = {
|
||||||
|
l4id_t tid
|
||||||
|
l4id_t pagerid;
|
||||||
|
l4id_t tgid;
|
||||||
|
l4id_t spid;
|
||||||
|
l4id_t cid;
|
||||||
|
struct capability *cap;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
struct capability *
|
||||||
|
cap_match_thread(struct capability *cap, void *match_args, unsigned int valid)
|
||||||
|
{
|
||||||
|
struct thread_match *match = match_args;
|
||||||
|
struct capability *cap = match->cap;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Check these for basic equality.
|
||||||
|
*/
|
||||||
|
if (valid & FIELD_TO_BIT(struct capability, capid))
|
||||||
|
if (cap->capid != match->capid)
|
||||||
|
return 0;
|
||||||
|
if (valid & FIELD_TO_BIT(struct capability, owner))
|
||||||
|
if (cap->owner != match->owner)
|
||||||
|
return 0;
|
||||||
|
if (valid & FIELD_TO_BIT(struct capability, access))
|
||||||
|
if ((cap->access & match->access)
|
||||||
|
!= match->access)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Check these optimised/specially.
|
||||||
|
* rtype and target are checked against each
|
||||||
|
* other all at once
|
||||||
|
*/
|
||||||
|
if (valid & FIELD_TO_BIT(struct capability, resid)) {
|
||||||
|
switch (cap_rtype(cap)) {
|
||||||
|
/* Ability to thread_control over a paged group */
|
||||||
|
case CAP_RTYPE_PGGROUP:
|
||||||
|
if (match->pagerid != resid)
|
||||||
|
return 0;
|
||||||
|
break;
|
||||||
|
case CAP_RTYPE_TGROUP:
|
||||||
|
if (match->tgid != resid)
|
||||||
|
return 0;
|
||||||
|
break;
|
||||||
|
case CAP_RTYPE_SPACE:
|
||||||
|
if (match->spid != resid)
|
||||||
|
return 0;
|
||||||
|
break;
|
||||||
|
case CAP_RTYPE_CONTAINER:
|
||||||
|
if (match->cid != resid)
|
||||||
|
return 0;
|
||||||
|
break;
|
||||||
|
/*
|
||||||
|
* It's simply a bug to
|
||||||
|
* get an unknown resource here
|
||||||
|
*/
|
||||||
|
default:
|
||||||
|
BUG();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return cap;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* TODO: We are here!!!
|
||||||
|
*/
|
||||||
|
int cap_exregs_check(unsigned int flags, struct task_ids *ids)
|
||||||
|
{
|
||||||
|
struct capability cap = {
|
||||||
|
.access = thread_control_flags_to_access(flags);
|
||||||
|
/* all resid's checked all at once by comparing against rtype */
|
||||||
|
};
|
||||||
|
struct thread_match match = {
|
||||||
|
.pagerid = current->tid
|
||||||
|
.tgid = current->tgid,
|
||||||
|
.spid = current->spid,
|
||||||
|
.cid = current->cid,
|
||||||
|
.cap = threadmatch,
|
||||||
|
};
|
||||||
|
unsigned int valid = 0;
|
||||||
|
|
||||||
|
valid |= FIELD_TO_BIT(struct capability, access);
|
||||||
|
valid |= FIELD_TO_BIT(struct capability, resid);
|
||||||
|
|
||||||
|
if (!(cap_find(task, cap_match_thread,
|
||||||
|
&thread_match, valid)))
|
||||||
|
return -ENOCAP;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* FIXME: As new pagers, thread groups,
|
||||||
|
* thread ids, spaces are created, we need to
|
||||||
|
* give them thread_control capabilities dynamically,
|
||||||
|
* based on those ids!!! How do we get to do that, so that
|
||||||
|
* in userspace it looks not so difficult ???
|
||||||
|
*/
|
||||||
|
struct thread_match = {
|
||||||
|
l4id_t tgid;
|
||||||
|
l4id_t tid;
|
||||||
|
l4id_t pagerid;
|
||||||
|
l4id_t spid;
|
||||||
|
l4id_t cid;
|
||||||
|
unsigned int thread_control_flags;
|
||||||
|
};
|
||||||
|
|
||||||
|
def thread_create():
|
||||||
|
new_space, same_tgid, same_pager,
|
||||||
|
check_existing_ids(tid, same_tgid, same_pager, thread_create)
|
||||||
|
thread_create(new_space)
|
||||||
|
thread_add_cap(new_space, all other caps)
|
||||||
|
/*
|
||||||
|
* What do you match here?
|
||||||
|
*
|
||||||
|
* THREAD_CREATE:
|
||||||
|
* - TC_SAME_SPACE
|
||||||
|
* - spid -> Does thread have cap to create in that space?
|
||||||
|
* - cid -> Does thread have cap to create in that container?
|
||||||
|
* - tgid -> Does thread have cap to create in that thread group?
|
||||||
|
* - pagerid -> Does thread have cap to create in that group of paged threads?
|
||||||
|
* - TC_NEW_SPACE or TC_COPY_SPACE
|
||||||
|
* - Check cid, tgid, pagerid,
|
||||||
|
* - TC_SHARE_GROUP
|
||||||
|
* - Check tgid
|
||||||
|
* - TC_AS_PAGER
|
||||||
|
* - pagerid -> Does thread have cap to create in that group of paged threads?
|
||||||
|
* - TC_SHARE_PAGER
|
||||||
|
* - pagerid -> Does thread have cap to create in that group of paged threads?
|
||||||
|
* New group -> New set of caps, thread_control, exregs, ipc, ... all of them!
|
||||||
|
* New pager -> New set of caps for that pager.
|
||||||
|
* New thread -> New set of caps for that thread!
|
||||||
|
* New space -> New set of caps for that space! So many capabilities!
|
||||||
|
*/
|
||||||
|
itn cap_thread_check(struct ktcb *task, unsigned int flags, struct task_ids *ids)
|
||||||
|
{
|
||||||
|
struct thread_matcher = {
|
||||||
|
.pagerid = current->tid
|
||||||
|
.tgid = current->tgid,
|
||||||
|
.spid = current->spid,
|
||||||
|
.cid = current->cid,
|
||||||
|
.thread_control_flags = flags;
|
||||||
|
};
|
||||||
|
unsigned int valid = 0;
|
||||||
|
|
||||||
|
valid |= FIELD_TO_BIT(struct capability, access);
|
||||||
|
valid |= FIELD_TO_BIT(struct capability, resid);
|
||||||
|
|
||||||
|
if (!(cap_find(task, cap_match_thread,
|
||||||
|
&thread_matcher, valid)))
|
||||||
|
return -ENOCAP;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int cap_map_check(struct ktcb *task, unsigned long phys, unsigned long virt,
|
||||||
|
unsigned long npages, unsigned int flags, l4id_t tid)
|
||||||
|
{
|
||||||
|
struct capability *physmem, *virtmem;
|
||||||
|
struct capability physmatch = {
|
||||||
|
.start = __pfn(phys),
|
||||||
|
.end = __pfn(phys) + npages,
|
||||||
|
.type = CAP_TYPE_PHYSMEM,
|
||||||
|
.flags = map_flags_to_cap_flags(flags),
|
||||||
|
}
|
||||||
|
struct capability virtmatch = {
|
||||||
|
.start = __pfn(virt),
|
||||||
|
.end = __pfn(virt) + npages,
|
||||||
|
.type = CAP_TYPE_VIRTMEM,
|
||||||
|
.flags = map_flags_to_cap_flags(flags),
|
||||||
|
}
|
||||||
|
unsigned int virt_valid = 0;
|
||||||
|
unsigned int phys_valid = 0;
|
||||||
|
|
||||||
|
virt_valid |= FIELD_TO_BIT(struct capability, access);
|
||||||
|
virt_valid |= FIELD_TO_BIT(struct capability, start);
|
||||||
|
virt_valid |= FIELD_TO_BIT(struct capability, end);
|
||||||
|
|
||||||
|
phys_valid |= FIELD_TO_BIT(struct capability, access);
|
||||||
|
phys_valid |= FIELD_TO_BIT(struct capability, start);
|
||||||
|
phys_valid |= FIELD_TO_BIT(struct capability, end);
|
||||||
|
|
||||||
|
if (!(physmem = cap_find(task, cap_match_mem,
|
||||||
|
&physmatch, phys_valid)))
|
||||||
|
return -ENOCAP;
|
||||||
|
|
||||||
|
if (!(virtmem = cap_find(task, cap_match_mem,
|
||||||
|
&virtmatch, virt_valid)))
|
||||||
|
return -ENOCAP;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* FIXME:
|
* FIXME:
|
||||||
*
|
*
|
||||||
|
|||||||
Reference in New Issue
Block a user