Capability-enabled kernel running 2_posix test OK.

This commit is contained in:
Bahadir Balban
2009-10-27 15:59:07 +02:00
parent d1f25763ac
commit 5840d6d696
12 changed files with 244 additions and 154 deletions

View File

@@ -39,6 +39,7 @@ containers_menu 'Container Setup'
arch_type 'Main architecture' arch_type 'Main architecture'
CONTAINERS 'Number of containers' CONTAINERS 'Number of containers'
CAPABILITIES 'Enable capability checking'
############# #############
# CHOICES # # CHOICES #
@@ -97,9 +98,11 @@ menu main_menu
CONTAINERS% CONTAINERS%
containers_menu containers_menu
############# #############`
# RULES # # RULES #
############# #############
#Capability rules:
default CAPABILITIES from y
#Platform rules: #Platform rules:
unless SUBARCH_V5 suppress PLATFORM_PB926 unless SUBARCH_V5 suppress PLATFORM_PB926

View File

@@ -210,7 +210,7 @@ int read_pager_capabilities()
/* Share all of them with paged children */ /* Share all of them with paged children */
if ((err = l4_capability_control(CAP_CONTROL_SHARE, if ((err = l4_capability_control(CAP_CONTROL_SHARE,
CAP_SHARE_CHILD, CAP_SHARE_CONTAINER,
0)) < 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 "

View File

@@ -9,6 +9,7 @@
static struct capability cap_array[30]; static struct capability cap_array[30];
#if 0
struct cap_group { struct cap_group {
struct cap_list virtmem; struct cap_list virtmem;
struct cap_list physmem; struct cap_list physmem;
@@ -73,6 +74,7 @@ void cap_grant_single(struct capability *orig, struct capability *share, l4id_t
{ {
} }
#endif
void cap_print(struct capability *cap) void cap_print(struct capability *cap)
{ {
@@ -151,7 +153,7 @@ void cap_print(struct capability *cap)
printf("\n"); printf("\n");
} }
int cap_read_all(void) int caps_read_all(void)
{ {
int ncaps; int ncaps;
int err; int err;

View File

@@ -1,4 +1,5 @@
#if 0
int mutex_user_thread(void *arg) int mutex_user_thread(void *arg)
{ {
@@ -215,5 +216,5 @@ out_err:
#endif

View File

@@ -5,9 +5,9 @@
#define THREAD_CREATE 0x0000 #define THREAD_CREATE 0x0000
#define THREAD_RUN 0x0001 #define THREAD_RUN 0x0001
#define THREAD_SUSPEND 0x0002 #define THREAD_SUSPEND 0x0002
#define THREAD_RESUME 0x0003 #define THREAD_DESTROY 0x0003
#define THREAD_DESTROY 0x0004 #define THREAD_RECYCLE 0x0004
#define THREAD_RECYCLE 0x0005 #define THREAD_WAIT 0x0005
#define THREAD_CREATE_MASK 0x0FF0 #define THREAD_CREATE_MASK 0x0FF0
#define TC_SHARE_CAPS 0x0010 /* Share all thread capabilities */ #define TC_SHARE_CAPS 0x0010 /* Share all thread capabilities */

View File

@@ -28,7 +28,7 @@
#define CAP_RTYPE_TGROUP (1 << 17) #define CAP_RTYPE_TGROUP (1 << 17)
#define CAP_RTYPE_SPACE (1 << 18) #define CAP_RTYPE_SPACE (1 << 18)
#define CAP_RTYPE_CONTAINER (1 << 19) #define CAP_RTYPE_CONTAINER (1 << 19)
#define CAP_RTYPE_UMUTEX (1 << 20) /* Don't mix with pool version */ #define CAP_RTYPE_PGGROUP (1 << 20) /* Group of paged threads */
#define CAP_RTYPE_VIRTMEM (1 << 21) #define CAP_RTYPE_VIRTMEM (1 << 21)
#define CAP_RTYPE_PHYSMEM (1 << 22) #define CAP_RTYPE_PHYSMEM (1 << 22)
#define CAP_RTYPE_CPUPOOL (1 << 23) #define CAP_RTYPE_CPUPOOL (1 << 23)
@@ -37,7 +37,6 @@
#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)
@@ -48,9 +47,10 @@
/* Thread control capability */ /* Thread control capability */
#define CAP_TCTRL_CREATE (1 << 0) #define CAP_TCTRL_CREATE (1 << 0)
#define CAP_TCTRL_DESTROY (1 << 1) #define CAP_TCTRL_DESTROY (1 << 1)
#define CAP_TCTRL_SUSPEND (1 << 2) #define CAP_TCTRL_RUN (1 << 2)
#define CAP_TCTRL_RESUME (1 << 3) #define CAP_TCTRL_SUSPEND (1 << 3)
#define CAP_TCTRL_RECYCLE (1 << 4) #define CAP_TCTRL_RECYCLE (1 << 4)
#define CAP_TCTRL_WAIT (1 << 5)
/* Exchange registers capability */ /* Exchange registers capability */
#define CAP_EXREGS_RW_PAGER (1 << 0) #define CAP_EXREGS_RW_PAGER (1 << 0)

View File

@@ -142,7 +142,7 @@ struct capability *cap_list_find_by_rtype(struct cap_list *clist,
/* Capability checking on system calls */ /* Capability checking on system calls */
int cap_map_check(struct ktcb *task, unsigned long phys, unsigned long virt, int cap_map_check(struct ktcb *task, unsigned long phys, unsigned long virt,
unsigned long npages, unsigned int flags, l4id_t tid); unsigned long npages, unsigned int flags);
int cap_thread_check(struct ktcb *task, unsigned int flags, int cap_thread_check(struct ktcb *task, unsigned int flags,
struct task_ids *ids); struct task_ids *ids);
int cap_exregs_check(struct ktcb *task, struct exregs_data *exregs); int cap_exregs_check(struct ktcb *task, struct exregs_data *exregs);

View File

@@ -19,6 +19,7 @@ from config.configuration import *
containers_menu = \ containers_menu = \
''' '''
menu containers_menu menu containers_menu
CAPABILITIES
''' '''
containers_constraint = \ containers_constraint = \

View File

@@ -109,7 +109,7 @@ cap_all_others = \
\t\t\t[%d] = { \t\t\t[%d] = {
\t\t\t\t.type = CAP_TYPE_TCTRL | CAP_RTYPE_CONTAINER, \t\t\t\t.type = CAP_TYPE_TCTRL | CAP_RTYPE_CONTAINER,
\t\t\t\t.access = CAP_TCTRL_CREATE | CAP_TCTRL_DESTROY \t\t\t\t.access = CAP_TCTRL_CREATE | CAP_TCTRL_DESTROY
\t\t\t\t | CAP_TCTRL_SUSPEND | CAP_TCTRL_RESUME \t\t\t\t | CAP_TCTRL_SUSPEND | CAP_TCTRL_RUN
\t\t\t\t | CAP_TCTRL_RECYCLE, \t\t\t\t | CAP_TCTRL_RECYCLE,
\t\t\t\t.start = 0, .end = 0, .size = 0, \t\t\t\t.start = 0, .end = 0, .size = 0,
\t\t\t}, \t\t\t},
@@ -121,6 +121,17 @@ cap_all_others = \
\t\t\t\t.start = 0, .end = 0, .size = 0, \t\t\t\t.start = 0, .end = 0, .size = 0,
\t\t\t}, \t\t\t},
\t\t\t[%d] = { \t\t\t[%d] = {
\t\t\t\t.type = CAP_TYPE_CAP | CAP_RTYPE_CONTAINER,
\t\t\t\t.access = CAP_CAP_MODIFY | CAP_CAP_GRANT
\t\t\t\t| CAP_CAP_READ | CAP_CAP_SHARE,
\t\t\t\t.start = 0, .end = 0, .size = 0,
\t\t\t},
\t\t\t[%d] = {
\t\t\t\t.type = CAP_TYPE_UMUTEX | CAP_RTYPE_CONTAINER,
\t\t\t\t.access = CAP_UMUTEX_LOCK | CAP_UMUTEX_UNLOCK,
\t\t\t\t.start = 0, .end = 0, .size = 0,
\t\t\t},
\t\t\t[%d] = {
\t\t\t\t.type = CAP_TYPE_QUANTITY \t\t\t\t.type = CAP_TYPE_QUANTITY
\t\t\t\t | CAP_RTYPE_THREADPOOL, \t\t\t\t | CAP_RTYPE_THREADPOOL,
\t\t\t\t.access = 0, .start = 0, .end = 0, \t\t\t\t.access = 0, .start = 0, .end = 0,
@@ -203,7 +214,7 @@ def generate_kernel_cinfo(config, cinfo_path):
with open(cinfo_path, 'w+') as cinfo_file: with open(cinfo_path, 'w+') as cinfo_file:
fbody = cinfo_file_start % pager_ifdefs fbody = cinfo_file_start % pager_ifdefs
total_other_caps = 9 total_other_caps = 11
for c in containers: for c in containers:
# Currently only these are considered as capabilities # Currently only these are considered as capabilities
total_caps = c.virt_regions + c.phys_regions + total_other_caps total_caps = c.virt_regions + c.phys_regions + total_other_caps
@@ -216,7 +227,7 @@ def generate_kernel_cinfo(config, cinfo_path):
for mem_index in range(c.phys_regions): for mem_index in range(c.phys_regions):
fbody += cap_physmem % { 'capidx' : cap_index, 'cn' : c.id, 'pn' : mem_index } fbody += cap_physmem % { 'capidx' : cap_index, 'cn' : c.id, 'pn' : mem_index }
cap_index += 1 cap_index += 1
fbody += cap_all_others % (tuple(range(cap_index, total_caps))) fbody += cap_all_others % tuple(range(cap_index, total_caps))
fbody += pager_end fbody += pager_end
fbody += cinfo_end fbody += cinfo_end
fbody += cinfo_file_end fbody += cinfo_file_end

View File

@@ -18,7 +18,7 @@ int sys_map(unsigned long phys, unsigned long virt, unsigned long npages,
if (!(target = tcb_find(tid))) if (!(target = tcb_find(tid)))
return -ESRCH; return -ESRCH;
if ((err = cap_map_check(target, phys, virt, npages, flags, tid)) < 0) if ((err = cap_map_check(target, phys, virt, npages, flags)) < 0)
return err; return err;
add_mapping_pgd(phys, virt, npages << PAGE_BITS, flags, TASK_PGD(target)); add_mapping_pgd(phys, virt, npages << PAGE_BITS, flags, TASK_PGD(target));

View File

@@ -203,20 +203,6 @@ void thread_destroy_current(void)
sched_suspend_sync(); sched_suspend_sync();
} }
int thread_resume(struct ktcb *task)
{
if (!mutex_trylock(&task->thread_control_lock))
return -EAGAIN;
/* Put task into runqueue as runnable */
sched_resume_async(task);
/* Release lock and return */
mutex_unlock(&task->thread_control_lock);
return 0;
}
/* Runs a thread for the first time */ /* Runs a thread for the first time */
int thread_start(struct ktcb *task) int thread_start(struct ktcb *task)
{ {
@@ -443,9 +429,6 @@ int sys_thread_control(unsigned int flags, struct task_ids *ids)
case THREAD_SUSPEND: case THREAD_SUSPEND:
ret = thread_suspend(task, flags); ret = thread_suspend(task, flags);
break; break;
case THREAD_RESUME:
ret = thread_resume(task);
break;
case THREAD_DESTROY: case THREAD_DESTROY:
ret = thread_destroy(task); ret = thread_destroy(task);
break; break;

View File

@@ -9,6 +9,7 @@
#include <l4/generic/cap-types.h> #include <l4/generic/cap-types.h>
#include <l4/generic/tcb.h> #include <l4/generic/tcb.h>
#include <l4/api/capability.h> #include <l4/api/capability.h>
#include <l4/api/thread.h>
#include <l4/api/errno.h> #include <l4/api/errno.h>
#include <l4/lib/printk.h> #include <l4/lib/printk.h>
#include <l4/api/thread.h> #include <l4/api/thread.h>
@@ -44,6 +45,7 @@ struct capability *capability_create(void)
return cap; return cap;
} }
#if defined(CONFIG_CAPABILITIES)
int capability_consume(struct capability *cap, int quantity) int capability_consume(struct capability *cap, int quantity)
{ {
if (cap->size < cap->used + quantity) if (cap->size < cap->used + quantity)
@@ -60,6 +62,18 @@ int capability_free(struct capability *cap, int quantity)
return 0; return 0;
} }
#else
int capability_consume(struct capability *cap, int quantity)
{
return 0;
}
int capability_free(struct capability *cap, int quantity)
{
return 0;
}
#endif
struct capability *cap_list_find_by_rtype(struct cap_list *cap_list, struct capability *cap_list_find_by_rtype(struct cap_list *cap_list,
unsigned int rtype) unsigned int rtype)
{ {
@@ -77,10 +91,12 @@ struct capability *cap_list_find_by_rtype(struct cap_list *cap_list,
* Search all capability lists that task is allowed. * Search all capability lists that task is allowed.
* *
* FIXME: * FIXME:
* Tasks won't always search for a capability randomly. Consider * Tasks should not always search for a capability randomly. Consider
* mutexes, if a mutex is freed, it needs to be accounted to private * mutexes, if a mutex is freed, it needs to be accounted to private
* pool first if that is not full, because freeing it into shared * pool first if that is not full, because freeing it into shared
* pool may lose the mutex right to another task. * pool may lose the mutex right to another task. In other words,
* when you're freeing a mutex, we should know which capability pool
* to free it to.
* *
* In conclusion freeing of pool-type capabilities need to be done * In conclusion freeing of pool-type capabilities need to be done
* in order of privacy. -> It may get confusing as a space, thread * in order of privacy. -> It may get confusing as a space, thread
@@ -116,25 +132,25 @@ typedef struct capability *(*cap_match_func_t) \
struct capability *cap_find(struct ktcb *task, cap_match_func_t cap_match_func, struct capability *cap_find(struct ktcb *task, cap_match_func_t cap_match_func,
void *match_args, unsigned int cap_type) void *match_args, unsigned int cap_type)
{ {
struct capability *cap; struct capability *cap, *found;
/* Search task's own list */ /* Search task's own list */
list_foreach_struct(cap, &task->cap_list.caps, list) list_foreach_struct(cap, &task->cap_list.caps, list)
if (cap_type(cap) == cap_type && if (cap_type(cap) == cap_type &&
((cap = cap_match_func(cap, match_args)))) ((found = cap_match_func(cap, match_args))))
return cap; return found;
/* Search space list */ /* Search space list */
list_foreach_struct(cap, &task->space->cap_list.caps, list) list_foreach_struct(cap, &task->space->cap_list.caps, list)
if (cap_type(cap) == cap_type && if (cap_type(cap) == cap_type &&
((cap = cap_match_func(cap, match_args)))) ((found = cap_match_func(cap, match_args))))
return cap; return found;
/* 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_type(cap) == cap_type && if (cap_type(cap) == cap_type &&
((cap = cap_match_func(cap, match_args)))) ((found = cap_match_func(cap, match_args))))
return cap; return found;
return 0; return 0;
} }
@@ -144,6 +160,24 @@ struct sys_mutex_args {
unsigned int op; unsigned int op;
}; };
/*
* Check broadly the ability to do mutex ops. Check it by
* the thread, space or container, (i.e. the group that can
* do this operation broadly)
*
* Note, that we check mutex_address elsewhere as a quick,
* per-task virt_to_phys translation that would not get
* easily/quickly satisfied by a memory capability checking.
*
* While this is not %100 right from a capability checking
* point-of-view, it is a shortcut that works and makes sense.
*
* For sake of completion, the right way to do it would be to
* add MUTEX_LOCKABLE, MUTEX_UNLOCKABLE attributes to both
* virtual and physical memory caps of a task, search those
* to validate the address. But we would have to translate
* from the page tables either ways.
*/
struct capability * struct capability *
cap_match_mutex(struct capability *cap, void *args) cap_match_mutex(struct capability *cap, void *args)
{ {
@@ -174,20 +208,6 @@ cap_match_mutex(struct capability *cap, void *args)
return cap; return cap;
} }
int cap_mutex_check(unsigned long mutex_address, int mutex_op)
{
struct sys_mutex_args args = {
.address = mutex_address,
.op = mutex_op,
};
if (!(cap_find(current, cap_match_mutex,
&args, CAP_TYPE_UMUTEX)))
return -ENOCAP;
return 0;
}
struct sys_capctrl_args { struct sys_capctrl_args {
unsigned int req; unsigned int req;
unsigned int flags; unsigned int flags;
@@ -237,21 +257,6 @@ cap_match_capctrl(struct capability *cap, void *args_ptr)
return cap; return cap;
} }
int cap_cap_check(struct ktcb *task, unsigned int req, unsigned int flags)
{
struct sys_capctrl_args args = {
.req = req,
.flags = flags,
.task = task,
};
if (!(cap_find(task, cap_match_capctrl,
&args, CAP_TYPE_CAP)))
return -ENOCAP;
return 0;
}
struct sys_ipc_args { struct sys_ipc_args {
struct ktcb *task; struct ktcb *task;
unsigned int ipc_type; unsigned int ipc_type;
@@ -307,40 +312,6 @@ cap_match_ipc(struct capability *cap, void *args_ptr)
return cap; return cap;
} }
/*
* Limitation: We currently only check from sender's
* perspective. Sender always targets a real thread.
* Does sender have the right to do this ipc?
*/
int cap_ipc_check(l4id_t to, l4id_t from,
unsigned int flags, unsigned int ipc_type)
{
struct ktcb *target;
struct sys_ipc_args args;
/* Receivers can get away from us (for now) */
if (ipc_type != IPC_SEND && ipc_type != IPC_SENDRECV)
return 0;
/*
* We're the sender, meaning we have
* a real target
*/
if (!(target = tcb_find(to)))
return -ESRCH;
/* Set up other args */
args.flags = flags;
args.ipc_type = ipc_type;
args.task = target;
if (!(cap_find(target, cap_match_ipc,
&args, CAP_TYPE_IPC)))
return -ENOCAP;
return 0;
}
struct sys_exregs_args { struct sys_exregs_args {
struct exregs_data *exregs; struct exregs_data *exregs;
struct ktcb *task; struct ktcb *task;
@@ -397,20 +368,6 @@ cap_match_exregs(struct capability *cap, void *args_ptr)
return cap; return cap;
} }
int cap_exregs_check(struct ktcb *task, struct exregs_data *exregs)
{
struct sys_exregs_args args = {
.exregs = exregs,
.task = task,
};
if (!(cap_find(task, cap_match_exregs,
&args, CAP_TYPE_EXREGS)))
return -ENOCAP;
return 0;
}
/* /*
* FIXME: Issues on capabilities: * FIXME: Issues on capabilities:
* *
@@ -456,26 +413,44 @@ struct capability *cap_match_thread(struct capability *cap,
{ {
struct sys_tctrl_args *args = args_ptr; struct sys_tctrl_args *args = args_ptr;
struct ktcb *target = args->task; struct ktcb *target = args->task;
unsigned int action_flags = args->flags & THREAD_ACTION_MASK;
/* Check operation privileges */ /* Check operation privileges */
if (args->flags & THREAD_CREATE) switch (action_flags) {
case THREAD_CREATE:
if (!(cap->access & CAP_TCTRL_CREATE)) if (!(cap->access & CAP_TCTRL_CREATE))
return 0; return 0;
if (args->flags & THREAD_DESTROY) break;
case THREAD_DESTROY:
if (!(cap->access & CAP_TCTRL_DESTROY)) if (!(cap->access & CAP_TCTRL_DESTROY))
return 0; return 0;
if (args->flags & THREAD_SUSPEND) break;
case THREAD_SUSPEND:
if (!(cap->access & CAP_TCTRL_SUSPEND)) if (!(cap->access & CAP_TCTRL_SUSPEND))
return 0; return 0;
if (args->flags & THREAD_RESUME) break;
if (!(cap->access & CAP_TCTRL_RESUME)) case THREAD_RUN:
if (!(cap->access & CAP_TCTRL_RUN))
return 0; return 0;
break;
case THREAD_RECYCLE:
if (!(cap->access & CAP_TCTRL_RECYCLE))
return 0;
break;
case THREAD_WAIT:
if (!(cap->access & CAP_TCTRL_WAIT))
return 0;
break;
default:
/* We refuse to accept anything else */
return 0;
}
/* If no target and create, or vice versa, it really is a bug */ /* If no target and create, or vice versa, it really is a bug */
BUG_ON(!target && !(args->flags & THREAD_CREATE)); BUG_ON(!target && action_flags != THREAD_CREATE);
BUG_ON(target && (args->flags & THREAD_CREATE)); BUG_ON(target && action_flags == THREAD_CREATE);
if (args->flags & THREAD_CREATE) { if (action_flags == THREAD_CREATE) {
/* /*
* FIXME: Add cid to task_ids arg. * FIXME: Add cid to task_ids arg.
* *
@@ -490,7 +465,7 @@ struct capability *cap_match_thread(struct capability *cap,
return 0; return 0;
if (cap->resid != current->container->cid) if (cap->resid != current->container->cid)
return 0; return 0;
/* Resource type and it match, success */ /* Resource type and id match, success */
return cap; return cap;
} }
@@ -517,23 +492,6 @@ struct capability *cap_match_thread(struct capability *cap,
return cap; return cap;
} }
int cap_thread_check(struct ktcb *task,
unsigned int flags,
struct task_ids *ids)
{
struct sys_tctrl_args args = {
.task = task,
.flags = flags,
.ids = ids,
};
if (!(cap_find(task, cap_match_thread,
&args, CAP_TYPE_TCTRL)))
return -ENOCAP;
return 0;
}
struct sys_map_args { struct sys_map_args {
struct ktcb *task; struct ktcb *task;
unsigned long phys; unsigned long phys;
@@ -541,7 +499,6 @@ struct sys_map_args {
unsigned long npages; unsigned long npages;
unsigned int flags; unsigned int flags;
unsigned int rtype; unsigned int rtype;
l4id_t tid;
}; };
/* /*
@@ -589,7 +546,9 @@ struct capability *cap_match_mem(struct capability *cap,
return cap; return cap;
/* /*
* TODO: Does it make sense to have a meaningful resid field * FIXME:
*
* Does it make sense to have a meaningful resid field
* in a memory resource? E.g. Which resources may I map it to? * in a memory resource? E.g. Which resources may I map it to?
* It might, as I can map an arbitrary mapping to an arbitrary * It might, as I can map an arbitrary mapping to an arbitrary
* thread in my container and break it's memory integrity. * thread in my container and break it's memory integrity.
@@ -601,32 +560,163 @@ struct capability *cap_match_mem(struct capability *cap,
*/ */
} }
int cap_map_check(struct ktcb *task, unsigned long phys, unsigned long virt, #if defined(CONFIG_CAPABILITIES)
unsigned long npages, unsigned int flags, l4id_t tid) int cap_mutex_check(unsigned long mutex_address, int mutex_op)
{
struct sys_mutex_args args = {
.address = mutex_address,
.op = mutex_op,
};
if (!(cap_find(current, cap_match_mutex,
&args, CAP_TYPE_UMUTEX)))
return -ENOCAP;
return 0;
}
int cap_cap_check(struct ktcb *task, unsigned int req, unsigned int flags)
{
struct sys_capctrl_args args = {
.req = req,
.flags = flags,
.task = task,
};
if (!(cap_find(current, cap_match_capctrl,
&args, CAP_TYPE_CAP)))
return -ENOCAP;
return 0;
}
int cap_map_check(struct ktcb *target, unsigned long phys, unsigned long virt,
unsigned long npages, unsigned int flags)
{ {
struct capability *physmem, *virtmem; struct capability *physmem, *virtmem;
struct sys_map_args args = { struct sys_map_args args = {
.task = task, .task = target,
.phys = phys, .phys = phys,
.virt = virt, .virt = virt,
.npages = npages, .npages = npages,
.flags = flags, .flags = flags,
.tid = tid,
}; };
args.rtype = CAP_RTYPE_PHYSMEM; args.rtype = CAP_RTYPE_PHYSMEM;
if (!(physmem = cap_find(task, cap_match_mem, if (!(physmem = cap_find(current, cap_match_mem,
&args, CAP_TYPE_MAP))) &args, CAP_TYPE_MAP)))
return -ENOCAP; return -ENOCAP;
args.rtype = CAP_RTYPE_VIRTMEM; args.rtype = CAP_RTYPE_VIRTMEM;
if (!(virtmem = cap_find(task, cap_match_mem, if (!(virtmem = cap_find(current, cap_match_mem,
&args, CAP_TYPE_MAP))) &args, CAP_TYPE_MAP)))
return -ENOCAP; return -ENOCAP;
return 0; return 0;
} }
/*
* Limitation: We currently only check from sender's
* perspective. Sender always targets a real thread.
* Does sender have the right to do this ipc?
*/
int cap_ipc_check(l4id_t to, l4id_t from,
unsigned int flags, unsigned int ipc_type)
{
struct ktcb *target;
struct sys_ipc_args args;
/* Receivers can get away from us (for now) */
if (ipc_type != IPC_SEND && ipc_type != IPC_SENDRECV)
return 0;
/*
* We're the sender, meaning we have
* a real target
*/
if (!(target = tcb_find(to)))
return -ESRCH;
/* Set up other args */
args.flags = flags;
args.ipc_type = ipc_type;
args.task = target;
if (!(cap_find(current, cap_match_ipc,
&args, CAP_TYPE_IPC)))
return -ENOCAP;
return 0;
}
int cap_exregs_check(struct ktcb *task, struct exregs_data *exregs)
{
struct sys_exregs_args args = {
.exregs = exregs,
.task = task,
};
/* We always search for current's caps */
if (!(cap_find(current, cap_match_exregs,
&args, CAP_TYPE_EXREGS)))
return -ENOCAP;
return 0;
}
int cap_thread_check(struct ktcb *task,
unsigned int flags,
struct task_ids *ids)
{
struct sys_tctrl_args args = {
.task = task,
.flags = flags,
.ids = ids,
};
if (!(cap_find(current, cap_match_thread,
&args, CAP_TYPE_TCTRL)))
return -ENOCAP;
return 0;
}
#else /* Meaning !CONFIG_CAPABILITIES */
int cap_mutex_check(unsigned long mutex_address, int mutex_op)
{
return 0;
}
int cap_cap_check(struct ktcb *task, unsigned int req, unsigned int flags)
{
return 0;
}
int cap_ipc_check(l4id_t to, l4id_t from,
unsigned int flags, unsigned int ipc_type)
{
return 0;
}
int cap_map_check(struct ktcb *task, unsigned long phys, unsigned long virt,
unsigned long npages, unsigned int flags)
{
return 0;
}
int cap_exregs_check(struct ktcb *task, struct exregs_data *exregs)
{
return 0;
}
int cap_thread_check(struct ktcb *task,
unsigned int flags,
struct task_ids *ids)
{
return 0;
}
#endif
/* /*
* FIXME: * FIXME:
* *
@@ -667,7 +757,6 @@ int capability_set_resource_id(struct capability *cap)
case CAP_RTYPE_TGROUP: case CAP_RTYPE_TGROUP:
case CAP_RTYPE_SPACE: case CAP_RTYPE_SPACE:
case CAP_RTYPE_CONTAINER: case CAP_RTYPE_CONTAINER:
case CAP_RTYPE_UMUTEX:
break; break;
} }
return 0; return 0;