Ignore:
File:
1 edited

Legend:

Unmodified
Added
Removed
  • kernel/generic/src/security/cap.c

    rb3f8fb7 r6b10dab  
    2727 */
    2828
    29 /** @addtogroup generic 
     29/** @addtogroup generic
    3030 * @{
    3131 */
    3232
    3333/**
    34  * @file        cap.c
    35  * @brief       Capabilities control.
     34 * @file cap.c
     35 * @brief Capabilities control.
    3636 *
    3737 * @see cap.h
    3838 */
    39  
     39
    4040#include <security/cap.h>
    4141#include <proc/task.h>
    4242#include <synch/spinlock.h>
    43 #include <syscall/sysarg64.h>
    4443#include <syscall/copy.h>
    4544#include <arch.h>
     
    4847/** Set capabilities.
    4948 *
    50  * @param t Task whose capabilities are to be changed.
     49 * @param task Task whose capabilities are to be changed.
    5150 * @param caps New set of capabilities.
    52  */
    53 void cap_set(task_t *t, cap_t caps)
    54 {
    55         ipl_t ipl;
    56        
    57         ipl = interrupts_disable();
    58         spinlock_lock(&t->lock);
    59        
    60         t->capabilities = caps;
    61        
    62         spinlock_unlock(&t->lock);
    63         interrupts_restore(ipl);
     51 *
     52 */
     53void cap_set(task_t *task, cap_t caps)
     54{
     55        irq_spinlock_lock(&task->lock, true);
     56        task->capabilities = caps;
     57        irq_spinlock_unlock(&task->lock, true);
    6458}
    6559
    6660/** Get capabilities.
    6761 *
    68  * @param t Task whose capabilities are to be returned.
     62 * @param task Task whose capabilities are to be returned.
     63 *
    6964 * @return Task's capabilities.
    70  */
    71 cap_t cap_get(task_t *t)
    72 {
    73         ipl_t ipl;
    74         cap_t caps;
    75        
    76         ipl = interrupts_disable();
    77         spinlock_lock(&t->lock);
    78        
    79         caps = t->capabilities;
    80        
    81         spinlock_unlock(&t->lock);
    82         interrupts_restore(ipl);
     65 *
     66 */
     67cap_t cap_get(task_t *task)
     68{
     69        irq_spinlock_lock(&task->lock, true);
     70        cap_t caps = task->capabilities;
     71        irq_spinlock_unlock(&task->lock, true);
    8372       
    8473        return caps;
     
    8978 * The calling task must have the CAP_CAP capability.
    9079 *
    91  * @param uspace_taskid_arg Userspace structure holding destination task ID.
    92  * @param caps Capabilities to grant.
    93  *
    94  * @return Zero on success or an error code from @ref errno.h.
    95  */
    96 unative_t sys_cap_grant(sysarg64_t *uspace_taskid_arg, cap_t caps)
    97 {
    98         sysarg64_t taskid_arg;
    99         task_t *t;
    100         ipl_t ipl;
    101         int rc;
    102        
     80 * @param taskid Destination task ID.
     81 * @param caps   Capabilities to grant.
     82 *
     83 * @return Zero on success or an error code from @ref errno.h.
     84 *
     85 */
     86static sysarg_t cap_grant(task_id_t taskid, cap_t caps)
     87{
    10388        if (!(cap_get(TASK) & CAP_CAP))
    104                 return (unative_t) EPERM;
    105        
    106         rc = copy_from_uspace(&taskid_arg, uspace_taskid_arg, sizeof(sysarg64_t));
    107         if (rc != 0)
    108                 return (unative_t) rc;
    109                
    110         ipl = interrupts_disable();
    111         spinlock_lock(&tasks_lock);
    112         t = task_find_by_id((task_id_t) taskid_arg.value);
    113         if ((!t) || (!context_check(CONTEXT, t->context))) {
    114                 spinlock_unlock(&tasks_lock);
    115                 interrupts_restore(ipl);
    116                 return (unative_t) ENOENT;
     89                return (sysarg_t) EPERM;
     90       
     91        irq_spinlock_lock(&tasks_lock, true);
     92        task_t *task = task_find_by_id(taskid);
     93       
     94        if ((!task) || (!context_check(CONTEXT, task->context))) {
     95                irq_spinlock_unlock(&tasks_lock, true);
     96                return (sysarg_t) ENOENT;
    11797        }
    11898       
    119         spinlock_lock(&t->lock);
    120         cap_set(t, cap_get(t) | caps);
    121         spinlock_unlock(&t->lock);
    122        
    123         spinlock_unlock(&tasks_lock);
    124         interrupts_restore(ipl);       
     99        irq_spinlock_lock(&task->lock, false);
     100        task->capabilities |= caps;
     101        irq_spinlock_unlock(&task->lock, false);
     102       
     103        irq_spinlock_unlock(&tasks_lock, true);
    125104        return 0;
    126105}
     
    131110 * attempt to revoke capabilities from itself.
    132111 *
    133  * @param uspace_taskid_arg Userspace structure holding destination task ID.
    134  * @param caps Capabilities to revoke.
    135  *
    136  * @return Zero on success or an error code from @ref errno.h.
    137  */
    138 unative_t sys_cap_revoke(sysarg64_t *uspace_taskid_arg, cap_t caps)
    139 {
    140         sysarg64_t taskid_arg;
    141         task_t *t;
    142         ipl_t ipl;
    143         int rc;
    144        
    145         rc = copy_from_uspace(&taskid_arg, uspace_taskid_arg, sizeof(sysarg64_t));
    146         if (rc != 0)
    147                 return (unative_t) rc;
    148 
    149         ipl = interrupts_disable();
    150         spinlock_lock(&tasks_lock);     
    151         t = task_find_by_id((task_id_t) taskid_arg.value);
    152         if ((!t) || (!context_check(CONTEXT, t->context))) {
    153                 spinlock_unlock(&tasks_lock);
    154                 interrupts_restore(ipl);
    155                 return (unative_t) ENOENT;
     112 * @param taskid Destination task ID.
     113 * @param caps   Capabilities to revoke.
     114 *
     115 * @return Zero on success or an error code from @ref errno.h.
     116 *
     117 */
     118static sysarg_t cap_revoke(task_id_t taskid, cap_t caps)
     119{
     120        irq_spinlock_lock(&tasks_lock, true);
     121       
     122        task_t *task = task_find_by_id(taskid);
     123        if ((!task) || (!context_check(CONTEXT, task->context))) {
     124                irq_spinlock_unlock(&tasks_lock, true);
     125                return (sysarg_t) ENOENT;
    156126        }
    157 
     127       
    158128        /*
    159129         * Revoking capabilities is different from granting them in that
     
    161131         * doesn't have CAP_CAP.
    162132         */
    163         if (!(cap_get(TASK) & CAP_CAP) || !(t == TASK)) {
    164                 spinlock_unlock(&tasks_lock);
    165                 interrupts_restore(ipl);
    166                 return (unative_t) EPERM;
     133        irq_spinlock_unlock(&TASK->lock, false);
     134       
     135        if ((!(TASK->capabilities & CAP_CAP)) || (task != TASK)) {
     136                irq_spinlock_unlock(&TASK->lock, false);
     137                irq_spinlock_unlock(&tasks_lock, true);
     138                return (sysarg_t) EPERM;
    167139        }
    168140       
    169         spinlock_lock(&t->lock);
    170         cap_set(t, cap_get(t) & ~caps);
    171         spinlock_unlock(&t->lock);
    172 
    173         spinlock_unlock(&tasks_lock);
    174 
    175         interrupts_restore(ipl);
     141        task->capabilities &= ~caps;
     142        irq_spinlock_unlock(&TASK->lock, false);
     143       
     144        irq_spinlock_unlock(&tasks_lock, true);
    176145        return 0;
    177146}
    178147
     148#ifdef __32_BITS__
     149
     150/** Grant capabilities to a task (32 bits)
     151 *
     152 * The calling task must have the CAP_CAP capability.
     153 *
     154 * @param uspace_taskid User-space pointer to destination task ID.
     155 * @param caps          Capabilities to grant.
     156 *
     157 * @return Zero on success or an error code from @ref errno.h.
     158 *
     159 */
     160sysarg_t sys_cap_grant(sysarg64_t *uspace_taskid, cap_t caps)
     161{
     162        sysarg64_t taskid;
     163        int rc = copy_from_uspace(&taskid, uspace_taskid, sizeof(sysarg64_t));
     164        if (rc != 0)
     165                return (sysarg_t) rc;
     166       
     167        return cap_grant((task_id_t) taskid, caps);
     168}
     169
     170/** Revoke capabilities from a task (32 bits)
     171 *
     172 * The calling task must have the CAP_CAP capability or the caller must
     173 * attempt to revoke capabilities from itself.
     174 *
     175 * @param uspace_taskid User-space pointer to destination task ID.
     176 * @param caps          Capabilities to revoke.
     177 *
     178 * @return Zero on success or an error code from @ref errno.h.
     179 *
     180 */
     181sysarg_t sys_cap_revoke(sysarg64_t *uspace_taskid, cap_t caps)
     182{
     183        sysarg64_t taskid;
     184        int rc = copy_from_uspace(&taskid, uspace_taskid, sizeof(sysarg64_t));
     185        if (rc != 0)
     186                return (sysarg_t) rc;
     187       
     188        return cap_revoke((task_id_t) taskid, caps);
     189}
     190
     191#endif  /* __32_BITS__ */
     192
     193#ifdef __64_BITS__
     194
     195/** Grant capabilities to a task (64 bits)
     196 *
     197 * The calling task must have the CAP_CAP capability.
     198 *
     199 * @param taskid Destination task ID.
     200 * @param caps   Capabilities to grant.
     201 *
     202 * @return Zero on success or an error code from @ref errno.h.
     203 *
     204 */
     205sysarg_t sys_cap_grant(sysarg_t taskid, cap_t caps)
     206{
     207        return cap_grant((task_id_t) taskid, caps);
     208}
     209
     210/** Revoke capabilities from a task (64 bits)
     211 *
     212 * The calling task must have the CAP_CAP capability or the caller must
     213 * attempt to revoke capabilities from itself.
     214 *
     215 * @param taskid Destination task ID.
     216 * @param caps   Capabilities to revoke.
     217 *
     218 * @return Zero on success or an error code from @ref errno.h.
     219 *
     220 */
     221sysarg_t sys_cap_revoke(sysarg_t taskid, cap_t caps)
     222{
     223        return cap_revoke((task_id_t) taskid, caps);
     224}
     225
     226#endif  /* __64_BITS__ */
     227
    179228/** @}
    180229 */
    181 
Note: See TracChangeset for help on using the changeset viewer.