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