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_iab_get_vector reads the single bit value from an IAB vector set.
151 */
cap_iab_get_vector(cap_iab_t iab,cap_iab_vector_t vec,cap_value_t bit)152 cap_flag_value_t cap_iab_get_vector(cap_iab_t iab, cap_iab_vector_t vec,
153 cap_value_t bit)
154 {
155 if (!good_cap_iab_t(iab) || bit >= cap_max_bits()) {
156 return 0;
157 }
158
159 unsigned o = (bit >> 5);
160 __u32 mask = 1u << (bit & 31);
161
162 switch (vec) {
163 case CAP_IAB_INH:
164 return !!(iab->i[o] & mask);
165 break;
166 case CAP_IAB_AMB:
167 return !!(iab->a[o] & mask);
168 break;
169 case CAP_IAB_BOUND:
170 return !!(iab->nb[o] & mask);
171 break;
172 default:
173 return 0;
174 }
175 }
176
177 /*
178 * cap_iab_set_vector sets the bits in an IAB to the value
179 * raised. Note, setting A implies setting I too, lowering I implies
180 * lowering A too. The B bits are, however, independently settable.
181 */
cap_iab_set_vector(cap_iab_t iab,cap_iab_vector_t vec,cap_value_t bit,cap_flag_value_t raised)182 int cap_iab_set_vector(cap_iab_t iab, cap_iab_vector_t vec, cap_value_t bit,
183 cap_flag_value_t raised)
184 {
185 if (!good_cap_iab_t(iab) || (raised >> 1) || bit >= cap_max_bits()) {
186 errno = EINVAL;
187 return -1;
188 }
189
190 unsigned o = (bit >> 5);
191 __u32 on = 1u << (bit & 31);
192 __u32 mask = ~on;
193
194 switch (vec) {
195 case CAP_IAB_INH:
196 iab->i[o] = (iab->i[o] & mask) | (raised ? on : 0);
197 iab->a[o] &= iab->i[o];
198 break;
199 case CAP_IAB_AMB:
200 iab->a[o] = (iab->a[o] & mask) | (raised ? on : 0);
201 iab->i[o] |= iab->a[o];
202 break;
203 case CAP_IAB_BOUND:
204 iab->nb[o] = (iab->nb[o] & mask) | (raised ? on : 0);
205 break;
206 default:
207 errno = EINVAL;
208 return -1;
209 }
210
211 return 0;
212 }
213
214 /*
215 * cap_iab_fill copies a bit-vector of capability state from a cap_t
216 * to a cap_iab_t. Note, because the bounding bits in an iab are to be
217 * dropped when applied, the copying process, when to a CAP_IAB_BOUND
218 * vector involves inverting the bits. Also, adjusting I will mask
219 * bits in A, and adjusting A may implicitly raise bits in I.
220 */
cap_iab_fill(cap_iab_t iab,cap_iab_vector_t vec,cap_t cap_d,cap_flag_t flag)221 int cap_iab_fill(cap_iab_t iab, cap_iab_vector_t vec,
222 cap_t cap_d, cap_flag_t flag)
223 {
224 if (!good_cap_t(cap_d) || !good_cap_iab_t(iab)) {
225 errno = EINVAL;
226 return -1;
227 }
228
229 switch (flag) {
230 case CAP_EFFECTIVE:
231 case CAP_INHERITABLE:
232 case CAP_PERMITTED:
233 break;
234 default:
235 errno = EINVAL;
236 return -1;
237 }
238
239 int i;
240 for (i = 0; i < _LIBCAP_CAPABILITY_U32S; i++) {
241 switch (vec) {
242 case CAP_IAB_INH:
243 iab->i[i] = cap_d->u[i].flat[flag];
244 iab->a[i] &= iab->i[i];
245 break;
246 case CAP_IAB_AMB:
247 iab->a[i] = cap_d->u[i].flat[flag];
248 iab->i[i] |= cap_d->u[i].flat[flag];
249 break;
250 case CAP_IAB_BOUND:
251 iab->nb[i] = ~cap_d->u[i].flat[flag];
252 break;
253 default:
254 errno = EINVAL;
255 return -1;
256 }
257 }
258
259 return 0;
260 }
261