blob: f70b0e369df998130409e5911fe961271555f881 [file] [log] [blame]
/*
* Copyright (c) 1997-8,2007,2011 Andrew G Morgan <morgan@kernel.org>
*
* This file deals with getting and setting capabilities on processes.
*/
#include <sys/prctl.h>
#include "libcap.h"
cap_t cap_get_proc(void)
{
cap_t result;
/* allocate a new capability set */
result = cap_init();
if (result) {
_cap_debug("getting current process' capabilities");
/* fill the capability sets via a system call */
if (capget(&result->head, &result->u[0].set)) {
cap_free(result);
result = NULL;
}
}
return result;
}
int cap_set_proc(cap_t cap_d)
{
int retval;
if (!good_cap_t(cap_d)) {
errno = EINVAL;
return -1;
}
_cap_debug("setting process capabilities");
retval = capset(&cap_d->head, &cap_d->u[0].set);
return retval;
}
/* the following two functions are not required by POSIX */
/* read the caps on a specific process */
int capgetp(pid_t pid, cap_t cap_d)
{
int error;
if (!good_cap_t(cap_d)) {
errno = EINVAL;
return -1;
}
_cap_debug("getting process capabilities for proc %d", pid);
cap_d->head.pid = pid;
error = capget(&cap_d->head, &cap_d->u[0].set);
cap_d->head.pid = 0;
return error;
}
/* allocate space for and return capabilities of target process */
cap_t cap_get_pid(pid_t pid)
{
cap_t result;
result = cap_init();
if (result) {
if (capgetp(pid, result) != 0) {
int my_errno;
my_errno = errno;
cap_free(result);
errno = my_errno;
result = NULL;
}
}
return result;
}
/* set the caps on a specific process/pg etc.. */
int capsetp(pid_t pid, cap_t cap_d)
{
int error;
if (!good_cap_t(cap_d)) {
errno = EINVAL;
return -1;
}
_cap_debug("setting process capabilities for proc %d", pid);
cap_d->head.pid = pid;
error = capset(&cap_d->head, &cap_d->u[0].set);
cap_d->head.version = _LIBCAP_CAPABILITY_VERSION;
cap_d->head.pid = 0;
return error;
}
/* the kernel api requires unsigned long arguments */
#define pr_arg(x) ((unsigned long) x)
/* get a capability from the bounding set */
int cap_get_bound(cap_value_t cap)
{
int result;
result = prctl(PR_CAPBSET_READ, pr_arg(cap));
if (result < 0) {
errno = -result;
return -1;
}
return result;
}
/* drop a capability from the bounding set */
int cap_drop_bound(cap_value_t cap)
{
int result;
result = prctl(PR_CAPBSET_DROP, pr_arg(cap));
if (result < 0) {
errno = -result;
return -1;
}
return result;
}
/* get a capability from the ambient set */
int cap_get_ambient(cap_value_t cap)
{
int result;
result = prctl(PR_CAP_AMBIENT, pr_arg(PR_CAP_AMBIENT_IS_SET),
pr_arg(cap), pr_arg(0), pr_arg(0));
if (result < 0) {
errno = -result;
return -1;
}
return result;
}
/* modify a single ambient capability value */
int cap_set_ambient(cap_value_t cap, cap_flag_value_t set)
{
int result, val;
switch (set) {
case CAP_SET:
val = PR_CAP_AMBIENT_RAISE;
break;
case CAP_CLEAR:
val = PR_CAP_AMBIENT_LOWER;
break;
default:
errno = EINVAL;
return -1;
}
result = prctl(PR_CAP_AMBIENT, pr_arg(val), pr_arg(cap),
pr_arg(0), pr_arg(0));
if (result < 0) {
errno = -result;
return -1;
}
return result;
}
/* erase all ambient capabilities */
int cap_reset_ambient()
{
int result;
result = prctl(PR_CAP_AMBIENT, pr_arg(PR_CAP_AMBIENT_CLEAR_ALL),
pr_arg(0), pr_arg(0), pr_arg(0));
if (result < 0) {
errno = -result;
return -1;
}
return result;
}