1 /*
2 * Copyright (c) 1997-8,2008 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
8 #include "libcap.h"
9
10 /*
11 * Return the state of a specified capability flag. The state is
12 * returned as the contents of *raised. The capability is from one of
13 * the sets stored in cap_d as specified by set and value
14 */
15
cap_get_flag(cap_t cap_d,cap_value_t value,cap_flag_t set,cap_flag_value_t * raised)16 int cap_get_flag(cap_t cap_d, cap_value_t value, cap_flag_t set,
17 cap_flag_value_t *raised)
18 {
19 /*
20 * Do we have a set and a place to store its value?
21 * Is it a known capability?
22 */
23
24 if (raised && good_cap_t(cap_d) && value >= 0 && value < __CAP_BITS
25 && set >= 0 && set < NUMBER_OF_CAP_SETS) {
26 *raised = isset_cap(cap_d,value,set) ? CAP_SET:CAP_CLEAR;
27 return 0;
28 } else {
29 _cap_debug("invalid arguments");
30 errno = EINVAL;
31 return -1;
32 }
33 }
34
35 /*
36 * raise/lower a selection of capabilities
37 */
38
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)39 int cap_set_flag(cap_t cap_d, cap_flag_t set,
40 int no_values, const cap_value_t *array_values,
41 cap_flag_value_t raise)
42 {
43 /*
44 * Do we have a set and a place to store its value?
45 * Is it a known capability?
46 */
47
48 if (good_cap_t(cap_d) && no_values > 0 && no_values <= __CAP_BITS
49 && (set >= 0) && (set < NUMBER_OF_CAP_SETS)
50 && (raise == CAP_SET || raise == CAP_CLEAR) ) {
51 int i;
52 for (i=0; i<no_values; ++i) {
53 if (array_values[i] < 0 || array_values[i] >= __CAP_BITS) {
54 _cap_debug("weird capability (%d) - skipped", array_values[i]);
55 } else {
56 int value = array_values[i];
57
58 if (raise == CAP_SET) {
59 cap_d->raise_cap(value,set);
60 } else {
61 cap_d->lower_cap(value,set);
62 }
63 }
64 }
65 return 0;
66
67 } else {
68
69 _cap_debug("invalid arguments");
70 errno = EINVAL;
71 return -1;
72
73 }
74 }
75
76 /*
77 * Reset the capability to be empty (nothing raised)
78 */
79
cap_clear(cap_t cap_d)80 int cap_clear(cap_t cap_d)
81 {
82 if (good_cap_t(cap_d)) {
83
84 memset(&(cap_d->u), 0, sizeof(cap_d->u));
85 return 0;
86
87 } else {
88
89 _cap_debug("invalid pointer");
90 errno = EINVAL;
91 return -1;
92
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 for (i=0; i<_LIBCAP_CAPABILITY_U32S; i++) {
110 cap_d->u[i].flat[flag] = 0;
111 }
112 return 0;
113 }
114 /*
115 * fall through
116 */
117
118 default:
119 _cap_debug("invalid pointer");
120 errno = EINVAL;
121 return -1;
122 }
123 }
124
125 /*
126 * Compare two capability sets
127 */
128
cap_compare(cap_t a,cap_t b)129 int cap_compare(cap_t a, cap_t b)
130 {
131 unsigned i;
132 int result;
133
134 if (!(good_cap_t(a) && good_cap_t(b))) {
135 _cap_debug("invalid arguments");
136 errno = EINVAL;
137 return -1;
138 }
139
140 for (i=0, result=0; i<_LIBCAP_CAPABILITY_U32S; i++) {
141 result |=
142 ((a->u[i].flat[CAP_EFFECTIVE] != b->u[i].flat[CAP_EFFECTIVE])
143 ? LIBCAP_EFF : 0)
144 | ((a->u[i].flat[CAP_INHERITABLE] != b->u[i].flat[CAP_INHERITABLE])
145 ? LIBCAP_INH : 0)
146 | ((a->u[i].flat[CAP_PERMITTED] != b->u[i].flat[CAP_PERMITTED])
147 ? LIBCAP_PER : 0);
148 }
149 return result;
150 }
151