• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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