1 /*
2 * Copyright (c) 1997-8,2008,20 Andrew G. Morgan <morgan@kernel.org>
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 */
17
cap_get_flag(cap_t cap_d,cap_value_t value,cap_flag_t set,cap_flag_value_t * raised)18 int cap_get_flag(cap_t cap_d, cap_value_t value, cap_flag_t set,
19 cap_flag_value_t *raised)
20 {
21 /*
22 * Do we have a set and a place to store its value?
23 * Is it a known capability?
24 */
25
26 if (raised && good_cap_t(cap_d) && value >= 0 && value < __CAP_MAXBITS
27 && set >= 0 && set < NUMBER_OF_CAP_SETS) {
28 *raised = isset_cap(cap_d,value,set) ? CAP_SET:CAP_CLEAR;
29 return 0;
30 } else {
31 _cap_debug("invalid arguments");
32 errno = EINVAL;
33 return -1;
34 }
35 }
36
37 /*
38 * raise/lower a selection of capabilities
39 */
40
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)41 int cap_set_flag(cap_t cap_d, cap_flag_t set,
42 int no_values, const cap_value_t *array_values,
43 cap_flag_value_t raise)
44 {
45 /*
46 * Do we have a set and a place to store its value?
47 * Is it a known capability?
48 */
49
50 if (good_cap_t(cap_d) && no_values > 0 && no_values < __CAP_MAXBITS
51 && (set >= 0) && (set < NUMBER_OF_CAP_SETS)
52 && (raise == CAP_SET || raise == CAP_CLEAR) ) {
53 int i;
54 for (i=0; i<no_values; ++i) {
55 if (array_values[i] < 0 || array_values[i] >= __CAP_MAXBITS) {
56 _cap_debug("weird capability (%d) - skipped", array_values[i]);
57 } else {
58 int value = array_values[i];
59
60 if (raise == CAP_SET) {
61 cap_d->raise_cap(value,set);
62 } else {
63 cap_d->lower_cap(value,set);
64 }
65 }
66 }
67 return 0;
68
69 } else {
70
71 _cap_debug("invalid arguments");
72 errno = EINVAL;
73 return -1;
74
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 memset(&(cap_d->u), 0, sizeof(cap_d->u));
86 return 0;
87 } else {
88 _cap_debug("invalid pointer");
89 errno = EINVAL;
90 return -1;
91 }
92 }
93
94 /*
95 * Reset the all of the capability bits for one of the flag sets
96 */
97
cap_clear_flag(cap_t cap_d,cap_flag_t flag)98 int cap_clear_flag(cap_t cap_d, cap_flag_t flag)
99 {
100 switch (flag) {
101 case CAP_EFFECTIVE:
102 case CAP_PERMITTED:
103 case CAP_INHERITABLE:
104 if (good_cap_t(cap_d)) {
105 unsigned i;
106
107 for (i=0; i<_LIBCAP_CAPABILITY_U32S; i++) {
108 cap_d->u[i].flat[flag] = 0;
109 }
110 return 0;
111 }
112 /*
113 * fall through
114 */
115
116 default:
117 _cap_debug("invalid pointer");
118 errno = EINVAL;
119 return -1;
120 }
121 }
122
123 /*
124 * Compare two capability sets
125 */
cap_compare(cap_t a,cap_t b)126 int cap_compare(cap_t a, cap_t b)
127 {
128 unsigned i;
129 int result;
130
131 if (!(good_cap_t(a) && good_cap_t(b))) {
132 _cap_debug("invalid arguments");
133 errno = EINVAL;
134 return -1;
135 }
136
137 for (i=0, result=0; i<_LIBCAP_CAPABILITY_U32S; i++) {
138 result |=
139 ((a->u[i].flat[CAP_EFFECTIVE] != b->u[i].flat[CAP_EFFECTIVE])
140 ? LIBCAP_EFF : 0)
141 | ((a->u[i].flat[CAP_INHERITABLE] != b->u[i].flat[CAP_INHERITABLE])
142 ? LIBCAP_INH : 0)
143 | ((a->u[i].flat[CAP_PERMITTED] != b->u[i].flat[CAP_PERMITTED])
144 ? LIBCAP_PER : 0);
145 }
146 return result;
147 }
148
149 /*
150 * cap_fill copies a bit-vector of capability state in a cap_t from
151 * one flag to another.
152 */
cap_fill(cap_t cap_d,cap_flag_t to,cap_flag_t from)153 int cap_fill(cap_t cap_d, cap_flag_t to, cap_flag_t from)
154 {
155 if (!good_cap_t(cap_d)) {
156 errno = EINVAL;
157 return -1;
158 }
159
160 if (to < CAP_EFFECTIVE || to > CAP_INHERITABLE ||
161 from < CAP_EFFECTIVE || from > CAP_INHERITABLE) {
162 errno = EINVAL;
163 return -1;
164 }
165
166 int i;
167 for (i = 0; i < _LIBCAP_CAPABILITY_U32S; i++) {
168 cap_d->u[i].flat[to] = cap_d->u[i].flat[from];
169 }
170
171 return 0;
172 }
173
174 /*
175 * cap_iab_get_vector reads the single bit value from an IAB vector set.
176 */
cap_iab_get_vector(cap_iab_t iab,cap_iab_vector_t vec,cap_value_t bit)177 cap_flag_value_t cap_iab_get_vector(cap_iab_t iab, cap_iab_vector_t vec,
178 cap_value_t bit)
179 {
180 if (!good_cap_iab_t(iab) || bit >= cap_max_bits()) {
181 return 0;
182 }
183
184 unsigned o = (bit >> 5);
185 __u32 mask = 1u << (bit & 31);
186
187 switch (vec) {
188 case CAP_IAB_INH:
189 return !!(iab->i[o] & mask);
190 break;
191 case CAP_IAB_AMB:
192 return !!(iab->a[o] & mask);
193 break;
194 case CAP_IAB_BOUND:
195 return !!(iab->nb[o] & mask);
196 break;
197 default:
198 return 0;
199 }
200 }
201
202 /*
203 * cap_iab_set_vector sets the bits in an IAB to the value
204 * raised. Note, setting A implies setting I too, lowering I implies
205 * lowering A too. The B bits are, however, independently settable.
206 */
cap_iab_set_vector(cap_iab_t iab,cap_iab_vector_t vec,cap_value_t bit,cap_flag_value_t raised)207 int cap_iab_set_vector(cap_iab_t iab, cap_iab_vector_t vec, cap_value_t bit,
208 cap_flag_value_t raised)
209 {
210 if (!good_cap_iab_t(iab) || (raised >> 1) || bit >= cap_max_bits()) {
211 errno = EINVAL;
212 return -1;
213 }
214
215 unsigned o = (bit >> 5);
216 __u32 on = 1u << (bit & 31);
217 __u32 mask = ~on;
218
219 switch (vec) {
220 case CAP_IAB_INH:
221 iab->i[o] = (iab->i[o] & mask) | (raised ? on : 0);
222 iab->a[o] &= iab->i[o];
223 break;
224 case CAP_IAB_AMB:
225 iab->a[o] = (iab->a[o] & mask) | (raised ? on : 0);
226 iab->i[o] |= iab->a[o];
227 break;
228 case CAP_IAB_BOUND:
229 iab->nb[o] = (iab->nb[o] & mask) | (raised ? on : 0);
230 break;
231 default:
232 errno = EINVAL;
233 return -1;
234 }
235
236 return 0;
237 }
238
239 /*
240 * cap_iab_fill copies a bit-vector of capability state from a cap_t
241 * to a cap_iab_t. Note, because the bounding bits in an iab are to be
242 * dropped when applied, the copying process, when to a CAP_IAB_BOUND
243 * vector involves inverting the bits. Also, adjusting I will mask
244 * bits in A, and adjusting A may implicitly raise bits in I.
245 */
cap_iab_fill(cap_iab_t iab,cap_iab_vector_t vec,cap_t cap_d,cap_flag_t flag)246 int cap_iab_fill(cap_iab_t iab, cap_iab_vector_t vec,
247 cap_t cap_d, cap_flag_t flag)
248 {
249 if (!good_cap_t(cap_d) || !good_cap_iab_t(iab)) {
250 errno = EINVAL;
251 return -1;
252 }
253
254 switch (flag) {
255 case CAP_EFFECTIVE:
256 case CAP_INHERITABLE:
257 case CAP_PERMITTED:
258 break;
259 default:
260 errno = EINVAL;
261 return -1;
262 }
263
264 int i;
265 for (i = 0; i < _LIBCAP_CAPABILITY_U32S; i++) {
266 switch (vec) {
267 case CAP_IAB_INH:
268 iab->i[i] = cap_d->u[i].flat[flag];
269 iab->a[i] &= iab->i[i];
270 break;
271 case CAP_IAB_AMB:
272 iab->a[i] = cap_d->u[i].flat[flag];
273 iab->i[i] |= cap_d->u[i].flat[flag];
274 break;
275 case CAP_IAB_BOUND:
276 iab->nb[i] = ~cap_d->u[i].flat[flag];
277 break;
278 default:
279 errno = EINVAL;
280 return -1;
281 }
282 }
283
284 return 0;
285 }
286