/* * Copyright (c) 1997-8 Andrew G Morgan * * 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) ) { size_t 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; }