mirror of
https://github.com/drasko/codezero.git
synced 2026-01-12 02:43:15 +01:00
Capability-enabled kernel running 2_posix test OK.
This commit is contained in:
@@ -39,6 +39,7 @@ containers_menu 'Container Setup'
|
||||
arch_type 'Main architecture'
|
||||
|
||||
CONTAINERS 'Number of containers'
|
||||
CAPABILITIES 'Enable capability checking'
|
||||
|
||||
#############
|
||||
# CHOICES #
|
||||
@@ -97,9 +98,11 @@ menu main_menu
|
||||
CONTAINERS%
|
||||
containers_menu
|
||||
|
||||
#############
|
||||
#############`
|
||||
# RULES #
|
||||
#############
|
||||
#Capability rules:
|
||||
default CAPABILITIES from y
|
||||
|
||||
#Platform rules:
|
||||
unless SUBARCH_V5 suppress PLATFORM_PB926
|
||||
|
||||
@@ -210,7 +210,7 @@ int read_pager_capabilities()
|
||||
|
||||
/* Share all of them with paged children */
|
||||
if ((err = l4_capability_control(CAP_CONTROL_SHARE,
|
||||
CAP_SHARE_CHILD,
|
||||
CAP_SHARE_CONTAINER,
|
||||
0)) < 0) {
|
||||
printf("l4_capability_control() sharing of "
|
||||
"capabilities failed.\n Could not "
|
||||
|
||||
@@ -9,6 +9,7 @@
|
||||
|
||||
static struct capability cap_array[30];
|
||||
|
||||
#if 0
|
||||
struct cap_group {
|
||||
struct cap_list virtmem;
|
||||
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)
|
||||
{
|
||||
@@ -151,7 +153,7 @@ void cap_print(struct capability *cap)
|
||||
printf("\n");
|
||||
}
|
||||
|
||||
int cap_read_all(void)
|
||||
int caps_read_all(void)
|
||||
{
|
||||
int ncaps;
|
||||
int err;
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
|
||||
#if 0
|
||||
|
||||
int mutex_user_thread(void *arg)
|
||||
{
|
||||
@@ -215,5 +216,5 @@ out_err:
|
||||
|
||||
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
@@ -5,9 +5,9 @@
|
||||
#define THREAD_CREATE 0x0000
|
||||
#define THREAD_RUN 0x0001
|
||||
#define THREAD_SUSPEND 0x0002
|
||||
#define THREAD_RESUME 0x0003
|
||||
#define THREAD_DESTROY 0x0004
|
||||
#define THREAD_RECYCLE 0x0005
|
||||
#define THREAD_DESTROY 0x0003
|
||||
#define THREAD_RECYCLE 0x0004
|
||||
#define THREAD_WAIT 0x0005
|
||||
|
||||
#define THREAD_CREATE_MASK 0x0FF0
|
||||
#define TC_SHARE_CAPS 0x0010 /* Share all thread capabilities */
|
||||
|
||||
@@ -28,7 +28,7 @@
|
||||
#define CAP_RTYPE_TGROUP (1 << 17)
|
||||
#define CAP_RTYPE_SPACE (1 << 18)
|
||||
#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_PHYSMEM (1 << 22)
|
||||
#define CAP_RTYPE_CPUPOOL (1 << 23)
|
||||
@@ -37,7 +37,6 @@
|
||||
#define CAP_RTYPE_MUTEXPOOL (1 << 26)
|
||||
#define CAP_RTYPE_MAPPOOL (1 << 27) /* For pmd spending */
|
||||
#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)
|
||||
|
||||
@@ -48,9 +47,10 @@
|
||||
/* Thread control capability */
|
||||
#define CAP_TCTRL_CREATE (1 << 0)
|
||||
#define CAP_TCTRL_DESTROY (1 << 1)
|
||||
#define CAP_TCTRL_SUSPEND (1 << 2)
|
||||
#define CAP_TCTRL_RESUME (1 << 3)
|
||||
#define CAP_TCTRL_RUN (1 << 2)
|
||||
#define CAP_TCTRL_SUSPEND (1 << 3)
|
||||
#define CAP_TCTRL_RECYCLE (1 << 4)
|
||||
#define CAP_TCTRL_WAIT (1 << 5)
|
||||
|
||||
/* Exchange registers capability */
|
||||
#define CAP_EXREGS_RW_PAGER (1 << 0)
|
||||
|
||||
@@ -142,7 +142,7 @@ struct capability *cap_list_find_by_rtype(struct cap_list *clist,
|
||||
|
||||
/* Capability checking on system calls */
|
||||
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,
|
||||
struct task_ids *ids);
|
||||
int cap_exregs_check(struct ktcb *task, struct exregs_data *exregs);
|
||||
|
||||
@@ -19,6 +19,7 @@ from config.configuration import *
|
||||
containers_menu = \
|
||||
'''
|
||||
menu containers_menu
|
||||
CAPABILITIES
|
||||
'''
|
||||
|
||||
containers_constraint = \
|
||||
|
||||
@@ -109,7 +109,7 @@ cap_all_others = \
|
||||
\t\t\t[%d] = {
|
||||
\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 | 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.start = 0, .end = 0, .size = 0,
|
||||
\t\t\t},
|
||||
@@ -121,6 +121,17 @@ cap_all_others = \
|
||||
\t\t\t\t.start = 0, .end = 0, .size = 0,
|
||||
\t\t\t},
|
||||
\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 | CAP_RTYPE_THREADPOOL,
|
||||
\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:
|
||||
fbody = cinfo_file_start % pager_ifdefs
|
||||
total_other_caps = 9
|
||||
total_other_caps = 11
|
||||
for c in containers:
|
||||
# Currently only these are considered as capabilities
|
||||
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):
|
||||
fbody += cap_physmem % { 'capidx' : cap_index, 'cn' : c.id, 'pn' : mem_index }
|
||||
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 += cinfo_end
|
||||
fbody += cinfo_file_end
|
||||
|
||||
@@ -18,7 +18,7 @@ int sys_map(unsigned long phys, unsigned long virt, unsigned long npages,
|
||||
if (!(target = tcb_find(tid)))
|
||||
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;
|
||||
|
||||
add_mapping_pgd(phys, virt, npages << PAGE_BITS, flags, TASK_PGD(target));
|
||||
|
||||
@@ -203,20 +203,6 @@ void thread_destroy_current(void)
|
||||
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 */
|
||||
int thread_start(struct ktcb *task)
|
||||
{
|
||||
@@ -443,9 +429,6 @@ int sys_thread_control(unsigned int flags, struct task_ids *ids)
|
||||
case THREAD_SUSPEND:
|
||||
ret = thread_suspend(task, flags);
|
||||
break;
|
||||
case THREAD_RESUME:
|
||||
ret = thread_resume(task);
|
||||
break;
|
||||
case THREAD_DESTROY:
|
||||
ret = thread_destroy(task);
|
||||
break;
|
||||
|
||||
@@ -9,6 +9,7 @@
|
||||
#include <l4/generic/cap-types.h>
|
||||
#include <l4/generic/tcb.h>
|
||||
#include <l4/api/capability.h>
|
||||
#include <l4/api/thread.h>
|
||||
#include <l4/api/errno.h>
|
||||
#include <l4/lib/printk.h>
|
||||
#include <l4/api/thread.h>
|
||||
@@ -44,6 +45,7 @@ struct capability *capability_create(void)
|
||||
return cap;
|
||||
}
|
||||
|
||||
#if defined(CONFIG_CAPABILITIES)
|
||||
int capability_consume(struct capability *cap, int quantity)
|
||||
{
|
||||
if (cap->size < cap->used + quantity)
|
||||
@@ -60,6 +62,18 @@ int capability_free(struct capability *cap, int quantity)
|
||||
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,
|
||||
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.
|
||||
*
|
||||
* 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
|
||||
* 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 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,
|
||||
void *match_args, unsigned int cap_type)
|
||||
{
|
||||
struct capability *cap;
|
||||
struct capability *cap, *found;
|
||||
|
||||
/* Search task's own list */
|
||||
list_foreach_struct(cap, &task->cap_list.caps, list)
|
||||
if (cap_type(cap) == cap_type &&
|
||||
((cap = cap_match_func(cap, match_args))))
|
||||
return cap;
|
||||
((found = cap_match_func(cap, match_args))))
|
||||
return found;
|
||||
|
||||
/* Search space list */
|
||||
list_foreach_struct(cap, &task->space->cap_list.caps, list)
|
||||
if (cap_type(cap) == cap_type &&
|
||||
((cap = cap_match_func(cap, match_args))))
|
||||
return cap;
|
||||
((found = cap_match_func(cap, match_args))))
|
||||
return found;
|
||||
|
||||
/* Search container list */
|
||||
list_foreach_struct(cap, &task->container->cap_list.caps, list)
|
||||
if (cap_type(cap) == cap_type &&
|
||||
((cap = cap_match_func(cap, match_args))))
|
||||
return cap;
|
||||
((found = cap_match_func(cap, match_args))))
|
||||
return found;
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -144,6 +160,24 @@ struct sys_mutex_args {
|
||||
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 *
|
||||
cap_match_mutex(struct capability *cap, void *args)
|
||||
{
|
||||
@@ -174,20 +208,6 @@ cap_match_mutex(struct capability *cap, void *args)
|
||||
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 {
|
||||
unsigned int req;
|
||||
unsigned int flags;
|
||||
@@ -237,21 +257,6 @@ cap_match_capctrl(struct capability *cap, void *args_ptr)
|
||||
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 ktcb *task;
|
||||
unsigned int ipc_type;
|
||||
@@ -307,40 +312,6 @@ cap_match_ipc(struct capability *cap, void *args_ptr)
|
||||
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 exregs_data *exregs;
|
||||
struct ktcb *task;
|
||||
@@ -397,20 +368,6 @@ cap_match_exregs(struct capability *cap, void *args_ptr)
|
||||
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:
|
||||
*
|
||||
@@ -456,26 +413,44 @@ struct capability *cap_match_thread(struct capability *cap,
|
||||
{
|
||||
struct sys_tctrl_args *args = args_ptr;
|
||||
struct ktcb *target = args->task;
|
||||
unsigned int action_flags = args->flags & THREAD_ACTION_MASK;
|
||||
|
||||
/* Check operation privileges */
|
||||
if (args->flags & THREAD_CREATE)
|
||||
switch (action_flags) {
|
||||
case THREAD_CREATE:
|
||||
if (!(cap->access & CAP_TCTRL_CREATE))
|
||||
return 0;
|
||||
if (args->flags & THREAD_DESTROY)
|
||||
break;
|
||||
case THREAD_DESTROY:
|
||||
if (!(cap->access & CAP_TCTRL_DESTROY))
|
||||
return 0;
|
||||
if (args->flags & THREAD_SUSPEND)
|
||||
break;
|
||||
case THREAD_SUSPEND:
|
||||
if (!(cap->access & CAP_TCTRL_SUSPEND))
|
||||
return 0;
|
||||
if (args->flags & THREAD_RESUME)
|
||||
if (!(cap->access & CAP_TCTRL_RESUME))
|
||||
break;
|
||||
case THREAD_RUN:
|
||||
if (!(cap->access & CAP_TCTRL_RUN))
|
||||
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 */
|
||||
BUG_ON(!target && !(args->flags & THREAD_CREATE));
|
||||
BUG_ON(target && (args->flags & THREAD_CREATE));
|
||||
BUG_ON(!target && action_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.
|
||||
*
|
||||
@@ -490,7 +465,7 @@ struct capability *cap_match_thread(struct capability *cap,
|
||||
return 0;
|
||||
if (cap->resid != current->container->cid)
|
||||
return 0;
|
||||
/* Resource type and it match, success */
|
||||
/* Resource type and id match, success */
|
||||
return cap;
|
||||
}
|
||||
|
||||
@@ -517,23 +492,6 @@ struct capability *cap_match_thread(struct capability *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 ktcb *task;
|
||||
unsigned long phys;
|
||||
@@ -541,7 +499,6 @@ struct sys_map_args {
|
||||
unsigned long npages;
|
||||
unsigned int flags;
|
||||
unsigned int rtype;
|
||||
l4id_t tid;
|
||||
};
|
||||
|
||||
/*
|
||||
@@ -589,7 +546,9 @@ struct capability *cap_match_mem(struct capability *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?
|
||||
* It might, as I can map an arbitrary mapping to an arbitrary
|
||||
* 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,
|
||||
unsigned long npages, unsigned int flags, l4id_t tid)
|
||||
#if defined(CONFIG_CAPABILITIES)
|
||||
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 sys_map_args args = {
|
||||
.task = task,
|
||||
.task = target,
|
||||
.phys = phys,
|
||||
.virt = virt,
|
||||
.npages = npages,
|
||||
.flags = flags,
|
||||
.tid = tid,
|
||||
};
|
||||
|
||||
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)))
|
||||
return -ENOCAP;
|
||||
|
||||
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)))
|
||||
return -ENOCAP;
|
||||
|
||||
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:
|
||||
*
|
||||
@@ -667,7 +757,6 @@ int capability_set_resource_id(struct capability *cap)
|
||||
case CAP_RTYPE_TGROUP:
|
||||
case CAP_RTYPE_SPACE:
|
||||
case CAP_RTYPE_CONTAINER:
|
||||
case CAP_RTYPE_UMUTEX:
|
||||
break;
|
||||
}
|
||||
return 0;
|
||||
|
||||
Reference in New Issue
Block a user