1 /*
2 * Class and permission mappings.
3 */
4
5 #include <errno.h>
6 #include <stdio.h>
7 #include <stdlib.h>
8 #include <stdarg.h>
9 #include <stdbool.h>
10 #include <selinux/selinux.h>
11 #include <selinux/avc.h>
12 #include "callbacks.h"
13 #include "mapping.h"
14 #include "selinux_internal.h"
15
16 /*
17 * Class and permission mappings
18 */
19
20 struct selinux_mapping {
21 security_class_t value; /* real, kernel value */
22 unsigned num_perms;
23 access_vector_t perms[sizeof(access_vector_t) * 8];
24 };
25
26 static struct selinux_mapping *current_mapping = NULL;
27 static security_class_t current_mapping_size = 0;
28
29 /*
30 * Mapping setting function
31 */
32
33 int
selinux_set_mapping(struct security_class_mapping * map)34 selinux_set_mapping(struct security_class_mapping *map)
35 {
36 size_t size = sizeof(struct selinux_mapping);
37 security_class_t i, j;
38 unsigned k;
39 bool print_unknown_handle = false;
40 bool reject = (security_reject_unknown() == 1);
41 bool deny = (security_deny_unknown() == 1);
42
43 free(current_mapping);
44 current_mapping = NULL;
45 current_mapping_size = 0;
46
47 if (avc_reset() < 0)
48 goto err;
49
50 /* Find number of classes in the input mapping */
51 if (!map) {
52 errno = EINVAL;
53 goto err;
54 }
55 i = 0;
56 while (map[i].name)
57 i++;
58
59 /* Allocate space for the class records, plus one for class zero */
60 current_mapping = (struct selinux_mapping *)calloc(++i, size);
61 if (!current_mapping)
62 goto err;
63
64 /* Store the raw class and permission values */
65 j = 0;
66 while (map[j].name) {
67 struct security_class_mapping *p_in = map + (j++);
68 struct selinux_mapping *p_out = current_mapping + j;
69
70 p_out->value = string_to_security_class(p_in->name);
71 if (!p_out->value) {
72 selinux_log(SELINUX_INFO,
73 "SELinux: Class %s not defined in policy.\n",
74 p_in->name);
75 if (reject)
76 goto err2;
77 p_out->num_perms = 0;
78 print_unknown_handle = true;
79 continue;
80 }
81
82 k = 0;
83 while (p_in->perms[k]) {
84 /* An empty permission string skips ahead */
85 if (!*p_in->perms[k]) {
86 k++;
87 continue;
88 }
89 p_out->perms[k] = string_to_av_perm(p_out->value,
90 p_in->perms[k]);
91 if (!p_out->perms[k]) {
92 selinux_log(SELINUX_INFO,
93 "SELinux: Permission %s in class %s not defined in policy.\n",
94 p_in->perms[k], p_in->name);
95 if (reject)
96 goto err2;
97 print_unknown_handle = true;
98 }
99 k++;
100 }
101 p_out->num_perms = k;
102 }
103
104 if (print_unknown_handle)
105 selinux_log(SELINUX_INFO,
106 "SELinux: the above unknown classes and permissions will be %s\n",
107 deny ? "denied" : "allowed");
108
109 /* Set the mapping size here so the above lookups are "raw" */
110 current_mapping_size = i;
111 return 0;
112 err2:
113 free(current_mapping);
114 current_mapping = NULL;
115 current_mapping_size = 0;
116 err:
117 return -1;
118 }
119
120 /*
121 * Get real, kernel values from mapped values
122 */
123
124 security_class_t
unmap_class(security_class_t tclass)125 unmap_class(security_class_t tclass)
126 {
127 if (tclass < current_mapping_size)
128 return current_mapping[tclass].value;
129
130 /* If here no mapping set or the class requested is not valid. */
131 if (current_mapping_size != 0) {
132 errno = EINVAL;
133 return 0;
134 }
135 else
136 return tclass;
137 }
138
139 access_vector_t
unmap_perm(security_class_t tclass,access_vector_t tperm)140 unmap_perm(security_class_t tclass, access_vector_t tperm)
141 {
142 if (tclass < current_mapping_size) {
143 unsigned i;
144 access_vector_t kperm = 0;
145
146 for (i=0; i<current_mapping[tclass].num_perms; i++)
147 if (tperm & (1<<i)) {
148 kperm |= current_mapping[tclass].perms[i];
149 tperm &= ~(1<<i);
150 }
151 return kperm;
152 }
153
154 /* If here no mapping set or the perm requested is not valid. */
155 if (current_mapping_size != 0) {
156 errno = EINVAL;
157 return 0;
158 }
159 else
160 return tperm;
161 }
162
163 /*
164 * Get mapped values from real, kernel values
165 */
166
167 security_class_t
map_class(security_class_t kclass)168 map_class(security_class_t kclass)
169 {
170 security_class_t i;
171
172 for (i=0; i<current_mapping_size; i++)
173 if (current_mapping[i].value == kclass)
174 return i;
175
176 /* If here no mapping set or the class requested is not valid. */
177 if (current_mapping_size != 0) {
178 errno = EINVAL;
179 return 0;
180 }
181 else
182 return kclass;
183 }
184
185 access_vector_t
map_perm(security_class_t tclass,access_vector_t kperm)186 map_perm(security_class_t tclass, access_vector_t kperm)
187 {
188 if (tclass < current_mapping_size) {
189 unsigned i;
190 access_vector_t tperm = 0;
191
192 for (i=0; i<current_mapping[tclass].num_perms; i++)
193 if (kperm & current_mapping[tclass].perms[i]) {
194 tperm |= 1<<i;
195 kperm &= ~current_mapping[tclass].perms[i];
196 }
197
198 if (tperm == 0) {
199 errno = EINVAL;
200 return 0;
201 }
202 else
203 return tperm;
204 }
205 return kperm;
206 }
207
208 void
map_decision(security_class_t tclass,struct av_decision * avd)209 map_decision(security_class_t tclass, struct av_decision *avd)
210 {
211 if (tclass < current_mapping_size) {
212 bool allow_unknown = (security_deny_unknown() == 0);
213 struct selinux_mapping *mapping = ¤t_mapping[tclass];
214 unsigned int i, n = mapping->num_perms;
215 access_vector_t result;
216
217 for (i = 0, result = 0; i < n; i++) {
218 if (avd->allowed & mapping->perms[i])
219 result |= 1<<i;
220 else if (allow_unknown && !mapping->perms[i])
221 result |= 1<<i;
222 }
223 avd->allowed = result;
224
225 for (i = 0, result = 0; i < n; i++) {
226 if (avd->decided & mapping->perms[i])
227 result |= 1<<i;
228 else if (allow_unknown && !mapping->perms[i])
229 result |= 1<<i;
230 }
231 avd->decided = result;
232
233 for (i = 0, result = 0; i < n; i++)
234 if (avd->auditallow & mapping->perms[i])
235 result |= 1<<i;
236 avd->auditallow = result;
237
238 for (i = 0, result = 0; i < n; i++) {
239 if (avd->auditdeny & mapping->perms[i])
240 result |= 1<<i;
241 else if (!allow_unknown && !mapping->perms[i])
242 result |= 1<<i;
243 }
244
245 /*
246 * Make sure we audit denials for any permission check
247 * beyond the mapping->num_perms since this indicates
248 * a bug in the object manager.
249 */
250 for (; i < (sizeof(result)*8); i++)
251 result |= 1<<i;
252 avd->auditdeny = result;
253 }
254 }
255