Subversion Repositories HelenOS-historic

Compare Revisions

Ignore whitespace Rev 1296 → Rev 1297

/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;
}