blob: 5fa5e9305c146529e297285befa03e7c5521e9ba [file] [log] [blame]
/*
* Copyright (c) 1997-8 Andrew G Morgan <morgan@kernel.org>
*
* This file deals with allocation and deallocation of internal
* capability sets as specified by POSIX.1e (formerlly, POSIX 6).
*/
#include "libcap.h"
/*
* Obtain a blank set of capabilities
*/
cap_t cap_init(void)
{
__u32 *raw_data;
cap_t result;
raw_data = malloc( sizeof(__u32) + sizeof(*result) );
if (raw_data == NULL) {
_cap_debug("out of memory");
errno = ENOMEM;
return NULL;
}
*raw_data = CAP_T_MAGIC;
result = (cap_t) (raw_data + 1);
memset(result, 0, sizeof(*result));
result->head.version = _LIBCAP_CAPABILITY_VERSION;
capget(&result->head, NULL); /* load the kernel-capability version */
switch (result->head.version) {
#ifdef _LINUX_CAPABILITY_VERSION_1
case _LINUX_CAPABILITY_VERSION_1:
break;
#endif
#ifdef _LINUX_CAPABILITY_VERSION_2
case _LINUX_CAPABILITY_VERSION_2:
break;
#endif
#ifdef _LINUX_CAPABILITY_VERSION_3
case _LINUX_CAPABILITY_VERSION_3:
break;
#endif
default: /* No idea what to do */
cap_free(result);
result = NULL;
break;
}
return result;
}
/*
* This is an internal library function to duplicate a string and
* tag the result as something cap_free can handle.
*/
char *_libcap_strdup(const char *old)
{
__u32 *raw_data;
if (old == NULL) {
errno = EINVAL;
return NULL;
}
raw_data = malloc( sizeof(__u32) + strlen(old) + 1 );
if (raw_data == NULL) {
errno = ENOMEM;
return NULL;
}
*(raw_data++) = CAP_S_MAGIC;
strcpy((char *) raw_data, old);
return ((char *) raw_data);
}
/*
* This function duplicates an internal capability set with
* malloc()'d memory. It is the responsibility of the user to call
* cap_free() to liberate it.
*/
cap_t cap_dup(cap_t cap_d)
{
cap_t result;
if (!good_cap_t(cap_d)) {
_cap_debug("bad argument");
errno = EINVAL;
return NULL;
}
result = cap_init();
if (result == NULL) {
_cap_debug("out of memory");
return NULL;
}
memcpy(result, cap_d, sizeof(*cap_d));
return result;
}
/*
* Scrub and then liberate an internal capability set.
*/
int cap_free(void *data_p)
{
if ( !data_p )
return 0;
if ( good_cap_t(data_p) ) {
data_p = -1 + (__u32 *) data_p;
memset(data_p, 0, sizeof(__u32) + sizeof(struct _cap_struct));
free(data_p);
data_p = NULL;
return 0;
}
if ( good_cap_string(data_p) ) {
int length = strlen(data_p) + sizeof(__u32);
data_p = -1 + (__u32 *) data_p;
memset(data_p, 0, length);
free(data_p);
data_p = NULL;
return 0;
}
_cap_debug("don't recognize what we're supposed to liberate");
errno = EINVAL;
return -1;
}