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