mirror of
https://github.com/drasko/codezero.git
synced 2026-01-13 11:23:16 +01:00
Capability checking added as compiling code.
Capability checking for thread_control, exregs, mutex, cap_control,
ipc, and map system calls.
The visualised model is implemented in code that compiles, but
actual functionality hasn't been tested.
Need to add:
- Dynamic assignment of initial resources matching with what's
defined in the configuration.
- A paged-thread-group, since that would be a logical group of
seperation from a capability point-of-view.
- Resource ids for various tasks. E.g.
- Memory capabilities don't have target resources.
- Thread capability assumes current container for THREAD_CREATE.
- Mutex syscall assumes current thread (this one may not need
any changing)
- cap_control syscall assumes current thread. It may happen to
be that another thread's capability list is manipulated.
Last but not least:
- A simple and easy-to-use userspace library for dynamic expansion
of resource domains as new resources are created such as threads.
This commit is contained in:
@@ -110,6 +110,13 @@ int sys_capability_control(unsigned int req, unsigned int flags, void *userbuf)
|
||||
{
|
||||
int err;
|
||||
|
||||
/*
|
||||
* Check capability to do a capability operation.
|
||||
* Supported only on current's caps for time being.
|
||||
*/
|
||||
if ((err = cap_cap_check(current, req, flags)) < 0)
|
||||
return err;
|
||||
|
||||
switch(req) {
|
||||
/* Return number of capabilities the thread has */
|
||||
case CAP_CONTROL_NCAPS:
|
||||
|
||||
@@ -137,14 +137,8 @@ int sys_exchange_registers(struct exregs_data *exregs, l4id_t tid)
|
||||
goto out;
|
||||
}
|
||||
|
||||
/*
|
||||
* FIXME:
|
||||
* Capability Check.
|
||||
* Whose clist are we ought to check? Pager's or threads?
|
||||
* Need to check exregs capability
|
||||
* Need to check utcb capability if present.
|
||||
* if ((exregs->flags & EXREGS_SET_UTCB) &&
|
||||
*/
|
||||
if ((err = cap_exregs_check(task, exregs)) < 0)
|
||||
return -ENOCAP;
|
||||
|
||||
/* Copy registers */
|
||||
do_exchange_registers(task, exregs);
|
||||
|
||||
@@ -15,17 +15,6 @@
|
||||
#include INC_GLUE(message.h)
|
||||
#include INC_GLUE(ipc.h)
|
||||
|
||||
/*
|
||||
* ipc syscall uses an ipc_type variable and send/recv
|
||||
* details are embedded in this variable.
|
||||
*/
|
||||
enum IPC_TYPE {
|
||||
IPC_INVALID = 0,
|
||||
IPC_SEND = 1,
|
||||
IPC_RECV = 2,
|
||||
IPC_SENDRECV = 3,
|
||||
};
|
||||
|
||||
int ipc_short_copy(struct ktcb *to, struct ktcb *from)
|
||||
{
|
||||
unsigned int *mr0_src = KTCB_REF_MR0(from);
|
||||
@@ -373,7 +362,7 @@ int ipc_sendrecv(l4id_t to, l4id_t from, unsigned int flags)
|
||||
|
||||
int ipc_sendrecv_extended(l4id_t to, l4id_t from, unsigned int flags)
|
||||
{
|
||||
return 0;
|
||||
return -ENOSYS;
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -577,8 +566,8 @@ int sys_ipc(l4id_t to, l4id_t from, unsigned int flags)
|
||||
}
|
||||
|
||||
/* Everything in place, now check capability */
|
||||
if ((err = cap_ipc_check(to, from, flags, ipc_type)) < 0)
|
||||
return -ENOCAP;
|
||||
if ((ret = cap_ipc_check(to, from, flags, ipc_type)) < 0)
|
||||
return ret;
|
||||
|
||||
/* Encode ipc type in task flags */
|
||||
tcb_set_ipc_flags(current, flags);
|
||||
|
||||
@@ -15,12 +15,12 @@ int sys_map(unsigned long phys, unsigned long virt, unsigned long npages,
|
||||
struct ktcb *target;
|
||||
int err;
|
||||
|
||||
if ((err = cap_map_check(phys, virt, npages, flags, tid)) < 0)
|
||||
return err;
|
||||
|
||||
if (!(target = tcb_find(tid)))
|
||||
return -ESRCH;
|
||||
|
||||
if ((err = cap_map_check(target, phys, virt, npages, flags, tid)) < 0)
|
||||
return err;
|
||||
|
||||
add_mapping_pgd(phys, virt, npages << PAGE_BITS, flags, TASK_PGD(target));
|
||||
|
||||
return 0;
|
||||
|
||||
@@ -239,7 +239,17 @@ int sys_mutex_control(unsigned long mutex_address, int mutex_op)
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
/* Find and check physical address for virtual mutex address */
|
||||
if ((ret = cap_mutex_check(mutex_address, mutex_op)) < 0)
|
||||
return ret;
|
||||
|
||||
/*
|
||||
* Find and check physical address for virtual mutex address
|
||||
*
|
||||
* FIXME: Could we check this as a capability? Perhaps not
|
||||
* since not always the caller but its pager possesses
|
||||
* relevant memory capability. Maybe check on behalf of
|
||||
* its pager?
|
||||
*/
|
||||
if (!(mutex_physical =
|
||||
virt_to_phys_by_pgd(mutex_address,
|
||||
TASK_PGD(current))))
|
||||
|
||||
@@ -13,6 +13,7 @@
|
||||
#include <l4/lib/mutex.h>
|
||||
#include <l4/lib/wait.h>
|
||||
#include <l4/generic/resource.h>
|
||||
#include <l4/generic/capability.h>
|
||||
#include INC_ARCH(asm.h)
|
||||
#include INC_SUBARCH(mm.h)
|
||||
|
||||
@@ -41,7 +42,7 @@ int sys_thread_switch(void)
|
||||
* already gone, the state is already TASK_INACTIVE so the pager
|
||||
* won't sleep at all.
|
||||
*/
|
||||
int task_suspend(struct ktcb *task, unsigned int flags)
|
||||
int thread_suspend(struct ktcb *task, unsigned int flags)
|
||||
{
|
||||
int ret = 0;
|
||||
|
||||
@@ -94,15 +95,11 @@ int arch_clear_thread(struct ktcb *tcb)
|
||||
return 0;
|
||||
}
|
||||
|
||||
int thread_recycle(struct task_ids *ids)
|
||||
int thread_recycle(struct ktcb *task)
|
||||
{
|
||||
struct ktcb *task;
|
||||
int ret;
|
||||
|
||||
if (!(task = tcb_find(ids->tid)))
|
||||
return -ESRCH;
|
||||
|
||||
if ((ret = task_suspend(task, 0)) < 0)
|
||||
if ((ret = thread_suspend(task, 0)) < 0)
|
||||
return ret;
|
||||
|
||||
/*
|
||||
@@ -124,9 +121,9 @@ int thread_recycle(struct task_ids *ids)
|
||||
return 0;
|
||||
}
|
||||
|
||||
void task_destroy_current();
|
||||
void thread_destroy_current();
|
||||
|
||||
int task_destroy(struct ktcb *task)
|
||||
int thread_destroy(struct ktcb *task)
|
||||
{
|
||||
int ret;
|
||||
|
||||
@@ -134,13 +131,13 @@ int task_destroy(struct ktcb *task)
|
||||
* Pager destroying itself
|
||||
*/
|
||||
if (task == current) {
|
||||
task_destroy_current();
|
||||
thread_destroy_current();
|
||||
|
||||
/* It should not return */
|
||||
BUG();
|
||||
}
|
||||
|
||||
if ((ret = task_suspend(task, 0)) < 0)
|
||||
if ((ret = thread_suspend(task, 0)) < 0)
|
||||
return ret;
|
||||
|
||||
/* Remove tcb from global list so any callers will get -ESRCH */
|
||||
@@ -182,7 +179,7 @@ void task_make_zombie(struct ktcb *task)
|
||||
* address or voluntarily. All threads managed also get
|
||||
* destroyed.
|
||||
*/
|
||||
void task_destroy_current(void)
|
||||
void thread_destroy_current(void)
|
||||
{
|
||||
struct ktcb *task, *n;
|
||||
|
||||
@@ -195,7 +192,7 @@ void task_destroy_current(void)
|
||||
task->pagerid != current->tid)
|
||||
continue;
|
||||
spin_unlock(&curcont->ktcb_list.list_lock);
|
||||
task_suspend(task, TASK_EXITING);
|
||||
thread_suspend(task, TASK_EXITING);
|
||||
spin_lock(&curcont->ktcb_list.list_lock);
|
||||
}
|
||||
spin_unlock(&curcont->ktcb_list.list_lock);
|
||||
@@ -206,7 +203,7 @@ void task_destroy_current(void)
|
||||
sched_suspend_sync();
|
||||
}
|
||||
|
||||
int task_resume(struct ktcb *task)
|
||||
int thread_resume(struct ktcb *task)
|
||||
{
|
||||
if (!mutex_trylock(&task->thread_control_lock))
|
||||
return -EAGAIN;
|
||||
@@ -221,13 +218,8 @@ int task_resume(struct ktcb *task)
|
||||
}
|
||||
|
||||
/* Runs a thread for the first time */
|
||||
int thread_start(struct task_ids *ids)
|
||||
int thread_start(struct ktcb *task)
|
||||
{
|
||||
struct ktcb *task;
|
||||
|
||||
if (!(task = tcb_find(ids->tid)))
|
||||
return -ESRCH;
|
||||
|
||||
if (!mutex_trylock(&task->thread_control_lock))
|
||||
return -EAGAIN;
|
||||
|
||||
@@ -420,37 +412,6 @@ out_err:
|
||||
return err;
|
||||
}
|
||||
|
||||
|
||||
static inline int thread_resume(struct task_ids *ids)
|
||||
{
|
||||
struct ktcb *task;
|
||||
|
||||
if (!(task = tcb_find(ids->tid)))
|
||||
return -ESRCH;
|
||||
|
||||
return task_resume(task);
|
||||
}
|
||||
|
||||
static inline int thread_suspend(struct task_ids *ids)
|
||||
{
|
||||
struct ktcb *task;
|
||||
|
||||
if (!(task = tcb_find(ids->tid)))
|
||||
return -ESRCH;
|
||||
|
||||
return task_suspend(task, 0);
|
||||
}
|
||||
|
||||
static inline int thread_destroy(struct task_ids *ids)
|
||||
{
|
||||
struct ktcb *task;
|
||||
|
||||
if (!(task = tcb_find(ids->tid)))
|
||||
return -ESRCH;
|
||||
|
||||
return task_destroy(task);
|
||||
}
|
||||
|
||||
/*
|
||||
* Creates, destroys and modifies threads. Also implicitly creates an address
|
||||
* space for a thread that doesn't already have one, or destroys it if the last
|
||||
@@ -458,13 +419,18 @@ static inline int thread_destroy(struct task_ids *ids)
|
||||
*/
|
||||
int sys_thread_control(unsigned int flags, struct task_ids *ids)
|
||||
{
|
||||
struct ktcb *task = 0;
|
||||
int err, ret = 0;
|
||||
|
||||
if ((err = check_access((unsigned long)ids, sizeof(*ids),
|
||||
MAP_USR_RW_FLAGS, 1)) < 0)
|
||||
return err;
|
||||
|
||||
if ((err = cap_thread_check(flags, ids)) < 0)
|
||||
if ((flags & THREAD_ACTION_MASK) != THREAD_CREATE)
|
||||
if (!(task = tcb_find(ids->tid)))
|
||||
return -ESRCH;
|
||||
|
||||
if ((err = cap_thread_check(task, flags, ids)) < 0)
|
||||
return err;
|
||||
|
||||
switch (flags & THREAD_ACTION_MASK) {
|
||||
@@ -472,19 +438,19 @@ int sys_thread_control(unsigned int flags, struct task_ids *ids)
|
||||
ret = thread_create(ids, flags);
|
||||
break;
|
||||
case THREAD_RUN:
|
||||
ret = thread_start(ids);
|
||||
ret = thread_start(task);
|
||||
break;
|
||||
case THREAD_SUSPEND:
|
||||
ret = thread_suspend(ids);
|
||||
ret = thread_suspend(task, flags);
|
||||
break;
|
||||
case THREAD_RESUME:
|
||||
ret = thread_resume(ids);
|
||||
ret = thread_resume(task);
|
||||
break;
|
||||
case THREAD_DESTROY:
|
||||
ret = thread_destroy(ids);
|
||||
ret = thread_destroy(task);
|
||||
break;
|
||||
case THREAD_RECYCLE:
|
||||
ret = thread_recycle(ids);
|
||||
ret = thread_recycle(task);
|
||||
break;
|
||||
default:
|
||||
ret = -EINVAL;
|
||||
|
||||
Reference in New Issue
Block a user