1 /*
2 * Copyright (c) 1997-8 Andrew G Morgan <morgan@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
cap_init(void)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
_libcap_strdup(const char * old)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
cap_dup(cap_t cap_d)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
cap_free(void * data_p)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