xref: /aosp_15_r20/external/libcap/libcap/cap_flag.c (revision 2810ac1b38eead2603277920c78344c84ddf3aff)
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