Ignore:
File:
1 edited

Legend:

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

    r6b10dab rb3f8fb7  
    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>
    4344#include <syscall/copy.h>
    4445#include <arch.h>
     
    4748/** Set capabilities.
    4849 *
    49  * @param task Task whose capabilities are to be changed.
     50 * @param t Task whose capabilities are to be changed.
    5051 * @param caps New set of capabilities.
    51  *
    5252 */
    53 void cap_set(task_t *task, cap_t caps)
     53void cap_set(task_t *t, cap_t caps)
    5454{
    55         irq_spinlock_lock(&task->lock, true);
    56         task->capabilities = caps;
    57         irq_spinlock_unlock(&task->lock, true);
     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);
    5864}
    5965
    6066/** Get capabilities.
    6167 *
    62  * @param task Task whose capabilities are to be returned.
    63  *
     68 * @param t Task whose capabilities are to be returned.
    6469 * @return Task's capabilities.
    65  *
    6670 */
    67 cap_t cap_get(task_t *task)
     71cap_t cap_get(task_t *t)
    6872{
    69         irq_spinlock_lock(&task->lock, true);
    70         cap_t caps = task->capabilities;
    71         irq_spinlock_unlock(&task->lock, true);
     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);
    7283       
    7384        return caps;
     
    7889 * The calling task must have the CAP_CAP capability.
    7990 *
    80  * @param taskid Destination task ID.
    81  * @param caps   Capabilities to grant.
     91 * @param uspace_taskid_arg Userspace structure holding destination task ID.
     92 * @param caps Capabilities to grant.
    8293 *
    8394 * @return Zero on success or an error code from @ref errno.h.
    84  *
    8595 */
    86 static sysarg_t cap_grant(task_id_t taskid, cap_t caps)
     96unative_t sys_cap_grant(sysarg64_t *uspace_taskid_arg, cap_t caps)
    8797{
     98        sysarg64_t taskid_arg;
     99        task_t *t;
     100        ipl_t ipl;
     101        int rc;
     102       
    88103        if (!(cap_get(TASK) & CAP_CAP))
    89                 return (sysarg_t) EPERM;
     104                return (unative_t) EPERM;
    90105       
    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;
     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;
    97117        }
    98118       
    99         irq_spinlock_lock(&task->lock, false);
    100         task->capabilities |= caps;
    101         irq_spinlock_unlock(&task->lock, false);
     119        spinlock_lock(&t->lock);
     120        cap_set(t, cap_get(t) | caps);
     121        spinlock_unlock(&t->lock);
    102122       
    103         irq_spinlock_unlock(&tasks_lock, true);
     123        spinlock_unlock(&tasks_lock);
     124        interrupts_restore(ipl);       
    104125        return 0;
    105126}
     
    110131 * attempt to revoke capabilities from itself.
    111132 *
    112  * @param taskid Destination task ID.
    113  * @param caps   Capabilities to revoke.
     133 * @param uspace_taskid_arg Userspace structure holding destination task ID.
     134 * @param caps Capabilities to revoke.
    114135 *
    115136 * @return Zero on success or an error code from @ref errno.h.
    116  *
    117137 */
    118 static sysarg_t cap_revoke(task_id_t taskid, cap_t caps)
     138unative_t sys_cap_revoke(sysarg64_t *uspace_taskid_arg, cap_t caps)
    119139{
    120         irq_spinlock_lock(&tasks_lock, true);
     140        sysarg64_t taskid_arg;
     141        task_t *t;
     142        ipl_t ipl;
     143        int rc;
    121144       
    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;
     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;
    126156        }
    127        
     157
    128158        /*
    129159         * Revoking capabilities is different from granting them in that
     
    131161         * doesn't have CAP_CAP.
    132162         */
    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;
     163        if (!(cap_get(TASK) & CAP_CAP) || !(t == TASK)) {
     164                spinlock_unlock(&tasks_lock);
     165                interrupts_restore(ipl);
     166                return (unative_t) EPERM;
    139167        }
    140168       
    141         task->capabilities &= ~caps;
    142         irq_spinlock_unlock(&TASK->lock, false);
    143        
    144         irq_spinlock_unlock(&tasks_lock, true);
     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);
    145176        return 0;
    146177}
    147178
    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  */
    160 sysarg_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  */
    181 sysarg_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  */
    205 sysarg_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  */
    221 sysarg_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 
    228179/** @}
    229180 */
     181
Note: See TracChangeset for help on using the changeset viewer.