/src/selinux/libsepol/src/policydb.c
Line | Count | Source (jump to first uncovered line) |
1 | | |
2 | | /* Author : Stephen Smalley, <stephen.smalley.work@gmail.com> */ |
3 | | |
4 | | /* |
5 | | * Updated: Trusted Computer Solutions, Inc. <dgoeddel@trustedcs.com> |
6 | | * |
7 | | * Support for enhanced MLS infrastructure. |
8 | | * |
9 | | * Updated: Frank Mayer <mayerf@tresys.com> and Karl MacMillan <kmacmillan@tresys.com> |
10 | | * |
11 | | * Added conditional policy language extensions |
12 | | * |
13 | | * Updated: Red Hat, Inc. James Morris <jmorris@redhat.com> |
14 | | * Fine-grained netlink support |
15 | | * IPv6 support |
16 | | * Code cleanup |
17 | | * |
18 | | * Copyright (C) 2004-2005 Trusted Computer Solutions, Inc. |
19 | | * Copyright (C) 2003 - 2005 Tresys Technology, LLC |
20 | | * Copyright (C) 2003 - 2007 Red Hat, Inc. |
21 | | * Copyright (C) 2017 Mellanox Technologies Inc. |
22 | | * |
23 | | * This library is free software; you can redistribute it and/or |
24 | | * modify it under the terms of the GNU Lesser General Public |
25 | | * License as published by the Free Software Foundation; either |
26 | | * version 2.1 of the License, or (at your option) any later version. |
27 | | * |
28 | | * This library is distributed in the hope that it will be useful, |
29 | | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
30 | | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
31 | | * Lesser General Public License for more details. |
32 | | * |
33 | | * You should have received a copy of the GNU Lesser General Public |
34 | | * License along with this library; if not, write to the Free Software |
35 | | * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA |
36 | | */ |
37 | | |
38 | | /* FLASK */ |
39 | | |
40 | | /* |
41 | | * Implementation of the policy database. |
42 | | */ |
43 | | |
44 | | #include <assert.h> |
45 | | #include <stdlib.h> |
46 | | |
47 | | #include <sepol/policydb/policydb.h> |
48 | | #include <sepol/policydb/expand.h> |
49 | | #include <sepol/policydb/conditional.h> |
50 | | #include <sepol/policydb/avrule_block.h> |
51 | | #include <sepol/policydb/util.h> |
52 | | |
53 | | #include "kernel_to_common.h" |
54 | | #include "private.h" |
55 | | #include "debug.h" |
56 | | #include "mls.h" |
57 | | #include "policydb_validate.h" |
58 | | |
59 | 18.9k | #define POLICYDB_TARGET_SZ ARRAY_SIZE(policydb_target_strings) |
60 | | const char * const policydb_target_strings[] = { POLICYDB_STRING, POLICYDB_XEN_STRING }; |
61 | | |
62 | | /* These need to be updated if SYM_NUM or OCON_NUM changes */ |
63 | | static const struct policydb_compat_info policydb_compat[] = { |
64 | | { |
65 | | .type = POLICY_KERN, |
66 | | .version = POLICYDB_VERSION_BOUNDARY, |
67 | | .sym_num = SYM_NUM, |
68 | | .ocon_num = OCON_XEN_PCIDEVICE + 1, |
69 | | .target_platform = SEPOL_TARGET_XEN, |
70 | | }, |
71 | | { |
72 | | .type = POLICY_KERN, |
73 | | .version = POLICYDB_VERSION_XEN_DEVICETREE, |
74 | | .sym_num = SYM_NUM, |
75 | | .ocon_num = OCON_XEN_DEVICETREE + 1, |
76 | | .target_platform = SEPOL_TARGET_XEN, |
77 | | }, |
78 | | { |
79 | | .type = POLICY_KERN, |
80 | | .version = POLICYDB_VERSION_BASE, |
81 | | .sym_num = SYM_NUM - 3, |
82 | | .ocon_num = OCON_FSUSE + 1, |
83 | | .target_platform = SEPOL_TARGET_SELINUX, |
84 | | }, |
85 | | { |
86 | | .type = POLICY_KERN, |
87 | | .version = POLICYDB_VERSION_BOOL, |
88 | | .sym_num = SYM_NUM - 2, |
89 | | .ocon_num = OCON_FSUSE + 1, |
90 | | .target_platform = SEPOL_TARGET_SELINUX, |
91 | | }, |
92 | | { |
93 | | .type = POLICY_KERN, |
94 | | .version = POLICYDB_VERSION_IPV6, |
95 | | .sym_num = SYM_NUM - 2, |
96 | | .ocon_num = OCON_NODE6 + 1, |
97 | | .target_platform = SEPOL_TARGET_SELINUX, |
98 | | }, |
99 | | { |
100 | | .type = POLICY_KERN, |
101 | | .version = POLICYDB_VERSION_NLCLASS, |
102 | | .sym_num = SYM_NUM - 2, |
103 | | .ocon_num = OCON_NODE6 + 1, |
104 | | .target_platform = SEPOL_TARGET_SELINUX, |
105 | | }, |
106 | | { |
107 | | .type = POLICY_KERN, |
108 | | .version = POLICYDB_VERSION_MLS, |
109 | | .sym_num = SYM_NUM, |
110 | | .ocon_num = OCON_NODE6 + 1, |
111 | | .target_platform = SEPOL_TARGET_SELINUX, |
112 | | }, |
113 | | { |
114 | | .type = POLICY_KERN, |
115 | | .version = POLICYDB_VERSION_AVTAB, |
116 | | .sym_num = SYM_NUM, |
117 | | .ocon_num = OCON_NODE6 + 1, |
118 | | .target_platform = SEPOL_TARGET_SELINUX, |
119 | | }, |
120 | | { |
121 | | .type = POLICY_KERN, |
122 | | .version = POLICYDB_VERSION_RANGETRANS, |
123 | | .sym_num = SYM_NUM, |
124 | | .ocon_num = OCON_NODE6 + 1, |
125 | | .target_platform = SEPOL_TARGET_SELINUX, |
126 | | }, |
127 | | { |
128 | | .type = POLICY_KERN, |
129 | | .version = POLICYDB_VERSION_POLCAP, |
130 | | .sym_num = SYM_NUM, |
131 | | .ocon_num = OCON_NODE6 + 1, |
132 | | .target_platform = SEPOL_TARGET_SELINUX, |
133 | | }, |
134 | | { |
135 | | .type = POLICY_KERN, |
136 | | .version = POLICYDB_VERSION_PERMISSIVE, |
137 | | .sym_num = SYM_NUM, |
138 | | .ocon_num = OCON_NODE6 + 1, |
139 | | .target_platform = SEPOL_TARGET_SELINUX, |
140 | | }, |
141 | | { |
142 | | .type = POLICY_KERN, |
143 | | .version = POLICYDB_VERSION_BOUNDARY, |
144 | | .sym_num = SYM_NUM, |
145 | | .ocon_num = OCON_NODE6 + 1, |
146 | | .target_platform = SEPOL_TARGET_SELINUX, |
147 | | }, |
148 | | { |
149 | | .type = POLICY_KERN, |
150 | | .version = POLICYDB_VERSION_FILENAME_TRANS, |
151 | | .sym_num = SYM_NUM, |
152 | | .ocon_num = OCON_NODE6 + 1, |
153 | | .target_platform = SEPOL_TARGET_SELINUX, |
154 | | }, |
155 | | { |
156 | | .type = POLICY_KERN, |
157 | | .version = POLICYDB_VERSION_ROLETRANS, |
158 | | .sym_num = SYM_NUM, |
159 | | .ocon_num = OCON_NODE6 + 1, |
160 | | .target_platform = SEPOL_TARGET_SELINUX, |
161 | | }, |
162 | | { |
163 | | .type = POLICY_KERN, |
164 | | .version = POLICYDB_VERSION_NEW_OBJECT_DEFAULTS, |
165 | | .sym_num = SYM_NUM, |
166 | | .ocon_num = OCON_NODE6 + 1, |
167 | | .target_platform = SEPOL_TARGET_SELINUX, |
168 | | }, |
169 | | { |
170 | | .type = POLICY_KERN, |
171 | | .version = POLICYDB_VERSION_DEFAULT_TYPE, |
172 | | .sym_num = SYM_NUM, |
173 | | .ocon_num = OCON_NODE6 + 1, |
174 | | .target_platform = SEPOL_TARGET_SELINUX, |
175 | | }, |
176 | | { |
177 | | .type = POLICY_KERN, |
178 | | .version = POLICYDB_VERSION_CONSTRAINT_NAMES, |
179 | | .sym_num = SYM_NUM, |
180 | | .ocon_num = OCON_NODE6 + 1, |
181 | | .target_platform = SEPOL_TARGET_SELINUX, |
182 | | }, |
183 | | { |
184 | | .type = POLICY_KERN, |
185 | | .version = POLICYDB_VERSION_XPERMS_IOCTL, |
186 | | .sym_num = SYM_NUM, |
187 | | .ocon_num = OCON_NODE6 + 1, |
188 | | .target_platform = SEPOL_TARGET_SELINUX, |
189 | | }, |
190 | | { |
191 | | .type = POLICY_KERN, |
192 | | .version = POLICYDB_VERSION_INFINIBAND, |
193 | | .sym_num = SYM_NUM, |
194 | | .ocon_num = OCON_IBENDPORT + 1, |
195 | | .target_platform = SEPOL_TARGET_SELINUX, |
196 | | }, |
197 | | { |
198 | | .type = POLICY_KERN, |
199 | | .version = POLICYDB_VERSION_GLBLUB, |
200 | | .sym_num = SYM_NUM, |
201 | | .ocon_num = OCON_IBENDPORT + 1, |
202 | | .target_platform = SEPOL_TARGET_SELINUX, |
203 | | }, |
204 | | { |
205 | | .type = POLICY_KERN, |
206 | | .version = POLICYDB_VERSION_COMP_FTRANS, |
207 | | .sym_num = SYM_NUM, |
208 | | .ocon_num = OCON_IBENDPORT + 1, |
209 | | .target_platform = SEPOL_TARGET_SELINUX, |
210 | | }, |
211 | | { |
212 | | .type = POLICY_BASE, |
213 | | .version = MOD_POLICYDB_VERSION_BASE, |
214 | | .sym_num = SYM_NUM, |
215 | | .ocon_num = OCON_NODE6 + 1, |
216 | | .target_platform = SEPOL_TARGET_SELINUX, |
217 | | }, |
218 | | { |
219 | | .type = POLICY_BASE, |
220 | | .version = MOD_POLICYDB_VERSION_MLS, |
221 | | .sym_num = SYM_NUM, |
222 | | .ocon_num = OCON_NODE6 + 1, |
223 | | .target_platform = SEPOL_TARGET_SELINUX, |
224 | | }, |
225 | | { |
226 | | .type = POLICY_BASE, |
227 | | .version = MOD_POLICYDB_VERSION_MLS_USERS, |
228 | | .sym_num = SYM_NUM, |
229 | | .ocon_num = OCON_NODE6 + 1, |
230 | | .target_platform = SEPOL_TARGET_SELINUX, |
231 | | }, |
232 | | { |
233 | | .type = POLICY_BASE, |
234 | | .version = MOD_POLICYDB_VERSION_POLCAP, |
235 | | .sym_num = SYM_NUM, |
236 | | .ocon_num = OCON_NODE6 + 1, |
237 | | .target_platform = SEPOL_TARGET_SELINUX, |
238 | | }, |
239 | | { |
240 | | .type = POLICY_BASE, |
241 | | .version = MOD_POLICYDB_VERSION_PERMISSIVE, |
242 | | .sym_num = SYM_NUM, |
243 | | .ocon_num = OCON_NODE6 + 1, |
244 | | .target_platform = SEPOL_TARGET_SELINUX, |
245 | | }, |
246 | | { |
247 | | .type = POLICY_BASE, |
248 | | .version = MOD_POLICYDB_VERSION_BOUNDARY, |
249 | | .sym_num = SYM_NUM, |
250 | | .ocon_num = OCON_NODE6 + 1, |
251 | | .target_platform = SEPOL_TARGET_SELINUX, |
252 | | }, |
253 | | { |
254 | | .type = POLICY_BASE, |
255 | | .version = MOD_POLICYDB_VERSION_BOUNDARY_ALIAS, |
256 | | .sym_num = SYM_NUM, |
257 | | .ocon_num = OCON_NODE6 + 1, |
258 | | .target_platform = SEPOL_TARGET_SELINUX, |
259 | | }, |
260 | | { |
261 | | .type = POLICY_BASE, |
262 | | .version = MOD_POLICYDB_VERSION_FILENAME_TRANS, |
263 | | .sym_num = SYM_NUM, |
264 | | .ocon_num = OCON_NODE6 + 1, |
265 | | .target_platform = SEPOL_TARGET_SELINUX, |
266 | | }, |
267 | | { |
268 | | .type = POLICY_BASE, |
269 | | .version = MOD_POLICYDB_VERSION_ROLETRANS, |
270 | | .sym_num = SYM_NUM, |
271 | | .ocon_num = OCON_NODE6 + 1, |
272 | | .target_platform = SEPOL_TARGET_SELINUX, |
273 | | }, |
274 | | { |
275 | | .type = POLICY_BASE, |
276 | | .version = MOD_POLICYDB_VERSION_ROLEATTRIB, |
277 | | .sym_num = SYM_NUM, |
278 | | .ocon_num = OCON_NODE6 + 1, |
279 | | .target_platform = SEPOL_TARGET_SELINUX, |
280 | | }, |
281 | | { |
282 | | .type = POLICY_BASE, |
283 | | .version = MOD_POLICYDB_VERSION_TUNABLE_SEP, |
284 | | .sym_num = SYM_NUM, |
285 | | .ocon_num = OCON_NODE6 + 1, |
286 | | .target_platform = SEPOL_TARGET_SELINUX, |
287 | | }, |
288 | | { |
289 | | .type = POLICY_BASE, |
290 | | .version = MOD_POLICYDB_VERSION_NEW_OBJECT_DEFAULTS, |
291 | | .sym_num = SYM_NUM, |
292 | | .ocon_num = OCON_NODE6 + 1, |
293 | | .target_platform = SEPOL_TARGET_SELINUX, |
294 | | }, |
295 | | { |
296 | | .type = POLICY_BASE, |
297 | | .version = MOD_POLICYDB_VERSION_DEFAULT_TYPE, |
298 | | .sym_num = SYM_NUM, |
299 | | .ocon_num = OCON_NODE6 + 1, |
300 | | .target_platform = SEPOL_TARGET_SELINUX, |
301 | | }, |
302 | | { |
303 | | .type = POLICY_BASE, |
304 | | .version = MOD_POLICYDB_VERSION_CONSTRAINT_NAMES, |
305 | | .sym_num = SYM_NUM, |
306 | | .ocon_num = OCON_NODE6 + 1, |
307 | | .target_platform = SEPOL_TARGET_SELINUX, |
308 | | }, |
309 | | { |
310 | | .type = POLICY_BASE, |
311 | | .version = MOD_POLICYDB_VERSION_XPERMS_IOCTL, |
312 | | .sym_num = SYM_NUM, |
313 | | .ocon_num = OCON_NODE6 + 1, |
314 | | .target_platform = SEPOL_TARGET_SELINUX, |
315 | | }, |
316 | | { |
317 | | .type = POLICY_BASE, |
318 | | .version = MOD_POLICYDB_VERSION_INFINIBAND, |
319 | | .sym_num = SYM_NUM, |
320 | | .ocon_num = OCON_IBENDPORT + 1, |
321 | | .target_platform = SEPOL_TARGET_SELINUX, |
322 | | }, |
323 | | { |
324 | | .type = POLICY_BASE, |
325 | | .version = MOD_POLICYDB_VERSION_GLBLUB, |
326 | | .sym_num = SYM_NUM, |
327 | | .ocon_num = OCON_IBENDPORT + 1, |
328 | | .target_platform = SEPOL_TARGET_SELINUX, |
329 | | }, |
330 | | { |
331 | | .type = POLICY_BASE, |
332 | | .version = MOD_POLICYDB_VERSION_SELF_TYPETRANS, |
333 | | .sym_num = SYM_NUM, |
334 | | .ocon_num = OCON_IBENDPORT + 1, |
335 | | .target_platform = SEPOL_TARGET_SELINUX, |
336 | | }, |
337 | | { |
338 | | .type = POLICY_MOD, |
339 | | .version = MOD_POLICYDB_VERSION_BASE, |
340 | | .sym_num = SYM_NUM, |
341 | | .ocon_num = 0, |
342 | | .target_platform = SEPOL_TARGET_SELINUX, |
343 | | }, |
344 | | { |
345 | | .type = POLICY_MOD, |
346 | | .version = MOD_POLICYDB_VERSION_MLS, |
347 | | .sym_num = SYM_NUM, |
348 | | .ocon_num = 0, |
349 | | .target_platform = SEPOL_TARGET_SELINUX, |
350 | | }, |
351 | | { |
352 | | .type = POLICY_MOD, |
353 | | .version = MOD_POLICYDB_VERSION_MLS_USERS, |
354 | | .sym_num = SYM_NUM, |
355 | | .ocon_num = 0, |
356 | | .target_platform = SEPOL_TARGET_SELINUX, |
357 | | }, |
358 | | { |
359 | | .type = POLICY_MOD, |
360 | | .version = MOD_POLICYDB_VERSION_POLCAP, |
361 | | .sym_num = SYM_NUM, |
362 | | .ocon_num = 0, |
363 | | .target_platform = SEPOL_TARGET_SELINUX, |
364 | | }, |
365 | | { |
366 | | .type = POLICY_MOD, |
367 | | .version = MOD_POLICYDB_VERSION_PERMISSIVE, |
368 | | .sym_num = SYM_NUM, |
369 | | .ocon_num = 0, |
370 | | .target_platform = SEPOL_TARGET_SELINUX, |
371 | | }, |
372 | | { |
373 | | .type = POLICY_MOD, |
374 | | .version = MOD_POLICYDB_VERSION_BOUNDARY, |
375 | | .sym_num = SYM_NUM, |
376 | | .ocon_num = 0, |
377 | | .target_platform = SEPOL_TARGET_SELINUX, |
378 | | }, |
379 | | { |
380 | | .type = POLICY_MOD, |
381 | | .version = MOD_POLICYDB_VERSION_BOUNDARY_ALIAS, |
382 | | .sym_num = SYM_NUM, |
383 | | .ocon_num = 0, |
384 | | .target_platform = SEPOL_TARGET_SELINUX, |
385 | | }, |
386 | | { |
387 | | .type = POLICY_MOD, |
388 | | .version = MOD_POLICYDB_VERSION_FILENAME_TRANS, |
389 | | .sym_num = SYM_NUM, |
390 | | .ocon_num = 0, |
391 | | .target_platform = SEPOL_TARGET_SELINUX, |
392 | | }, |
393 | | { |
394 | | .type = POLICY_MOD, |
395 | | .version = MOD_POLICYDB_VERSION_ROLETRANS, |
396 | | .sym_num = SYM_NUM, |
397 | | .ocon_num = 0, |
398 | | .target_platform = SEPOL_TARGET_SELINUX, |
399 | | }, |
400 | | { |
401 | | .type = POLICY_MOD, |
402 | | .version = MOD_POLICYDB_VERSION_ROLEATTRIB, |
403 | | .sym_num = SYM_NUM, |
404 | | .ocon_num = 0, |
405 | | .target_platform = SEPOL_TARGET_SELINUX, |
406 | | }, |
407 | | { |
408 | | .type = POLICY_MOD, |
409 | | .version = MOD_POLICYDB_VERSION_TUNABLE_SEP, |
410 | | .sym_num = SYM_NUM, |
411 | | .ocon_num = 0, |
412 | | .target_platform = SEPOL_TARGET_SELINUX, |
413 | | }, |
414 | | { |
415 | | .type = POLICY_MOD, |
416 | | .version = MOD_POLICYDB_VERSION_NEW_OBJECT_DEFAULTS, |
417 | | .sym_num = SYM_NUM, |
418 | | .ocon_num = 0, |
419 | | .target_platform = SEPOL_TARGET_SELINUX, |
420 | | }, |
421 | | { |
422 | | .type = POLICY_MOD, |
423 | | .version = MOD_POLICYDB_VERSION_DEFAULT_TYPE, |
424 | | .sym_num = SYM_NUM, |
425 | | .ocon_num = 0, |
426 | | .target_platform = SEPOL_TARGET_SELINUX, |
427 | | }, |
428 | | { |
429 | | .type = POLICY_MOD, |
430 | | .version = MOD_POLICYDB_VERSION_CONSTRAINT_NAMES, |
431 | | .sym_num = SYM_NUM, |
432 | | .ocon_num = 0, |
433 | | .target_platform = SEPOL_TARGET_SELINUX, |
434 | | }, |
435 | | { |
436 | | .type = POLICY_MOD, |
437 | | .version = MOD_POLICYDB_VERSION_XPERMS_IOCTL, |
438 | | .sym_num = SYM_NUM, |
439 | | .ocon_num = 0, |
440 | | .target_platform = SEPOL_TARGET_SELINUX, |
441 | | }, |
442 | | { |
443 | | .type = POLICY_MOD, |
444 | | .version = MOD_POLICYDB_VERSION_INFINIBAND, |
445 | | .sym_num = SYM_NUM, |
446 | | .ocon_num = 0, |
447 | | .target_platform = SEPOL_TARGET_SELINUX, |
448 | | }, |
449 | | { |
450 | | .type = POLICY_MOD, |
451 | | .version = MOD_POLICYDB_VERSION_GLBLUB, |
452 | | .sym_num = SYM_NUM, |
453 | | .ocon_num = 0, |
454 | | .target_platform = SEPOL_TARGET_SELINUX, |
455 | | }, |
456 | | { |
457 | | .type = POLICY_MOD, |
458 | | .version = MOD_POLICYDB_VERSION_SELF_TYPETRANS, |
459 | | .sym_num = SYM_NUM, |
460 | | .ocon_num = 0, |
461 | | .target_platform = SEPOL_TARGET_SELINUX, |
462 | | }, |
463 | | }; |
464 | | |
465 | | #if 0 |
466 | | static char *symtab_name[SYM_NUM] = { |
467 | | "common prefixes", |
468 | | "classes", |
469 | | "roles", |
470 | | "types", |
471 | | "users", |
472 | | "bools" mls_symtab_names cond_symtab_names |
473 | | }; |
474 | | #endif |
475 | | |
476 | | static const unsigned int symtab_sizes[SYM_NUM] = { |
477 | | 2, |
478 | | 32, |
479 | | 16, |
480 | | 512, |
481 | | 128, |
482 | | 16, |
483 | | 16, |
484 | | 16, |
485 | | }; |
486 | | |
487 | | const struct policydb_compat_info *policydb_lookup_compat(unsigned int version, |
488 | | unsigned int type, |
489 | | unsigned int target_platform) |
490 | 12.6k | { |
491 | 12.6k | unsigned int i; |
492 | 12.6k | const struct policydb_compat_info *info = NULL; |
493 | | |
494 | 193k | for (i = 0; i < sizeof(policydb_compat) / sizeof(*info); i++) { |
495 | 193k | if (policydb_compat[i].version == version && |
496 | 193k | policydb_compat[i].type == type && |
497 | 193k | policydb_compat[i].target_platform == target_platform) { |
498 | 12.5k | info = &policydb_compat[i]; |
499 | 12.5k | break; |
500 | 12.5k | } |
501 | 193k | } |
502 | 12.6k | return info; |
503 | 12.6k | } |
504 | | |
505 | | void type_set_init(type_set_t * x) |
506 | 13.7k | { |
507 | 13.7k | memset(x, 0, sizeof(type_set_t)); |
508 | 13.7k | ebitmap_init(&x->types); |
509 | 13.7k | ebitmap_init(&x->negset); |
510 | 13.7k | } |
511 | | |
512 | | void type_set_destroy(type_set_t * x) |
513 | 28.1k | { |
514 | 28.1k | if (x != NULL) { |
515 | 28.1k | ebitmap_destroy(&x->types); |
516 | 28.1k | ebitmap_destroy(&x->negset); |
517 | 28.1k | } |
518 | 28.1k | } |
519 | | |
520 | | void role_set_init(role_set_t * x) |
521 | 901 | { |
522 | 901 | memset(x, 0, sizeof(role_set_t)); |
523 | 901 | ebitmap_init(&x->roles); |
524 | 901 | } |
525 | | |
526 | | void role_set_destroy(role_set_t * x) |
527 | 4.00k | { |
528 | 4.00k | ebitmap_destroy(&x->roles); |
529 | 4.00k | } |
530 | | |
531 | | void role_datum_init(role_datum_t * x) |
532 | 0 | { |
533 | 0 | memset(x, 0, sizeof(role_datum_t)); |
534 | 0 | ebitmap_init(&x->dominates); |
535 | 0 | type_set_init(&x->types); |
536 | 0 | ebitmap_init(&x->cache); |
537 | 0 | ebitmap_init(&x->roles); |
538 | 0 | } |
539 | | |
540 | | void role_datum_destroy(role_datum_t * x) |
541 | 14.3k | { |
542 | 14.3k | if (x != NULL) { |
543 | 14.3k | ebitmap_destroy(&x->dominates); |
544 | 14.3k | type_set_destroy(&x->types); |
545 | 14.3k | ebitmap_destroy(&x->cache); |
546 | 14.3k | ebitmap_destroy(&x->roles); |
547 | 14.3k | } |
548 | 14.3k | } |
549 | | |
550 | | void type_datum_init(type_datum_t * x) |
551 | 0 | { |
552 | 0 | memset(x, 0, sizeof(*x)); |
553 | 0 | ebitmap_init(&x->types); |
554 | 0 | } |
555 | | |
556 | | void type_datum_destroy(type_datum_t * x) |
557 | 5.02k | { |
558 | 5.02k | if (x != NULL) { |
559 | 5.02k | ebitmap_destroy(&x->types); |
560 | 5.02k | } |
561 | 5.02k | } |
562 | | |
563 | | void user_datum_init(user_datum_t * x) |
564 | 0 | { |
565 | 0 | memset(x, 0, sizeof(user_datum_t)); |
566 | 0 | role_set_init(&x->roles); |
567 | 0 | mls_semantic_range_init(&x->range); |
568 | 0 | mls_semantic_level_init(&x->dfltlevel); |
569 | 0 | ebitmap_init(&x->cache); |
570 | 0 | mls_range_init(&x->exp_range); |
571 | 0 | mls_level_init(&x->exp_dfltlevel); |
572 | 0 | } |
573 | | |
574 | | void user_datum_destroy(user_datum_t * x) |
575 | 3.10k | { |
576 | 3.10k | if (x != NULL) { |
577 | 3.10k | role_set_destroy(&x->roles); |
578 | 3.10k | mls_semantic_range_destroy(&x->range); |
579 | 3.10k | mls_semantic_level_destroy(&x->dfltlevel); |
580 | 3.10k | ebitmap_destroy(&x->cache); |
581 | 3.10k | mls_range_destroy(&x->exp_range); |
582 | 3.10k | mls_level_destroy(&x->exp_dfltlevel); |
583 | 3.10k | } |
584 | 3.10k | } |
585 | | |
586 | | void level_datum_init(level_datum_t * x) |
587 | 1.13k | { |
588 | 1.13k | memset(x, 0, sizeof(level_datum_t)); |
589 | 1.13k | } |
590 | | |
591 | | void level_datum_destroy(level_datum_t * x __attribute__ ((unused))) |
592 | 1.13k | { |
593 | | /* the mls_level_t referenced by the level_datum is managed |
594 | | * separately for now, so there is nothing to destroy */ |
595 | 1.13k | return; |
596 | 1.13k | } |
597 | | |
598 | | void cat_datum_init(cat_datum_t * x) |
599 | 905 | { |
600 | 905 | memset(x, 0, sizeof(cat_datum_t)); |
601 | 905 | } |
602 | | |
603 | | void cat_datum_destroy(cat_datum_t * x __attribute__ ((unused))) |
604 | 905 | { |
605 | | /* it's currently a simple struct - really nothing to destroy */ |
606 | 905 | return; |
607 | 905 | } |
608 | | |
609 | | void class_perm_node_init(class_perm_node_t * x) |
610 | 743 | { |
611 | 743 | memset(x, 0, sizeof(class_perm_node_t)); |
612 | 743 | } |
613 | | |
614 | | void avrule_init(avrule_t * x) |
615 | 2.20k | { |
616 | 2.20k | memset(x, 0, sizeof(avrule_t)); |
617 | 2.20k | type_set_init(&x->stypes); |
618 | 2.20k | type_set_init(&x->ttypes); |
619 | 2.20k | } |
620 | | |
621 | | void avrule_destroy(avrule_t * x) |
622 | 2.20k | { |
623 | 2.20k | class_perm_node_t *cur, *next; |
624 | | |
625 | 2.20k | if (x == NULL) { |
626 | 0 | return; |
627 | 0 | } |
628 | 2.20k | type_set_destroy(&x->stypes); |
629 | 2.20k | type_set_destroy(&x->ttypes); |
630 | | |
631 | 2.20k | free(x->source_filename); |
632 | | |
633 | 2.20k | next = x->perms; |
634 | 2.89k | while (next) { |
635 | 688 | cur = next; |
636 | 688 | next = cur->next; |
637 | 688 | free(cur); |
638 | 688 | } |
639 | | |
640 | 2.20k | free(x->xperms); |
641 | 2.20k | } |
642 | | |
643 | | void role_trans_rule_init(role_trans_rule_t * x) |
644 | 391 | { |
645 | 391 | memset(x, 0, sizeof(*x)); |
646 | 391 | role_set_init(&x->roles); |
647 | 391 | type_set_init(&x->types); |
648 | 391 | ebitmap_init(&x->classes); |
649 | 391 | } |
650 | | |
651 | | static void role_trans_rule_destroy(role_trans_rule_t * x) |
652 | 391 | { |
653 | 391 | if (x != NULL) { |
654 | 391 | role_set_destroy(&x->roles); |
655 | 391 | type_set_destroy(&x->types); |
656 | 391 | ebitmap_destroy(&x->classes); |
657 | 391 | } |
658 | 391 | } |
659 | | |
660 | | void role_trans_rule_list_destroy(role_trans_rule_t * x) |
661 | 21.0k | { |
662 | 21.4k | while (x != NULL) { |
663 | 391 | role_trans_rule_t *next = x->next; |
664 | 391 | role_trans_rule_destroy(x); |
665 | 391 | free(x); |
666 | 391 | x = next; |
667 | 391 | } |
668 | 21.0k | } |
669 | | |
670 | | void filename_trans_rule_init(filename_trans_rule_t * x) |
671 | 445 | { |
672 | 445 | memset(x, 0, sizeof(*x)); |
673 | 445 | type_set_init(&x->stypes); |
674 | 445 | type_set_init(&x->ttypes); |
675 | 445 | } |
676 | | |
677 | | static void filename_trans_rule_destroy(filename_trans_rule_t * x) |
678 | 445 | { |
679 | 445 | if (!x) |
680 | 0 | return; |
681 | 445 | type_set_destroy(&x->stypes); |
682 | 445 | type_set_destroy(&x->ttypes); |
683 | 445 | free(x->name); |
684 | 445 | } |
685 | | |
686 | | void filename_trans_rule_list_destroy(filename_trans_rule_t * x) |
687 | 21.0k | { |
688 | 21.0k | filename_trans_rule_t *next; |
689 | 21.5k | while (x) { |
690 | 445 | next = x->next; |
691 | 445 | filename_trans_rule_destroy(x); |
692 | 445 | free(x); |
693 | 445 | x = next; |
694 | 445 | } |
695 | 21.0k | } |
696 | | |
697 | | void role_allow_rule_init(role_allow_rule_t * x) |
698 | 255 | { |
699 | 255 | memset(x, 0, sizeof(role_allow_rule_t)); |
700 | 255 | role_set_init(&x->roles); |
701 | 255 | role_set_init(&x->new_roles); |
702 | 255 | } |
703 | | |
704 | | void role_allow_rule_destroy(role_allow_rule_t * x) |
705 | 255 | { |
706 | 255 | role_set_destroy(&x->roles); |
707 | 255 | role_set_destroy(&x->new_roles); |
708 | 255 | } |
709 | | |
710 | | void role_allow_rule_list_destroy(role_allow_rule_t * x) |
711 | 21.0k | { |
712 | 21.3k | while (x != NULL) { |
713 | 255 | role_allow_rule_t *next = x->next; |
714 | 255 | role_allow_rule_destroy(x); |
715 | 255 | free(x); |
716 | 255 | x = next; |
717 | 255 | } |
718 | 21.0k | } |
719 | | |
720 | | void range_trans_rule_init(range_trans_rule_t * x) |
721 | 1.25k | { |
722 | 1.25k | type_set_init(&x->stypes); |
723 | 1.25k | type_set_init(&x->ttypes); |
724 | 1.25k | ebitmap_init(&x->tclasses); |
725 | 1.25k | mls_semantic_range_init(&x->trange); |
726 | 1.25k | x->next = NULL; |
727 | 1.25k | } |
728 | | |
729 | | void range_trans_rule_destroy(range_trans_rule_t * x) |
730 | 1.25k | { |
731 | 1.25k | type_set_destroy(&x->stypes); |
732 | 1.25k | type_set_destroy(&x->ttypes); |
733 | 1.25k | ebitmap_destroy(&x->tclasses); |
734 | 1.25k | mls_semantic_range_destroy(&x->trange); |
735 | 1.25k | } |
736 | | |
737 | | void range_trans_rule_list_destroy(range_trans_rule_t * x) |
738 | 21.0k | { |
739 | 22.3k | while (x != NULL) { |
740 | 1.25k | range_trans_rule_t *next = x->next; |
741 | 1.25k | range_trans_rule_destroy(x); |
742 | 1.25k | free(x); |
743 | 1.25k | x = next; |
744 | 1.25k | } |
745 | 21.0k | } |
746 | | |
747 | | void avrule_list_destroy(avrule_t * x) |
748 | 28.0k | { |
749 | 28.0k | avrule_t *next, *cur; |
750 | | |
751 | 28.0k | if (!x) |
752 | 27.7k | return; |
753 | | |
754 | 293 | next = x; |
755 | 2.27k | while (next) { |
756 | 1.98k | cur = next; |
757 | 1.98k | next = next->next; |
758 | 1.98k | avrule_destroy(cur); |
759 | 1.98k | free(cur); |
760 | 1.98k | } |
761 | 293 | } |
762 | | |
763 | | /* |
764 | | * Initialize the role table by implicitly adding role 'object_r'. If |
765 | | * the policy is a module, set object_r's scope to be SCOPE_REQ, |
766 | | * otherwise set it to SCOPE_DECL. |
767 | | */ |
768 | | static int roles_init(policydb_t * p) |
769 | 12.1k | { |
770 | 12.1k | char *key = 0; |
771 | 12.1k | int rc; |
772 | 12.1k | role_datum_t *role; |
773 | | |
774 | 12.1k | role = calloc(1, sizeof(role_datum_t)); |
775 | 12.1k | if (!role) { |
776 | 0 | rc = -ENOMEM; |
777 | 0 | goto out; |
778 | 0 | } |
779 | 12.1k | key = strdup(OBJECT_R); |
780 | 12.1k | if (!key) { |
781 | 0 | rc = -ENOMEM; |
782 | 0 | goto out_free_role; |
783 | 0 | } |
784 | 12.1k | rc = symtab_insert(p, SYM_ROLES, key, role, |
785 | 12.1k | (p->policy_type == |
786 | 12.1k | POLICY_MOD ? SCOPE_REQ : SCOPE_DECL), 1, |
787 | 12.1k | &role->s.value); |
788 | 12.1k | if (rc) |
789 | 0 | goto out_free_key; |
790 | 12.1k | if (role->s.value != OBJECT_R_VAL) { |
791 | 0 | rc = -EINVAL; |
792 | 0 | goto out_free_role; |
793 | 0 | } |
794 | 12.1k | out: |
795 | 12.1k | return rc; |
796 | | |
797 | 0 | out_free_key: |
798 | 0 | free(key); |
799 | 0 | out_free_role: |
800 | 0 | free(role); |
801 | 0 | goto out; |
802 | 0 | } |
803 | | |
804 | | ignore_unsigned_overflow_ |
805 | | static inline unsigned long |
806 | | partial_name_hash(unsigned long c, unsigned long prevhash) |
807 | 2.06k | { |
808 | 2.06k | return (prevhash + (c << 4) + (c >> 4)) * 11; |
809 | 2.06k | } |
810 | | |
811 | | static unsigned int filenametr_hash(hashtab_t h, const_hashtab_key_t k) |
812 | 3.31k | { |
813 | 3.31k | const filename_trans_key_t *ft = (const filename_trans_key_t *)k; |
814 | 3.31k | unsigned long hash; |
815 | 3.31k | unsigned int byte_num; |
816 | 3.31k | unsigned char focus; |
817 | | |
818 | 3.31k | hash = ft->ttype ^ ft->tclass; |
819 | | |
820 | 3.31k | byte_num = 0; |
821 | 5.37k | while ((focus = ft->name[byte_num++])) |
822 | 2.06k | hash = partial_name_hash(focus, hash); |
823 | 3.31k | return hash & (h->size - 1); |
824 | 3.31k | } |
825 | | |
826 | | static int filenametr_cmp(hashtab_t h __attribute__ ((unused)), |
827 | | const_hashtab_key_t k1, const_hashtab_key_t k2) |
828 | 4.50k | { |
829 | 4.50k | const filename_trans_key_t *ft1 = (const filename_trans_key_t *)k1; |
830 | 4.50k | const filename_trans_key_t *ft2 = (const filename_trans_key_t *)k2; |
831 | 4.50k | int v; |
832 | | |
833 | 4.50k | v = spaceship_cmp(ft1->ttype, ft2->ttype); |
834 | 4.50k | if (v) |
835 | 2.89k | return v; |
836 | | |
837 | 1.61k | v = spaceship_cmp(ft1->tclass, ft2->tclass); |
838 | 1.61k | if (v) |
839 | 874 | return v; |
840 | | |
841 | 736 | return strcmp(ft1->name, ft2->name); |
842 | | |
843 | 1.61k | } |
844 | | |
845 | | static unsigned int rangetr_hash(hashtab_t h, const_hashtab_key_t k) |
846 | 137 | { |
847 | 137 | const struct range_trans *key = (const struct range_trans *)k; |
848 | 137 | return (key->source_type + (key->target_type << 3) + |
849 | 137 | (key->target_class << 5)) & (h->size - 1); |
850 | 137 | } |
851 | | |
852 | | static int rangetr_cmp(hashtab_t h __attribute__ ((unused)), |
853 | | const_hashtab_key_t k1, const_hashtab_key_t k2) |
854 | 141 | { |
855 | 141 | const struct range_trans *key1 = (const struct range_trans *)k1; |
856 | 141 | const struct range_trans *key2 = (const struct range_trans *)k2; |
857 | 141 | int v; |
858 | | |
859 | 141 | v = spaceship_cmp(key1->source_type, key2->source_type); |
860 | 141 | if (v) |
861 | 72 | return v; |
862 | | |
863 | 69 | v = spaceship_cmp(key1->target_type, key2->target_type); |
864 | 69 | if (v) |
865 | 56 | return v; |
866 | | |
867 | 13 | v = spaceship_cmp(key1->target_class, key2->target_class); |
868 | | |
869 | 13 | return v; |
870 | 69 | } |
871 | | |
872 | | /* |
873 | | * Initialize a policy database structure. |
874 | | */ |
875 | | int policydb_init(policydb_t * p) |
876 | 12.1k | { |
877 | 12.1k | int i, rc; |
878 | | |
879 | 12.1k | memset(p, 0, sizeof(policydb_t)); |
880 | | |
881 | 109k | for (i = 0; i < SYM_NUM; i++) { |
882 | 97.3k | p->sym_val_to_name[i] = NULL; |
883 | 97.3k | rc = symtab_init(&p->symtab[i], symtab_sizes[i]); |
884 | 97.3k | if (rc) |
885 | 0 | goto err; |
886 | 97.3k | } |
887 | | |
888 | | /* initialize the module stuff */ |
889 | 109k | for (i = 0; i < SYM_NUM; i++) { |
890 | 97.3k | if (symtab_init(&p->scope[i], symtab_sizes[i])) { |
891 | 0 | goto err; |
892 | 0 | } |
893 | 97.3k | } |
894 | 12.1k | if ((p->global = avrule_block_create()) == NULL || |
895 | 12.1k | (p->global->branch_list = avrule_decl_create(1)) == NULL) { |
896 | 0 | goto err; |
897 | 0 | } |
898 | 12.1k | p->decl_val_to_struct = NULL; |
899 | | |
900 | 12.1k | rc = avtab_init(&p->te_avtab); |
901 | 12.1k | if (rc) |
902 | 0 | goto err; |
903 | | |
904 | 12.1k | rc = roles_init(p); |
905 | 12.1k | if (rc) |
906 | 0 | goto err; |
907 | | |
908 | 12.1k | rc = cond_policydb_init(p); |
909 | 12.1k | if (rc) |
910 | 0 | goto err; |
911 | | |
912 | 12.1k | p->filename_trans = hashtab_create(filenametr_hash, filenametr_cmp, (1 << 10)); |
913 | 12.1k | if (!p->filename_trans) { |
914 | 0 | rc = -ENOMEM; |
915 | 0 | goto err; |
916 | 0 | } |
917 | | |
918 | 12.1k | p->range_tr = hashtab_create(rangetr_hash, rangetr_cmp, 256); |
919 | 12.1k | if (!p->range_tr) { |
920 | 0 | rc = -ENOMEM; |
921 | 0 | goto err; |
922 | 0 | } |
923 | | |
924 | 12.1k | ebitmap_init(&p->policycaps); |
925 | 12.1k | ebitmap_init(&p->permissive_map); |
926 | | |
927 | 12.1k | return 0; |
928 | 0 | err: |
929 | 0 | hashtab_destroy(p->filename_trans); |
930 | 0 | hashtab_destroy(p->range_tr); |
931 | 0 | for (i = 0; i < SYM_NUM; i++) { |
932 | 0 | hashtab_destroy(p->symtab[i].table); |
933 | 0 | hashtab_destroy(p->scope[i].table); |
934 | 0 | } |
935 | 0 | avrule_block_list_destroy(p->global); |
936 | 0 | return rc; |
937 | 12.1k | } |
938 | | |
939 | | int policydb_role_cache(hashtab_key_t key |
940 | | __attribute__ ((unused)), hashtab_datum_t datum, |
941 | | void *arg) |
942 | 6.71k | { |
943 | 6.71k | policydb_t *p; |
944 | 6.71k | role_datum_t *role; |
945 | | |
946 | 6.71k | role = (role_datum_t *) datum; |
947 | 6.71k | p = (policydb_t *) arg; |
948 | | |
949 | 6.71k | ebitmap_destroy(&role->cache); |
950 | 6.71k | if (type_set_expand(&role->types, &role->cache, p, 1)) { |
951 | 38 | return -1; |
952 | 38 | } |
953 | | |
954 | 6.68k | return 0; |
955 | 6.71k | } |
956 | | |
957 | | int policydb_user_cache(hashtab_key_t key |
958 | | __attribute__ ((unused)), hashtab_datum_t datum, |
959 | | void *arg) |
960 | 1.00k | { |
961 | 1.00k | policydb_t *p; |
962 | 1.00k | user_datum_t *user; |
963 | | |
964 | 1.00k | user = (user_datum_t *) datum; |
965 | 1.00k | p = (policydb_t *) arg; |
966 | | |
967 | 1.00k | ebitmap_destroy(&user->cache); |
968 | 1.00k | if (role_set_expand(&user->roles, &user->cache, p, NULL, NULL)) { |
969 | 0 | return -1; |
970 | 0 | } |
971 | | |
972 | | /* we do not expand user's MLS info in kernel policies because the |
973 | | * semantic representation is not present and we do not expand user's |
974 | | * MLS info in module policies because all of the necessary mls |
975 | | * information is not present */ |
976 | 1.00k | if (p->policy_type != POLICY_KERN && p->policy_type != POLICY_MOD) { |
977 | 324 | mls_range_destroy(&user->exp_range); |
978 | 324 | if (mls_semantic_range_expand(&user->range, |
979 | 324 | &user->exp_range, p, NULL)) { |
980 | 184 | return -1; |
981 | 184 | } |
982 | | |
983 | 140 | mls_level_destroy(&user->exp_dfltlevel); |
984 | 140 | if (mls_semantic_level_expand(&user->dfltlevel, |
985 | 140 | &user->exp_dfltlevel, p, NULL)) { |
986 | 10 | return -1; |
987 | 10 | } |
988 | 140 | } |
989 | | |
990 | 807 | return 0; |
991 | 1.00k | } |
992 | | |
993 | | /* |
994 | | * The following *_index functions are used to |
995 | | * define the val_to_name and val_to_struct arrays |
996 | | * in a policy database structure. The val_to_name |
997 | | * arrays are used when converting security context |
998 | | * structures into string representations. The |
999 | | * val_to_struct arrays are used when the attributes |
1000 | | * of a class, role, or user are needed. |
1001 | | */ |
1002 | | |
1003 | | static int common_index(hashtab_key_t key, hashtab_datum_t datum, void *datap) |
1004 | 138 | { |
1005 | 138 | policydb_t *p; |
1006 | 138 | common_datum_t *comdatum; |
1007 | | |
1008 | 138 | comdatum = (common_datum_t *) datum; |
1009 | 138 | p = (policydb_t *) datap; |
1010 | 138 | if (!value_isvalid(comdatum->s.value, p->p_commons.nprim)) |
1011 | 2 | return -EINVAL; |
1012 | 136 | if (p->p_common_val_to_name[comdatum->s.value - 1] != NULL) |
1013 | 1 | return -EINVAL; |
1014 | 135 | p->p_common_val_to_name[comdatum->s.value - 1] = (char *)key; |
1015 | | |
1016 | 135 | return 0; |
1017 | 136 | } |
1018 | | |
1019 | | static int class_index(hashtab_key_t key, hashtab_datum_t datum, void *datap) |
1020 | 5.94k | { |
1021 | 5.94k | policydb_t *p; |
1022 | 5.94k | class_datum_t *cladatum; |
1023 | | |
1024 | 5.94k | cladatum = (class_datum_t *) datum; |
1025 | 5.94k | p = (policydb_t *) datap; |
1026 | 5.94k | if (!value_isvalid(cladatum->s.value, p->p_classes.nprim)) |
1027 | 1 | return -EINVAL; |
1028 | 5.93k | if (p->p_class_val_to_name[cladatum->s.value - 1] != NULL) |
1029 | 1 | return -EINVAL; |
1030 | 5.93k | p->p_class_val_to_name[cladatum->s.value - 1] = (char *)key; |
1031 | 5.93k | p->class_val_to_struct[cladatum->s.value - 1] = cladatum; |
1032 | | |
1033 | 5.93k | return 0; |
1034 | 5.93k | } |
1035 | | |
1036 | | static int role_index(hashtab_key_t key, hashtab_datum_t datum, void *datap) |
1037 | 5.91k | { |
1038 | 5.91k | policydb_t *p; |
1039 | 5.91k | role_datum_t *role; |
1040 | | |
1041 | 5.91k | role = (role_datum_t *) datum; |
1042 | 5.91k | p = (policydb_t *) datap; |
1043 | 5.91k | if (!value_isvalid(role->s.value, p->p_roles.nprim)) |
1044 | 1 | return -EINVAL; |
1045 | 5.91k | if (p->p_role_val_to_name[role->s.value - 1] != NULL) |
1046 | 1 | return -EINVAL; |
1047 | 5.91k | p->p_role_val_to_name[role->s.value - 1] = (char *)key; |
1048 | 5.91k | p->role_val_to_struct[role->s.value - 1] = role; |
1049 | | |
1050 | 5.91k | return 0; |
1051 | 5.91k | } |
1052 | | |
1053 | | static int type_index(hashtab_key_t key, hashtab_datum_t datum, void *datap) |
1054 | 4.56k | { |
1055 | 4.56k | policydb_t *p; |
1056 | 4.56k | type_datum_t *typdatum; |
1057 | | |
1058 | 4.56k | typdatum = (type_datum_t *) datum; |
1059 | 4.56k | p = (policydb_t *) datap; |
1060 | | |
1061 | 4.56k | if (typdatum->primary) { |
1062 | 2.97k | if (!value_isvalid(typdatum->s.value, p->p_types.nprim)) |
1063 | 43 | return -EINVAL; |
1064 | 2.92k | if (p->p_type_val_to_name[typdatum->s.value - 1] != NULL) |
1065 | 3 | return -EINVAL; |
1066 | 2.92k | p->p_type_val_to_name[typdatum->s.value - 1] = (char *)key; |
1067 | 2.92k | p->type_val_to_struct[typdatum->s.value - 1] = typdatum; |
1068 | 2.92k | } |
1069 | | |
1070 | 4.51k | return 0; |
1071 | 4.56k | } |
1072 | | |
1073 | | static int user_index(hashtab_key_t key, hashtab_datum_t datum, void *datap) |
1074 | 1.01k | { |
1075 | 1.01k | policydb_t *p; |
1076 | 1.01k | user_datum_t *usrdatum; |
1077 | | |
1078 | 1.01k | usrdatum = (user_datum_t *) datum; |
1079 | 1.01k | p = (policydb_t *) datap; |
1080 | | |
1081 | 1.01k | if (!value_isvalid(usrdatum->s.value, p->p_users.nprim)) |
1082 | 1 | return -EINVAL; |
1083 | 1.01k | if (p->p_user_val_to_name[usrdatum->s.value - 1] != NULL) |
1084 | 2 | return -EINVAL; |
1085 | 1.01k | p->p_user_val_to_name[usrdatum->s.value - 1] = (char *)key; |
1086 | 1.01k | p->user_val_to_struct[usrdatum->s.value - 1] = usrdatum; |
1087 | | |
1088 | 1.01k | return 0; |
1089 | 1.01k | } |
1090 | | |
1091 | | static int sens_index(hashtab_key_t key, hashtab_datum_t datum, void *datap) |
1092 | 972 | { |
1093 | 972 | policydb_t *p; |
1094 | 972 | level_datum_t *levdatum; |
1095 | | |
1096 | 972 | levdatum = (level_datum_t *) datum; |
1097 | 972 | p = (policydb_t *) datap; |
1098 | | |
1099 | 972 | if (!levdatum->isalias) { |
1100 | 642 | if (!value_isvalid(levdatum->level->sens, p->p_levels.nprim)) |
1101 | 3 | return -EINVAL; |
1102 | 639 | if (p->p_sens_val_to_name[levdatum->level->sens - 1] != NULL) |
1103 | 1 | return -EINVAL; |
1104 | 638 | p->p_sens_val_to_name[levdatum->level->sens - 1] = (char *)key; |
1105 | 638 | } |
1106 | | |
1107 | 968 | return 0; |
1108 | 972 | } |
1109 | | |
1110 | | static int cat_index(hashtab_key_t key, hashtab_datum_t datum, void *datap) |
1111 | 551 | { |
1112 | 551 | policydb_t *p; |
1113 | 551 | cat_datum_t *catdatum; |
1114 | | |
1115 | 551 | catdatum = (cat_datum_t *) datum; |
1116 | 551 | p = (policydb_t *) datap; |
1117 | | |
1118 | 551 | if (!catdatum->isalias) { |
1119 | 336 | if (!value_isvalid(catdatum->s.value, p->p_cats.nprim)) |
1120 | 4 | return -EINVAL; |
1121 | 332 | if (p->p_cat_val_to_name[catdatum->s.value - 1] != NULL) |
1122 | 1 | return -EINVAL; |
1123 | 331 | p->p_cat_val_to_name[catdatum->s.value - 1] = (char *)key; |
1124 | 331 | } |
1125 | | |
1126 | 546 | return 0; |
1127 | 551 | } |
1128 | | |
1129 | | static int (*const index_f[SYM_NUM]) (hashtab_key_t key, hashtab_datum_t datum, |
1130 | | void *datap) = { |
1131 | | common_index, class_index, role_index, type_index, user_index, |
1132 | | cond_index_bool, sens_index, cat_index,}; |
1133 | | |
1134 | | /* |
1135 | | * Define the common val_to_name array and the class |
1136 | | * val_to_name and val_to_struct arrays in a policy |
1137 | | * database structure. |
1138 | | */ |
1139 | | int policydb_index_classes(policydb_t * p) |
1140 | 5.83k | { |
1141 | 5.83k | free(p->p_common_val_to_name); |
1142 | 5.83k | p->p_common_val_to_name = (char **) |
1143 | 5.83k | calloc(p->p_commons.nprim, sizeof(char *)); |
1144 | 5.83k | if (!p->p_common_val_to_name) |
1145 | 0 | return -1; |
1146 | | |
1147 | 5.83k | if (hashtab_map(p->p_commons.table, common_index, p)) |
1148 | 3 | return -1; |
1149 | | |
1150 | 5.83k | free(p->class_val_to_struct); |
1151 | 5.83k | p->class_val_to_struct = (class_datum_t **) |
1152 | 5.83k | calloc(p->p_classes.nprim, sizeof(class_datum_t *)); |
1153 | 5.83k | if (!p->class_val_to_struct) |
1154 | 0 | return -1; |
1155 | | |
1156 | 5.83k | free(p->p_class_val_to_name); |
1157 | 5.83k | p->p_class_val_to_name = (char **) |
1158 | 5.83k | calloc(p->p_classes.nprim, sizeof(char *)); |
1159 | 5.83k | if (!p->p_class_val_to_name) |
1160 | 0 | return -1; |
1161 | | |
1162 | 5.83k | if (hashtab_map(p->p_classes.table, class_index, p)) |
1163 | 2 | return -1; |
1164 | | |
1165 | 5.83k | return 0; |
1166 | 5.83k | } |
1167 | | |
1168 | | int policydb_index_bools(policydb_t * p) |
1169 | 0 | { |
1170 | |
|
1171 | 0 | if (cond_init_bool_indexes(p) == -1) |
1172 | 0 | return -1; |
1173 | 0 | p->p_bool_val_to_name = (char **) |
1174 | 0 | calloc(p->p_bools.nprim, sizeof(char *)); |
1175 | 0 | if (!p->p_bool_val_to_name) |
1176 | 0 | return -1; |
1177 | 0 | if (hashtab_map(p->p_bools.table, cond_index_bool, p)) |
1178 | 0 | return -1; |
1179 | 0 | return 0; |
1180 | 0 | } |
1181 | | |
1182 | | static int policydb_index_decls(sepol_handle_t * handle, policydb_t * p) |
1183 | 5.65k | { |
1184 | 5.65k | avrule_block_t *curblock; |
1185 | 5.65k | avrule_decl_t *decl; |
1186 | 5.65k | unsigned int num_decls = 0; |
1187 | | |
1188 | 5.65k | free(p->decl_val_to_struct); |
1189 | | |
1190 | 14.5k | for (curblock = p->global; curblock != NULL; curblock = curblock->next) { |
1191 | 14.2k | for (decl = curblock->branch_list; decl != NULL; |
1192 | 8.85k | decl = decl->next) { |
1193 | 5.39k | num_decls++; |
1194 | 5.39k | } |
1195 | 8.85k | } |
1196 | | |
1197 | 5.65k | p->decl_val_to_struct = |
1198 | 5.65k | calloc(num_decls, sizeof(*(p->decl_val_to_struct))); |
1199 | 5.65k | if (!p->decl_val_to_struct) { |
1200 | 0 | return -1; |
1201 | 0 | } |
1202 | | |
1203 | 13.8k | for (curblock = p->global; curblock != NULL; curblock = curblock->next) { |
1204 | 13.3k | for (decl = curblock->branch_list; decl != NULL; |
1205 | 8.18k | decl = decl->next) { |
1206 | 5.15k | if (!value_isvalid(decl->decl_id, num_decls)) { |
1207 | 13 | ERR(handle, "invalid decl ID %u", decl->decl_id); |
1208 | 13 | return -1; |
1209 | 13 | } |
1210 | 5.14k | if (p->decl_val_to_struct[decl->decl_id - 1] != NULL) { |
1211 | 3 | ERR(handle, "duplicated decl ID %u", decl->decl_id); |
1212 | 3 | return -1; |
1213 | 3 | } |
1214 | 5.13k | p->decl_val_to_struct[decl->decl_id - 1] = decl; |
1215 | 5.13k | } |
1216 | 8.18k | } |
1217 | | |
1218 | 5.63k | return 0; |
1219 | 5.65k | } |
1220 | | |
1221 | | /* |
1222 | | * Define the other val_to_name and val_to_struct arrays |
1223 | | * in a policy database structure. |
1224 | | */ |
1225 | | int policydb_index_others(sepol_handle_t * handle, |
1226 | | policydb_t * p, unsigned verbose) |
1227 | 5.98k | { |
1228 | 5.98k | int i; |
1229 | | |
1230 | 5.98k | if (verbose) { |
1231 | 0 | INFO(handle, |
1232 | 0 | "security: %d users, %d roles, %d types, %d bools", |
1233 | 0 | p->p_users.nprim, p->p_roles.nprim, p->p_types.nprim, |
1234 | 0 | p->p_bools.nprim); |
1235 | |
|
1236 | 0 | if (p->mls) |
1237 | 0 | INFO(handle, "security: %d sens, %d cats", |
1238 | 0 | p->p_levels.nprim, p->p_cats.nprim); |
1239 | |
|
1240 | 0 | INFO(handle, "security: %d classes, %d rules, %d cond rules", |
1241 | 0 | p->p_classes.nprim, p->te_avtab.nel, p->te_cond_avtab.nel); |
1242 | 0 | } |
1243 | | #if 0 |
1244 | | avtab_hash_eval(&p->te_avtab, "rules"); |
1245 | | for (i = 0; i < SYM_NUM; i++) |
1246 | | hashtab_hash_eval(p->symtab[i].table, symtab_name[i]); |
1247 | | #endif |
1248 | | |
1249 | 5.98k | free(p->role_val_to_struct); |
1250 | 5.98k | p->role_val_to_struct = (role_datum_t **) |
1251 | 5.98k | calloc(p->p_roles.nprim, sizeof(role_datum_t *)); |
1252 | 5.98k | if (!p->role_val_to_struct) |
1253 | 0 | return -1; |
1254 | | |
1255 | 5.98k | free(p->user_val_to_struct); |
1256 | 5.98k | p->user_val_to_struct = (user_datum_t **) |
1257 | 5.98k | calloc(p->p_users.nprim, sizeof(user_datum_t *)); |
1258 | 5.98k | if (!p->user_val_to_struct) |
1259 | 0 | return -1; |
1260 | | |
1261 | 5.98k | free(p->type_val_to_struct); |
1262 | 5.98k | p->type_val_to_struct = (type_datum_t **) |
1263 | 5.98k | calloc(p->p_types.nprim, sizeof(type_datum_t *)); |
1264 | 5.98k | if (!p->type_val_to_struct) |
1265 | 0 | return -1; |
1266 | | |
1267 | 5.98k | if (cond_init_bool_indexes(p)) |
1268 | 0 | return -1; |
1269 | | |
1270 | 41.4k | for (i = SYM_ROLES; i < SYM_NUM; i++) { |
1271 | 35.5k | free(p->sym_val_to_name[i]); |
1272 | 35.5k | p->sym_val_to_name[i] = NULL; |
1273 | 35.5k | if (p->symtab[i].nprim) { |
1274 | 21.6k | p->sym_val_to_name[i] = (char **) |
1275 | 21.6k | calloc(p->symtab[i].nprim, sizeof(char *)); |
1276 | 21.6k | if (!p->sym_val_to_name[i]) |
1277 | 0 | return -1; |
1278 | 21.6k | if (hashtab_map(p->symtab[i].table, index_f[i], p)) |
1279 | 106 | return -1; |
1280 | 21.6k | } |
1281 | 35.5k | } |
1282 | | |
1283 | | /* This pre-expands the roles and users for context validity checking */ |
1284 | 5.87k | if (hashtab_map(p->p_roles.table, policydb_role_cache, p)) |
1285 | 38 | return -1; |
1286 | | |
1287 | 5.83k | if (hashtab_map(p->p_users.table, policydb_user_cache, p)) |
1288 | 194 | return -1; |
1289 | | |
1290 | 5.64k | return 0; |
1291 | 5.83k | } |
1292 | | |
1293 | | /* |
1294 | | * The following *_destroy functions are used to |
1295 | | * free any memory allocated for each kind of |
1296 | | * symbol data in the policy database. |
1297 | | */ |
1298 | | |
1299 | | static int perm_destroy(hashtab_key_t key, hashtab_datum_t datum, void *p |
1300 | | __attribute__ ((unused))) |
1301 | 7.04k | { |
1302 | 7.04k | if (key) |
1303 | 6.94k | free(key); |
1304 | 7.04k | free(datum); |
1305 | 7.04k | return 0; |
1306 | 7.04k | } |
1307 | | |
1308 | | static int common_destroy(hashtab_key_t key, hashtab_datum_t datum, void *p |
1309 | | __attribute__ ((unused))) |
1310 | 2.73k | { |
1311 | 2.73k | common_datum_t *comdatum; |
1312 | | |
1313 | 2.73k | if (key) |
1314 | 2.36k | free(key); |
1315 | 2.73k | comdatum = (common_datum_t *) datum; |
1316 | 2.73k | (void)hashtab_map(comdatum->permissions.table, perm_destroy, 0); |
1317 | 2.73k | hashtab_destroy(comdatum->permissions.table); |
1318 | 2.73k | free(datum); |
1319 | 2.73k | return 0; |
1320 | 2.73k | } |
1321 | | |
1322 | | static int class_destroy(hashtab_key_t key, hashtab_datum_t datum, void *p |
1323 | | __attribute__ ((unused))) |
1324 | 21.9k | { |
1325 | 21.9k | class_datum_t *cladatum; |
1326 | 21.9k | constraint_node_t *constraint, *ctemp; |
1327 | | |
1328 | 21.9k | if (key) |
1329 | 21.9k | free(key); |
1330 | 21.9k | cladatum = (class_datum_t *) datum; |
1331 | 21.9k | if (cladatum == NULL) { |
1332 | 0 | return 0; |
1333 | 0 | } |
1334 | 21.9k | (void)hashtab_map(cladatum->permissions.table, perm_destroy, 0); |
1335 | 21.9k | hashtab_destroy(cladatum->permissions.table); |
1336 | 21.9k | constraint = cladatum->constraints; |
1337 | 25.3k | while (constraint) { |
1338 | 3.32k | constraint_expr_destroy(constraint->expr); |
1339 | 3.32k | ctemp = constraint; |
1340 | 3.32k | constraint = constraint->next; |
1341 | 3.32k | free(ctemp); |
1342 | 3.32k | } |
1343 | | |
1344 | 21.9k | constraint = cladatum->validatetrans; |
1345 | 22.3k | while (constraint) { |
1346 | 362 | constraint_expr_destroy(constraint->expr); |
1347 | 362 | ctemp = constraint; |
1348 | 362 | constraint = constraint->next; |
1349 | 362 | free(ctemp); |
1350 | 362 | } |
1351 | | |
1352 | 21.9k | if (cladatum->comkey) |
1353 | 143 | free(cladatum->comkey); |
1354 | 21.9k | free(datum); |
1355 | 21.9k | return 0; |
1356 | 21.9k | } |
1357 | | |
1358 | | static int role_destroy(hashtab_key_t key, hashtab_datum_t datum, void *p |
1359 | | __attribute__ ((unused))) |
1360 | 14.3k | { |
1361 | 14.3k | free(key); |
1362 | 14.3k | role_datum_destroy((role_datum_t *) datum); |
1363 | 14.3k | free(datum); |
1364 | 14.3k | return 0; |
1365 | 14.3k | } |
1366 | | |
1367 | | static int type_destroy(hashtab_key_t key, hashtab_datum_t datum, void *p |
1368 | | __attribute__ ((unused))) |
1369 | 5.02k | { |
1370 | 5.02k | free(key); |
1371 | 5.02k | type_datum_destroy((type_datum_t *) datum); |
1372 | 5.02k | free(datum); |
1373 | 5.02k | return 0; |
1374 | 5.02k | } |
1375 | | |
1376 | | static int user_destroy(hashtab_key_t key, hashtab_datum_t datum, void *p |
1377 | | __attribute__ ((unused))) |
1378 | 3.10k | { |
1379 | 3.10k | free(key); |
1380 | 3.10k | user_datum_destroy((user_datum_t *) datum); |
1381 | 3.10k | free(datum); |
1382 | 3.10k | return 0; |
1383 | 3.10k | } |
1384 | | |
1385 | | static int sens_destroy(hashtab_key_t key, hashtab_datum_t datum, void *p |
1386 | | __attribute__ ((unused))) |
1387 | 1.13k | { |
1388 | 1.13k | level_datum_t *levdatum; |
1389 | | |
1390 | 1.13k | if (key) |
1391 | 1.11k | free(key); |
1392 | 1.13k | levdatum = (level_datum_t *) datum; |
1393 | 1.13k | if (!levdatum->isalias || !levdatum->notdefined) { |
1394 | 1.13k | mls_level_destroy(levdatum->level); |
1395 | 1.13k | free(levdatum->level); |
1396 | 1.13k | } |
1397 | 1.13k | level_datum_destroy(levdatum); |
1398 | 1.13k | free(levdatum); |
1399 | 1.13k | return 0; |
1400 | 1.13k | } |
1401 | | |
1402 | | static int cat_destroy(hashtab_key_t key, hashtab_datum_t datum, void *p |
1403 | | __attribute__ ((unused))) |
1404 | 905 | { |
1405 | 905 | if (key) |
1406 | 891 | free(key); |
1407 | 905 | cat_datum_destroy((cat_datum_t *) datum); |
1408 | 905 | free(datum); |
1409 | 905 | return 0; |
1410 | 905 | } |
1411 | | |
1412 | | static int (*const destroy_f[SYM_NUM]) (hashtab_key_t key, hashtab_datum_t datum, |
1413 | | void *datap) = { |
1414 | | common_destroy, class_destroy, role_destroy, type_destroy, user_destroy, |
1415 | | cond_destroy_bool, sens_destroy, cat_destroy,}; |
1416 | | |
1417 | | static int filenametr_destroy(hashtab_key_t key, hashtab_datum_t datum, |
1418 | | void *p __attribute__ ((unused))) |
1419 | 1.48k | { |
1420 | 1.48k | filename_trans_key_t *ft = (filename_trans_key_t *)key; |
1421 | 1.48k | filename_trans_datum_t *fd = datum, *next; |
1422 | | |
1423 | 1.48k | free(ft->name); |
1424 | 1.48k | free(key); |
1425 | 2.60k | do { |
1426 | 2.60k | next = fd->next; |
1427 | 2.60k | ebitmap_destroy(&fd->stypes); |
1428 | 2.60k | free(fd); |
1429 | 2.60k | fd = next; |
1430 | 2.60k | } while (fd); |
1431 | 1.48k | return 0; |
1432 | 1.48k | } |
1433 | | |
1434 | | static int range_tr_destroy(hashtab_key_t key, hashtab_datum_t datum, |
1435 | | void *p __attribute__ ((unused))) |
1436 | 128 | { |
1437 | 128 | struct mls_range *rt = (struct mls_range *)datum; |
1438 | 128 | free(key); |
1439 | 128 | ebitmap_destroy(&rt->level[0].cat); |
1440 | 128 | ebitmap_destroy(&rt->level[1].cat); |
1441 | 128 | free(datum); |
1442 | 128 | return 0; |
1443 | 128 | } |
1444 | | |
1445 | | static void ocontext_selinux_free(ocontext_t **ocontexts) |
1446 | 22.5k | { |
1447 | 22.5k | ocontext_t *c, *ctmp; |
1448 | 22.5k | int i; |
1449 | | |
1450 | 225k | for (i = 0; i < OCON_NUM; i++) { |
1451 | 203k | c = ocontexts[i]; |
1452 | 207k | while (c) { |
1453 | 4.55k | ctmp = c; |
1454 | 4.55k | c = c->next; |
1455 | 4.55k | context_destroy(&ctmp->context[0]); |
1456 | 4.55k | context_destroy(&ctmp->context[1]); |
1457 | 4.55k | if (i == OCON_ISID || i == OCON_FS || i == OCON_NETIF |
1458 | 4.55k | || i == OCON_FSUSE) |
1459 | 3.59k | free(ctmp->u.name); |
1460 | 957 | else if (i == OCON_IBENDPORT) |
1461 | 180 | free(ctmp->u.ibendport.dev_name); |
1462 | 4.55k | free(ctmp); |
1463 | 4.55k | } |
1464 | 203k | } |
1465 | 22.5k | } |
1466 | | |
1467 | | static void ocontext_xen_free(ocontext_t **ocontexts) |
1468 | 1.60k | { |
1469 | 1.60k | ocontext_t *c, *ctmp; |
1470 | 1.60k | int i; |
1471 | | |
1472 | 16.0k | for (i = 0; i < OCON_NUM; i++) { |
1473 | 14.4k | c = ocontexts[i]; |
1474 | 18.2k | while (c) { |
1475 | 3.81k | ctmp = c; |
1476 | 3.81k | c = c->next; |
1477 | 3.81k | context_destroy(&ctmp->context[0]); |
1478 | 3.81k | context_destroy(&ctmp->context[1]); |
1479 | 3.81k | if (i == OCON_ISID || i == OCON_XEN_DEVICETREE) |
1480 | 2.61k | free(ctmp->u.name); |
1481 | 3.81k | free(ctmp); |
1482 | 3.81k | } |
1483 | 14.4k | } |
1484 | 1.60k | } |
1485 | | |
1486 | | /* |
1487 | | * Free any memory allocated by a policy database structure. |
1488 | | */ |
1489 | | void policydb_destroy(policydb_t * p) |
1490 | 24.1k | { |
1491 | 24.1k | ocontext_t *c, *ctmp; |
1492 | 24.1k | genfs_t *g, *gtmp; |
1493 | 24.1k | unsigned int i; |
1494 | 24.1k | role_allow_t *ra, *lra = NULL; |
1495 | 24.1k | role_trans_t *tr, *ltr = NULL; |
1496 | | |
1497 | 24.1k | if (!p) |
1498 | 0 | return; |
1499 | | |
1500 | 24.1k | ebitmap_destroy(&p->policycaps); |
1501 | | |
1502 | 24.1k | ebitmap_destroy(&p->permissive_map); |
1503 | | |
1504 | 24.1k | symtabs_destroy(p->symtab); |
1505 | | |
1506 | 217k | for (i = 0; i < SYM_NUM; i++) { |
1507 | 193k | if (p->sym_val_to_name[i]) |
1508 | 32.3k | free(p->sym_val_to_name[i]); |
1509 | 193k | } |
1510 | | |
1511 | 24.1k | if (p->class_val_to_struct) |
1512 | 5.71k | free(p->class_val_to_struct); |
1513 | 24.1k | if (p->role_val_to_struct) |
1514 | 5.70k | free(p->role_val_to_struct); |
1515 | 24.1k | if (p->user_val_to_struct) |
1516 | 5.70k | free(p->user_val_to_struct); |
1517 | 24.1k | if (p->type_val_to_struct) |
1518 | 5.70k | free(p->type_val_to_struct); |
1519 | 24.1k | free(p->decl_val_to_struct); |
1520 | | |
1521 | 217k | for (i = 0; i < SYM_NUM; i++) { |
1522 | 193k | (void)hashtab_map(p->scope[i].table, scope_destroy, 0); |
1523 | 193k | hashtab_destroy(p->scope[i].table); |
1524 | 193k | } |
1525 | 24.1k | avrule_block_list_destroy(p->global); |
1526 | 24.1k | free(p->name); |
1527 | 24.1k | free(p->version); |
1528 | | |
1529 | 24.1k | avtab_destroy(&p->te_avtab); |
1530 | | |
1531 | 24.1k | if (p->target_platform == SEPOL_TARGET_SELINUX) |
1532 | 22.5k | ocontext_selinux_free(p->ocontexts); |
1533 | 1.60k | else if (p->target_platform == SEPOL_TARGET_XEN) |
1534 | 1.60k | ocontext_xen_free(p->ocontexts); |
1535 | | |
1536 | 24.1k | g = p->genfs; |
1537 | 24.8k | while (g) { |
1538 | 691 | free(g->fstype); |
1539 | 691 | c = g->head; |
1540 | 1.27k | while (c) { |
1541 | 579 | ctmp = c; |
1542 | 579 | c = c->next; |
1543 | 579 | context_destroy(&ctmp->context[0]); |
1544 | 579 | free(ctmp->u.name); |
1545 | 579 | free(ctmp); |
1546 | 579 | } |
1547 | 691 | gtmp = g; |
1548 | 691 | g = g->next; |
1549 | 691 | free(gtmp); |
1550 | 691 | } |
1551 | 24.1k | cond_policydb_destroy(p); |
1552 | | |
1553 | 25.6k | for (tr = p->role_tr; tr; tr = tr->next) { |
1554 | 1.43k | if (ltr) |
1555 | 1.12k | free(ltr); |
1556 | 1.43k | ltr = tr; |
1557 | 1.43k | } |
1558 | 24.1k | if (ltr) |
1559 | 307 | free(ltr); |
1560 | | |
1561 | 25.9k | for (ra = p->role_allow; ra; ra = ra->next) { |
1562 | 1.74k | if (lra) |
1563 | 1.60k | free(lra); |
1564 | 1.74k | lra = ra; |
1565 | 1.74k | } |
1566 | 24.1k | if (lra) |
1567 | 145 | free(lra); |
1568 | | |
1569 | 24.1k | hashtab_map(p->filename_trans, filenametr_destroy, NULL); |
1570 | 24.1k | hashtab_destroy(p->filename_trans); |
1571 | | |
1572 | 24.1k | hashtab_map(p->range_tr, range_tr_destroy, NULL); |
1573 | 24.1k | hashtab_destroy(p->range_tr); |
1574 | | |
1575 | 24.1k | if (p->type_attr_map) { |
1576 | 217k | for (i = 0; i < p->p_types.nprim; i++) { |
1577 | 214k | ebitmap_destroy(&p->type_attr_map[i]); |
1578 | 214k | } |
1579 | 2.87k | free(p->type_attr_map); |
1580 | 2.87k | } |
1581 | | |
1582 | 24.1k | if (p->attr_type_map) { |
1583 | 217k | for (i = 0; i < p->p_types.nprim; i++) { |
1584 | 214k | ebitmap_destroy(&p->attr_type_map[i]); |
1585 | 214k | } |
1586 | 2.87k | free(p->attr_type_map); |
1587 | 2.87k | } |
1588 | | |
1589 | 24.1k | return; |
1590 | 24.1k | } |
1591 | | |
1592 | | void symtabs_destroy(symtab_t * symtab) |
1593 | 45.2k | { |
1594 | 45.2k | int i; |
1595 | 407k | for (i = 0; i < SYM_NUM; i++) { |
1596 | 362k | (void)hashtab_map(symtab[i].table, destroy_f[i], 0); |
1597 | 362k | hashtab_destroy(symtab[i].table); |
1598 | 362k | } |
1599 | 45.2k | } |
1600 | | |
1601 | | int scope_destroy(hashtab_key_t key, hashtab_datum_t datum, void *p |
1602 | | __attribute__ ((unused))) |
1603 | 12.8k | { |
1604 | 12.8k | scope_datum_t *cur = (scope_datum_t *) datum; |
1605 | 12.8k | free(key); |
1606 | 12.8k | if (cur != NULL) { |
1607 | 12.7k | free(cur->decl_ids); |
1608 | 12.7k | } |
1609 | 12.8k | free(cur); |
1610 | 12.8k | return 0; |
1611 | 12.8k | } |
1612 | | |
1613 | | /* |
1614 | | * Load the initial SIDs specified in a policy database |
1615 | | * structure into a SID table. |
1616 | | */ |
1617 | | int policydb_load_isids(policydb_t * p, sidtab_t * s) |
1618 | 937 | { |
1619 | 937 | ocontext_t *head, *c; |
1620 | | |
1621 | 937 | if (sepol_sidtab_init(s)) { |
1622 | 0 | ERR(NULL, "out of memory on SID table init"); |
1623 | 0 | return -1; |
1624 | 0 | } |
1625 | | |
1626 | 937 | head = p->ocontexts[OCON_ISID]; |
1627 | 1.20k | for (c = head; c; c = c->next) { |
1628 | 275 | if (sepol_sidtab_insert(s, c->sid[0], &c->context[0])) { |
1629 | 5 | ERR(NULL, "unable to load initial SID %s", c->u.name); |
1630 | 5 | return -1; |
1631 | 5 | } |
1632 | 275 | } |
1633 | | |
1634 | 932 | return 0; |
1635 | 937 | } |
1636 | | |
1637 | | /* Declare a symbol for a certain avrule_block context. Insert it |
1638 | | * into a symbol table for a policy. This function will handle |
1639 | | * inserting the appropriate scope information in addition to |
1640 | | * inserting the symbol into the hash table. |
1641 | | * |
1642 | | * arguments: |
1643 | | * policydb_t *pol module policy to modify |
1644 | | * uint32_t sym the symbole table for insertion (SYM_*) |
1645 | | * hashtab_key_t key the key for the symbol - not cloned |
1646 | | * hashtab_datum_t data the data for the symbol - not cloned |
1647 | | * scope scope of this symbol, either SCOPE_REQ or SCOPE_DECL |
1648 | | * avrule_decl_id identifier for this symbol's encapsulating declaration |
1649 | | * value (out) assigned value to the symbol (if value is not NULL) |
1650 | | * |
1651 | | * returns: |
1652 | | * 0 success |
1653 | | * 1 success, but symbol already existed as a requirement |
1654 | | * (datum was not inserted and needs to be free()d) |
1655 | | * -1 general error |
1656 | | * -2 scope conflicted |
1657 | | * -ENOMEM memory error |
1658 | | * error codes from hashtab_insert |
1659 | | */ |
1660 | | int symtab_insert(policydb_t * pol, uint32_t sym, |
1661 | | hashtab_key_t key, hashtab_datum_t datum, |
1662 | | uint32_t scope, uint32_t avrule_decl_id, uint32_t * value) |
1663 | 12.1k | { |
1664 | 12.1k | int rc, retval = 0; |
1665 | 12.1k | unsigned int i; |
1666 | 12.1k | scope_datum_t *scope_datum; |
1667 | | |
1668 | | /* check if the symbol is already there. multiple |
1669 | | * declarations of non-roles/non-users are illegal, but |
1670 | | * multiple requires are allowed. */ |
1671 | | |
1672 | | /* FIX ME - the failures after the hashtab_insert will leave |
1673 | | * the policy in a inconsistent state. */ |
1674 | 12.1k | rc = hashtab_insert(pol->symtab[sym].table, key, datum); |
1675 | 12.1k | if (rc == SEPOL_OK) { |
1676 | | /* if no value is passed in the symbol is not primary |
1677 | | * (i.e. aliases) */ |
1678 | 12.1k | if (value) |
1679 | 12.1k | *value = ++pol->symtab[sym].nprim; |
1680 | 12.1k | } else if (rc == SEPOL_EEXIST) { |
1681 | 0 | retval = 1; /* symbol not added -- need to free() later */ |
1682 | 0 | } else { |
1683 | 0 | return rc; |
1684 | 0 | } |
1685 | | |
1686 | | /* get existing scope information; if there is not one then |
1687 | | * create it */ |
1688 | 12.1k | scope_datum = |
1689 | 12.1k | (scope_datum_t *) hashtab_search(pol->scope[sym].table, key); |
1690 | 12.1k | if (scope_datum == NULL) { |
1691 | 12.1k | hashtab_key_t key2 = strdup((char *)key); |
1692 | 12.1k | if (!key2) |
1693 | 0 | return -ENOMEM; |
1694 | 12.1k | if ((scope_datum = malloc(sizeof(*scope_datum))) == NULL) { |
1695 | 0 | free(key2); |
1696 | 0 | return -ENOMEM; |
1697 | 0 | } |
1698 | 12.1k | scope_datum->scope = scope; |
1699 | 12.1k | scope_datum->decl_ids = NULL; |
1700 | 12.1k | scope_datum->decl_ids_len = 0; |
1701 | 12.1k | if ((rc = |
1702 | 12.1k | hashtab_insert(pol->scope[sym].table, key2, |
1703 | 12.1k | scope_datum)) != 0) { |
1704 | 0 | free(key2); |
1705 | 0 | free(scope_datum); |
1706 | 0 | return rc; |
1707 | 0 | } |
1708 | 12.1k | } else if (scope_datum->scope == SCOPE_DECL && scope == SCOPE_DECL) { |
1709 | | /* disallow multiple declarations for non-roles/users */ |
1710 | 0 | if (sym != SYM_ROLES && sym != SYM_USERS) { |
1711 | 0 | return -2; |
1712 | 0 | } |
1713 | | /* Further confine that a role attribute can't have the same |
1714 | | * name as another regular role, and a role attribute can't |
1715 | | * be declared more than once. */ |
1716 | 0 | if (sym == SYM_ROLES) { |
1717 | 0 | role_datum_t *base_role; |
1718 | 0 | role_datum_t *cur_role = (role_datum_t *)datum; |
1719 | | |
1720 | 0 | base_role = (role_datum_t *) |
1721 | 0 | hashtab_search(pol->symtab[sym].table, |
1722 | 0 | key); |
1723 | 0 | assert(base_role != NULL); |
1724 | | |
1725 | 0 | if (!((base_role->flavor == ROLE_ROLE) && |
1726 | 0 | (cur_role->flavor == ROLE_ROLE))) { |
1727 | | /* Only regular roles are allowed to have |
1728 | | * multiple declarations. */ |
1729 | 0 | return -2; |
1730 | 0 | } |
1731 | 0 | } |
1732 | 0 | } else if (scope_datum->scope == SCOPE_REQ && scope == SCOPE_DECL) { |
1733 | 0 | scope_datum->scope = SCOPE_DECL; |
1734 | 0 | } |
1735 | | |
1736 | | /* search through the pre-existing list to avoid adding duplicates */ |
1737 | 12.1k | for (i = 0; i < scope_datum->decl_ids_len; i++) { |
1738 | 0 | if (scope_datum->decl_ids[i] == avrule_decl_id) { |
1739 | | /* already there, so don't modify its scope */ |
1740 | 0 | return retval; |
1741 | 0 | } |
1742 | 0 | } |
1743 | | |
1744 | 12.1k | if (add_i_to_a(avrule_decl_id, |
1745 | 12.1k | &scope_datum->decl_ids_len, |
1746 | 12.1k | &scope_datum->decl_ids) == -1) { |
1747 | 0 | return -ENOMEM; |
1748 | 0 | } |
1749 | | |
1750 | 12.1k | if (scope_datum->scope == SCOPE_DECL && scope == SCOPE_REQ) { |
1751 | | /* Need to keep the decl at the end of the list */ |
1752 | 0 | uint32_t len, tmp; |
1753 | 0 | len = scope_datum->decl_ids_len; |
1754 | 0 | if (len < 2) { |
1755 | | /* This should be impossible here */ |
1756 | 0 | return -1; |
1757 | 0 | } |
1758 | 0 | tmp = scope_datum->decl_ids[len-2]; |
1759 | 0 | scope_datum->decl_ids[len-2] = scope_datum->decl_ids[len-1]; |
1760 | 0 | scope_datum->decl_ids[len-1] = tmp; |
1761 | 0 | } |
1762 | | |
1763 | 12.1k | return retval; |
1764 | 12.1k | } |
1765 | | |
1766 | | static int type_set_or(type_set_t * dst, const type_set_t * a, const type_set_t * b) |
1767 | 0 | { |
1768 | 0 | type_set_init(dst); |
1769 | |
|
1770 | 0 | if (ebitmap_or(&dst->types, &a->types, &b->types)) { |
1771 | 0 | return -1; |
1772 | 0 | } |
1773 | 0 | if (ebitmap_or(&dst->negset, &a->negset, &b->negset)) { |
1774 | 0 | return -1; |
1775 | 0 | } |
1776 | | |
1777 | 0 | dst->flags |= a->flags; |
1778 | 0 | dst->flags |= b->flags; |
1779 | |
|
1780 | 0 | return 0; |
1781 | 0 | } |
1782 | | |
1783 | | int type_set_cpy(type_set_t * dst, const type_set_t * src) |
1784 | 0 | { |
1785 | 0 | type_set_init(dst); |
1786 | |
|
1787 | 0 | dst->flags = src->flags; |
1788 | 0 | if (ebitmap_cpy(&dst->types, &src->types)) |
1789 | 0 | return -1; |
1790 | 0 | if (ebitmap_cpy(&dst->negset, &src->negset)) |
1791 | 0 | return -1; |
1792 | | |
1793 | 0 | return 0; |
1794 | 0 | } |
1795 | | |
1796 | | int type_set_or_eq(type_set_t * dst, const type_set_t * other) |
1797 | 0 | { |
1798 | 0 | int ret; |
1799 | 0 | type_set_t tmp; |
1800 | |
|
1801 | 0 | if (type_set_or(&tmp, dst, other)) |
1802 | 0 | return -1; |
1803 | 0 | type_set_destroy(dst); |
1804 | 0 | ret = type_set_cpy(dst, &tmp); |
1805 | 0 | type_set_destroy(&tmp); |
1806 | |
|
1807 | 0 | return ret; |
1808 | 0 | } |
1809 | | |
1810 | | /***********************************************************************/ |
1811 | | /* everything below is for policy reads */ |
1812 | | |
1813 | | /* The following are read functions for module structures */ |
1814 | | |
1815 | | static int role_set_read(role_set_t * r, struct policy_file *fp) |
1816 | 3.09k | { |
1817 | 3.09k | uint32_t buf[1]; |
1818 | 3.09k | int rc; |
1819 | | |
1820 | 3.09k | if (ebitmap_read(&r->roles, fp)) |
1821 | 127 | return -1; |
1822 | 2.96k | rc = next_entry(buf, fp, sizeof(uint32_t)); |
1823 | 2.96k | if (rc < 0) |
1824 | 4 | return -1; |
1825 | 2.96k | r->flags = le32_to_cpu(buf[0]); |
1826 | | |
1827 | 2.96k | return 0; |
1828 | 2.96k | } |
1829 | | |
1830 | | static int type_set_read(type_set_t * t, struct policy_file *fp) |
1831 | 7.94k | { |
1832 | 7.94k | uint32_t buf[1]; |
1833 | 7.94k | int rc; |
1834 | | |
1835 | 7.94k | if (ebitmap_read(&t->types, fp)) |
1836 | 114 | return -1; |
1837 | 7.83k | if (ebitmap_read(&t->negset, fp)) |
1838 | 23 | return -1; |
1839 | | |
1840 | 7.80k | rc = next_entry(buf, fp, sizeof(uint32_t)); |
1841 | 7.80k | if (rc < 0) |
1842 | 12 | return -1; |
1843 | 7.79k | t->flags = le32_to_cpu(buf[0]); |
1844 | | |
1845 | 7.79k | return 0; |
1846 | 7.80k | } |
1847 | | |
1848 | | /* |
1849 | | * Read a MLS range structure from a policydb binary |
1850 | | * representation file. |
1851 | | */ |
1852 | | static int mls_read_range_helper(mls_range_t * r, struct policy_file *fp) |
1853 | 6.46k | { |
1854 | 6.46k | uint32_t buf[2], items; |
1855 | 6.46k | int rc; |
1856 | | |
1857 | 6.46k | rc = next_entry(buf, fp, sizeof(uint32_t)); |
1858 | 6.46k | if (rc < 0) |
1859 | 38 | goto out; |
1860 | | |
1861 | 6.43k | items = le32_to_cpu(buf[0]); |
1862 | 6.43k | if (items > ARRAY_SIZE(buf)) { |
1863 | 42 | ERR(fp->handle, "range overflow"); |
1864 | 42 | rc = -EINVAL; |
1865 | 42 | goto out; |
1866 | 42 | } |
1867 | 6.38k | rc = next_entry(buf, fp, sizeof(uint32_t) * items); |
1868 | 6.38k | if (rc < 0) { |
1869 | 2 | ERR(fp->handle, "truncated range"); |
1870 | 2 | goto out; |
1871 | 2 | } |
1872 | 6.38k | r->level[0].sens = le32_to_cpu(buf[0]); |
1873 | 6.38k | if (items > 1) |
1874 | 374 | r->level[1].sens = le32_to_cpu(buf[1]); |
1875 | 6.01k | else |
1876 | 6.01k | r->level[1].sens = r->level[0].sens; |
1877 | | |
1878 | 6.38k | rc = ebitmap_read(&r->level[0].cat, fp); |
1879 | 6.38k | if (rc) { |
1880 | 16 | ERR(fp->handle, "error reading low categories"); |
1881 | 16 | goto out; |
1882 | 16 | } |
1883 | 6.37k | if (items > 1) { |
1884 | 367 | rc = ebitmap_read(&r->level[1].cat, fp); |
1885 | 367 | if (rc) { |
1886 | 2 | ERR(fp->handle, "error reading high categories"); |
1887 | 2 | goto bad_high; |
1888 | 2 | } |
1889 | 6.00k | } else { |
1890 | 6.00k | rc = ebitmap_cpy(&r->level[1].cat, &r->level[0].cat); |
1891 | 6.00k | if (rc) { |
1892 | 0 | ERR(fp->handle, "out of memory"); |
1893 | 0 | goto bad_high; |
1894 | 0 | } |
1895 | 6.00k | } |
1896 | | |
1897 | 6.36k | rc = 0; |
1898 | 6.46k | out: |
1899 | 6.46k | return rc; |
1900 | 2 | bad_high: |
1901 | 2 | ebitmap_destroy(&r->level[0].cat); |
1902 | 2 | goto out; |
1903 | 6.36k | } |
1904 | | |
1905 | | /* |
1906 | | * Read a semantic MLS level structure from a policydb binary |
1907 | | * representation file. |
1908 | | */ |
1909 | | static int mls_read_semantic_level_helper(mls_semantic_level_t * l, |
1910 | | struct policy_file *fp) |
1911 | 7.61k | { |
1912 | 7.61k | uint32_t buf[2], ncat; |
1913 | 7.61k | unsigned int i; |
1914 | 7.61k | mls_semantic_cat_t *cat; |
1915 | 7.61k | int rc; |
1916 | | |
1917 | 7.61k | mls_semantic_level_init(l); |
1918 | | |
1919 | 7.61k | rc = next_entry(buf, fp, sizeof(uint32_t) * 2); |
1920 | 7.61k | if (rc < 0) { |
1921 | 37 | ERR(fp->handle, "truncated level"); |
1922 | 37 | goto bad; |
1923 | 37 | } |
1924 | 7.57k | l->sens = le32_to_cpu(buf[0]); |
1925 | | |
1926 | 7.57k | ncat = le32_to_cpu(buf[1]); |
1927 | 24.4k | for (i = 0; i < ncat; i++) { |
1928 | 16.9k | cat = (mls_semantic_cat_t *) malloc(sizeof(mls_semantic_cat_t)); |
1929 | 16.9k | if (!cat) { |
1930 | 0 | ERR(fp->handle, "out of memory"); |
1931 | 0 | goto bad; |
1932 | 0 | } |
1933 | | |
1934 | 16.9k | mls_semantic_cat_init(cat); |
1935 | 16.9k | cat->next = l->cat; |
1936 | 16.9k | l->cat = cat; |
1937 | | |
1938 | 16.9k | rc = next_entry(buf, fp, sizeof(uint32_t) * 2); |
1939 | 16.9k | if (rc < 0) { |
1940 | 72 | ERR(fp->handle, "error reading level categories"); |
1941 | 72 | goto bad; |
1942 | 72 | } |
1943 | 16.8k | cat->low = le32_to_cpu(buf[0]); |
1944 | 16.8k | cat->high = le32_to_cpu(buf[1]); |
1945 | 16.8k | } |
1946 | | |
1947 | 7.50k | return 0; |
1948 | | |
1949 | 109 | bad: |
1950 | 109 | return -EINVAL; |
1951 | 7.57k | } |
1952 | | |
1953 | | /* |
1954 | | * Read a semantic MLS range structure from a policydb binary |
1955 | | * representation file. |
1956 | | */ |
1957 | | static int mls_read_semantic_range_helper(mls_semantic_range_t * r, |
1958 | | struct policy_file *fp) |
1959 | 2.97k | { |
1960 | 2.97k | int rc; |
1961 | | |
1962 | 2.97k | rc = mls_read_semantic_level_helper(&r->level[0], fp); |
1963 | 2.97k | if (rc) |
1964 | 71 | return rc; |
1965 | | |
1966 | 2.90k | rc = mls_read_semantic_level_helper(&r->level[1], fp); |
1967 | | |
1968 | 2.90k | return rc; |
1969 | 2.97k | } |
1970 | | |
1971 | | static int mls_level_to_semantic(mls_level_t * l, mls_semantic_level_t * sl) |
1972 | 939 | { |
1973 | 939 | unsigned int i; |
1974 | 939 | ebitmap_node_t *cnode; |
1975 | 939 | mls_semantic_cat_t *open_cat = NULL; |
1976 | | |
1977 | 939 | mls_semantic_level_init(sl); |
1978 | 939 | sl->sens = l->sens; |
1979 | 55.9k | ebitmap_for_each_bit(&l->cat, cnode, i) { |
1980 | 55.9k | if (ebitmap_node_get_bit(cnode, i)) { |
1981 | 20.2k | if (open_cat) |
1982 | 12.8k | continue; |
1983 | 7.43k | open_cat = (mls_semantic_cat_t *) |
1984 | 7.43k | malloc(sizeof(mls_semantic_cat_t)); |
1985 | 7.43k | if (!open_cat) |
1986 | 0 | return -1; |
1987 | | |
1988 | 7.43k | mls_semantic_cat_init(open_cat); |
1989 | 7.43k | open_cat->low = i + 1; |
1990 | 7.43k | open_cat->next = sl->cat; |
1991 | 7.43k | sl->cat = open_cat; |
1992 | 35.6k | } else { |
1993 | 35.6k | if (!open_cat) |
1994 | 28.3k | continue; |
1995 | 7.34k | open_cat->high = i; |
1996 | 7.34k | open_cat = NULL; |
1997 | 7.34k | } |
1998 | 55.9k | } |
1999 | 939 | if (open_cat) |
2000 | 91 | open_cat->high = i; |
2001 | | |
2002 | 939 | return 0; |
2003 | 939 | } |
2004 | | |
2005 | | static int mls_range_to_semantic(mls_range_t * r, mls_semantic_range_t * sr) |
2006 | 313 | { |
2007 | 313 | if (mls_level_to_semantic(&r->level[0], &sr->level[0])) |
2008 | 0 | return -1; |
2009 | | |
2010 | 313 | if (mls_level_to_semantic(&r->level[1], &sr->level[1])) |
2011 | 0 | return -1; |
2012 | | |
2013 | 313 | return 0; |
2014 | 313 | } |
2015 | | |
2016 | | /* |
2017 | | * Read and validate a security context structure |
2018 | | * from a policydb binary representation file. |
2019 | | */ |
2020 | | static int context_read_and_validate(context_struct_t * c, |
2021 | | policydb_t * p, struct policy_file *fp) |
2022 | 9.19k | { |
2023 | 9.19k | uint32_t buf[3]; |
2024 | 9.19k | int rc; |
2025 | | |
2026 | 9.19k | rc = next_entry(buf, fp, sizeof(uint32_t) * 3); |
2027 | 9.19k | if (rc < 0) { |
2028 | 139 | ERR(fp->handle, "context truncated"); |
2029 | 139 | return -1; |
2030 | 139 | } |
2031 | 9.05k | c->user = le32_to_cpu(buf[0]); |
2032 | 9.05k | c->role = le32_to_cpu(buf[1]); |
2033 | 9.05k | c->type = le32_to_cpu(buf[2]); |
2034 | 9.05k | if ((p->policy_type == POLICY_KERN |
2035 | 9.05k | && p->policyvers >= POLICYDB_VERSION_MLS) |
2036 | 9.05k | || (p->policy_type == POLICY_BASE |
2037 | 5.30k | && p->policyvers >= MOD_POLICYDB_VERSION_MLS)) { |
2038 | 5.30k | if (mls_read_range_helper(&c->range, fp)) { |
2039 | 30 | ERR(fp->handle, "error reading MLS range " |
2040 | 30 | "of context"); |
2041 | 30 | return -1; |
2042 | 30 | } |
2043 | 5.30k | } |
2044 | | |
2045 | 9.02k | if (!policydb_context_isvalid(p, c)) { |
2046 | 396 | ERR(fp->handle, "invalid security context"); |
2047 | 396 | context_destroy(c); |
2048 | 396 | return -1; |
2049 | 396 | } |
2050 | 8.63k | return 0; |
2051 | 9.02k | } |
2052 | | |
2053 | | /* |
2054 | | * The following *_read functions are used to |
2055 | | * read the symbol data from a policy database |
2056 | | * binary representation file. |
2057 | | */ |
2058 | | |
2059 | | static int perm_read(policydb_t * p |
2060 | | __attribute__ ((unused)), hashtab_t h, |
2061 | | struct policy_file *fp, uint32_t nprim) |
2062 | 7.04k | { |
2063 | 7.04k | char *key = 0; |
2064 | 7.04k | perm_datum_t *perdatum; |
2065 | 7.04k | uint32_t buf[2]; |
2066 | 7.04k | size_t len; |
2067 | 7.04k | int rc; |
2068 | | |
2069 | 7.04k | perdatum = calloc(1, sizeof(perm_datum_t)); |
2070 | 7.04k | if (!perdatum) |
2071 | 0 | return -1; |
2072 | | |
2073 | 7.04k | rc = next_entry(buf, fp, sizeof(uint32_t) * 2); |
2074 | 7.04k | if (rc < 0) |
2075 | 88 | goto bad; |
2076 | | |
2077 | 6.95k | len = le32_to_cpu(buf[0]); |
2078 | 6.95k | if(str_read(&key, fp, len)) |
2079 | 10 | goto bad; |
2080 | | |
2081 | 6.94k | perdatum->s.value = le32_to_cpu(buf[1]); |
2082 | 6.94k | if (!value_isvalid(perdatum->s.value, nprim)) |
2083 | 68 | goto bad; |
2084 | | |
2085 | 6.87k | if (hashtab_insert(h, key, perdatum)) |
2086 | 3 | goto bad; |
2087 | | |
2088 | 6.87k | return 0; |
2089 | | |
2090 | 169 | bad: |
2091 | 169 | perm_destroy(key, perdatum, NULL); |
2092 | 169 | return -1; |
2093 | 6.87k | } |
2094 | | |
2095 | | static int common_read(policydb_t * p, hashtab_t h, struct policy_file *fp) |
2096 | 2.73k | { |
2097 | 2.73k | char *key = 0; |
2098 | 2.73k | common_datum_t *comdatum; |
2099 | 2.73k | uint32_t buf[4]; |
2100 | 2.73k | size_t len, nel; |
2101 | 2.73k | unsigned int i; |
2102 | 2.73k | int rc; |
2103 | | |
2104 | 2.73k | comdatum = calloc(1, sizeof(common_datum_t)); |
2105 | 2.73k | if (!comdatum) |
2106 | 0 | return -1; |
2107 | | |
2108 | 2.73k | rc = next_entry(buf, fp, sizeof(uint32_t) * 4); |
2109 | 2.73k | if (rc < 0) |
2110 | 374 | goto bad; |
2111 | | |
2112 | 2.36k | len = le32_to_cpu(buf[0]); |
2113 | 2.36k | rc = str_read(&key, fp, len); |
2114 | 2.36k | if (rc < 0) |
2115 | 3 | goto bad; |
2116 | | |
2117 | 2.36k | comdatum->s.value = le32_to_cpu(buf[1]); |
2118 | | |
2119 | 2.36k | if (symtab_init(&comdatum->permissions, PERM_SYMTAB_SIZE)) |
2120 | 0 | goto bad; |
2121 | 2.36k | comdatum->permissions.nprim = le32_to_cpu(buf[2]); |
2122 | 2.36k | if (comdatum->permissions.nprim > PERM_SYMTAB_SIZE) |
2123 | 39 | goto bad; |
2124 | 2.32k | nel = le32_to_cpu(buf[3]); |
2125 | | |
2126 | 2.74k | for (i = 0; i < nel; i++) { |
2127 | 574 | if (perm_read(p, comdatum->permissions.table, fp, comdatum->permissions.nprim)) |
2128 | 149 | goto bad; |
2129 | 574 | } |
2130 | | |
2131 | 2.17k | if (hashtab_insert(h, key, comdatum)) |
2132 | 8 | goto bad; |
2133 | | |
2134 | 2.16k | return 0; |
2135 | | |
2136 | 573 | bad: |
2137 | 573 | common_destroy(key, comdatum, NULL); |
2138 | 573 | return -1; |
2139 | 2.17k | } |
2140 | | |
2141 | | static int read_cons_helper(policydb_t * p, constraint_node_t ** nodep, |
2142 | | unsigned int ncons, |
2143 | | int allowxtarget, struct policy_file *fp) |
2144 | 42.4k | { |
2145 | 42.4k | constraint_node_t *c, *lc; |
2146 | 42.4k | constraint_expr_t *e, *le; |
2147 | 42.4k | uint32_t buf[3]; |
2148 | 42.4k | size_t nexpr; |
2149 | 42.4k | unsigned int i, j; |
2150 | 42.4k | int rc, depth; |
2151 | | |
2152 | 42.4k | lc = NULL; |
2153 | 45.8k | for (i = 0; i < ncons; i++) { |
2154 | 3.68k | c = calloc(1, sizeof(constraint_node_t)); |
2155 | 3.68k | if (!c) |
2156 | 0 | return -1; |
2157 | | |
2158 | 3.68k | if (lc) |
2159 | 1.00k | lc->next = c; |
2160 | 2.68k | else |
2161 | 2.68k | *nodep = c; |
2162 | | |
2163 | 3.68k | rc = next_entry(buf, fp, (sizeof(uint32_t) * 2)); |
2164 | 3.68k | if (rc < 0) |
2165 | 86 | return -1; |
2166 | 3.60k | c->permissions = le32_to_cpu(buf[0]); |
2167 | 3.60k | nexpr = le32_to_cpu(buf[1]); |
2168 | 3.60k | le = NULL; |
2169 | 3.60k | depth = -1; |
2170 | 8.96k | for (j = 0; j < nexpr; j++) { |
2171 | 5.51k | e = malloc(sizeof(constraint_expr_t)); |
2172 | 5.51k | if (!e) |
2173 | 0 | return -1; |
2174 | 5.51k | if (constraint_expr_init(e) == -1) { |
2175 | 0 | free(e); |
2176 | 0 | return -1; |
2177 | 0 | } |
2178 | 5.51k | if (le) { |
2179 | 1.91k | le->next = e; |
2180 | 3.60k | } else { |
2181 | 3.60k | c->expr = e; |
2182 | 3.60k | } |
2183 | | |
2184 | 5.51k | rc = next_entry(buf, fp, (sizeof(uint32_t) * 3)); |
2185 | 5.51k | if (rc < 0) |
2186 | 106 | return -1; |
2187 | 5.41k | e->expr_type = le32_to_cpu(buf[0]); |
2188 | 5.41k | e->attr = le32_to_cpu(buf[1]); |
2189 | 5.41k | e->op = le32_to_cpu(buf[2]); |
2190 | | |
2191 | 5.41k | switch (e->expr_type) { |
2192 | 354 | case CEXPR_NOT: |
2193 | 354 | if (depth < 0) |
2194 | 1 | return -1; |
2195 | 353 | break; |
2196 | 353 | case CEXPR_AND: |
2197 | 706 | case CEXPR_OR: |
2198 | 706 | if (depth < 1) |
2199 | 14 | return -1; |
2200 | 692 | depth--; |
2201 | 692 | break; |
2202 | 3.86k | case CEXPR_ATTR: |
2203 | 3.86k | if (depth == (CEXPR_MAXDEPTH - 1)) |
2204 | 1 | return -1; |
2205 | 3.86k | depth++; |
2206 | 3.86k | break; |
2207 | 479 | case CEXPR_NAMES: |
2208 | 479 | if (!allowxtarget && (e->attr & CEXPR_XTARGET)) |
2209 | 1 | return -1; |
2210 | 478 | if (depth == (CEXPR_MAXDEPTH - 1)) |
2211 | 3 | return -1; |
2212 | 475 | depth++; |
2213 | 475 | if (ebitmap_read(&e->names, fp)) |
2214 | 16 | return -1; |
2215 | 459 | if (p->policy_type != POLICY_KERN && |
2216 | 459 | type_set_read(e->type_names, fp)) |
2217 | 5 | return -1; |
2218 | 454 | else if (p->policy_type == POLICY_KERN && |
2219 | 454 | p->policyvers >= POLICYDB_VERSION_CONSTRAINT_NAMES && |
2220 | 454 | type_set_read(e->type_names, fp)) |
2221 | 6 | return -1; |
2222 | 448 | break; |
2223 | 448 | default: |
2224 | 5 | return -1; |
2225 | 5.41k | } |
2226 | 5.35k | le = e; |
2227 | 5.35k | } |
2228 | 3.44k | if (depth != 0) |
2229 | 5 | return -1; |
2230 | 3.44k | lc = c; |
2231 | 3.44k | } |
2232 | | |
2233 | 42.2k | return 0; |
2234 | 42.4k | } |
2235 | | |
2236 | | static int class_read(policydb_t * p, hashtab_t h, struct policy_file *fp) |
2237 | 21.9k | { |
2238 | 21.9k | char *key = 0; |
2239 | 21.9k | class_datum_t *cladatum; |
2240 | 21.9k | uint32_t buf[6]; |
2241 | 21.9k | size_t len, len2, ncons, nel; |
2242 | 21.9k | unsigned int i; |
2243 | 21.9k | int rc; |
2244 | | |
2245 | 21.9k | cladatum = (class_datum_t *) calloc(1, sizeof(class_datum_t)); |
2246 | 21.9k | if (!cladatum) |
2247 | 0 | return -1; |
2248 | | |
2249 | 21.9k | rc = next_entry(buf, fp, sizeof(uint32_t) * 6); |
2250 | 21.9k | if (rc < 0) |
2251 | 50 | goto bad; |
2252 | | |
2253 | 21.9k | len = le32_to_cpu(buf[0]); |
2254 | 21.9k | rc = str_read(&key, fp, len); |
2255 | 21.9k | if (rc < 0) |
2256 | 5 | goto bad; |
2257 | | |
2258 | 21.9k | len2 = le32_to_cpu(buf[1]); |
2259 | 21.9k | cladatum->s.value = le32_to_cpu(buf[2]); |
2260 | 21.9k | if (cladatum->s.value > UINT16_MAX) |
2261 | 21 | goto bad; |
2262 | | |
2263 | 21.9k | if (symtab_init(&cladatum->permissions, PERM_SYMTAB_SIZE)) |
2264 | 0 | goto bad; |
2265 | 21.9k | cladatum->permissions.nprim = le32_to_cpu(buf[3]); |
2266 | 21.9k | if (cladatum->permissions.nprim > PERM_SYMTAB_SIZE) |
2267 | 36 | goto bad; |
2268 | 21.8k | nel = le32_to_cpu(buf[4]); |
2269 | | |
2270 | 21.8k | ncons = le32_to_cpu(buf[5]); |
2271 | | |
2272 | 21.8k | if (len2) { |
2273 | 188 | rc = str_read(&cladatum->comkey, fp, len2); |
2274 | 188 | if (rc < 0) |
2275 | 45 | goto bad; |
2276 | | |
2277 | 143 | cladatum->comdatum = hashtab_search(p->p_commons.table, |
2278 | 143 | cladatum->comkey); |
2279 | 143 | if (!cladatum->comdatum) { |
2280 | 113 | ERR(fp->handle, "unknown common %s", cladatum->comkey); |
2281 | 113 | goto bad; |
2282 | 113 | } |
2283 | 143 | } |
2284 | 28.1k | for (i = 0; i < nel; i++) { |
2285 | 6.46k | if (perm_read(p, cladatum->permissions.table, fp, cladatum->permissions.nprim)) |
2286 | 20 | goto bad; |
2287 | 6.46k | } |
2288 | | |
2289 | 21.6k | if (read_cons_helper(p, &cladatum->constraints, ncons, 0, fp)) |
2290 | 225 | goto bad; |
2291 | | |
2292 | 21.4k | if ((p->policy_type == POLICY_KERN |
2293 | 21.4k | && p->policyvers >= POLICYDB_VERSION_VALIDATETRANS) |
2294 | 21.4k | || (p->policy_type == POLICY_BASE |
2295 | 20.7k | && p->policyvers >= MOD_POLICYDB_VERSION_VALIDATETRANS)) { |
2296 | | /* grab the validatetrans rules */ |
2297 | 20.7k | rc = next_entry(buf, fp, sizeof(uint32_t)); |
2298 | 20.7k | if (rc < 0) |
2299 | 18 | goto bad; |
2300 | 20.7k | ncons = le32_to_cpu(buf[0]); |
2301 | 20.7k | if (read_cons_helper(p, &cladatum->validatetrans, ncons, 1, fp)) |
2302 | 24 | goto bad; |
2303 | 20.7k | } |
2304 | | |
2305 | 21.4k | if ((p->policy_type == POLICY_KERN && |
2306 | 21.4k | p->policyvers >= POLICYDB_VERSION_NEW_OBJECT_DEFAULTS) || |
2307 | 21.4k | (p->policy_type == POLICY_BASE && |
2308 | 20.6k | p->policyvers >= MOD_POLICYDB_VERSION_NEW_OBJECT_DEFAULTS)) { |
2309 | 20.6k | rc = next_entry(buf, fp, sizeof(uint32_t) * 3); |
2310 | 20.6k | if (rc < 0) |
2311 | 17 | goto bad; |
2312 | 20.5k | cladatum->default_user = le32_to_cpu(buf[0]); |
2313 | 20.5k | cladatum->default_role = le32_to_cpu(buf[1]); |
2314 | 20.5k | cladatum->default_range = le32_to_cpu(buf[2]); |
2315 | 20.5k | } |
2316 | | |
2317 | 21.4k | if ((p->policy_type == POLICY_KERN && |
2318 | 21.4k | p->policyvers >= POLICYDB_VERSION_DEFAULT_TYPE) || |
2319 | 21.4k | (p->policy_type == POLICY_BASE && |
2320 | 20.5k | p->policyvers >= MOD_POLICYDB_VERSION_DEFAULT_TYPE)) { |
2321 | 20.5k | rc = next_entry(buf, fp, sizeof(uint32_t)); |
2322 | 20.5k | if (rc < 0) |
2323 | 15 | goto bad; |
2324 | 20.5k | cladatum->default_type = le32_to_cpu(buf[0]); |
2325 | 20.5k | } |
2326 | | |
2327 | 21.3k | if (hashtab_insert(h, key, cladatum)) |
2328 | 14 | goto bad; |
2329 | | |
2330 | 21.3k | return 0; |
2331 | | |
2332 | 603 | bad: |
2333 | 603 | class_destroy(key, cladatum, NULL); |
2334 | 603 | return -1; |
2335 | 21.3k | } |
2336 | | |
2337 | | static int role_read(policydb_t * p, hashtab_t h, struct policy_file *fp) |
2338 | 2.22k | { |
2339 | 2.22k | char *key = 0; |
2340 | 2.22k | role_datum_t *role; |
2341 | 2.22k | uint32_t buf[3]; |
2342 | 2.22k | size_t len; |
2343 | 2.22k | int rc, to_read = 2; |
2344 | | |
2345 | 2.22k | role = calloc(1, sizeof(role_datum_t)); |
2346 | 2.22k | if (!role) |
2347 | 0 | return -1; |
2348 | | |
2349 | 2.22k | if (policydb_has_boundary_feature(p)) |
2350 | 1.32k | to_read = 3; |
2351 | | |
2352 | 2.22k | rc = next_entry(buf, fp, sizeof(uint32_t) * to_read); |
2353 | 2.22k | if (rc < 0) |
2354 | 111 | goto bad; |
2355 | | |
2356 | 2.11k | len = le32_to_cpu(buf[0]); |
2357 | 2.11k | rc = str_read(&key, fp, len); |
2358 | 2.11k | if (rc < 0) |
2359 | 7 | goto bad; |
2360 | | |
2361 | 2.10k | role->s.value = le32_to_cpu(buf[1]); |
2362 | 2.10k | if (policydb_has_boundary_feature(p)) |
2363 | 1.30k | role->bounds = le32_to_cpu(buf[2]); |
2364 | | |
2365 | 2.10k | if (ebitmap_read(&role->dominates, fp)) |
2366 | 33 | goto bad; |
2367 | | |
2368 | 2.07k | if (p->policy_type == POLICY_KERN) { |
2369 | 1.96k | if (ebitmap_read(&role->types.types, fp)) |
2370 | 4 | goto bad; |
2371 | 1.96k | } else { |
2372 | 104 | if (type_set_read(&role->types, fp)) |
2373 | 5 | goto bad; |
2374 | 104 | } |
2375 | | |
2376 | 2.06k | if (p->policy_type != POLICY_KERN && |
2377 | 2.06k | p->policyvers >= MOD_POLICYDB_VERSION_ROLEATTRIB) { |
2378 | 51 | rc = next_entry(buf, fp, sizeof(uint32_t)); |
2379 | 51 | if (rc < 0) |
2380 | 1 | goto bad; |
2381 | | |
2382 | 50 | role->flavor = le32_to_cpu(buf[0]); |
2383 | | |
2384 | 50 | if (ebitmap_read(&role->roles, fp)) |
2385 | 2 | goto bad; |
2386 | 50 | } |
2387 | | |
2388 | 2.06k | if (strcmp(key, OBJECT_R) == 0) { |
2389 | 853 | if (role->s.value != OBJECT_R_VAL) { |
2390 | 46 | ERR(fp->handle, "role %s has wrong value %d", |
2391 | 46 | OBJECT_R, role->s.value); |
2392 | 46 | role_destroy(key, role, NULL); |
2393 | 46 | return -1; |
2394 | 46 | } |
2395 | 807 | role_destroy(key, role, NULL); |
2396 | 807 | return 0; |
2397 | 853 | } |
2398 | | |
2399 | 1.20k | if (hashtab_insert(h, key, role)) |
2400 | 2 | goto bad; |
2401 | | |
2402 | 1.20k | return 0; |
2403 | | |
2404 | 165 | bad: |
2405 | 165 | role_destroy(key, role, NULL); |
2406 | 165 | return -1; |
2407 | 1.20k | } |
2408 | | |
2409 | | static int type_read(policydb_t * p, hashtab_t h, struct policy_file *fp) |
2410 | 5.02k | { |
2411 | 5.02k | char *key = 0; |
2412 | 5.02k | type_datum_t *typdatum; |
2413 | 5.02k | uint32_t buf[5]; |
2414 | 5.02k | size_t len; |
2415 | 5.02k | int rc, to_read; |
2416 | 5.02k | int pos = 0; |
2417 | | |
2418 | 5.02k | typdatum = calloc(1, sizeof(type_datum_t)); |
2419 | 5.02k | if (!typdatum) |
2420 | 0 | return -1; |
2421 | | |
2422 | 5.02k | if (policydb_has_boundary_feature(p)) { |
2423 | 4.74k | if (p->policy_type != POLICY_KERN |
2424 | 4.74k | && p->policyvers >= MOD_POLICYDB_VERSION_BOUNDARY_ALIAS) |
2425 | 99 | to_read = 5; |
2426 | 4.64k | else |
2427 | 4.64k | to_read = 4; |
2428 | 4.74k | } |
2429 | 281 | else if (p->policy_type == POLICY_KERN) |
2430 | 223 | to_read = 3; |
2431 | 58 | else if (p->policyvers >= MOD_POLICYDB_VERSION_PERMISSIVE) |
2432 | 20 | to_read = 5; |
2433 | 38 | else |
2434 | 38 | to_read = 4; |
2435 | | |
2436 | 5.02k | rc = next_entry(buf, fp, sizeof(uint32_t) * to_read); |
2437 | 5.02k | if (rc < 0) |
2438 | 40 | goto bad; |
2439 | | |
2440 | 4.98k | len = le32_to_cpu(buf[pos]); |
2441 | 4.98k | typdatum->s.value = le32_to_cpu(buf[++pos]); |
2442 | 4.98k | if (policydb_has_boundary_feature(p)) { |
2443 | 4.72k | uint32_t properties; |
2444 | | |
2445 | 4.72k | if (p->policy_type != POLICY_KERN |
2446 | 4.72k | && p->policyvers >= MOD_POLICYDB_VERSION_BOUNDARY_ALIAS) { |
2447 | 91 | typdatum->primary = le32_to_cpu(buf[++pos]); |
2448 | 91 | properties = le32_to_cpu(buf[++pos]); |
2449 | 91 | } |
2450 | 4.62k | else { |
2451 | 4.62k | properties = le32_to_cpu(buf[++pos]); |
2452 | | |
2453 | 4.62k | if (properties & TYPEDATUM_PROPERTY_PRIMARY) |
2454 | 2.90k | typdatum->primary = 1; |
2455 | 4.62k | } |
2456 | | |
2457 | 4.72k | if (properties & TYPEDATUM_PROPERTY_ATTRIBUTE) |
2458 | 1.32k | typdatum->flavor = TYPE_ATTRIB; |
2459 | 4.72k | if (properties & TYPEDATUM_PROPERTY_ALIAS |
2460 | 4.72k | && p->policy_type != POLICY_KERN) |
2461 | 60 | typdatum->flavor = TYPE_ALIAS; |
2462 | 4.72k | if (properties & TYPEDATUM_PROPERTY_PERMISSIVE |
2463 | 4.72k | && p->policy_type != POLICY_KERN) |
2464 | 71 | typdatum->flags |= TYPE_FLAGS_PERMISSIVE; |
2465 | | |
2466 | 4.72k | typdatum->bounds = le32_to_cpu(buf[++pos]); |
2467 | 4.72k | } else { |
2468 | 261 | typdatum->primary = le32_to_cpu(buf[++pos]); |
2469 | 261 | if (p->policy_type != POLICY_KERN) { |
2470 | 47 | typdatum->flavor = le32_to_cpu(buf[++pos]); |
2471 | 47 | if (p->policyvers >= MOD_POLICYDB_VERSION_PERMISSIVE) |
2472 | 16 | typdatum->flags = le32_to_cpu(buf[++pos]); |
2473 | 47 | } |
2474 | 261 | } |
2475 | | |
2476 | 4.98k | if (p->policy_type != POLICY_KERN) { |
2477 | 156 | if (ebitmap_read(&typdatum->types, fp)) |
2478 | 22 | goto bad; |
2479 | 156 | } |
2480 | | |
2481 | 4.95k | rc = str_read(&key, fp, len); |
2482 | 4.95k | if (rc < 0) |
2483 | 30 | goto bad; |
2484 | | |
2485 | 4.92k | if (hashtab_insert(h, key, typdatum)) |
2486 | 1 | goto bad; |
2487 | | |
2488 | 4.92k | return 0; |
2489 | | |
2490 | 93 | bad: |
2491 | 93 | type_destroy(key, typdatum, NULL); |
2492 | 93 | return -1; |
2493 | 4.92k | } |
2494 | | |
2495 | | static int role_trans_read(policydb_t *p, struct policy_file *fp) |
2496 | 5.22k | { |
2497 | 5.22k | role_trans_t **t = &p->role_tr; |
2498 | 5.22k | unsigned int i; |
2499 | 5.22k | uint32_t buf[3], nel; |
2500 | 5.22k | role_trans_t *tr, *ltr; |
2501 | 5.22k | int rc; |
2502 | 5.22k | int new_roletr = (p->policy_type == POLICY_KERN && |
2503 | 5.22k | p->policyvers >= POLICYDB_VERSION_ROLETRANS); |
2504 | | |
2505 | 5.22k | rc = next_entry(buf, fp, sizeof(uint32_t)); |
2506 | 5.22k | if (rc < 0) |
2507 | 38 | return -1; |
2508 | 5.18k | nel = le32_to_cpu(buf[0]); |
2509 | 5.18k | ltr = NULL; |
2510 | 6.56k | for (i = 0; i < nel; i++) { |
2511 | 1.43k | tr = calloc(1, sizeof(struct role_trans)); |
2512 | 1.43k | if (!tr) { |
2513 | 0 | return -1; |
2514 | 0 | } |
2515 | 1.43k | if (ltr) { |
2516 | 1.12k | ltr->next = tr; |
2517 | 1.12k | } else { |
2518 | 307 | *t = tr; |
2519 | 307 | } |
2520 | 1.43k | rc = next_entry(buf, fp, sizeof(uint32_t) * 3); |
2521 | 1.43k | if (rc < 0) |
2522 | 56 | return -1; |
2523 | 1.37k | tr->role = le32_to_cpu(buf[0]); |
2524 | 1.37k | tr->type = le32_to_cpu(buf[1]); |
2525 | 1.37k | tr->new_role = le32_to_cpu(buf[2]); |
2526 | 1.37k | if (new_roletr) { |
2527 | 478 | rc = next_entry(buf, fp, sizeof(uint32_t)); |
2528 | 478 | if (rc < 0) |
2529 | 1 | return -1; |
2530 | 477 | tr->tclass = le32_to_cpu(buf[0]); |
2531 | 477 | } else |
2532 | 901 | tr->tclass = p->process_class; |
2533 | 1.37k | ltr = tr; |
2534 | 1.37k | } |
2535 | 5.12k | return 0; |
2536 | 5.18k | } |
2537 | | |
2538 | | static int role_allow_read(role_allow_t ** r, struct policy_file *fp) |
2539 | 5.12k | { |
2540 | 5.12k | unsigned int i; |
2541 | 5.12k | uint32_t buf[2], nel; |
2542 | 5.12k | role_allow_t *ra, *lra; |
2543 | 5.12k | int rc; |
2544 | | |
2545 | 5.12k | rc = next_entry(buf, fp, sizeof(uint32_t)); |
2546 | 5.12k | if (rc < 0) |
2547 | 2 | return -1; |
2548 | 5.12k | nel = le32_to_cpu(buf[0]); |
2549 | 5.12k | lra = NULL; |
2550 | 6.86k | for (i = 0; i < nel; i++) { |
2551 | 1.74k | ra = calloc(1, sizeof(struct role_allow)); |
2552 | 1.74k | if (!ra) { |
2553 | 0 | return -1; |
2554 | 0 | } |
2555 | 1.74k | if (lra) { |
2556 | 1.60k | lra->next = ra; |
2557 | 1.60k | } else { |
2558 | 145 | *r = ra; |
2559 | 145 | } |
2560 | 1.74k | rc = next_entry(buf, fp, sizeof(uint32_t) * 2); |
2561 | 1.74k | if (rc < 0) |
2562 | 9 | return -1; |
2563 | 1.73k | ra->role = le32_to_cpu(buf[0]); |
2564 | 1.73k | ra->new_role = le32_to_cpu(buf[1]); |
2565 | 1.73k | lra = ra; |
2566 | 1.73k | } |
2567 | 5.11k | return 0; |
2568 | 5.12k | } |
2569 | | |
2570 | | int policydb_filetrans_insert(policydb_t *p, uint32_t stype, uint32_t ttype, |
2571 | | uint32_t tclass, const char *name, |
2572 | | char **name_alloc, uint32_t otype, |
2573 | | uint32_t *present_otype) |
2574 | 1.81k | { |
2575 | 1.81k | filename_trans_key_t *ft, key; |
2576 | 1.81k | filename_trans_datum_t *datum, *last; |
2577 | | |
2578 | 1.81k | key.ttype = ttype; |
2579 | 1.81k | key.tclass = tclass; |
2580 | 1.81k | key.name = (char *)name; |
2581 | | |
2582 | 1.81k | last = NULL; |
2583 | 1.81k | datum = hashtab_search(p->filename_trans, (hashtab_key_t)&key); |
2584 | 2.71k | while (datum) { |
2585 | 1.35k | if (ebitmap_get_bit(&datum->stypes, stype - 1)) { |
2586 | 299 | if (present_otype) |
2587 | 0 | *present_otype = datum->otype; |
2588 | 299 | return SEPOL_EEXIST; |
2589 | 299 | } |
2590 | 1.05k | if (datum->otype == otype) |
2591 | 149 | break; |
2592 | 902 | last = datum; |
2593 | 902 | datum = datum->next; |
2594 | 902 | } |
2595 | 1.51k | if (!datum) { |
2596 | 1.36k | datum = malloc(sizeof(*datum)); |
2597 | 1.36k | if (!datum) |
2598 | 0 | return SEPOL_ENOMEM; |
2599 | | |
2600 | 1.36k | ebitmap_init(&datum->stypes); |
2601 | 1.36k | datum->otype = otype; |
2602 | 1.36k | datum->next = NULL; |
2603 | | |
2604 | 1.36k | if (last) { |
2605 | 173 | last->next = datum; |
2606 | 1.19k | } else { |
2607 | 1.19k | char *name_dup; |
2608 | | |
2609 | 1.19k | if (name_alloc) { |
2610 | 1.19k | name_dup = *name_alloc; |
2611 | 1.19k | *name_alloc = NULL; |
2612 | 1.19k | } else { |
2613 | 0 | name_dup = strdup(name); |
2614 | 0 | if (!name_dup) { |
2615 | 0 | free(datum); |
2616 | 0 | return SEPOL_ENOMEM; |
2617 | 0 | } |
2618 | 0 | } |
2619 | | |
2620 | 1.19k | ft = malloc(sizeof(*ft)); |
2621 | 1.19k | if (!ft) { |
2622 | 0 | free(name_dup); |
2623 | 0 | free(datum); |
2624 | 0 | return SEPOL_ENOMEM; |
2625 | 0 | } |
2626 | | |
2627 | 1.19k | ft->ttype = ttype; |
2628 | 1.19k | ft->tclass = tclass; |
2629 | 1.19k | ft->name = name_dup; |
2630 | | |
2631 | 1.19k | if (hashtab_insert(p->filename_trans, (hashtab_key_t)ft, |
2632 | 1.19k | (hashtab_datum_t)datum)) { |
2633 | 0 | free(name_dup); |
2634 | 0 | free(datum); |
2635 | 0 | free(ft); |
2636 | 0 | return SEPOL_ENOMEM; |
2637 | 0 | } |
2638 | 1.19k | } |
2639 | 1.36k | } |
2640 | | |
2641 | 1.51k | p->filename_trans_count++; |
2642 | 1.51k | return ebitmap_set_bit(&datum->stypes, stype - 1, 1); |
2643 | 1.51k | } |
2644 | | |
2645 | | static int filename_trans_read_one_compat(policydb_t *p, struct policy_file *fp) |
2646 | 2.15k | { |
2647 | 2.15k | uint32_t buf[4], len, stype, ttype, tclass, otype; |
2648 | 2.15k | char *name = NULL; |
2649 | 2.15k | int rc; |
2650 | | |
2651 | 2.15k | rc = next_entry(buf, fp, sizeof(uint32_t)); |
2652 | 2.15k | if (rc < 0) |
2653 | 334 | return -1; |
2654 | 1.81k | len = le32_to_cpu(buf[0]); |
2655 | | |
2656 | 1.81k | rc = str_read(&name, fp, len); |
2657 | 1.81k | if (rc < 0) |
2658 | 2 | goto err; |
2659 | | |
2660 | 1.81k | rc = next_entry(buf, fp, sizeof(uint32_t) * 4); |
2661 | 1.81k | if (rc < 0) |
2662 | 1 | goto err; |
2663 | | |
2664 | 1.81k | stype = le32_to_cpu(buf[0]); |
2665 | 1.81k | if (stype == 0) |
2666 | 1 | goto err; |
2667 | | |
2668 | 1.81k | ttype = le32_to_cpu(buf[1]); |
2669 | 1.81k | tclass = le32_to_cpu(buf[2]); |
2670 | 1.81k | otype = le32_to_cpu(buf[3]); |
2671 | | |
2672 | 1.81k | rc = policydb_filetrans_insert(p, stype, ttype, tclass, name, &name, |
2673 | 1.81k | otype, NULL); |
2674 | 1.81k | if (rc) { |
2675 | 307 | if (rc != SEPOL_EEXIST) |
2676 | 8 | goto err; |
2677 | | /* |
2678 | | * Some old policies were wrongly generated with |
2679 | | * duplicate filename transition rules. For backward |
2680 | | * compatibility, do not reject such policies, just |
2681 | | * ignore the duplicate. |
2682 | | */ |
2683 | 307 | } |
2684 | 1.80k | free(name); |
2685 | 1.80k | return 0; |
2686 | 12 | err: |
2687 | 12 | free(name); |
2688 | 12 | return -1; |
2689 | 1.81k | } |
2690 | | |
2691 | | static int filename_trans_check_datum(filename_trans_datum_t *datum) |
2692 | 371 | { |
2693 | 371 | ebitmap_t stypes, otypes; |
2694 | 371 | int rc = -1; |
2695 | | |
2696 | 371 | ebitmap_init(&stypes); |
2697 | 371 | ebitmap_init(&otypes); |
2698 | | |
2699 | 1.72k | while (datum) { |
2700 | 1.44k | if (ebitmap_get_bit(&otypes, datum->otype)) |
2701 | 1 | goto out; |
2702 | | |
2703 | 1.44k | if (ebitmap_set_bit(&otypes, datum->otype, 1)) |
2704 | 1 | goto out; |
2705 | | |
2706 | 1.44k | if (ebitmap_match_any(&stypes, &datum->stypes)) |
2707 | 88 | goto out; |
2708 | | |
2709 | 1.35k | if (ebitmap_union(&stypes, &datum->stypes)) |
2710 | 0 | goto out; |
2711 | | |
2712 | 1.35k | datum = datum->next; |
2713 | 1.35k | } |
2714 | 281 | rc = 0; |
2715 | 371 | out: |
2716 | 371 | ebitmap_destroy(&stypes); |
2717 | 371 | ebitmap_destroy(&otypes); |
2718 | 371 | return rc; |
2719 | 281 | } |
2720 | | |
2721 | | static int filename_trans_read_one(policydb_t *p, struct policy_file *fp) |
2722 | 638 | { |
2723 | 638 | filename_trans_key_t *ft = NULL; |
2724 | 638 | filename_trans_datum_t **dst, *datum, *first = NULL; |
2725 | 638 | unsigned int i; |
2726 | 638 | uint32_t buf[3], len, ttype, tclass, ndatum; |
2727 | 638 | char *name = NULL; |
2728 | 638 | int rc; |
2729 | | |
2730 | 638 | rc = next_entry(buf, fp, sizeof(uint32_t)); |
2731 | 638 | if (rc < 0) |
2732 | 169 | return -1; |
2733 | 469 | len = le32_to_cpu(buf[0]); |
2734 | | |
2735 | 469 | rc = str_read(&name, fp, len); |
2736 | 469 | if (rc < 0) |
2737 | 1 | goto err; |
2738 | | |
2739 | 468 | rc = next_entry(buf, fp, sizeof(uint32_t) * 3); |
2740 | 468 | if (rc < 0) |
2741 | 1 | goto err; |
2742 | | |
2743 | 467 | ttype = le32_to_cpu(buf[0]); |
2744 | 467 | tclass = le32_to_cpu(buf[1]); |
2745 | 467 | ndatum = le32_to_cpu(buf[2]); |
2746 | 467 | if (ndatum == 0) |
2747 | 1 | goto err; |
2748 | | |
2749 | 466 | dst = &first; |
2750 | 2.89k | for (i = 0; i < ndatum; i++) { |
2751 | 2.49k | datum = malloc(sizeof(*datum)); |
2752 | 2.49k | if (!datum) |
2753 | 0 | goto err; |
2754 | | |
2755 | 2.49k | datum->next = NULL; |
2756 | 2.49k | *dst = datum; |
2757 | | |
2758 | | /* ebitmap_read() will at least init the bitmap */ |
2759 | 2.49k | rc = ebitmap_read(&datum->stypes, fp); |
2760 | 2.49k | if (rc < 0) |
2761 | 68 | goto err; |
2762 | | |
2763 | 2.43k | rc = next_entry(buf, fp, sizeof(uint32_t)); |
2764 | 2.43k | if (rc < 0) |
2765 | 1 | goto err; |
2766 | | |
2767 | 2.43k | datum->otype = le32_to_cpu(buf[0]); |
2768 | | |
2769 | 2.43k | p->filename_trans_count += ebitmap_cardinality(&datum->stypes); |
2770 | | |
2771 | 2.43k | dst = &datum->next; |
2772 | 2.43k | } |
2773 | | |
2774 | 397 | if (ndatum > 1 && filename_trans_check_datum(first)) |
2775 | 90 | goto err; |
2776 | | |
2777 | 307 | ft = malloc(sizeof(*ft)); |
2778 | 307 | if (!ft) |
2779 | 0 | goto err; |
2780 | | |
2781 | 307 | ft->ttype = ttype; |
2782 | 307 | ft->tclass = tclass; |
2783 | 307 | ft->name = name; |
2784 | | |
2785 | 307 | rc = hashtab_insert(p->filename_trans, (hashtab_key_t)ft, |
2786 | 307 | (hashtab_datum_t)first); |
2787 | 307 | if (rc) |
2788 | 10 | goto err; |
2789 | | |
2790 | 297 | return 0; |
2791 | 172 | err: |
2792 | 172 | free(ft); |
2793 | 172 | free(name); |
2794 | 1.42k | while (first) { |
2795 | 1.25k | datum = first; |
2796 | 1.25k | first = first->next; |
2797 | | |
2798 | 1.25k | ebitmap_destroy(&datum->stypes); |
2799 | 1.25k | free(datum); |
2800 | 1.25k | } |
2801 | 172 | return -1; |
2802 | 307 | } |
2803 | | |
2804 | | static int filename_trans_read(policydb_t *p, struct policy_file *fp) |
2805 | 3.54k | { |
2806 | 3.54k | unsigned int i; |
2807 | 3.54k | uint32_t buf[1], nel; |
2808 | 3.54k | int rc; |
2809 | | |
2810 | 3.54k | rc = next_entry(buf, fp, sizeof(uint32_t)); |
2811 | 3.54k | if (rc < 0) |
2812 | 1 | return -1; |
2813 | 3.54k | nel = le32_to_cpu(buf[0]); |
2814 | | |
2815 | 3.54k | if (p->policyvers < POLICYDB_VERSION_COMP_FTRANS) { |
2816 | 4.72k | for (i = 0; i < nel; i++) { |
2817 | 2.15k | rc = filename_trans_read_one_compat(p, fp); |
2818 | 2.15k | if (rc < 0) |
2819 | 346 | return -1; |
2820 | 2.15k | } |
2821 | 2.92k | } else { |
2822 | 914 | for (i = 0; i < nel; i++) { |
2823 | 638 | rc = filename_trans_read_one(p, fp); |
2824 | 638 | if (rc < 0) |
2825 | 341 | return -1; |
2826 | 638 | } |
2827 | 617 | } |
2828 | 2.85k | return 0; |
2829 | 3.54k | } |
2830 | | |
2831 | | static int ocontext_read_xen(const struct policydb_compat_info *info, |
2832 | | policydb_t *p, struct policy_file *fp) |
2833 | 1.41k | { |
2834 | 1.41k | unsigned int i, j; |
2835 | 1.41k | size_t nel, len; |
2836 | 1.41k | ocontext_t *l, *c; |
2837 | 1.41k | uint32_t buf[8]; |
2838 | 1.41k | int rc; |
2839 | | |
2840 | 8.13k | for (i = 0; i < info->ocon_num; i++) { |
2841 | 7.05k | rc = next_entry(buf, fp, sizeof(uint32_t)); |
2842 | 7.05k | if (rc < 0) |
2843 | 16 | return -1; |
2844 | 7.03k | nel = le32_to_cpu(buf[0]); |
2845 | 7.03k | l = NULL; |
2846 | 10.5k | for (j = 0; j < nel; j++) { |
2847 | 3.81k | c = calloc(1, sizeof(ocontext_t)); |
2848 | 3.81k | if (!c) |
2849 | 0 | return -1; |
2850 | 3.81k | if (l) |
2851 | 3.30k | l->next = c; |
2852 | 509 | else |
2853 | 509 | p->ocontexts[i] = c; |
2854 | 3.81k | l = c; |
2855 | 3.81k | switch (i) { |
2856 | 1.96k | case OCON_XEN_ISID: |
2857 | 1.96k | rc = next_entry(buf, fp, sizeof(uint32_t)); |
2858 | 1.96k | if (rc < 0) |
2859 | 117 | return -1; |
2860 | 1.84k | c->sid[0] = le32_to_cpu(buf[0]); |
2861 | 1.84k | if (is_saturated(c->sid[0])) |
2862 | 1 | return -1; |
2863 | 1.84k | if (context_read_and_validate |
2864 | 1.84k | (&c->context[0], p, fp)) |
2865 | 115 | return -1; |
2866 | 1.73k | break; |
2867 | 1.73k | case OCON_XEN_PIRQ: |
2868 | 439 | rc = next_entry(buf, fp, sizeof(uint32_t)); |
2869 | 439 | if (rc < 0) |
2870 | 15 | return -1; |
2871 | 424 | c->u.pirq = le32_to_cpu(buf[0]); |
2872 | 424 | if (context_read_and_validate |
2873 | 424 | (&c->context[0], p, fp)) |
2874 | 2 | return -1; |
2875 | 422 | break; |
2876 | 422 | case OCON_XEN_IOPORT: |
2877 | 253 | rc = next_entry(buf, fp, sizeof(uint32_t) * 2); |
2878 | 253 | if (rc < 0) |
2879 | 10 | return -1; |
2880 | 243 | c->u.ioport.low_ioport = le32_to_cpu(buf[0]); |
2881 | 243 | c->u.ioport.high_ioport = le32_to_cpu(buf[1]); |
2882 | 243 | if (context_read_and_validate |
2883 | 243 | (&c->context[0], p, fp)) |
2884 | 1 | return -1; |
2885 | 242 | break; |
2886 | 290 | case OCON_XEN_IOMEM: |
2887 | 290 | if (p->policyvers >= POLICYDB_VERSION_XEN_DEVICETREE) { |
2888 | 180 | uint64_t b64[2]; |
2889 | 180 | rc = next_entry(b64, fp, sizeof(uint64_t) * 2); |
2890 | 180 | if (rc < 0) |
2891 | 1 | return -1; |
2892 | 179 | c->u.iomem.low_iomem = le64_to_cpu(b64[0]); |
2893 | 179 | c->u.iomem.high_iomem = le64_to_cpu(b64[1]); |
2894 | 179 | } else { |
2895 | 110 | rc = next_entry(buf, fp, sizeof(uint32_t) * 2); |
2896 | 110 | if (rc < 0) |
2897 | 9 | return -1; |
2898 | 101 | c->u.iomem.low_iomem = le32_to_cpu(buf[0]); |
2899 | 101 | c->u.iomem.high_iomem = le32_to_cpu(buf[1]); |
2900 | 101 | } |
2901 | 280 | if (context_read_and_validate |
2902 | 280 | (&c->context[0], p, fp)) |
2903 | 13 | return -1; |
2904 | 267 | break; |
2905 | 267 | case OCON_XEN_PCIDEVICE: |
2906 | 215 | rc = next_entry(buf, fp, sizeof(uint32_t)); |
2907 | 215 | if (rc < 0) |
2908 | 10 | return -1; |
2909 | 205 | c->u.device = le32_to_cpu(buf[0]); |
2910 | 205 | if (context_read_and_validate |
2911 | 205 | (&c->context[0], p, fp)) |
2912 | 1 | return -1; |
2913 | 204 | break; |
2914 | 649 | case OCON_XEN_DEVICETREE: |
2915 | 649 | rc = next_entry(buf, fp, sizeof(uint32_t)); |
2916 | 649 | if (rc < 0) |
2917 | 15 | return -1; |
2918 | 634 | len = le32_to_cpu(buf[0]); |
2919 | 634 | rc = str_read(&c->u.name, fp, len); |
2920 | 634 | if (rc < 0) |
2921 | 1 | return -1; |
2922 | 633 | if (context_read_and_validate |
2923 | 633 | (&c->context[0], p, fp)) |
2924 | 3 | return -1; |
2925 | 630 | break; |
2926 | 630 | default: |
2927 | | /* should never get here */ |
2928 | 0 | ERR(fp->handle, "Unknown Xen ocontext"); |
2929 | 0 | return -1; |
2930 | 3.81k | } |
2931 | 3.81k | } |
2932 | 7.03k | } |
2933 | 1.08k | return 0; |
2934 | 1.41k | } |
2935 | | static int ocontext_read_selinux(const struct policydb_compat_info *info, |
2936 | | policydb_t * p, struct policy_file *fp) |
2937 | 3.88k | { |
2938 | 3.88k | unsigned int i, j; |
2939 | 3.88k | size_t nel, len; |
2940 | 3.88k | ocontext_t *l, *c; |
2941 | 3.88k | uint32_t buf[8]; |
2942 | 3.88k | int rc; |
2943 | | |
2944 | 26.4k | for (i = 0; i < info->ocon_num; i++) { |
2945 | 23.4k | rc = next_entry(buf, fp, sizeof(uint32_t)); |
2946 | 23.4k | if (rc < 0) |
2947 | 145 | return -1; |
2948 | 23.3k | nel = le32_to_cpu(buf[0]); |
2949 | 23.3k | l = NULL; |
2950 | 27.1k | for (j = 0; j < nel; j++) { |
2951 | 4.55k | c = calloc(1, sizeof(ocontext_t)); |
2952 | 4.55k | if (!c) { |
2953 | 0 | return -1; |
2954 | 0 | } |
2955 | 4.55k | if (l) { |
2956 | 3.64k | l->next = c; |
2957 | 3.64k | } else { |
2958 | 911 | p->ocontexts[i] = c; |
2959 | 911 | } |
2960 | 4.55k | l = c; |
2961 | 4.55k | switch (i) { |
2962 | 2.29k | case OCON_ISID: |
2963 | 2.29k | rc = next_entry(buf, fp, sizeof(uint32_t)); |
2964 | 2.29k | if (rc < 0) |
2965 | 61 | return -1; |
2966 | 2.23k | c->sid[0] = le32_to_cpu(buf[0]); |
2967 | 2.23k | if (is_saturated(c->sid[0])) |
2968 | 1 | return -1; |
2969 | 2.23k | if (context_read_and_validate |
2970 | 2.23k | (&c->context[0], p, fp)) |
2971 | 395 | return -1; |
2972 | 1.84k | break; |
2973 | 1.84k | case OCON_FS: |
2974 | 756 | case OCON_NETIF: |
2975 | 756 | rc = next_entry(buf, fp, sizeof(uint32_t)); |
2976 | 756 | if (rc < 0) |
2977 | 25 | return -1; |
2978 | 731 | len = le32_to_cpu(buf[0]); |
2979 | 731 | if (len > 63) |
2980 | 32 | return -1; |
2981 | | |
2982 | 699 | rc = str_read(&c->u.name, fp, len); |
2983 | 699 | if (rc < 0) |
2984 | 11 | return -1; |
2985 | | |
2986 | 688 | if (context_read_and_validate |
2987 | 688 | (&c->context[0], p, fp)) |
2988 | 1 | return -1; |
2989 | 687 | if (context_read_and_validate |
2990 | 687 | (&c->context[1], p, fp)) |
2991 | 7 | return -1; |
2992 | 680 | break; |
2993 | 680 | case OCON_IBPKEY: { |
2994 | 96 | uint32_t pkey_lo, pkey_hi; |
2995 | | |
2996 | 96 | rc = next_entry(buf, fp, sizeof(uint32_t) * 4); |
2997 | 96 | if (rc < 0) |
2998 | 6 | return -1; |
2999 | | |
3000 | 90 | pkey_lo = le32_to_cpu(buf[2]); |
3001 | 90 | pkey_hi = le32_to_cpu(buf[3]); |
3002 | | |
3003 | 90 | if (pkey_lo > UINT16_MAX || pkey_hi > UINT16_MAX) |
3004 | 24 | return -1; |
3005 | | |
3006 | 66 | c->u.ibpkey.low_pkey = pkey_lo; |
3007 | 66 | c->u.ibpkey.high_pkey = pkey_hi; |
3008 | | |
3009 | | /* we want c->u.ibpkey.subnet_prefix in network |
3010 | | * (big-endian) order, just memcpy it */ |
3011 | 66 | memcpy(&c->u.ibpkey.subnet_prefix, buf, |
3012 | 66 | sizeof(c->u.ibpkey.subnet_prefix)); |
3013 | | |
3014 | 66 | if (context_read_and_validate |
3015 | 66 | (&c->context[0], p, fp)) |
3016 | 17 | return -1; |
3017 | 49 | break; |
3018 | 66 | } |
3019 | 180 | case OCON_IBENDPORT: { |
3020 | 180 | uint32_t port; |
3021 | | |
3022 | 180 | rc = next_entry(buf, fp, sizeof(uint32_t) * 2); |
3023 | 180 | if (rc < 0) |
3024 | 11 | return -1; |
3025 | 169 | len = le32_to_cpu(buf[0]); |
3026 | 169 | if (len == 0 || len > IB_DEVICE_NAME_MAX - 1) |
3027 | 42 | return -1; |
3028 | | |
3029 | 127 | port = le32_to_cpu(buf[1]); |
3030 | 127 | if (port > UINT8_MAX || port == 0) |
3031 | 4 | return -1; |
3032 | | |
3033 | 123 | rc = str_read(&c->u.ibendport.dev_name, fp, len); |
3034 | 123 | if (rc < 0) |
3035 | 3 | return -1; |
3036 | | |
3037 | 120 | c->u.ibendport.port = port; |
3038 | 120 | if (context_read_and_validate |
3039 | 120 | (&c->context[0], p, fp)) |
3040 | 1 | return -1; |
3041 | 119 | break; |
3042 | 120 | } |
3043 | 211 | case OCON_PORT: |
3044 | 211 | rc = next_entry(buf, fp, sizeof(uint32_t) * 3); |
3045 | 211 | if (rc < 0) |
3046 | 10 | return -1; |
3047 | 201 | c->u.port.protocol = le32_to_cpu(buf[0]); |
3048 | 201 | c->u.port.low_port = le32_to_cpu(buf[1]); |
3049 | 201 | c->u.port.high_port = le32_to_cpu(buf[2]); |
3050 | 201 | if (context_read_and_validate |
3051 | 201 | (&c->context[0], p, fp)) |
3052 | 1 | return -1; |
3053 | 200 | break; |
3054 | 264 | case OCON_NODE: |
3055 | 264 | rc = next_entry(buf, fp, sizeof(uint32_t) * 2); |
3056 | 264 | if (rc < 0) |
3057 | 12 | return -1; |
3058 | 252 | c->u.node.addr = buf[0]; /* network order */ |
3059 | 252 | c->u.node.mask = buf[1]; /* network order */ |
3060 | 252 | if (context_read_and_validate |
3061 | 252 | (&c->context[0], p, fp)) |
3062 | 1 | return -1; |
3063 | 251 | break; |
3064 | 540 | case OCON_FSUSE: |
3065 | 540 | rc = next_entry(buf, fp, sizeof(uint32_t) * 2); |
3066 | 540 | if (rc < 0) |
3067 | 13 | return -1; |
3068 | 527 | c->v.behavior = le32_to_cpu(buf[0]); |
3069 | 527 | len = le32_to_cpu(buf[1]); |
3070 | | |
3071 | 527 | rc = str_read(&c->u.name, fp, len); |
3072 | 527 | if (rc < 0) |
3073 | 2 | return -1; |
3074 | | |
3075 | 525 | if (context_read_and_validate |
3076 | 525 | (&c->context[0], p, fp)) |
3077 | 2 | return -1; |
3078 | 523 | break; |
3079 | 523 | case OCON_NODE6:{ |
3080 | 206 | int k; |
3081 | | |
3082 | 206 | rc = next_entry(buf, fp, sizeof(uint32_t) * 8); |
3083 | 206 | if (rc < 0) |
3084 | 9 | return -1; |
3085 | 985 | for (k = 0; k < 4; k++) |
3086 | | /* network order */ |
3087 | 788 | c->u.node6.addr[k] = buf[k]; |
3088 | 985 | for (k = 0; k < 4; k++) |
3089 | | /* network order */ |
3090 | 788 | c->u.node6.mask[k] = buf[k + 4]; |
3091 | 197 | if (context_read_and_validate |
3092 | 197 | (&c->context[0], p, fp)) |
3093 | 1 | return -1; |
3094 | 196 | break; |
3095 | 197 | } |
3096 | 196 | default:{ |
3097 | 0 | ERR(fp->handle, "Unknown SELinux ocontext"); |
3098 | 0 | return -1; |
3099 | 0 | } |
3100 | 4.55k | } |
3101 | 4.55k | } |
3102 | 23.3k | } |
3103 | 3.04k | return 0; |
3104 | 3.88k | } |
3105 | | |
3106 | | static int ocontext_read(const struct policydb_compat_info *info, |
3107 | | policydb_t *p, struct policy_file *fp) |
3108 | 5.29k | { |
3109 | 5.29k | int rc = -1; |
3110 | 5.29k | switch (p->target_platform) { |
3111 | 3.88k | case SEPOL_TARGET_SELINUX: |
3112 | 3.88k | rc = ocontext_read_selinux(info, p, fp); |
3113 | 3.88k | break; |
3114 | 1.41k | case SEPOL_TARGET_XEN: |
3115 | 1.41k | rc = ocontext_read_xen(info, p, fp); |
3116 | 1.41k | break; |
3117 | 0 | default: |
3118 | 0 | ERR(fp->handle, "Unknown target"); |
3119 | 5.29k | } |
3120 | 5.29k | return rc; |
3121 | 5.29k | } |
3122 | | |
3123 | | static int genfs_read(policydb_t * p, struct policy_file *fp) |
3124 | 4.12k | { |
3125 | 4.12k | uint32_t buf[1]; |
3126 | 4.12k | size_t nel, nel2, len, len2; |
3127 | 4.12k | genfs_t *genfs_p, *newgenfs, *genfs; |
3128 | 4.12k | size_t i, j; |
3129 | 4.12k | ocontext_t *l, *c, *newc = NULL; |
3130 | 4.12k | int rc; |
3131 | | |
3132 | 4.12k | rc = next_entry(buf, fp, sizeof(uint32_t)); |
3133 | 4.12k | if (rc < 0) |
3134 | 7 | goto bad; |
3135 | 4.12k | nel = le32_to_cpu(buf[0]); |
3136 | 4.12k | genfs_p = NULL; |
3137 | 4.39k | for (i = 0; i < nel; i++) { |
3138 | 743 | rc = next_entry(buf, fp, sizeof(uint32_t)); |
3139 | 743 | if (rc < 0) |
3140 | 55 | goto bad; |
3141 | 688 | len = le32_to_cpu(buf[0]); |
3142 | 688 | newgenfs = calloc(1, sizeof(genfs_t)); |
3143 | 688 | if (!newgenfs) |
3144 | 0 | goto bad; |
3145 | | |
3146 | 688 | rc = str_read(&newgenfs->fstype, fp, len); |
3147 | 688 | if (rc < 0) { |
3148 | 2 | free(newgenfs->fstype); |
3149 | 2 | free(newgenfs); |
3150 | 2 | goto bad; |
3151 | 2 | } |
3152 | | |
3153 | 981 | for (genfs_p = NULL, genfs = p->genfs; genfs; |
3154 | 686 | genfs_p = genfs, genfs = genfs->next) { |
3155 | 442 | if (strcmp(newgenfs->fstype, genfs->fstype) == 0) { |
3156 | 1 | ERR(fp->handle, "dup genfs fstype %s", |
3157 | 1 | newgenfs->fstype); |
3158 | 1 | free(newgenfs->fstype); |
3159 | 1 | free(newgenfs); |
3160 | 1 | goto bad; |
3161 | 1 | } |
3162 | 441 | if (strcmp(newgenfs->fstype, genfs->fstype) < 0) |
3163 | 146 | break; |
3164 | 441 | } |
3165 | 685 | newgenfs->next = genfs; |
3166 | 685 | if (genfs_p) |
3167 | 138 | genfs_p->next = newgenfs; |
3168 | 547 | else |
3169 | 547 | p->genfs = newgenfs; |
3170 | 685 | rc = next_entry(buf, fp, sizeof(uint32_t)); |
3171 | 685 | if (rc < 0) |
3172 | 129 | goto bad; |
3173 | 556 | nel2 = le32_to_cpu(buf[0]); |
3174 | 1.13k | for (j = 0; j < nel2; j++) { |
3175 | 866 | newc = calloc(1, sizeof(ocontext_t)); |
3176 | 866 | if (!newc) { |
3177 | 0 | goto bad; |
3178 | 0 | } |
3179 | 866 | rc = next_entry(buf, fp, sizeof(uint32_t)); |
3180 | 866 | if (rc < 0) |
3181 | 274 | goto bad; |
3182 | 592 | len = le32_to_cpu(buf[0]); |
3183 | 592 | rc = str_read(&newc->u.name, fp, len); |
3184 | 592 | if (rc < 0) |
3185 | 1 | goto bad; |
3186 | | |
3187 | 591 | rc = next_entry(buf, fp, sizeof(uint32_t)); |
3188 | 591 | if (rc < 0) |
3189 | 1 | goto bad; |
3190 | 590 | newc->v.sclass = le32_to_cpu(buf[0]); |
3191 | 590 | if (context_read_and_validate(&newc->context[0], p, fp)) |
3192 | 4 | goto bad; |
3193 | 1.05k | for (l = NULL, c = newgenfs->head; c; |
3194 | 586 | l = c, c = c->next) { |
3195 | 537 | if (!strcmp(newc->u.name, c->u.name) && |
3196 | 537 | (!c->v.sclass || !newc->v.sclass || |
3197 | 243 | newc->v.sclass == c->v.sclass)) { |
3198 | 7 | ERR(fp->handle, "dup genfs entry " |
3199 | 7 | "(%s,%s)", newgenfs->fstype, |
3200 | 7 | c->u.name); |
3201 | 7 | goto bad; |
3202 | 7 | } |
3203 | 530 | len = strlen(newc->u.name); |
3204 | 530 | len2 = strlen(c->u.name); |
3205 | 530 | if (len > len2) |
3206 | 60 | break; |
3207 | 530 | } |
3208 | 579 | newc->next = c; |
3209 | 579 | if (l) |
3210 | 282 | l->next = newc; |
3211 | 297 | else |
3212 | 297 | newgenfs->head = newc; |
3213 | | /* clear newc after a new owner has the pointer */ |
3214 | 579 | newc = NULL; |
3215 | 579 | } |
3216 | 556 | } |
3217 | | |
3218 | 3.64k | return 0; |
3219 | | |
3220 | 481 | bad: |
3221 | 481 | if (newc) { |
3222 | 287 | context_destroy(&newc->context[0]); |
3223 | 287 | context_destroy(&newc->context[1]); |
3224 | 287 | free(newc->u.name); |
3225 | 287 | free(newc); |
3226 | 287 | } |
3227 | 481 | return -1; |
3228 | 4.12k | } |
3229 | | |
3230 | | /* |
3231 | | * Read a MLS level structure from a policydb binary |
3232 | | * representation file. |
3233 | | */ |
3234 | | static int mls_read_level(mls_level_t * lp, struct policy_file *fp) |
3235 | 2.07k | { |
3236 | 2.07k | uint32_t buf[1]; |
3237 | 2.07k | int rc; |
3238 | | |
3239 | 2.07k | mls_level_init(lp); |
3240 | | |
3241 | 2.07k | rc = next_entry(buf, fp, sizeof(uint32_t)); |
3242 | 2.07k | if (rc < 0) { |
3243 | 28 | ERR(fp->handle, "truncated level"); |
3244 | 28 | goto bad; |
3245 | 28 | } |
3246 | 2.04k | lp->sens = le32_to_cpu(buf[0]); |
3247 | | |
3248 | 2.04k | if (ebitmap_read(&lp->cat, fp)) { |
3249 | 3 | ERR(fp->handle, "error reading level categories"); |
3250 | 3 | goto bad; |
3251 | 3 | } |
3252 | 2.04k | return 0; |
3253 | | |
3254 | 31 | bad: |
3255 | 31 | return -EINVAL; |
3256 | 2.04k | } |
3257 | | |
3258 | | static int user_read(policydb_t * p, hashtab_t h, struct policy_file *fp) |
3259 | 3.10k | { |
3260 | 3.10k | char *key = 0; |
3261 | 3.10k | user_datum_t *usrdatum; |
3262 | 3.10k | uint32_t buf[3]; |
3263 | 3.10k | size_t len; |
3264 | 3.10k | int rc, to_read = 2; |
3265 | | |
3266 | 3.10k | usrdatum = calloc(1, sizeof(user_datum_t)); |
3267 | 3.10k | if (!usrdatum) |
3268 | 0 | return -1; |
3269 | | |
3270 | 3.10k | if (policydb_has_boundary_feature(p)) |
3271 | 2.16k | to_read = 3; |
3272 | | |
3273 | 3.10k | rc = next_entry(buf, fp, sizeof(uint32_t) * to_read); |
3274 | 3.10k | if (rc < 0) |
3275 | 95 | goto bad; |
3276 | | |
3277 | 3.01k | len = le32_to_cpu(buf[0]); |
3278 | 3.01k | rc = str_read(&key, fp, len); |
3279 | 3.01k | if (rc < 0) |
3280 | 12 | goto bad; |
3281 | | |
3282 | 2.99k | usrdatum->s.value = le32_to_cpu(buf[1]); |
3283 | 2.99k | if (policydb_has_boundary_feature(p)) |
3284 | 2.15k | usrdatum->bounds = le32_to_cpu(buf[2]); |
3285 | | |
3286 | 2.99k | if (p->policy_type == POLICY_KERN) { |
3287 | 753 | if (ebitmap_read(&usrdatum->roles.roles, fp)) |
3288 | 16 | goto bad; |
3289 | 2.24k | } else { |
3290 | 2.24k | if (role_set_read(&usrdatum->roles, fp)) |
3291 | 18 | goto bad; |
3292 | 2.24k | } |
3293 | | |
3294 | | /* users were not allowed in mls modules before version |
3295 | | * MOD_POLICYDB_VERSION_MLS_USERS, but they could have been |
3296 | | * required - the mls fields will be empty. user declarations in |
3297 | | * non-mls modules will also have empty mls fields */ |
3298 | 2.96k | if ((p->policy_type == POLICY_KERN |
3299 | 2.96k | && p->policyvers >= POLICYDB_VERSION_MLS) |
3300 | 2.96k | || (p->policy_type == POLICY_MOD |
3301 | 2.27k | && p->policyvers >= MOD_POLICYDB_VERSION_MLS |
3302 | 2.27k | && p->policyvers < MOD_POLICYDB_VERSION_MLS_USERS) |
3303 | 2.96k | || (p->policy_type == POLICY_BASE |
3304 | 2.17k | && p->policyvers >= MOD_POLICYDB_VERSION_MLS |
3305 | 2.17k | && p->policyvers < MOD_POLICYDB_VERSION_MLS_USERS)) { |
3306 | 1.02k | if (mls_read_range_helper(&usrdatum->exp_range, fp)) |
3307 | 65 | goto bad; |
3308 | 960 | if (mls_read_level(&usrdatum->exp_dfltlevel, fp)) |
3309 | 17 | goto bad; |
3310 | 943 | if (p->policy_type != POLICY_KERN) { |
3311 | 313 | if (mls_range_to_semantic(&usrdatum->exp_range, |
3312 | 313 | &usrdatum->range)) |
3313 | 0 | goto bad; |
3314 | 313 | if (mls_level_to_semantic(&usrdatum->exp_dfltlevel, |
3315 | 313 | &usrdatum->dfltlevel)) |
3316 | 0 | goto bad; |
3317 | 313 | } |
3318 | 1.94k | } else if ((p->policy_type == POLICY_MOD |
3319 | 1.94k | && p->policyvers >= MOD_POLICYDB_VERSION_MLS_USERS) |
3320 | 1.94k | || (p->policy_type == POLICY_BASE |
3321 | 1.81k | && p->policyvers >= MOD_POLICYDB_VERSION_MLS_USERS)) { |
3322 | 1.81k | if (mls_read_semantic_range_helper(&usrdatum->range, fp)) |
3323 | 85 | goto bad; |
3324 | 1.72k | if (mls_read_semantic_level_helper(&usrdatum->dfltlevel, fp)) |
3325 | 12 | goto bad; |
3326 | 1.72k | } |
3327 | | |
3328 | 2.78k | if (hashtab_insert(h, key, usrdatum)) |
3329 | 17 | goto bad; |
3330 | | |
3331 | 2.76k | return 0; |
3332 | | |
3333 | 337 | bad: |
3334 | 337 | user_destroy(key, usrdatum, NULL); |
3335 | 337 | return -1; |
3336 | 2.78k | } |
3337 | | |
3338 | | static int sens_read(policydb_t * p |
3339 | | __attribute__ ((unused)), hashtab_t h, |
3340 | | struct policy_file *fp) |
3341 | 1.13k | { |
3342 | 1.13k | char *key = 0; |
3343 | 1.13k | level_datum_t *levdatum; |
3344 | 1.13k | uint32_t buf[2], len; |
3345 | 1.13k | int rc; |
3346 | | |
3347 | 1.13k | levdatum = malloc(sizeof(level_datum_t)); |
3348 | 1.13k | if (!levdatum) |
3349 | 0 | return -1; |
3350 | 1.13k | level_datum_init(levdatum); |
3351 | | |
3352 | 1.13k | rc = next_entry(buf, fp, (sizeof(uint32_t) * 2)); |
3353 | 1.13k | if (rc < 0) |
3354 | 22 | goto bad; |
3355 | | |
3356 | 1.11k | len = le32_to_cpu(buf[0]); |
3357 | 1.11k | rc = str_read(&key, fp, len); |
3358 | 1.11k | if (rc < 0) |
3359 | 1 | goto bad; |
3360 | | |
3361 | 1.11k | levdatum->isalias = le32_to_cpu(buf[1]); |
3362 | | |
3363 | 1.11k | levdatum->level = malloc(sizeof(mls_level_t)); |
3364 | 1.11k | if (!levdatum->level || mls_read_level(levdatum->level, fp)) |
3365 | 14 | goto bad; |
3366 | | |
3367 | 1.09k | if (hashtab_insert(h, key, levdatum)) |
3368 | 1 | goto bad; |
3369 | | |
3370 | 1.09k | return 0; |
3371 | | |
3372 | 38 | bad: |
3373 | 38 | sens_destroy(key, levdatum, NULL); |
3374 | 38 | return -1; |
3375 | 1.09k | } |
3376 | | |
3377 | | static int cat_read(policydb_t * p |
3378 | | __attribute__ ((unused)), hashtab_t h, |
3379 | | struct policy_file *fp) |
3380 | 905 | { |
3381 | 905 | char *key = 0; |
3382 | 905 | cat_datum_t *catdatum; |
3383 | 905 | uint32_t buf[3], len; |
3384 | 905 | int rc; |
3385 | | |
3386 | 905 | catdatum = malloc(sizeof(cat_datum_t)); |
3387 | 905 | if (!catdatum) |
3388 | 0 | return -1; |
3389 | 905 | cat_datum_init(catdatum); |
3390 | | |
3391 | 905 | rc = next_entry(buf, fp, (sizeof(uint32_t) * 3)); |
3392 | 905 | if (rc < 0) |
3393 | 12 | goto bad; |
3394 | | |
3395 | 893 | len = le32_to_cpu(buf[0]); |
3396 | 893 | rc = str_read(&key, fp, len); |
3397 | 893 | if (rc < 0) |
3398 | 2 | goto bad; |
3399 | | |
3400 | 891 | catdatum->s.value = le32_to_cpu(buf[1]); |
3401 | 891 | catdatum->isalias = le32_to_cpu(buf[2]); |
3402 | | |
3403 | 891 | if (hashtab_insert(h, key, catdatum)) |
3404 | 2 | goto bad; |
3405 | | |
3406 | 889 | return 0; |
3407 | | |
3408 | 16 | bad: |
3409 | 16 | cat_destroy(key, catdatum, NULL); |
3410 | 16 | return -1; |
3411 | 891 | } |
3412 | | |
3413 | | static int (*const read_f[SYM_NUM]) (policydb_t * p, hashtab_t h, |
3414 | | struct policy_file * fp) = { |
3415 | | common_read, class_read, role_read, type_read, user_read, |
3416 | | cond_read_bool, sens_read, cat_read,}; |
3417 | | |
3418 | | /************** module reading functions below **************/ |
3419 | | |
3420 | | static avrule_t *avrule_read(policydb_t * p, struct policy_file *fp) |
3421 | 2.20k | { |
3422 | 2.20k | unsigned int i; |
3423 | 2.20k | uint32_t buf[2], len; |
3424 | 2.20k | class_perm_node_t *cur, *tail = NULL; |
3425 | 2.20k | avrule_t *avrule; |
3426 | 2.20k | int rc; |
3427 | | |
3428 | 2.20k | avrule = (avrule_t *) malloc(sizeof(avrule_t)); |
3429 | 2.20k | if (!avrule) |
3430 | 0 | return NULL; |
3431 | | |
3432 | 2.20k | avrule_init(avrule); |
3433 | | |
3434 | 2.20k | rc = next_entry(buf, fp, sizeof(uint32_t) * 2); |
3435 | 2.20k | if (rc < 0) |
3436 | 122 | goto bad; |
3437 | | |
3438 | 2.08k | avrule->specified = le32_to_cpu(buf[0]); |
3439 | 2.08k | avrule->flags = le32_to_cpu(buf[1]); |
3440 | | |
3441 | 2.08k | if (type_set_read(&avrule->stypes, fp)) |
3442 | 14 | goto bad; |
3443 | | |
3444 | 2.06k | if (type_set_read(&avrule->ttypes, fp)) |
3445 | 13 | goto bad; |
3446 | | |
3447 | 2.05k | rc = next_entry(buf, fp, sizeof(uint32_t)); |
3448 | 2.05k | if (rc < 0) |
3449 | 7 | goto bad; |
3450 | 2.04k | len = le32_to_cpu(buf[0]); |
3451 | | |
3452 | 2.73k | for (i = 0; i < len; i++) { |
3453 | 743 | cur = (class_perm_node_t *) malloc(sizeof(class_perm_node_t)); |
3454 | 743 | if (!cur) |
3455 | 0 | goto bad; |
3456 | 743 | class_perm_node_init(cur); |
3457 | | |
3458 | 743 | rc = next_entry(buf, fp, sizeof(uint32_t) * 2); |
3459 | 743 | if (rc < 0) { |
3460 | 55 | free(cur); |
3461 | 55 | goto bad; |
3462 | 55 | } |
3463 | | |
3464 | 688 | cur->tclass = le32_to_cpu(buf[0]); |
3465 | 688 | cur->data = le32_to_cpu(buf[1]); |
3466 | | |
3467 | 688 | if (!tail) { |
3468 | 314 | avrule->perms = cur; |
3469 | 374 | } else { |
3470 | 374 | tail->next = cur; |
3471 | 374 | } |
3472 | 688 | tail = cur; |
3473 | 688 | } |
3474 | | |
3475 | 1.99k | if (avrule->specified & AVRULE_XPERMS) { |
3476 | 559 | uint8_t buf8; |
3477 | 559 | size_t nel = ARRAY_SIZE(avrule->xperms->perms); |
3478 | 559 | uint32_t buf32[nel]; |
3479 | | |
3480 | 559 | if (p->policyvers < MOD_POLICYDB_VERSION_XPERMS_IOCTL) { |
3481 | 8 | ERR(fp->handle, |
3482 | 8 | "module policy version %u does not support ioctl" |
3483 | 8 | " extended permissions rules and one was specified", |
3484 | 8 | p->policyvers); |
3485 | 8 | goto bad; |
3486 | 8 | } |
3487 | | |
3488 | 551 | if (p->target_platform != SEPOL_TARGET_SELINUX) { |
3489 | 0 | ERR(fp->handle, |
3490 | 0 | "Target platform %s does not support ioctl" |
3491 | 0 | " extended permissions rules and one was specified", |
3492 | 0 | policydb_target_strings[p->target_platform]); |
3493 | 0 | goto bad; |
3494 | 0 | } |
3495 | | |
3496 | 551 | avrule->xperms = calloc(1, sizeof(*avrule->xperms)); |
3497 | 551 | if (!avrule->xperms) |
3498 | 0 | goto bad; |
3499 | | |
3500 | 551 | rc = next_entry(&buf8, fp, sizeof(uint8_t)); |
3501 | 551 | if (rc < 0) { |
3502 | 1 | ERR(fp->handle, "truncated entry"); |
3503 | 1 | goto bad; |
3504 | 1 | } |
3505 | 550 | avrule->xperms->specified = buf8; |
3506 | 550 | rc = next_entry(&buf8, fp, sizeof(uint8_t)); |
3507 | 550 | if (rc < 0) { |
3508 | 1 | ERR(fp->handle, "truncated entry"); |
3509 | 1 | goto bad; |
3510 | 1 | } |
3511 | 549 | avrule->xperms->driver = buf8; |
3512 | 549 | rc = next_entry(buf32, fp, sizeof(uint32_t)*nel); |
3513 | 549 | if (rc < 0) { |
3514 | 1 | ERR(fp->handle, "truncated entry"); |
3515 | 1 | goto bad; |
3516 | 1 | } |
3517 | 4.93k | for (i = 0; i < nel; i++) |
3518 | 4.38k | avrule->xperms->perms[i] = le32_to_cpu(buf32[i]); |
3519 | 548 | } |
3520 | | |
3521 | 1.98k | return avrule; |
3522 | 222 | bad: |
3523 | 222 | if (avrule) { |
3524 | 222 | avrule_destroy(avrule); |
3525 | 222 | free(avrule); |
3526 | 222 | } |
3527 | 222 | return NULL; |
3528 | 1.99k | } |
3529 | | |
3530 | | static int range_read(policydb_t * p, struct policy_file *fp) |
3531 | 2.69k | { |
3532 | 2.69k | uint32_t buf[2], nel; |
3533 | 2.69k | range_trans_t *rt = NULL; |
3534 | 2.69k | struct mls_range *r = NULL; |
3535 | 2.69k | range_trans_rule_t *rtr = NULL, *lrtr = NULL; |
3536 | 2.69k | unsigned int i; |
3537 | 2.69k | int new_rangetr = (p->policy_type == POLICY_KERN && |
3538 | 2.69k | p->policyvers >= POLICYDB_VERSION_RANGETRANS); |
3539 | 2.69k | int rc; |
3540 | | |
3541 | 2.69k | rc = next_entry(buf, fp, sizeof(uint32_t)); |
3542 | 2.69k | if (rc < 0) |
3543 | 2 | return -1; |
3544 | 2.69k | nel = le32_to_cpu(buf[0]); |
3545 | 2.82k | for (i = 0; i < nel; i++) { |
3546 | 180 | rt = calloc(1, sizeof(range_trans_t)); |
3547 | 180 | if (!rt) |
3548 | 0 | return -1; |
3549 | 180 | rc = next_entry(buf, fp, (sizeof(uint32_t) * 2)); |
3550 | 180 | if (rc < 0) |
3551 | 29 | goto err; |
3552 | 151 | rt->source_type = le32_to_cpu(buf[0]); |
3553 | 151 | if (!value_isvalid(rt->source_type, p->p_types.nprim)) |
3554 | 4 | goto err; |
3555 | 147 | rt->target_type = le32_to_cpu(buf[1]); |
3556 | 147 | if (!value_isvalid(rt->target_type, p->p_types.nprim)) |
3557 | 1 | goto err; |
3558 | 146 | if (new_rangetr) { |
3559 | 145 | rc = next_entry(buf, fp, (sizeof(uint32_t))); |
3560 | 145 | if (rc < 0) |
3561 | 1 | goto err; |
3562 | 144 | rt->target_class = le32_to_cpu(buf[0]); |
3563 | 144 | } else |
3564 | 1 | rt->target_class = p->process_class; |
3565 | 145 | if (!value_isvalid(rt->target_class, p->p_classes.nprim)) |
3566 | 3 | goto err; |
3567 | 142 | r = calloc(1, sizeof(*r)); |
3568 | 142 | if (!r) |
3569 | 0 | goto err; |
3570 | 142 | if (mls_read_range_helper(r, fp)) |
3571 | 5 | goto err; |
3572 | | |
3573 | 137 | if (p->policy_type == POLICY_KERN) { |
3574 | 137 | rc = hashtab_insert(p->range_tr, (hashtab_key_t)rt, r); |
3575 | 137 | if (rc) |
3576 | 9 | goto err; |
3577 | 128 | rt = NULL; |
3578 | 128 | r = NULL; |
3579 | 128 | continue; |
3580 | 137 | } |
3581 | | |
3582 | | /* Module policy: convert to range_trans_rule and discard. */ |
3583 | 0 | rtr = malloc(sizeof(range_trans_rule_t)); |
3584 | 0 | if (!rtr) |
3585 | 0 | goto err; |
3586 | 0 | range_trans_rule_init(rtr); |
3587 | |
|
3588 | 0 | if (ebitmap_set_bit(&rtr->stypes.types, rt->source_type - 1, 1)) |
3589 | 0 | goto err; |
3590 | | |
3591 | 0 | if (ebitmap_set_bit(&rtr->ttypes.types, rt->target_type - 1, 1)) |
3592 | 0 | goto err; |
3593 | | |
3594 | 0 | if (ebitmap_set_bit(&rtr->tclasses, rt->target_class - 1, 1)) |
3595 | 0 | goto err; |
3596 | | |
3597 | 0 | if (mls_range_to_semantic(r, &rtr->trange)) |
3598 | 0 | goto err; |
3599 | | |
3600 | 0 | if (lrtr) |
3601 | 0 | lrtr->next = rtr; |
3602 | 0 | else |
3603 | 0 | p->global->enabled->range_tr_rules = rtr; |
3604 | |
|
3605 | 0 | free(rt); |
3606 | 0 | rt = NULL; |
3607 | 0 | free(r); |
3608 | 0 | r = NULL; |
3609 | 0 | lrtr = rtr; |
3610 | 0 | } |
3611 | | |
3612 | 2.64k | return 0; |
3613 | 52 | err: |
3614 | 52 | free(rt); |
3615 | 52 | if (r) { |
3616 | 14 | mls_range_destroy(r); |
3617 | 14 | free(r); |
3618 | 14 | } |
3619 | 52 | if (rtr) { |
3620 | 0 | range_trans_rule_destroy(rtr); |
3621 | 0 | free(rtr); |
3622 | 0 | } |
3623 | 52 | return -1; |
3624 | 2.69k | } |
3625 | | |
3626 | | int avrule_read_list(policydb_t * p, avrule_t ** avrules, |
3627 | | struct policy_file *fp) |
3628 | 10.5k | { |
3629 | 10.5k | unsigned int i; |
3630 | 10.5k | avrule_t *cur, *tail; |
3631 | 10.5k | uint32_t buf[1], len; |
3632 | 10.5k | int rc; |
3633 | | |
3634 | 10.5k | *avrules = tail = NULL; |
3635 | | |
3636 | 10.5k | rc = next_entry(buf, fp, sizeof(uint32_t)); |
3637 | 10.5k | if (rc < 0) { |
3638 | 24 | return -1; |
3639 | 24 | } |
3640 | 10.5k | len = le32_to_cpu(buf[0]); |
3641 | | |
3642 | 12.5k | for (i = 0; i < len; i++) { |
3643 | 2.20k | cur = avrule_read(p, fp); |
3644 | 2.20k | if (!cur) { |
3645 | 222 | return -1; |
3646 | 222 | } |
3647 | | |
3648 | 1.98k | if (!tail) { |
3649 | 290 | *avrules = cur; |
3650 | 1.69k | } else { |
3651 | 1.69k | tail->next = cur; |
3652 | 1.69k | } |
3653 | 1.98k | tail = cur; |
3654 | 1.98k | } |
3655 | | |
3656 | 10.3k | return 0; |
3657 | 10.5k | } |
3658 | | |
3659 | | static int role_trans_rule_read(policydb_t *p, role_trans_rule_t ** r, |
3660 | | struct policy_file *fp) |
3661 | 8.50k | { |
3662 | 8.50k | uint32_t buf[1], nel; |
3663 | 8.50k | unsigned int i; |
3664 | 8.50k | role_trans_rule_t *tr, *ltr; |
3665 | 8.50k | int rc; |
3666 | | |
3667 | 8.50k | rc = next_entry(buf, fp, sizeof(uint32_t)); |
3668 | 8.50k | if (rc < 0) |
3669 | 11 | return -1; |
3670 | 8.48k | nel = le32_to_cpu(buf[0]); |
3671 | 8.48k | ltr = NULL; |
3672 | 8.79k | for (i = 0; i < nel; i++) { |
3673 | 391 | tr = malloc(sizeof(role_trans_rule_t)); |
3674 | 391 | if (!tr) { |
3675 | 0 | return -1; |
3676 | 0 | } |
3677 | 391 | role_trans_rule_init(tr); |
3678 | | |
3679 | 391 | if (ltr) { |
3680 | 305 | ltr->next = tr; |
3681 | 305 | } else { |
3682 | 86 | *r = tr; |
3683 | 86 | } |
3684 | | |
3685 | 391 | if (role_set_read(&tr->roles, fp)) |
3686 | 52 | return -1; |
3687 | | |
3688 | 339 | if (type_set_read(&tr->types, fp)) |
3689 | 13 | return -1; |
3690 | | |
3691 | 326 | if (p->policyvers >= MOD_POLICYDB_VERSION_ROLETRANS) { |
3692 | 322 | if (ebitmap_read(&tr->classes, fp)) |
3693 | 9 | return -1; |
3694 | 322 | } else { |
3695 | 4 | if (!p->process_class) |
3696 | 4 | return -1; |
3697 | 0 | if (ebitmap_set_bit(&tr->classes, p->process_class - 1, 1)) |
3698 | 0 | return -1; |
3699 | 0 | } |
3700 | | |
3701 | 313 | rc = next_entry(buf, fp, sizeof(uint32_t)); |
3702 | 313 | if (rc < 0) |
3703 | 7 | return -1; |
3704 | 306 | tr->new_role = le32_to_cpu(buf[0]); |
3705 | 306 | ltr = tr; |
3706 | 306 | } |
3707 | | |
3708 | 8.40k | return 0; |
3709 | 8.48k | } |
3710 | | |
3711 | | static int role_allow_rule_read(role_allow_rule_t ** r, struct policy_file *fp) |
3712 | 8.40k | { |
3713 | 8.40k | unsigned int i; |
3714 | 8.40k | uint32_t buf[1], nel; |
3715 | 8.40k | role_allow_rule_t *ra, *lra; |
3716 | 8.40k | int rc; |
3717 | | |
3718 | 8.40k | rc = next_entry(buf, fp, sizeof(uint32_t)); |
3719 | 8.40k | if (rc < 0) |
3720 | 7 | return -1; |
3721 | 8.39k | nel = le32_to_cpu(buf[0]); |
3722 | 8.39k | lra = NULL; |
3723 | 8.59k | for (i = 0; i < nel; i++) { |
3724 | 255 | ra = malloc(sizeof(role_allow_rule_t)); |
3725 | 255 | if (!ra) { |
3726 | 0 | return -1; |
3727 | 0 | } |
3728 | 255 | role_allow_rule_init(ra); |
3729 | | |
3730 | 255 | if (lra) { |
3731 | 125 | lra->next = ra; |
3732 | 130 | } else { |
3733 | 130 | *r = ra; |
3734 | 130 | } |
3735 | | |
3736 | 255 | if (role_set_read(&ra->roles, fp)) |
3737 | 53 | return -1; |
3738 | | |
3739 | 202 | if (role_set_read(&ra->new_roles, fp)) |
3740 | 8 | return -1; |
3741 | | |
3742 | 194 | lra = ra; |
3743 | 194 | } |
3744 | 8.33k | return 0; |
3745 | 8.39k | } |
3746 | | |
3747 | | static int filename_trans_rule_read(policydb_t *p, filename_trans_rule_t **r, |
3748 | | struct policy_file *fp) |
3749 | 3.73k | { |
3750 | 3.73k | uint32_t buf[3], nel, i, len; |
3751 | 3.73k | unsigned int entries; |
3752 | 3.73k | filename_trans_rule_t *ftr, *lftr; |
3753 | 3.73k | int rc; |
3754 | | |
3755 | 3.73k | rc = next_entry(buf, fp, sizeof(uint32_t)); |
3756 | 3.73k | if (rc < 0) |
3757 | 1 | return -1; |
3758 | 3.73k | nel = le32_to_cpu(buf[0]); |
3759 | 3.73k | lftr = NULL; |
3760 | 4.09k | for (i = 0; i < nel; i++) { |
3761 | 445 | ftr = malloc(sizeof(*ftr)); |
3762 | 445 | if (!ftr) |
3763 | 0 | return -1; |
3764 | | |
3765 | 445 | filename_trans_rule_init(ftr); |
3766 | | |
3767 | 445 | if (lftr) |
3768 | 179 | lftr->next = ftr; |
3769 | 266 | else |
3770 | 266 | *r = ftr; |
3771 | 445 | lftr = ftr; |
3772 | | |
3773 | 445 | rc = next_entry(buf, fp, sizeof(uint32_t)); |
3774 | 445 | if (rc < 0) |
3775 | 57 | return -1; |
3776 | | |
3777 | 388 | len = le32_to_cpu(buf[0]); |
3778 | | |
3779 | 388 | rc = str_read(&ftr->name, fp, len); |
3780 | 388 | if (rc < 0) |
3781 | 3 | return -1; |
3782 | | |
3783 | 385 | if (type_set_read(&ftr->stypes, fp)) |
3784 | 4 | return -1; |
3785 | | |
3786 | 381 | if (type_set_read(&ftr->ttypes, fp)) |
3787 | 10 | return -1; |
3788 | | |
3789 | 371 | if (p->policyvers >= MOD_POLICYDB_VERSION_SELF_TYPETRANS) |
3790 | 76 | entries = 3; |
3791 | 295 | else |
3792 | 295 | entries = 2; |
3793 | | |
3794 | 371 | rc = next_entry(buf, fp, sizeof(uint32_t) * entries); |
3795 | 371 | if (rc < 0) |
3796 | 13 | return -1; |
3797 | 358 | ftr->tclass = le32_to_cpu(buf[0]); |
3798 | 358 | ftr->otype = le32_to_cpu(buf[1]); |
3799 | 358 | if (p->policyvers >= MOD_POLICYDB_VERSION_SELF_TYPETRANS) |
3800 | 72 | ftr->flags = le32_to_cpu(buf[2]); |
3801 | 358 | } |
3802 | | |
3803 | 3.64k | return 0; |
3804 | 3.73k | } |
3805 | | |
3806 | | static int range_trans_rule_read(range_trans_rule_t ** r, |
3807 | | struct policy_file *fp) |
3808 | 4.71k | { |
3809 | 4.71k | uint32_t buf[1], nel; |
3810 | 4.71k | unsigned int i; |
3811 | 4.71k | range_trans_rule_t *rt, *lrt = NULL; |
3812 | 4.71k | int rc; |
3813 | | |
3814 | 4.71k | rc = next_entry(buf, fp, sizeof(uint32_t)); |
3815 | 4.71k | if (rc < 0) |
3816 | 20 | return -1; |
3817 | 4.69k | nel = le32_to_cpu(buf[0]); |
3818 | 5.84k | for (i = 0; i < nel; i++) { |
3819 | 1.25k | rt = malloc(sizeof(range_trans_rule_t)); |
3820 | 1.25k | if (!rt) { |
3821 | 0 | return -1; |
3822 | 0 | } |
3823 | 1.25k | range_trans_rule_init(rt); |
3824 | | |
3825 | 1.25k | if (lrt) |
3826 | 1.04k | lrt->next = rt; |
3827 | 204 | else |
3828 | 204 | *r = rt; |
3829 | | |
3830 | 1.25k | if (type_set_read(&rt->stypes, fp)) |
3831 | 68 | return -1; |
3832 | | |
3833 | 1.18k | if (type_set_read(&rt->ttypes, fp)) |
3834 | 11 | return -1; |
3835 | | |
3836 | 1.17k | if (ebitmap_read(&rt->tclasses, fp)) |
3837 | 8 | return -1; |
3838 | | |
3839 | 1.16k | if (mls_read_semantic_range_helper(&rt->trange, fp)) |
3840 | 12 | return -1; |
3841 | | |
3842 | 1.15k | lrt = rt; |
3843 | 1.15k | } |
3844 | | |
3845 | 4.59k | return 0; |
3846 | 4.69k | } |
3847 | | |
3848 | | static int scope_index_read(scope_index_t * scope_index, |
3849 | | unsigned int num_scope_syms, struct policy_file *fp) |
3850 | 16.1k | { |
3851 | 16.1k | unsigned int i; |
3852 | 16.1k | uint32_t buf[1]; |
3853 | 16.1k | int rc; |
3854 | | |
3855 | 144k | for (i = 0; i < num_scope_syms; i++) { |
3856 | 128k | if (ebitmap_read(scope_index->scope + i, fp) < 0) { |
3857 | 55 | return -1; |
3858 | 55 | } |
3859 | 128k | } |
3860 | 16.0k | rc = next_entry(buf, fp, sizeof(uint32_t)); |
3861 | 16.0k | if (rc < 0) |
3862 | 10 | return -1; |
3863 | 16.0k | scope_index->class_perms_len = le32_to_cpu(buf[0]); |
3864 | 16.0k | if (is_saturated(scope_index->class_perms_len) || |
3865 | 16.0k | exceeds_available_bytes(fp, scope_index->class_perms_len, sizeof(uint32_t) * 3)) |
3866 | 74 | return -1; |
3867 | 15.9k | if (scope_index->class_perms_len == 0) { |
3868 | 14.1k | scope_index->class_perms_map = NULL; |
3869 | 14.1k | return 0; |
3870 | 14.1k | } |
3871 | 1.84k | if ((scope_index->class_perms_map = |
3872 | 1.84k | calloc(scope_index->class_perms_len, |
3873 | 1.84k | sizeof(*scope_index->class_perms_map))) == NULL) { |
3874 | 0 | return -1; |
3875 | 0 | } |
3876 | 4.38k | for (i = 0; i < scope_index->class_perms_len; i++) { |
3877 | 2.57k | if (ebitmap_read(scope_index->class_perms_map + i, fp) < 0) { |
3878 | 40 | return -1; |
3879 | 40 | } |
3880 | 2.57k | } |
3881 | 1.80k | return 0; |
3882 | 1.84k | } |
3883 | | |
3884 | | static int avrule_decl_read(policydb_t * p, avrule_decl_t * decl, |
3885 | | unsigned int num_scope_syms, struct policy_file *fp) |
3886 | 8.91k | { |
3887 | 8.91k | uint32_t buf[2], nprim, nel; |
3888 | 8.91k | unsigned int i, j; |
3889 | 8.91k | int rc; |
3890 | | |
3891 | 8.91k | rc = next_entry(buf, fp, sizeof(uint32_t) * 2); |
3892 | 8.91k | if (rc < 0) |
3893 | 121 | return -1; |
3894 | 8.79k | decl->decl_id = le32_to_cpu(buf[0]); |
3895 | 8.79k | decl->enabled = le32_to_cpu(buf[1]); |
3896 | 8.79k | if (cond_read_list(p, &decl->cond_list, fp) == -1 || |
3897 | 8.79k | avrule_read_list(p, &decl->avrules, fp) == -1 || |
3898 | 8.79k | role_trans_rule_read(p, &decl->role_tr_rules, fp) == -1 || |
3899 | 8.79k | role_allow_rule_read(&decl->role_allow_rules, fp) == -1) { |
3900 | 462 | return -1; |
3901 | 462 | } |
3902 | | |
3903 | 8.33k | if (p->policyvers >= MOD_POLICYDB_VERSION_FILENAME_TRANS && |
3904 | 8.33k | filename_trans_rule_read(p, &decl->filename_trans_rules, fp)) |
3905 | 88 | return -1; |
3906 | | |
3907 | 8.24k | if (p->policyvers >= MOD_POLICYDB_VERSION_RANGETRANS && |
3908 | 8.24k | range_trans_rule_read(&decl->range_tr_rules, fp) == -1) { |
3909 | 119 | return -1; |
3910 | 119 | } |
3911 | 8.12k | if (scope_index_read(&decl->required, num_scope_syms, fp) == -1 || |
3912 | 8.12k | scope_index_read(&decl->declared, num_scope_syms, fp) == -1) { |
3913 | 179 | return -1; |
3914 | 179 | } |
3915 | | |
3916 | 70.4k | for (i = 0; i < num_scope_syms; i++) { |
3917 | 62.6k | rc = next_entry(buf, fp, sizeof(uint32_t) * 2); |
3918 | 62.6k | if (rc < 0) |
3919 | 33 | return -1; |
3920 | 62.6k | nprim = le32_to_cpu(buf[0]); |
3921 | 62.6k | if (is_saturated(nprim)) |
3922 | 1 | return -1; |
3923 | 62.6k | nel = le32_to_cpu(buf[1]); |
3924 | 80.8k | for (j = 0; j < nel; j++) { |
3925 | 18.2k | if (read_f[i] (p, decl->symtab[i].table, fp)) { |
3926 | 137 | return -1; |
3927 | 137 | } |
3928 | 18.2k | } |
3929 | 62.5k | decl->symtab[i].nprim = nprim; |
3930 | 62.5k | } |
3931 | 7.77k | return 0; |
3932 | 7.95k | } |
3933 | | |
3934 | | static int avrule_block_read(policydb_t * p, |
3935 | | avrule_block_t ** block, |
3936 | | unsigned int num_scope_syms, |
3937 | | struct policy_file *fp) |
3938 | 2.60k | { |
3939 | 2.60k | avrule_block_t *last_block = NULL, *curblock; |
3940 | 2.60k | uint32_t buf[1], num_blocks, nel; |
3941 | 2.60k | int rc; |
3942 | | |
3943 | 2.60k | assert(*block == NULL); |
3944 | | |
3945 | 2.60k | rc = next_entry(buf, fp, sizeof(uint32_t)); |
3946 | 2.60k | if (rc < 0) |
3947 | 1 | return -1; |
3948 | 2.60k | num_blocks = le32_to_cpu(buf[0]); |
3949 | 2.60k | nel = num_blocks; |
3950 | 13.2k | while (num_blocks > 0) { |
3951 | 11.8k | avrule_decl_t *last_decl = NULL, *curdecl; |
3952 | 11.8k | uint32_t num_decls; |
3953 | 11.8k | if ((curblock = calloc(1, sizeof(*curblock))) == NULL) { |
3954 | 0 | return -1; |
3955 | 0 | } |
3956 | 11.8k | rc = next_entry(buf, fp, sizeof(uint32_t)); |
3957 | 11.8k | if (rc < 0) { |
3958 | 75 | free(curblock); |
3959 | 75 | return -1; |
3960 | 75 | } |
3961 | | /* if this is the first block its non-optional, else its optional */ |
3962 | 11.8k | if (num_blocks != nel) |
3963 | 9.24k | curblock->flags |= AVRULE_OPTIONAL; |
3964 | | |
3965 | 11.8k | num_decls = le32_to_cpu(buf[0]); |
3966 | 19.5k | while (num_decls > 0) { |
3967 | 8.91k | if ((curdecl = avrule_decl_create(0)) == NULL) { |
3968 | 0 | avrule_block_destroy(curblock); |
3969 | 0 | return -1; |
3970 | 0 | } |
3971 | 8.91k | if (avrule_decl_read(p, curdecl, num_scope_syms, fp) == |
3972 | 8.91k | -1) { |
3973 | 1.14k | avrule_decl_destroy(curdecl); |
3974 | 1.14k | avrule_block_destroy(curblock); |
3975 | 1.14k | return -1; |
3976 | 1.14k | } |
3977 | 7.77k | if (curdecl->enabled) { |
3978 | 2.54k | if (curblock->enabled != NULL) { |
3979 | | /* probably a corrupt file */ |
3980 | 1 | avrule_decl_destroy(curdecl); |
3981 | 1 | avrule_block_destroy(curblock); |
3982 | 1 | return -1; |
3983 | 1 | } |
3984 | 2.54k | curblock->enabled = curdecl; |
3985 | 2.54k | } |
3986 | | /* one must be careful to reconstruct the |
3987 | | * decl chain in its correct order */ |
3988 | 7.77k | if (curblock->branch_list == NULL) { |
3989 | 4.50k | curblock->branch_list = curdecl; |
3990 | 4.50k | } else { |
3991 | 3.27k | assert(last_decl); |
3992 | 3.27k | last_decl->next = curdecl; |
3993 | 3.27k | } |
3994 | 7.77k | last_decl = curdecl; |
3995 | 7.77k | num_decls--; |
3996 | 7.77k | } |
3997 | | |
3998 | 10.6k | if (*block == NULL) { |
3999 | 1.55k | *block = curblock; |
4000 | 9.10k | } else { |
4001 | 9.10k | assert(last_block); |
4002 | 9.10k | last_block->next = curblock; |
4003 | 9.10k | } |
4004 | 10.6k | last_block = curblock; |
4005 | | |
4006 | 10.6k | num_blocks--; |
4007 | 10.6k | } |
4008 | | |
4009 | 1.39k | return 0; |
4010 | 2.60k | } |
4011 | | |
4012 | | static int scope_read(policydb_t * p, int symnum, struct policy_file *fp) |
4013 | 675 | { |
4014 | 675 | scope_datum_t *scope = NULL; |
4015 | 675 | uint32_t buf[2]; |
4016 | 675 | char *key = NULL; |
4017 | 675 | size_t key_len; |
4018 | 675 | unsigned int i; |
4019 | 675 | hashtab_t h = p->scope[symnum].table; |
4020 | 675 | int rc; |
4021 | | |
4022 | 675 | rc = next_entry(buf, fp, sizeof(uint32_t)); |
4023 | 675 | if (rc < 0) |
4024 | 58 | goto cleanup; |
4025 | 617 | key_len = le32_to_cpu(buf[0]); |
4026 | | |
4027 | 617 | rc = str_read(&key, fp, key_len); |
4028 | 617 | if (rc < 0) |
4029 | 2 | goto cleanup; |
4030 | | |
4031 | | /* ensure that there already exists a symbol with this key */ |
4032 | 615 | if (hashtab_search(p->symtab[symnum].table, key) == NULL) { |
4033 | 37 | goto cleanup; |
4034 | 37 | } |
4035 | | |
4036 | 578 | if ((scope = calloc(1, sizeof(*scope))) == NULL) { |
4037 | 0 | goto cleanup; |
4038 | 0 | } |
4039 | 578 | rc = next_entry(buf, fp, sizeof(uint32_t) * 2); |
4040 | 578 | if (rc < 0) |
4041 | 1 | goto cleanup; |
4042 | 577 | scope->scope = le32_to_cpu(buf[0]); |
4043 | 577 | scope->decl_ids_len = le32_to_cpu(buf[1]); |
4044 | 577 | if (zero_or_saturated(scope->decl_ids_len) || |
4045 | 577 | exceeds_available_bytes(fp, scope->decl_ids_len, sizeof(uint32_t))) { |
4046 | 54 | ERR(fp->handle, "invalid scope with no declaration"); |
4047 | 54 | goto cleanup; |
4048 | 54 | } |
4049 | 523 | if ((scope->decl_ids = |
4050 | 523 | calloc(scope->decl_ids_len, sizeof(uint32_t))) == NULL) { |
4051 | 0 | goto cleanup; |
4052 | 0 | } |
4053 | 523 | rc = next_entry(scope->decl_ids, fp, sizeof(uint32_t) * scope->decl_ids_len); |
4054 | 523 | if (rc < 0) |
4055 | 0 | goto cleanup; |
4056 | 9.36k | for (i = 0; i < scope->decl_ids_len; i++) { |
4057 | 8.84k | scope->decl_ids[i] = le32_to_cpu(scope->decl_ids[i]); |
4058 | 8.84k | } |
4059 | | |
4060 | 523 | if (strcmp(key, "object_r") == 0 && h == p->p_roles_scope.table) { |
4061 | | /* object_r was already added to this table in roles_init() */ |
4062 | 403 | scope_destroy(key, scope, NULL); |
4063 | 403 | } else { |
4064 | 120 | if (hashtab_insert(h, key, scope)) { |
4065 | 2 | goto cleanup; |
4066 | 2 | } |
4067 | 120 | } |
4068 | | |
4069 | 521 | return 0; |
4070 | | |
4071 | 154 | cleanup: |
4072 | 154 | scope_destroy(key, scope, NULL); |
4073 | 154 | return -1; |
4074 | 523 | } |
4075 | | |
4076 | | static sepol_security_class_t policydb_string_to_security_class( |
4077 | | struct policydb *policydb, |
4078 | | const char *class_name) |
4079 | 16.9k | { |
4080 | 16.9k | class_datum_t *tclass_datum; |
4081 | | |
4082 | 16.9k | tclass_datum = hashtab_search(policydb->p_classes.table, |
4083 | 16.9k | class_name); |
4084 | 16.9k | if (!tclass_datum) |
4085 | 16.5k | return 0; |
4086 | 340 | return tclass_datum->s.value; |
4087 | 16.9k | } |
4088 | | |
4089 | | static sepol_access_vector_t policydb_string_to_av_perm( |
4090 | | struct policydb *policydb, |
4091 | | sepol_security_class_t tclass, |
4092 | | const char *perm_name) |
4093 | 11.2k | { |
4094 | 11.2k | class_datum_t *tclass_datum; |
4095 | 11.2k | perm_datum_t *perm_datum; |
4096 | | |
4097 | 11.2k | if (!tclass || tclass > policydb->p_classes.nprim) |
4098 | 11.1k | return 0; |
4099 | 138 | tclass_datum = policydb->class_val_to_struct[tclass - 1]; |
4100 | | |
4101 | 138 | perm_datum = (perm_datum_t *) |
4102 | 138 | hashtab_search(tclass_datum->permissions.table, |
4103 | 138 | perm_name); |
4104 | 138 | if (perm_datum != NULL) |
4105 | 4 | return UINT32_C(1) << (perm_datum->s.value - 1); |
4106 | | |
4107 | 134 | if (tclass_datum->comdatum == NULL) |
4108 | 130 | return 0; |
4109 | | |
4110 | 4 | perm_datum = (perm_datum_t *) |
4111 | 4 | hashtab_search(tclass_datum->comdatum->permissions.table, |
4112 | 4 | perm_name); |
4113 | | |
4114 | 4 | if (perm_datum != NULL) |
4115 | 0 | return UINT32_C(1) << (perm_datum->s.value - 1); |
4116 | | |
4117 | 4 | return 0; |
4118 | 4 | } |
4119 | | |
4120 | | |
4121 | | /* |
4122 | | * Read the configuration data from a policy database binary |
4123 | | * representation file into a policy database structure. |
4124 | | */ |
4125 | | int policydb_read(policydb_t * p, struct policy_file *fp, unsigned verbose) |
4126 | 12.0k | { |
4127 | | |
4128 | 12.0k | unsigned int i, j, r_policyvers; |
4129 | 12.0k | uint32_t buf[5], nprim; |
4130 | 12.0k | size_t len, nel; |
4131 | 12.0k | char *policydb_str; |
4132 | 12.0k | const struct policydb_compat_info *info; |
4133 | 12.0k | unsigned int policy_type, bufindex; |
4134 | 12.0k | ebitmap_node_t *tnode; |
4135 | 12.0k | int rc; |
4136 | | |
4137 | | /* Read the magic number and string length. */ |
4138 | 12.0k | rc = next_entry(buf, fp, sizeof(uint32_t) * 2); |
4139 | 12.0k | if (rc < 0) |
4140 | 3 | return POLICYDB_ERROR; |
4141 | 36.2k | for (i = 0; i < 2; i++) |
4142 | 24.1k | buf[i] = le32_to_cpu(buf[i]); |
4143 | | |
4144 | 12.0k | if (buf[0] == POLICYDB_MAGIC) { |
4145 | 8.62k | policy_type = POLICY_KERN; |
4146 | 8.62k | } else if (buf[0] == POLICYDB_MOD_MAGIC) { |
4147 | 3.40k | policy_type = POLICY_MOD; |
4148 | 3.40k | } else { |
4149 | 66 | ERR(fp->handle, "policydb magic number %#08x does not " |
4150 | 66 | "match expected magic number %#08x or %#08x", |
4151 | 66 | buf[0], POLICYDB_MAGIC, POLICYDB_MOD_MAGIC); |
4152 | 66 | return POLICYDB_ERROR; |
4153 | 66 | } |
4154 | | |
4155 | 12.0k | len = buf[1]; |
4156 | 12.0k | if (len == 0 || len > POLICYDB_STRING_MAX_LENGTH) { |
4157 | 51 | ERR(fp->handle, "policydb string length %s ", len ? "too long" : "zero"); |
4158 | 51 | return POLICYDB_ERROR; |
4159 | 51 | } |
4160 | | |
4161 | 11.9k | policydb_str = malloc(len + 1); |
4162 | 11.9k | if (!policydb_str) { |
4163 | 0 | ERR(fp->handle, "unable to allocate memory for policydb " |
4164 | 0 | "string of length %zu", len); |
4165 | 0 | return POLICYDB_ERROR; |
4166 | 0 | } |
4167 | 11.9k | rc = next_entry(policydb_str, fp, len); |
4168 | 11.9k | if (rc < 0) { |
4169 | 9 | ERR(fp->handle, "truncated policydb string identifier"); |
4170 | 9 | free(policydb_str); |
4171 | 9 | return POLICYDB_ERROR; |
4172 | 9 | } |
4173 | 11.9k | policydb_str[len] = 0; |
4174 | | |
4175 | 11.9k | if (policy_type == POLICY_KERN) { |
4176 | 10.3k | for (i = 0; i < POLICYDB_TARGET_SZ; i++) { |
4177 | 10.2k | if ((strcmp(policydb_str, policydb_target_strings[i]) |
4178 | 10.2k | == 0)) { |
4179 | 8.51k | policydb_set_target_platform(p, i); |
4180 | 8.51k | break; |
4181 | 8.51k | } |
4182 | 10.2k | } |
4183 | | |
4184 | 8.58k | if (i == POLICYDB_TARGET_SZ) { |
4185 | 68 | ERR(fp->handle, "cannot find a valid target for policy " |
4186 | 68 | "string %s", policydb_str); |
4187 | 68 | free(policydb_str); |
4188 | 68 | return POLICYDB_ERROR; |
4189 | 68 | } |
4190 | 8.58k | } else { |
4191 | 3.38k | if (strcmp(policydb_str, POLICYDB_MOD_STRING)) { |
4192 | 139 | ERR(fp->handle, "invalid string identifier %s", |
4193 | 139 | policydb_str); |
4194 | 139 | free(policydb_str); |
4195 | 139 | return POLICYDB_ERROR; |
4196 | 139 | } |
4197 | 3.38k | } |
4198 | | |
4199 | | /* Done with policydb_str. */ |
4200 | 11.7k | free(policydb_str); |
4201 | 11.7k | policydb_str = NULL; |
4202 | | |
4203 | | /* Read the version, config, and table sizes (and policy type if it's a module). */ |
4204 | 11.7k | if (policy_type == POLICY_KERN) |
4205 | 8.51k | nel = 4; |
4206 | 3.24k | else |
4207 | 3.24k | nel = 5; |
4208 | | |
4209 | 11.7k | rc = next_entry(buf, fp, sizeof(uint32_t) * nel); |
4210 | 11.7k | if (rc < 0) |
4211 | 3 | return POLICYDB_ERROR; |
4212 | 62.0k | for (i = 0; i < nel; i++) |
4213 | 50.2k | buf[i] = le32_to_cpu(buf[i]); |
4214 | | |
4215 | 11.7k | bufindex = 0; |
4216 | | |
4217 | 11.7k | if (policy_type == POLICY_MOD) { |
4218 | | /* We know it's a module but not whether it's a base |
4219 | | module or regular binary policy module. buf[0] |
4220 | | tells us which. */ |
4221 | 3.24k | policy_type = buf[bufindex]; |
4222 | 3.24k | if (policy_type != POLICY_MOD && policy_type != POLICY_BASE) { |
4223 | 53 | ERR(fp->handle, "unknown module type: %#08x", |
4224 | 53 | policy_type); |
4225 | 53 | return POLICYDB_ERROR; |
4226 | 53 | } |
4227 | 3.18k | bufindex++; |
4228 | 3.18k | } |
4229 | | |
4230 | 11.7k | r_policyvers = buf[bufindex]; |
4231 | 11.7k | if (policy_type == POLICY_KERN) { |
4232 | 8.51k | if (r_policyvers < POLICYDB_VERSION_MIN || |
4233 | 8.51k | r_policyvers > POLICYDB_VERSION_MAX) { |
4234 | 53 | ERR(fp->handle, "policydb version %d does not match " |
4235 | 53 | "my version range %d-%d", buf[bufindex], |
4236 | 53 | POLICYDB_VERSION_MIN, POLICYDB_VERSION_MAX); |
4237 | 53 | return POLICYDB_ERROR; |
4238 | 53 | } |
4239 | 8.51k | } else if (policy_type == POLICY_BASE || policy_type == POLICY_MOD) { |
4240 | 3.18k | if (r_policyvers < MOD_POLICYDB_VERSION_MIN || |
4241 | 3.18k | r_policyvers > MOD_POLICYDB_VERSION_MAX) { |
4242 | 55 | ERR(fp->handle, "policydb module version %d does " |
4243 | 55 | "not match my version range %d-%d", |
4244 | 55 | buf[bufindex], MOD_POLICYDB_VERSION_MIN, |
4245 | 55 | MOD_POLICYDB_VERSION_MAX); |
4246 | 55 | return POLICYDB_ERROR; |
4247 | 55 | } |
4248 | 3.18k | } else { |
4249 | 0 | assert(0); |
4250 | 0 | } |
4251 | 11.5k | bufindex++; |
4252 | | |
4253 | | /* Set the policy type and version from the read values. */ |
4254 | 11.5k | p->policy_type = policy_type; |
4255 | 11.5k | p->policyvers = r_policyvers; |
4256 | | |
4257 | 11.5k | if (buf[bufindex] & POLICYDB_CONFIG_MLS) { |
4258 | 4.84k | p->mls = 1; |
4259 | 6.74k | } else { |
4260 | 6.74k | p->mls = 0; |
4261 | 6.74k | } |
4262 | | |
4263 | 11.5k | p->handle_unknown = buf[bufindex] & POLICYDB_CONFIG_UNKNOWN_MASK; |
4264 | | |
4265 | 11.5k | bufindex++; |
4266 | | |
4267 | 11.5k | info = policydb_lookup_compat(r_policyvers, policy_type, |
4268 | 11.5k | p->target_platform); |
4269 | 11.5k | if (!info) { |
4270 | 3 | ERR(fp->handle, "unable to find policy compat info " |
4271 | 3 | "for version %d", r_policyvers); |
4272 | 3 | goto bad; |
4273 | 3 | } |
4274 | | |
4275 | 11.5k | if (buf[bufindex] != info->sym_num |
4276 | 11.5k | || buf[bufindex + 1] != info->ocon_num) { |
4277 | 61 | ERR(fp->handle, |
4278 | 61 | "policydb table sizes (%d,%d) do not " "match mine (%d,%d)", |
4279 | 61 | buf[bufindex], buf[bufindex + 1], info->sym_num, |
4280 | 61 | info->ocon_num); |
4281 | 61 | goto bad; |
4282 | 61 | } |
4283 | | |
4284 | 11.5k | if (p->policy_type == POLICY_MOD) { |
4285 | | /* Get the module name and version */ |
4286 | 446 | if ((rc = next_entry(buf, fp, sizeof(uint32_t))) < 0) { |
4287 | 2 | goto bad; |
4288 | 2 | } |
4289 | 444 | len = le32_to_cpu(buf[0]); |
4290 | 444 | rc = str_read(&p->name, fp, len); |
4291 | 444 | if (rc < 0) |
4292 | 33 | goto bad; |
4293 | | |
4294 | 411 | if ((rc = next_entry(buf, fp, sizeof(uint32_t))) < 0) { |
4295 | 6 | goto bad; |
4296 | 6 | } |
4297 | 405 | len = le32_to_cpu(buf[0]); |
4298 | 405 | rc = str_read(&p->version, fp, len); |
4299 | 405 | if (rc < 0) |
4300 | 4 | goto bad; |
4301 | 405 | } |
4302 | | |
4303 | 11.4k | if ((p->policyvers >= POLICYDB_VERSION_POLCAP && |
4304 | 11.4k | p->policy_type == POLICY_KERN) || |
4305 | 11.4k | (p->policyvers >= MOD_POLICYDB_VERSION_POLCAP && |
4306 | 7.19k | p->policy_type == POLICY_BASE) || |
4307 | 11.4k | (p->policyvers >= MOD_POLICYDB_VERSION_POLCAP && |
4308 | 6.33k | p->policy_type == POLICY_MOD)) { |
4309 | 5.47k | if (ebitmap_read(&p->policycaps, fp)) |
4310 | 311 | goto bad; |
4311 | 5.47k | } |
4312 | | |
4313 | 11.1k | if (p->policyvers >= POLICYDB_VERSION_PERMISSIVE && |
4314 | 11.1k | p->policy_type == POLICY_KERN) { |
4315 | 3.97k | if (ebitmap_read(&p->permissive_map, fp)) |
4316 | 11 | goto bad; |
4317 | 3.97k | } |
4318 | | |
4319 | 82.1k | for (i = 0; i < info->sym_num; i++) { |
4320 | 72.9k | rc = next_entry(buf, fp, sizeof(uint32_t) * 2); |
4321 | 72.9k | if (rc < 0) |
4322 | 22 | goto bad; |
4323 | 72.9k | nprim = le32_to_cpu(buf[0]); |
4324 | 72.9k | if (is_saturated(nprim) || |
4325 | 72.9k | exceeds_available_bytes(fp, nprim, sizeof(uint32_t) * 3)) |
4326 | 98 | goto bad; |
4327 | 72.8k | nel = le32_to_cpu(buf[1]); |
4328 | 72.8k | if (nel && !nprim) { |
4329 | 43 | ERR(fp->handle, "unexpected items in symbol table with no symbol"); |
4330 | 43 | goto bad; |
4331 | 43 | } |
4332 | 90.4k | for (j = 0; j < nel; j++) { |
4333 | 19.4k | if (read_f[i] (p, p->symtab[i].table, fp)) |
4334 | 1.81k | goto bad; |
4335 | 19.4k | } |
4336 | | |
4337 | 70.9k | p->symtab[i].nprim = nprim; |
4338 | 70.9k | } |
4339 | | |
4340 | 9.18k | switch (p->target_platform) { |
4341 | 7.75k | case SEPOL_TARGET_SELINUX: |
4342 | 7.75k | p->process_class = policydb_string_to_security_class(p, "process"); |
4343 | 7.75k | p->dir_class = policydb_string_to_security_class(p, "dir"); |
4344 | 7.75k | break; |
4345 | 1.42k | case SEPOL_TARGET_XEN: |
4346 | 1.42k | p->process_class = policydb_string_to_security_class(p, "domain"); |
4347 | 1.42k | break; |
4348 | 0 | default: |
4349 | 0 | break; |
4350 | 9.18k | } |
4351 | | |
4352 | 9.18k | if (policy_type == POLICY_KERN) { |
4353 | 6.57k | if (avtab_read(&p->te_avtab, fp, r_policyvers)) |
4354 | 402 | goto bad; |
4355 | 6.17k | if (r_policyvers >= POLICYDB_VERSION_BOOL) |
4356 | 5.00k | if (cond_read_list(p, &p->cond_list, fp)) |
4357 | 949 | goto bad; |
4358 | 5.22k | if (role_trans_read(p, fp)) |
4359 | 95 | goto bad; |
4360 | 5.12k | if (role_allow_read(&p->role_allow, fp)) |
4361 | 11 | goto bad; |
4362 | 5.11k | if (r_policyvers >= POLICYDB_VERSION_FILENAME_TRANS && |
4363 | 5.11k | filename_trans_read(p, fp)) |
4364 | 688 | goto bad; |
4365 | 5.11k | } else { |
4366 | | /* first read the AV rule blocks, then the scope tables */ |
4367 | 2.60k | avrule_block_destroy(p->global); |
4368 | 2.60k | p->global = NULL; |
4369 | 2.60k | if (avrule_block_read(p, &p->global, info->sym_num, fp) == -1) { |
4370 | 1.21k | goto bad; |
4371 | 1.21k | } |
4372 | 1.39k | if (p->global == NULL) { |
4373 | 1 | ERR(fp->handle, "no avrule block in policy"); |
4374 | 1 | goto bad; |
4375 | 1 | } |
4376 | 11.4k | for (i = 0; i < info->sym_num; i++) { |
4377 | 10.2k | if ((rc = next_entry(buf, fp, sizeof(uint32_t))) < 0) { |
4378 | 11 | goto bad; |
4379 | 11 | } |
4380 | 10.2k | nel = le32_to_cpu(buf[0]); |
4381 | 10.7k | for (j = 0; j < nel; j++) { |
4382 | 675 | if (scope_read(p, i, fp)) |
4383 | 154 | goto bad; |
4384 | 675 | } |
4385 | 10.2k | } |
4386 | | |
4387 | 1.39k | } |
4388 | | |
4389 | 5.65k | if (policydb_index_decls(fp->handle, p)) |
4390 | 16 | goto bad; |
4391 | | |
4392 | 5.63k | if (policydb_index_classes(p)) |
4393 | 5 | goto bad; |
4394 | | |
4395 | 5.63k | switch (p->target_platform) { |
4396 | 4.21k | case SEPOL_TARGET_SELINUX: |
4397 | | /* fall through */ |
4398 | 5.63k | case SEPOL_TARGET_XEN: |
4399 | 5.63k | p->process_trans = policydb_string_to_av_perm(p, p->process_class, |
4400 | 5.63k | "transition"); |
4401 | 5.63k | p->process_trans_dyntrans = p->process_trans | |
4402 | 5.63k | policydb_string_to_av_perm(p, p->process_class, |
4403 | 5.63k | "dyntransition"); |
4404 | 5.63k | break; |
4405 | 0 | default: |
4406 | 0 | break; |
4407 | 5.63k | } |
4408 | | |
4409 | 5.63k | if (policydb_index_others(fp->handle, p, verbose)) |
4410 | 338 | goto bad; |
4411 | | |
4412 | 5.29k | if (ocontext_read(info, p, fp) == -1) { |
4413 | 1.16k | goto bad; |
4414 | 1.16k | } |
4415 | | |
4416 | 4.12k | if (genfs_read(p, fp) == -1) { |
4417 | 481 | goto bad; |
4418 | 481 | } |
4419 | | |
4420 | 3.64k | if ((p->policy_type == POLICY_KERN |
4421 | 3.64k | && p->policyvers >= POLICYDB_VERSION_MLS) |
4422 | 3.64k | || (p->policy_type == POLICY_BASE |
4423 | 959 | && p->policyvers >= MOD_POLICYDB_VERSION_MLS |
4424 | 2.69k | && p->policyvers < MOD_POLICYDB_VERSION_RANGETRANS)) { |
4425 | 2.69k | if (range_read(p, fp)) { |
4426 | 54 | goto bad; |
4427 | 54 | } |
4428 | 2.69k | } |
4429 | | |
4430 | 3.59k | if (policy_type == POLICY_KERN) { |
4431 | 2.80k | p->type_attr_map = calloc(p->p_types.nprim, sizeof(ebitmap_t)); |
4432 | 2.80k | p->attr_type_map = calloc(p->p_types.nprim, sizeof(ebitmap_t)); |
4433 | 2.80k | if (!p->type_attr_map || !p->attr_type_map) |
4434 | 0 | goto bad; |
4435 | 17.1k | for (i = 0; i < p->p_types.nprim; i++) { |
4436 | 14.4k | if (r_policyvers >= POLICYDB_VERSION_AVTAB) { |
4437 | 3.29k | if (ebitmap_read(&p->type_attr_map[i], fp)) |
4438 | 20 | goto bad; |
4439 | 28.8k | ebitmap_for_each_positive_bit(&p->type_attr_map[i], |
4440 | 28.8k | tnode, j) { |
4441 | 7.13k | if (i == j) |
4442 | 229 | continue; |
4443 | | |
4444 | 6.90k | if (j >= p->p_types.nprim) |
4445 | 91 | goto bad; |
4446 | | |
4447 | 6.81k | if (ebitmap_set_bit |
4448 | 6.81k | (&p->attr_type_map[j], i, 1)) |
4449 | 0 | goto bad; |
4450 | 6.81k | } |
4451 | 3.27k | } |
4452 | | /* add the type itself as the degenerate case */ |
4453 | 14.3k | if (p->type_val_to_struct[i] && ebitmap_set_bit(&p->type_attr_map[i], i, 1)) |
4454 | 0 | goto bad; |
4455 | 14.3k | if (p->type_val_to_struct[i] && p->type_val_to_struct[i]->flavor != TYPE_ATTRIB) { |
4456 | 1.91k | if (ebitmap_set_bit(&p->attr_type_map[i], i, 1)) |
4457 | 0 | goto bad; |
4458 | 1.91k | } |
4459 | 14.3k | } |
4460 | 2.80k | } |
4461 | | |
4462 | 3.48k | if (policydb_validate(fp->handle, p)) |
4463 | 2.54k | goto bad; |
4464 | | |
4465 | 937 | return POLICYDB_SUCCESS; |
4466 | 10.6k | bad: |
4467 | 10.6k | return POLICYDB_ERROR; |
4468 | 3.48k | } |
4469 | | |
4470 | | int policydb_reindex_users(policydb_t * p) |
4471 | 0 | { |
4472 | 0 | unsigned int i = SYM_USERS; |
4473 | |
|
4474 | 0 | if (p->user_val_to_struct) |
4475 | 0 | free(p->user_val_to_struct); |
4476 | 0 | if (p->sym_val_to_name[i]) |
4477 | 0 | free(p->sym_val_to_name[i]); |
4478 | |
|
4479 | 0 | p->user_val_to_struct = (user_datum_t **) |
4480 | 0 | calloc(p->p_users.nprim, sizeof(user_datum_t *)); |
4481 | 0 | if (!p->user_val_to_struct) |
4482 | 0 | return -1; |
4483 | | |
4484 | 0 | p->sym_val_to_name[i] = (char **) |
4485 | 0 | calloc(p->symtab[i].nprim, sizeof(char *)); |
4486 | 0 | if (!p->sym_val_to_name[i]) |
4487 | 0 | return -1; |
4488 | | |
4489 | 0 | if (hashtab_map(p->symtab[i].table, index_f[i], p)) |
4490 | 0 | return -1; |
4491 | | |
4492 | | /* Expand user roles for context validity checking */ |
4493 | 0 | if (hashtab_map(p->p_users.table, policydb_user_cache, p)) |
4494 | 0 | return -1; |
4495 | | |
4496 | 0 | return 0; |
4497 | 0 | } |
4498 | | |
4499 | | void policy_file_init(policy_file_t *pf) |
4500 | 13.1k | { |
4501 | 13.1k | memset(pf, 0, sizeof(policy_file_t)); |
4502 | 13.1k | } |
4503 | | |
4504 | | int policydb_set_target_platform(policydb_t *p, int platform) |
4505 | 8.51k | { |
4506 | 8.51k | if (platform == SEPOL_TARGET_SELINUX) |
4507 | 6.90k | p->target_platform = SEPOL_TARGET_SELINUX; |
4508 | 1.60k | else if (platform == SEPOL_TARGET_XEN) |
4509 | 1.60k | p->target_platform = SEPOL_TARGET_XEN; |
4510 | 0 | else |
4511 | 0 | return -1; |
4512 | | |
4513 | 8.51k | return 0; |
4514 | 8.51k | } |
4515 | | |
4516 | | int policydb_sort_ocontexts(policydb_t *p) |
4517 | 0 | { |
4518 | 0 | return sort_ocontexts(p); |
4519 | 0 | } |