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

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