Home | History | Annotate | Download | only in libcap
      1 /*
      2  * Copyright (c) 1997-8 Andrew G Morgan <morgan (at) kernel.org>
      3  *
      4  * This file deals with allocation and deallocation of internal
      5  * capability sets as specified by POSIX.1e (formerlly, POSIX 6).
      6  */
      7 
      8 #include "libcap.h"
      9 
     10 /*
     11  * Obtain a blank set of capabilities
     12  */
     13 
     14 cap_t cap_init(void)
     15 {
     16     __u32 *raw_data;
     17     cap_t result;
     18 
     19     raw_data = malloc( sizeof(__u32) + sizeof(*result) );
     20 
     21     if (raw_data == NULL) {
     22 	_cap_debug("out of memory");
     23 	errno = ENOMEM;
     24 	return NULL;
     25     }
     26 
     27     *raw_data = CAP_T_MAGIC;
     28     result = (cap_t) (raw_data + 1);
     29     memset(result, 0, sizeof(*result));
     30 
     31     result->head.version = _LIBCAP_CAPABILITY_VERSION;
     32     capget(&result->head, NULL);      /* load the kernel-capability version */
     33 
     34     switch (result->head.version) {
     35 #ifdef _LINUX_CAPABILITY_VERSION_1
     36     case _LINUX_CAPABILITY_VERSION_1:
     37 	break;
     38 #endif
     39 #ifdef _LINUX_CAPABILITY_VERSION_2
     40     case _LINUX_CAPABILITY_VERSION_2:
     41 	break;
     42 #endif
     43 #ifdef _LINUX_CAPABILITY_VERSION_3
     44     case _LINUX_CAPABILITY_VERSION_3:
     45 	break;
     46 #endif
     47     default:                          /* No idea what to do */
     48 	cap_free(result);
     49 	result = NULL;
     50 	break;
     51     }
     52 
     53     return result;
     54 }
     55 
     56 /*
     57  * This is an internal library function to duplicate a string and
     58  * tag the result as something cap_free can handle.
     59  */
     60 
     61 char *_libcap_strdup(const char *old)
     62 {
     63     __u32 *raw_data;
     64 
     65     if (old == NULL) {
     66 	errno = EINVAL;
     67 	return NULL;
     68     }
     69 
     70     raw_data = malloc( sizeof(__u32) + strlen(old) + 1 );
     71     if (raw_data == NULL) {
     72 	errno = ENOMEM;
     73 	return NULL;
     74     }
     75 
     76     *(raw_data++) = CAP_S_MAGIC;
     77     strcpy((char *) raw_data, old);
     78 
     79     return ((char *) raw_data);
     80 }
     81 
     82 /*
     83  * This function duplicates an internal capability set with
     84  * malloc()'d memory. It is the responsibility of the user to call
     85  * cap_free() to liberate it.
     86  */
     87 
     88 cap_t cap_dup(cap_t cap_d)
     89 {
     90     cap_t result;
     91 
     92     if (!good_cap_t(cap_d)) {
     93 	_cap_debug("bad argument");
     94 	errno = EINVAL;
     95 	return NULL;
     96     }
     97 
     98     result = cap_init();
     99     if (result == NULL) {
    100 	_cap_debug("out of memory");
    101 	return NULL;
    102     }
    103 
    104     memcpy(result, cap_d, sizeof(*cap_d));
    105 
    106     return result;
    107 }
    108 
    109 
    110 /*
    111  * Scrub and then liberate an internal capability set.
    112  */
    113 
    114 int cap_free(void *data_p)
    115 {
    116     if ( !data_p )
    117 	return 0;
    118 
    119     if ( good_cap_t(data_p) ) {
    120 	data_p = -1 + (__u32 *) data_p;
    121 	memset(data_p, 0, sizeof(__u32) + sizeof(struct _cap_struct));
    122 	free(data_p);
    123 	data_p = NULL;
    124 	return 0;
    125     }
    126 
    127     if ( good_cap_string(data_p) ) {
    128 	size_t length = strlen(data_p) + sizeof(__u32);
    129      	data_p = -1 + (__u32 *) data_p;
    130      	memset(data_p, 0, length);
    131      	free(data_p);
    132      	data_p = NULL;
    133      	return 0;
    134     }
    135 
    136     _cap_debug("don't recognize what we're supposed to liberate");
    137     errno = EINVAL;
    138     return -1;
    139 }
    140