1 /*
2 * Copyright (c) 1997-8,2008,20-21 Andrew G. Morgan <[email protected]>
3 *
4 * This file deals with flipping of capabilities on internal
5 * capability sets as specified by POSIX.1e (formerlly, POSIX 6).
6 *
7 * It also contains similar code for bit flipping cap_iab_t values.
8 */
9
10 #include "libcap.h"
11
12 /*
13 * Return the state of a specified capability flag. The state is
14 * returned as the contents of *raised. The capability is from one of
15 * the sets stored in cap_d as specified by set and value
16 */
cap_get_flag(cap_t cap_d,cap_value_t value,cap_flag_t set,cap_flag_value_t * raised)17 int cap_get_flag(cap_t cap_d, cap_value_t value, cap_flag_t set,
18 cap_flag_value_t *raised)
19 {
20 /*
21 * Do we have a set and a place to store its value?
22 * Is it a known capability?
23 */
24
25 if (raised && good_cap_t(cap_d) && value >= 0 && value < __CAP_MAXBITS
26 && set >= 0 && set < NUMBER_OF_CAP_SETS) {
27 _cap_mu_lock(&cap_d->mutex);
28 *raised = isset_cap(cap_d,value,set) ? CAP_SET:CAP_CLEAR;
29 _cap_mu_unlock(&cap_d->mutex);
30 return 0;
31 } else {
32 _cap_debug("invalid arguments");
33 errno = EINVAL;
34 return -1;
35 }
36 }
37
38 /*
39 * raise/lower a selection of capabilities
40 */
41
cap_set_flag(cap_t cap_d,cap_flag_t set,int no_values,const cap_value_t * array_values,cap_flag_value_t raise)42 int cap_set_flag(cap_t cap_d, cap_flag_t set,
43 int no_values, const cap_value_t *array_values,
44 cap_flag_value_t raise)
45 {
46 /*
47 * Do we have a set and a place to store its value?
48 * Is it a known capability?
49 */
50
51 if (good_cap_t(cap_d) && no_values > 0 && no_values < __CAP_MAXBITS
52 && (set >= 0) && (set < NUMBER_OF_CAP_SETS)
53 && (raise == CAP_SET || raise == CAP_CLEAR) ) {
54 int i;
55 _cap_mu_lock(&cap_d->mutex);
56 for (i=0; i<no_values; ++i) {
57 if (array_values[i] < 0 || array_values[i] >= __CAP_MAXBITS) {
58 _cap_debug("weird capability (%d) - skipped", array_values[i]);
59 } else {
60 int value = array_values[i];
61
62 if (raise == CAP_SET) {
63 cap_d->raise_cap(value,set);
64 } else {
65 cap_d->lower_cap(value,set);
66 }
67 }
68 }
69 _cap_mu_unlock(&cap_d->mutex);
70 return 0;
71 } else {
72 _cap_debug("invalid arguments");
73 errno = EINVAL;
74 return -1;
75 }
76 }
77
78 /*
79 * Reset the capability to be empty (nothing raised)
80 */
81
cap_clear(cap_t cap_d)82 int cap_clear(cap_t cap_d)
83 {
84 if (good_cap_t(cap_d)) {
85 _cap_mu_lock(&cap_d->mutex);
86 memset(&(cap_d->u), 0, sizeof(cap_d->u));
87 _cap_mu_unlock(&cap_d->mutex);
88 return 0;
89 } else {
90 _cap_debug("invalid pointer");
91 errno = EINVAL;
92 return -1;
93 }
94 }
95
96 /*
97 * Reset the all of the capability bits for one of the flag sets
98 */
99
cap_clear_flag(cap_t cap_d,cap_flag_t flag)100 int cap_clear_flag(cap_t cap_d, cap_flag_t flag)
101 {
102 switch (flag) {
103 case CAP_EFFECTIVE:
104 case CAP_PERMITTED:
105 case CAP_INHERITABLE:
106 if (good_cap_t(cap_d)) {
107 unsigned i;
108
109 _cap_mu_lock(&cap_d->mutex);
110 for (i=0; i<_LIBCAP_CAPABILITY_U32S; i++) {
111 cap_d->u[i].flat[flag] = 0;
112 }
113 _cap_mu_unlock(&cap_d->mutex);
114 return 0;
115 }
116 /*
117 * fall through
118 */
119
120 default:
121 _cap_debug("invalid pointer");
122 errno = EINVAL;
123 return -1;
124 }
125 }
126
127 /*
128 * Compare two capability sets
129 */
cap_compare(cap_t a,cap_t b)130 int cap_compare(cap_t a, cap_t b)
131 {
132 unsigned i;
133 int result;
134
135 if (!(good_cap_t(a) && good_cap_t(b))) {
136 _cap_debug("invalid arguments");
137 errno = EINVAL;
138 return -1;
139 }
140
141 /*
142 * To avoid a deadlock corner case, we operate on an unlocked
143 * private copy of b
144 */
145 b = cap_dup(b);
146 if (b == NULL) {
147 return -1;
148 }
149 _cap_mu_lock(&a->mutex);
150 for (i=0, result=0; i<_LIBCAP_CAPABILITY_U32S; i++) {
151 result |=
152 ((a->u[i].flat[CAP_EFFECTIVE] != b->u[i].flat[CAP_EFFECTIVE])
153 ? LIBCAP_EFF : 0)
154 | ((a->u[i].flat[CAP_INHERITABLE] != b->u[i].flat[CAP_INHERITABLE])
155 ? LIBCAP_INH : 0)
156 | ((a->u[i].flat[CAP_PERMITTED] != b->u[i].flat[CAP_PERMITTED])
157 ? LIBCAP_PER : 0);
158 }
159 _cap_mu_unlock(&a->mutex);
160 cap_free(b);
161 return result;
162 }
163
164 /*
165 * cap_fill_flag copies a bit-vector of capability state in one cap_t from one
166 * flag to another flag of another cap_t.
167 */
cap_fill_flag(cap_t cap_d,cap_flag_t to,cap_t ref,cap_flag_t from)168 int cap_fill_flag(cap_t cap_d, cap_flag_t to, cap_t ref, cap_flag_t from)
169 {
170 int i;
171 cap_t orig;
172
173 if (!good_cap_t(cap_d) || !good_cap_t(ref)) {
174 errno = EINVAL;
175 return -1;
176 }
177
178 if (to < CAP_EFFECTIVE || to > CAP_INHERITABLE ||
179 from < CAP_EFFECTIVE || from > CAP_INHERITABLE) {
180 errno = EINVAL;
181 return -1;
182 }
183
184 orig = cap_dup(ref);
185 if (orig == NULL) {
186 return -1;
187 }
188
189 _cap_mu_lock(&cap_d->mutex);
190 for (i = 0; i < _LIBCAP_CAPABILITY_U32S; i++) {
191 cap_d->u[i].flat[to] = orig->u[i].flat[from];
192 }
193 _cap_mu_unlock(&cap_d->mutex);
194
195 cap_free(orig);
196 return 0;
197 }
198
199 /*
200 * cap_fill copies a bit-vector of capability state in a cap_t from
201 * one flag to another.
202 */
cap_fill(cap_t cap_d,cap_flag_t to,cap_flag_t from)203 int cap_fill(cap_t cap_d, cap_flag_t to, cap_flag_t from)
204 {
205 return cap_fill_flag(cap_d, to, cap_d, from);
206 }
207
208 /*
209 * cap_iab_get_vector reads the single bit value from an IAB vector set.
210 */
cap_iab_get_vector(cap_iab_t iab,cap_iab_vector_t vec,cap_value_t bit)211 cap_flag_value_t cap_iab_get_vector(cap_iab_t iab, cap_iab_vector_t vec,
212 cap_value_t bit)
213 {
214 if (!good_cap_iab_t(iab) || bit >= cap_max_bits()) {
215 return 0;
216 }
217
218 unsigned o = (bit >> 5);
219 __u32 mask = 1u << (bit & 31);
220 cap_flag_value_t ret;
221
222 _cap_mu_lock(&iab->mutex);
223 switch (vec) {
224 case CAP_IAB_INH:
225 ret = !!(iab->i[o] & mask);
226 break;
227 case CAP_IAB_AMB:
228 ret = !!(iab->a[o] & mask);
229 break;
230 case CAP_IAB_BOUND:
231 ret = !!(iab->nb[o] & mask);
232 break;
233 default:
234 ret = 0;
235 }
236 _cap_mu_unlock(&iab->mutex);
237
238 return ret;
239 }
240
241 /*
242 * cap_iab_set_vector sets the bits in an IAB to the value
243 * raised. Note, setting A implies setting I too, lowering I implies
244 * lowering A too. The B bits are, however, independently settable.
245 */
cap_iab_set_vector(cap_iab_t iab,cap_iab_vector_t vec,cap_value_t bit,cap_flag_value_t raised)246 int cap_iab_set_vector(cap_iab_t iab, cap_iab_vector_t vec, cap_value_t bit,
247 cap_flag_value_t raised)
248 {
249 if (!good_cap_iab_t(iab) || (raised >> 1) || bit >= cap_max_bits()) {
250 errno = EINVAL;
251 return -1;
252 }
253
254 unsigned o = (bit >> 5);
255 __u32 on = 1u << (bit & 31);
256 __u32 mask = ~on;
257
258 _cap_mu_lock(&iab->mutex);
259 switch (vec) {
260 case CAP_IAB_INH:
261 iab->i[o] = (iab->i[o] & mask) | (raised ? on : 0);
262 iab->a[o] &= iab->i[o];
263 break;
264 case CAP_IAB_AMB:
265 iab->a[o] = (iab->a[o] & mask) | (raised ? on : 0);
266 iab->i[o] |= iab->a[o];
267 break;
268 case CAP_IAB_BOUND:
269 iab->nb[o] = (iab->nb[o] & mask) | (raised ? on : 0);
270 break;
271 default:
272 errno = EINVAL;
273 _cap_mu_unlock_return(&iab->mutex, -1);
274 }
275
276 _cap_mu_unlock(&iab->mutex);
277 return 0;
278 }
279
280 /*
281 * cap_iab_fill copies a bit-vector of capability state from a cap_t
282 * to a cap_iab_t. Note, because the bounding bits in an iab are to be
283 * dropped when applied, the copying process, when to a CAP_IAB_BOUND
284 * vector involves inverting the bits. Also, adjusting I will mask
285 * bits in A, and adjusting A may implicitly raise bits in I.
286 */
cap_iab_fill(cap_iab_t iab,cap_iab_vector_t vec,cap_t cap_d,cap_flag_t flag)287 int cap_iab_fill(cap_iab_t iab, cap_iab_vector_t vec,
288 cap_t cap_d, cap_flag_t flag)
289 {
290 int i, ret = 0;
291
292 if (!good_cap_t(cap_d) || !good_cap_iab_t(iab)) {
293 errno = EINVAL;
294 return -1;
295 }
296
297 switch (flag) {
298 case CAP_EFFECTIVE:
299 case CAP_INHERITABLE:
300 case CAP_PERMITTED:
301 break;
302 default:
303 errno = EINVAL;
304 return -1;
305 }
306
307 /*
308 * Make a private copy so we don't need to hold two locks at once
309 * avoiding a recipe for a deadlock.
310 */
311 cap_d = cap_dup(cap_d);
312 if (cap_d == NULL) {
313 return -1;
314 }
315
316 _cap_mu_lock(&iab->mutex);
317 for (i = 0; !ret && i < _LIBCAP_CAPABILITY_U32S; i++) {
318 switch (vec) {
319 case CAP_IAB_INH:
320 iab->i[i] = cap_d->u[i].flat[flag];
321 iab->a[i] &= iab->i[i];
322 break;
323 case CAP_IAB_AMB:
324 iab->a[i] = cap_d->u[i].flat[flag];
325 iab->i[i] |= cap_d->u[i].flat[flag];
326 break;
327 case CAP_IAB_BOUND:
328 iab->nb[i] = ~cap_d->u[i].flat[flag];
329 break;
330 default:
331 errno = EINVAL;
332 ret = -1;
333 break;
334 }
335 }
336 _cap_mu_unlock(&iab->mutex);
337
338 cap_free(cap_d);
339 return ret;
340 }
341
342 /*
343 * cap_iab_compare compares two iab tuples.
344 */
cap_iab_compare(cap_iab_t a,cap_iab_t b)345 int cap_iab_compare(cap_iab_t a, cap_iab_t b)
346 {
347 int j, result;
348 if (!(good_cap_iab_t(a) && good_cap_iab_t(b))) {
349 _cap_debug("invalid arguments");
350 errno = EINVAL;
351 return -1;
352 }
353 b = cap_iab_dup(b);
354 if (b == NULL) {
355 return -1;
356 }
357
358 _cap_mu_lock(&a->mutex);
359 for (j=0, result=0; j<_LIBCAP_CAPABILITY_U32S; j++) {
360 result |=
361 (a->i[j] == b->i[j] ? 0 : (1 << CAP_IAB_INH)) |
362 (a->a[j] == b->a[j] ? 0 : (1 << CAP_IAB_AMB)) |
363 (a->nb[j] == b->nb[j] ? 0 : (1 << CAP_IAB_BOUND));
364 }
365 _cap_mu_unlock(&a->mutex);
366 cap_free(b);
367
368 return result;
369 }
370