/kernel/trunk/generic/src/main/kinit.c |
---|
159,7 → 159,7 |
/* |
* Set capabilities to init userspace tasks. |
*/ |
cap_set(utask, CAP_CAP | CAP_MEM_MANAGER | CAP_IO_MANAGER); |
cap_set(utask, CAP_CAP | CAP_MEM_MANAGER | CAP_IO_MANAGER | CAP_PREEMPT_CONTROL); |
if (!ipc_phone_0) |
ipc_phone_0 = &utask->answerbox; |
/kernel/trunk/generic/src/ddi/ddi.c |
---|
211,3 → 211,22 |
return (__native) ddi_iospace_enable((task_id_t) arg.task_id, (__address) arg.ioaddr, (size_t) arg.size); |
} |
/** Disable or enable preemption. |
* |
* @param enable If non-zero, the preemption counter will be decremented, leading to potential |
* enabling of preemption. Otherwise the preemption counter will be incremented, |
* preventing preemption from occurring. |
* |
* @return Zero on success or EPERM if callers capabilities are not sufficient. |
*/ |
__native sys_preempt_control(int enable) |
{ |
if (! cap_get(TASK) & CAP_PREEMPT_CONTROL) |
return EPERM; |
if (enable) |
preemption_enable(); |
else |
preemption_disable(); |
return 0; |
} |
/kernel/trunk/generic/src/security/cap.c |
---|
36,8 → 36,11 |
#include <security/cap.h> |
#include <proc/task.h> |
#include <synch/spinlock.h> |
#include <syscall/sysarg64.h> |
#include <syscall/copy.h> |
#include <arch.h> |
#include <typedefs.h> |
#include <errno.h> |
/** Set capabilities. |
* |
77,3 → 80,89 |
return caps; |
} |
/** Grant capabilities to a task. |
* |
* The calling task must have the CAP_CAP capability. |
* |
* @param uspace_taskid_arg Userspace structure holding destination task ID. |
* @param caps Capabilities to grant. |
* |
* @return Zero on success or an error code from @ref errno.h. |
*/ |
__native sys_cap_grant(sysarg64_t *uspace_taskid_arg, cap_t caps) |
{ |
sysarg64_t taskid_arg; |
task_t *t; |
ipl_t ipl; |
int rc; |
if (!(cap_get(TASK) & CAP_CAP)) |
return (__native) EPERM; |
rc = copy_from_uspace(&taskid_arg, uspace_taskid_arg, sizeof(sysarg64_t)); |
if (rc != 0) |
return (__native) rc; |
ipl = interrupts_disable(); |
spinlock_lock(&tasks_lock); |
t = task_find_by_id((task_id_t) taskid_arg.value); |
if (!t) { |
spinlock_unlock(&tasks_lock); |
interrupts_restore(ipl); |
return (__native) ENOENT; |
} |
spinlock_unlock(&tasks_lock); |
cap_set(t, cap_get(t) | caps); |
interrupts_restore(ipl); |
return 0; |
} |
/** Revoke capabilities from a task. |
* |
* The calling task must have the CAP_CAP capability or the caller must |
* attempt to revoke capabilities from itself. |
* |
* @param uspace_taskid_arg Userspace structure holding destination task ID. |
* @param caps Capabilities to revoke. |
* |
* @return Zero on success or an error code from @ref errno.h. |
*/ |
__native sys_cap_revoke(sysarg64_t *uspace_taskid_arg, cap_t caps) |
{ |
sysarg64_t taskid_arg; |
task_t *t; |
ipl_t ipl; |
int rc; |
rc = copy_from_uspace(&taskid_arg, uspace_taskid_arg, sizeof(sysarg64_t)); |
if (rc != 0) |
return (__native) rc; |
ipl = interrupts_disable(); |
spinlock_lock(&tasks_lock); |
t = task_find_by_id((task_id_t) taskid_arg.value); |
if (!t) { |
spinlock_unlock(&tasks_lock); |
interrupts_restore(ipl); |
return (__native) ENOENT; |
} |
spinlock_unlock(&tasks_lock); |
/* |
* Revoking capabilities is different from granting them in that |
* a task can revoke capabilities from itself even if it |
* doesn't have CAP_CAP. |
*/ |
if (!(cap_get(TASK) & CAP_CAP) || !(t == TASK)) { |
interrupts_restore(ipl); |
return (__native) EPERM; |
} |
cap_set(t, cap_get(t) & ~caps); |
interrupts_restore(ipl); |
return 0; |
} |
/kernel/trunk/generic/src/mm/tlb.c |
---|
29,6 → 29,10 |
/** |
* @file tlb.c |
* @brief Generic TLB shootdown algorithm. |
* |
* The algorithm implemented here is based on the CMU TLB shootdown |
* algorithm and is further simplified (e.g. all CPUs receive all TLB |
* shootdown messages). |
*/ |
#include <mm/tlb.h> |
/kernel/trunk/generic/src/syscall/syscall.c |
---|
43,6 → 43,7 |
#include <ipc/sysipc.h> |
#include <synch/futex.h> |
#include <ddi/ddi.h> |
#include <security/cap.h> |
#include <syscall/copy.h> |
static __native sys_io(int fd, const void * buf, size_t count) { |
57,17 → 58,6 |
return count; |
} |
static __native sys_preempt_control(int enable) |
{ |
if (! cap_get(TASK) & CAP_PREEMPT_CONTROL) |
return EPERM; |
if (enable) |
preemption_enable(); |
else |
preemption_disable(); |
return 0; |
} |
/** Dispatch system call */ |
__native syscall_handler(__native a1, __native a2, __native a3, |
__native a4, __native id) |
81,7 → 71,6 |
syshandler_t syscall_table[SYSCALL_END] = { |
sys_io, |
sys_tls_set, |
sys_preempt_control, |
/* Thread and task related syscalls. */ |
sys_thread_create, |
111,7 → 100,12 |
sys_ipc_register_irq, |
sys_ipc_unregister_irq, |
/* Capabilities related syscalls. */ |
sys_cap_grant, |
sys_cap_revoke, |
/* DDI related syscalls. */ |
sys_physmem_map, |
sys_iospace_enable |
sys_iospace_enable, |
sys_preempt_control |
}; |
/kernel/trunk/generic/src/ipc/sysipc.c |
---|
39,6 → 39,7 |
#include <arch/interrupt.h> |
#include <print.h> |
#include <syscall/copy.h> |
#include <security/cap.h> |
#define GET_CHECK_PHONE(phone,phoneid,err) { \ |
if (phoneid > IPC_MAX_PHONES) { err; } \ |
490,8 → 491,11 |
/** Connect irq handler to task */ |
__native sys_ipc_register_irq(__native irq, irq_code_t *ucode) |
{ |
if (!(cap_get(TASK) & CAP_IRQ_REG)) |
return EPERM; |
if (irq >= IRQ_COUNT) |
return -ELIMIT; |
return (__native) ELIMIT; |
irq_ipc_bind_arch(irq); |
501,8 → 505,11 |
/* Disconnect irq handler from task */ |
__native sys_ipc_unregister_irq(__native irq) |
{ |
if (!(cap_get(TASK) & CAP_IRQ_REG)) |
return EPERM; |
if (irq >= IRQ_COUNT) |
return -ELIMIT; |
return (__native) ELIMIT; |
ipc_irq_unregister(&TASK->answerbox, irq); |