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:
Bahadir Balban
2009-10-25 23:57:17 +02:00
parent 83ce4280b0
commit 88e3706474
18 changed files with 511 additions and 320 deletions

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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