/kernel/trunk/generic/include/ddi/ddi.h |
---|
35,6 → 35,7 |
extern __native sys_physmem_map(ddi_memarg_t *uspace_mem_arg); |
extern __native sys_iospace_enable(ddi_ioarg_t *uspace_io_arg); |
extern __native sys_preempt_control(int enable); |
/* |
* Interface to be implemented by all architectures. |
/kernel/trunk/generic/include/security/cap.h |
---|
41,6 → 41,7 |
#ifndef __CAP_H__ |
#define __CAP_H__ |
#include <syscall/sysarg64.h> |
#include <arch/types.h> |
#include <typedefs.h> |
63,13 → 64,21 |
#define CAP_IO_MANAGER (1<<2) |
/** |
* CAP_PREEMPT_CONTROL allows its holder to disable interrupts |
* CAP_PREEMPT_CONTROL allows its holder to disable/enable preemption. |
*/ |
#define CAP_PREEMPT_CONTROL (1<<3) |
/** |
* CAP_IRQ_REG entitles its holder to register IRQ handlers. |
*/ |
#define CAP_IRQ_REG (1<<4) |
typedef __u32 cap_t; |
extern void cap_set(task_t *t, cap_t caps); |
extern cap_t cap_get(task_t *t); |
extern __native sys_cap_grant(sysarg64_t *uspace_taskid_arg, cap_t caps); |
extern __native sys_cap_revoke(sysarg64_t *uspace_taskid_arg, cap_t caps); |
#endif |
/kernel/trunk/generic/include/syscall/syscall.h |
---|
32,7 → 32,6 |
typedef enum { |
SYS_IO = 0, |
SYS_TLS_SET = 1, /* Hardcoded in AMD64,IA32 uspace - psthread.S */ |
SYS_PREEMPT_CONTROL, |
SYS_THREAD_CREATE, |
SYS_THREAD_EXIT, |
SYS_TASK_GET_ID, |
53,8 → 52,11 |
SYS_IPC_HANGUP, |
SYS_IPC_REGISTER_IRQ, |
SYS_IPC_UNREGISTER_IRQ, |
SYS_CAP_GRANT, |
SYS_CAP_REVOKE, |
SYS_MAP_PHYSMEM, |
SYS_IOSPACE_ENABLE, |
SYS_PREEMPT_CONTROL, |
SYSCALL_END |
} syscall_t; |
/kernel/trunk/generic/include/syscall/sysarg64.h |
---|
0,0 → 1,41 |
/* |
* Copyright (C) 2006 Jakub Jermar |
* All rights reserved. |
* |
* Redistribution and use in source and binary forms, with or without |
* modification, are permitted provided that the following conditions |
* are met: |
* |
* - Redistributions of source code must retain the above copyright |
* notice, this list of conditions and the following disclaimer. |
* - Redistributions in binary form must reproduce the above copyright |
* notice, this list of conditions and the following disclaimer in the |
* documentation and/or other materials provided with the distribution. |
* - The name of the author may not be used to endorse or promote products |
* derived from this software without specific prior written permission. |
* |
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR |
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES |
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. |
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, |
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT |
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF |
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
*/ |
/** |
* @file sysarg64.h |
* @brief Wrapper for explicit 64-bit arguments passed to syscalls. |
*/ |
#ifndef __SYSARG64_H__ |
#define __SYSARG64_H__ |
typedef struct { |
unsigned long long value; |
} sysarg64_t; |
#endif |
/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); |