00001 /* 00002 * Copyright (C) 2006 Jakub Jermar 00003 * All rights reserved. 00004 * 00005 * Redistribution and use in source and binary forms, with or without 00006 * modification, are permitted provided that the following conditions 00007 * are met: 00008 * 00009 * - Redistributions of source code must retain the above copyright 00010 * notice, this list of conditions and the following disclaimer. 00011 * - Redistributions in binary form must reproduce the above copyright 00012 * notice, this list of conditions and the following disclaimer in the 00013 * documentation and/or other materials provided with the distribution. 00014 * - The name of the author may not be used to endorse or promote products 00015 * derived from this software without specific prior written permission. 00016 * 00017 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 00018 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 00019 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 00020 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 00021 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 00022 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 00023 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 00024 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 00025 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 00026 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 00027 */ 00028 00040 #include <security/cap.h> 00041 #include <proc/task.h> 00042 #include <synch/spinlock.h> 00043 #include <syscall/sysarg64.h> 00044 #include <syscall/copy.h> 00045 #include <arch.h> 00046 #include <typedefs.h> 00047 #include <errno.h> 00048 00054 void cap_set(task_t *t, cap_t caps) 00055 { 00056 ipl_t ipl; 00057 00058 ipl = interrupts_disable(); 00059 spinlock_lock(&t->lock); 00060 00061 t->capabilities = caps; 00062 00063 spinlock_unlock(&t->lock); 00064 interrupts_restore(ipl); 00065 } 00066 00072 cap_t cap_get(task_t *t) 00073 { 00074 ipl_t ipl; 00075 cap_t caps; 00076 00077 ipl = interrupts_disable(); 00078 spinlock_lock(&t->lock); 00079 00080 caps = t->capabilities; 00081 00082 spinlock_unlock(&t->lock); 00083 interrupts_restore(ipl); 00084 00085 return caps; 00086 } 00087 00097 __native sys_cap_grant(sysarg64_t *uspace_taskid_arg, cap_t caps) 00098 { 00099 sysarg64_t taskid_arg; 00100 task_t *t; 00101 ipl_t ipl; 00102 int rc; 00103 00104 if (!(cap_get(TASK) & CAP_CAP)) 00105 return (__native) EPERM; 00106 00107 rc = copy_from_uspace(&taskid_arg, uspace_taskid_arg, sizeof(sysarg64_t)); 00108 if (rc != 0) 00109 return (__native) rc; 00110 00111 ipl = interrupts_disable(); 00112 spinlock_lock(&tasks_lock); 00113 t = task_find_by_id((task_id_t) taskid_arg.value); 00114 if (!t) { 00115 spinlock_unlock(&tasks_lock); 00116 interrupts_restore(ipl); 00117 return (__native) ENOENT; 00118 } 00119 00120 spinlock_lock(&t->lock); 00121 cap_set(t, cap_get(t) | caps); 00122 spinlock_unlock(&t->lock); 00123 00124 spinlock_unlock(&tasks_lock); 00125 00126 00127 00128 interrupts_restore(ipl); 00129 return 0; 00130 } 00131 00142 __native sys_cap_revoke(sysarg64_t *uspace_taskid_arg, cap_t caps) 00143 { 00144 sysarg64_t taskid_arg; 00145 task_t *t; 00146 ipl_t ipl; 00147 int rc; 00148 00149 rc = copy_from_uspace(&taskid_arg, uspace_taskid_arg, sizeof(sysarg64_t)); 00150 if (rc != 0) 00151 return (__native) rc; 00152 00153 ipl = interrupts_disable(); 00154 spinlock_lock(&tasks_lock); 00155 t = task_find_by_id((task_id_t) taskid_arg.value); 00156 if (!t) { 00157 spinlock_unlock(&tasks_lock); 00158 interrupts_restore(ipl); 00159 return (__native) ENOENT; 00160 } 00161 00162 /* 00163 * Revoking capabilities is different from granting them in that 00164 * a task can revoke capabilities from itself even if it 00165 * doesn't have CAP_CAP. 00166 */ 00167 if (!(cap_get(TASK) & CAP_CAP) || !(t == TASK)) { 00168 spinlock_unlock(&tasks_lock); 00169 interrupts_restore(ipl); 00170 return (__native) EPERM; 00171 } 00172 00173 spinlock_lock(&t->lock); 00174 cap_set(t, cap_get(t) & ~caps); 00175 spinlock_unlock(&t->lock); 00176 00177 spinlock_unlock(&tasks_lock); 00178 00179 interrupts_restore(ipl); 00180 return 0; 00181 } 00182