1 /* Author: Karl MacMillan <kmacmillan@tresys.com>
2 * Jason Tang <jtang@tresys.com>
3 * Chris PeBenito <cpebenito@tresys.com>
4 *
5 * Copyright (C) 2004-2005 Tresys Technology, LLC
6 *
7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation; either
10 * version 2.1 of the License, or (at your option) any later version.
11 *
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
16 *
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with this library; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
20 */
21
22 #include "policydb_internal.h"
23 #include "module_internal.h"
24 #include <sepol/policydb/link.h>
25 #include <sepol/policydb/expand.h>
26 #include <sepol/policydb/module.h>
27 #include "debug.h"
28 #include "private.h"
29
30 #include <stdio.h>
31 #include <stdlib.h>
32 #include <limits.h>
33
34 #define SEPOL_PACKAGE_SECTION_FC 0xf97cff90
35 #define SEPOL_PACKAGE_SECTION_SEUSER 0x97cff91
36 #define SEPOL_PACKAGE_SECTION_USER_EXTRA 0x97cff92
37 #define SEPOL_PACKAGE_SECTION_NETFILTER 0x97cff93
38
policy_file_seek(struct policy_file * fp,size_t offset)39 static int policy_file_seek(struct policy_file *fp, size_t offset)
40 {
41 switch (fp->type) {
42 case PF_USE_STDIO:
43 if (offset > LONG_MAX) {
44 errno = EFAULT;
45 return -1;
46 }
47 return fseek(fp->fp, (long)offset, SEEK_SET);
48 case PF_USE_MEMORY:
49 if (offset > fp->size) {
50 errno = EFAULT;
51 return -1;
52 }
53 fp->data -= fp->size - fp->len;
54 fp->data += offset;
55 fp->len = fp->size - offset;
56 return 0;
57 default:
58 return 0;
59 }
60 }
61
policy_file_length(struct policy_file * fp)62 static size_t policy_file_length(struct policy_file *fp)
63 {
64 long prev_offset, end_offset;
65 switch (fp->type) {
66 case PF_USE_STDIO:
67 prev_offset = ftell(fp->fp);
68 fseek(fp->fp, 0L, SEEK_END);
69 end_offset = ftell(fp->fp);
70 fseek(fp->fp, prev_offset, SEEK_SET);
71 return end_offset;
72 case PF_USE_MEMORY:
73 return fp->size;
74 default:
75 return 0;
76 }
77 }
78
module_package_init(sepol_module_package_t * p)79 static int module_package_init(sepol_module_package_t * p)
80 {
81 memset(p, 0, sizeof(sepol_module_package_t));
82 if (sepol_policydb_create(&p->policy))
83 return -1;
84
85 p->version = 1;
86 return 0;
87 }
88
set_char(char ** field,char * data,size_t len)89 static int set_char(char **field, char *data, size_t len)
90 {
91 if (*field) {
92 free(*field);
93 *field = NULL;
94 }
95 if (len) {
96 *field = malloc(len);
97 if (!*field)
98 return -1;
99 memcpy(*field, data, len);
100 }
101 return 0;
102 }
103
sepol_module_package_create(sepol_module_package_t ** p)104 int sepol_module_package_create(sepol_module_package_t ** p)
105 {
106 *p = calloc(1, sizeof(sepol_module_package_t));
107 if (!(*p))
108 return -1;
109 return module_package_init(*p);
110 }
111
hidden_def(sepol_module_package_create)112 hidden_def(sepol_module_package_create)
113
114 /* Deallocates all memory associated with a module package, including
115 * the pointer itself. Does nothing if p is NULL.
116 */
117 void sepol_module_package_free(sepol_module_package_t * p)
118 {
119 if (p == NULL)
120 return;
121
122 sepol_policydb_free(p->policy);
123 free(p->file_contexts);
124 free(p->seusers);
125 free(p->user_extra);
126 free(p->netfilter_contexts);
127 free(p);
128 }
129
hidden_def(sepol_module_package_free)130 hidden_def(sepol_module_package_free)
131
132 char *sepol_module_package_get_file_contexts(sepol_module_package_t * p)
133 {
134 return p->file_contexts;
135 }
136
sepol_module_package_get_file_contexts_len(sepol_module_package_t * p)137 size_t sepol_module_package_get_file_contexts_len(sepol_module_package_t * p)
138 {
139 return p->file_contexts_len;
140 }
141
sepol_module_package_get_seusers(sepol_module_package_t * p)142 char *sepol_module_package_get_seusers(sepol_module_package_t * p)
143 {
144 return p->seusers;
145 }
146
sepol_module_package_get_seusers_len(sepol_module_package_t * p)147 size_t sepol_module_package_get_seusers_len(sepol_module_package_t * p)
148 {
149 return p->seusers_len;
150 }
151
sepol_module_package_get_user_extra(sepol_module_package_t * p)152 char *sepol_module_package_get_user_extra(sepol_module_package_t * p)
153 {
154 return p->user_extra;
155 }
156
sepol_module_package_get_user_extra_len(sepol_module_package_t * p)157 size_t sepol_module_package_get_user_extra_len(sepol_module_package_t * p)
158 {
159 return p->user_extra_len;
160 }
161
sepol_module_package_get_netfilter_contexts(sepol_module_package_t * p)162 char *sepol_module_package_get_netfilter_contexts(sepol_module_package_t * p)
163 {
164 return p->netfilter_contexts;
165 }
166
sepol_module_package_get_netfilter_contexts_len(sepol_module_package_t * p)167 size_t sepol_module_package_get_netfilter_contexts_len(sepol_module_package_t *
168 p)
169 {
170 return p->netfilter_contexts_len;
171 }
172
sepol_module_package_set_file_contexts(sepol_module_package_t * p,char * data,size_t len)173 int sepol_module_package_set_file_contexts(sepol_module_package_t * p,
174 char *data, size_t len)
175 {
176 if (set_char(&p->file_contexts, data, len))
177 return -1;
178
179 p->file_contexts_len = len;
180 return 0;
181 }
182
sepol_module_package_set_seusers(sepol_module_package_t * p,char * data,size_t len)183 int sepol_module_package_set_seusers(sepol_module_package_t * p,
184 char *data, size_t len)
185 {
186 if (set_char(&p->seusers, data, len))
187 return -1;
188
189 p->seusers_len = len;
190 return 0;
191 }
192
sepol_module_package_set_user_extra(sepol_module_package_t * p,char * data,size_t len)193 int sepol_module_package_set_user_extra(sepol_module_package_t * p,
194 char *data, size_t len)
195 {
196 if (set_char(&p->user_extra, data, len))
197 return -1;
198
199 p->user_extra_len = len;
200 return 0;
201 }
202
sepol_module_package_set_netfilter_contexts(sepol_module_package_t * p,char * data,size_t len)203 int sepol_module_package_set_netfilter_contexts(sepol_module_package_t * p,
204 char *data, size_t len)
205 {
206 if (set_char(&p->netfilter_contexts, data, len))
207 return -1;
208
209 p->netfilter_contexts_len = len;
210 return 0;
211 }
212
sepol_module_package_get_policy(sepol_module_package_t * p)213 sepol_policydb_t *sepol_module_package_get_policy(sepol_module_package_t * p)
214 {
215 return p->policy;
216 }
217
218 /* Append each of the file contexts from each module to the base
219 * policy's file context. 'base_context' will be reallocated to a
220 * larger size (and thus it is an in/out reference
221 * variable). 'base_fc_len' is the length of base's file context; it
222 * too is a reference variable. Return 0 on success, -1 if out of
223 * memory. */
link_file_contexts(sepol_module_package_t * base,sepol_module_package_t ** modules,int num_modules)224 static int link_file_contexts(sepol_module_package_t * base,
225 sepol_module_package_t ** modules,
226 int num_modules)
227 {
228 size_t fc_len;
229 int i;
230 char *s;
231
232 fc_len = base->file_contexts_len;
233 for (i = 0; i < num_modules; i++) {
234 fc_len += modules[i]->file_contexts_len;
235 }
236
237 if ((s = (char *)realloc(base->file_contexts, fc_len)) == NULL) {
238 return -1;
239 }
240 base->file_contexts = s;
241 for (i = 0; i < num_modules; i++) {
242 memcpy(base->file_contexts + base->file_contexts_len,
243 modules[i]->file_contexts,
244 modules[i]->file_contexts_len);
245 base->file_contexts_len += modules[i]->file_contexts_len;
246 }
247 return 0;
248 }
249
250 /* Append each of the netfilter contexts from each module to the base
251 * policy's netfilter context. 'base_context' will be reallocated to a
252 * larger size (and thus it is an in/out reference
253 * variable). 'base_nc_len' is the length of base's netfilter contexts; it
254 * too is a reference variable. Return 0 on success, -1 if out of
255 * memory. */
link_netfilter_contexts(sepol_module_package_t * base,sepol_module_package_t ** modules,int num_modules)256 static int link_netfilter_contexts(sepol_module_package_t * base,
257 sepol_module_package_t ** modules,
258 int num_modules)
259 {
260 size_t base_nc_len;
261 int i;
262 char *base_context;
263
264 base_nc_len = base->netfilter_contexts_len;
265 for (i = 0; i < num_modules; i++) {
266 base_nc_len += modules[i]->netfilter_contexts_len;
267 }
268
269 if ((base_context =
270 (char *)realloc(base->netfilter_contexts, base_nc_len)) == NULL) {
271 return -1;
272 }
273 base->netfilter_contexts = base_context;
274 for (i = 0; i < num_modules; i++) {
275 memcpy(base->netfilter_contexts + base->netfilter_contexts_len,
276 modules[i]->netfilter_contexts,
277 modules[i]->netfilter_contexts_len);
278 base->netfilter_contexts_len +=
279 modules[i]->netfilter_contexts_len;
280 }
281 return 0;
282 }
283
284 /* Links the module packages into the base. Returns 0 on success, -1
285 * if a requirement was not met, or -2 for all other errors. */
sepol_link_packages(sepol_handle_t * handle,sepol_module_package_t * base,sepol_module_package_t ** modules,int num_modules,int verbose)286 int sepol_link_packages(sepol_handle_t * handle,
287 sepol_module_package_t * base,
288 sepol_module_package_t ** modules, int num_modules,
289 int verbose)
290 {
291 policydb_t **mod_pols = NULL;
292 int i, retval;
293
294 if ((mod_pols = calloc(num_modules, sizeof(*mod_pols))) == NULL) {
295 ERR(handle, "Out of memory!");
296 return -2;
297 }
298 for (i = 0; i < num_modules; i++) {
299 mod_pols[i] = &modules[i]->policy->p;
300 }
301
302 retval = link_modules(handle, &base->policy->p, mod_pols, num_modules,
303 verbose);
304 free(mod_pols);
305 if (retval == -3) {
306 return -1;
307 } else if (retval < 0) {
308 return -2;
309 }
310
311 if (link_file_contexts(base, modules, num_modules) == -1) {
312 ERR(handle, "Out of memory!");
313 return -2;
314 }
315
316 if (link_netfilter_contexts(base, modules, num_modules) == -1) {
317 ERR(handle, "Out of memory!");
318 return -2;
319 }
320
321 return 0;
322 }
323
324 /* buf must be large enough - no checks are performed */
325 #define _read_helper_bufsize BUFSIZ
read_helper(char * buf,struct policy_file * file,uint32_t bytes)326 static int read_helper(char *buf, struct policy_file *file, uint32_t bytes)
327 {
328 uint32_t offset, nel, read_len;
329 int rc;
330
331 offset = 0;
332 nel = bytes;
333
334 while (nel) {
335 if (nel < _read_helper_bufsize)
336 read_len = nel;
337 else
338 read_len = _read_helper_bufsize;
339 rc = next_entry(&buf[offset], file, read_len);
340 if (rc < 0)
341 return -1;
342 offset += read_len;
343 nel -= read_len;
344 }
345 return 0;
346 }
347
348 #define MAXSECTIONS 100
349
350 /* Get the section offsets from a package file, offsets will be malloc'd to
351 * the appropriate size and the caller must free() them */
module_package_read_offsets(sepol_module_package_t * mod,struct policy_file * file,size_t ** offsets,uint32_t * sections)352 static int module_package_read_offsets(sepol_module_package_t * mod,
353 struct policy_file *file,
354 size_t ** offsets, uint32_t * sections)
355 {
356 uint32_t *buf = NULL, nsec;
357 unsigned i;
358 size_t *off = NULL;
359 int rc;
360
361 buf = malloc(sizeof(uint32_t)*3);
362 if (!buf) {
363 ERR(file->handle, "out of memory");
364 goto err;
365 }
366
367 rc = next_entry(buf, file, sizeof(uint32_t) * 3);
368 if (rc < 0) {
369 ERR(file->handle, "module package header truncated");
370 goto err;
371 }
372 if (le32_to_cpu(buf[0]) != SEPOL_MODULE_PACKAGE_MAGIC) {
373 ERR(file->handle,
374 "wrong magic number for module package: expected %#08x, got %#08x",
375 SEPOL_MODULE_PACKAGE_MAGIC, le32_to_cpu(buf[0]));
376 goto err;
377 }
378
379 mod->version = le32_to_cpu(buf[1]);
380 nsec = *sections = le32_to_cpu(buf[2]);
381
382 if (nsec > MAXSECTIONS) {
383 ERR(file->handle, "too many sections (%u) in module package",
384 nsec);
385 goto err;
386 }
387
388 off = (size_t *) malloc((nsec + 1) * sizeof(size_t));
389 if (!off) {
390 ERR(file->handle, "out of memory");
391 goto err;
392 }
393
394 free(buf);
395 buf = malloc(sizeof(uint32_t) * nsec);
396 if (!buf) {
397 ERR(file->handle, "out of memory");
398 goto err;
399 }
400 rc = next_entry(buf, file, sizeof(uint32_t) * nsec);
401 if (rc < 0) {
402 ERR(file->handle, "module package offset array truncated");
403 goto err;
404 }
405
406 for (i = 0; i < nsec; i++) {
407 off[i] = le32_to_cpu(buf[i]);
408 if (i && off[i] < off[i - 1]) {
409 ERR(file->handle, "offsets are not increasing (at %u, "
410 "offset %zu -> %zu", i, off[i - 1],
411 off[i]);
412 goto err;
413 }
414 }
415
416 off[nsec] = policy_file_length(file);
417 if (nsec && off[nsec] < off[nsec-1]) {
418 ERR(file->handle, "offset greater than file size (at %u, "
419 "offset %zu -> %zu", nsec, off[nsec - 1],
420 off[nsec]);
421 goto err;
422 }
423 *offsets = off;
424 free(buf);
425 return 0;
426
427 err:
428 free(buf);
429 free(off);
430 return -1;
431 }
432
433 /* Flags for which sections have been seen during parsing of module package. */
434 #define SEEN_MOD 1
435 #define SEEN_FC 2
436 #define SEEN_SEUSER 4
437 #define SEEN_USER_EXTRA 8
438 #define SEEN_NETFILTER 16
439
sepol_module_package_read(sepol_module_package_t * mod,struct sepol_policy_file * spf,int verbose)440 int sepol_module_package_read(sepol_module_package_t * mod,
441 struct sepol_policy_file *spf, int verbose)
442 {
443 struct policy_file *file = &spf->pf;
444 uint32_t buf[1], nsec;
445 size_t *offsets, len;
446 int rc;
447 unsigned i, seen = 0;
448
449 if (module_package_read_offsets(mod, file, &offsets, &nsec))
450 return -1;
451
452 /* we know the section offsets, seek to them and read in the data */
453
454 for (i = 0; i < nsec; i++) {
455
456 if (policy_file_seek(file, offsets[i])) {
457 ERR(file->handle, "error seeking to offset %zu for "
458 "module package section %u", offsets[i], i);
459 goto cleanup;
460 }
461
462 len = offsets[i + 1] - offsets[i];
463
464 if (len < sizeof(uint32_t)) {
465 ERR(file->handle, "module package section %u "
466 "has too small length %zu", i, len);
467 goto cleanup;
468 }
469
470 /* read the magic number, so that we know which function to call */
471 rc = next_entry(buf, file, sizeof(uint32_t));
472 if (rc < 0) {
473 ERR(file->handle,
474 "module package section %u truncated, lacks magic number",
475 i);
476 goto cleanup;
477 }
478
479 switch (le32_to_cpu(buf[0])) {
480 case SEPOL_PACKAGE_SECTION_FC:
481 if (seen & SEEN_FC) {
482 ERR(file->handle,
483 "found multiple file contexts sections in module package (at section %u)",
484 i);
485 goto cleanup;
486 }
487
488 mod->file_contexts_len = len - sizeof(uint32_t);
489 mod->file_contexts =
490 (char *)malloc(mod->file_contexts_len);
491 if (!mod->file_contexts) {
492 ERR(file->handle, "out of memory");
493 goto cleanup;
494 }
495 if (read_helper
496 (mod->file_contexts, file,
497 mod->file_contexts_len)) {
498 ERR(file->handle,
499 "invalid file contexts section at section %u",
500 i);
501 free(mod->file_contexts);
502 mod->file_contexts = NULL;
503 goto cleanup;
504 }
505 seen |= SEEN_FC;
506 break;
507 case SEPOL_PACKAGE_SECTION_SEUSER:
508 if (seen & SEEN_SEUSER) {
509 ERR(file->handle,
510 "found multiple seuser sections in module package (at section %u)",
511 i);
512 goto cleanup;
513 }
514
515 mod->seusers_len = len - sizeof(uint32_t);
516 mod->seusers = (char *)malloc(mod->seusers_len);
517 if (!mod->seusers) {
518 ERR(file->handle, "out of memory");
519 goto cleanup;
520 }
521 if (read_helper(mod->seusers, file, mod->seusers_len)) {
522 ERR(file->handle,
523 "invalid seuser section at section %u", i);
524 free(mod->seusers);
525 mod->seusers = NULL;
526 goto cleanup;
527 }
528 seen |= SEEN_SEUSER;
529 break;
530 case SEPOL_PACKAGE_SECTION_USER_EXTRA:
531 if (seen & SEEN_USER_EXTRA) {
532 ERR(file->handle,
533 "found multiple user_extra sections in module package (at section %u)",
534 i);
535 goto cleanup;
536 }
537
538 mod->user_extra_len = len - sizeof(uint32_t);
539 mod->user_extra = (char *)malloc(mod->user_extra_len);
540 if (!mod->user_extra) {
541 ERR(file->handle, "out of memory");
542 goto cleanup;
543 }
544 if (read_helper
545 (mod->user_extra, file, mod->user_extra_len)) {
546 ERR(file->handle,
547 "invalid user_extra section at section %u",
548 i);
549 free(mod->user_extra);
550 mod->user_extra = NULL;
551 goto cleanup;
552 }
553 seen |= SEEN_USER_EXTRA;
554 break;
555 case SEPOL_PACKAGE_SECTION_NETFILTER:
556 if (seen & SEEN_NETFILTER) {
557 ERR(file->handle,
558 "found multiple netfilter contexts sections in module package (at section %u)",
559 i);
560 goto cleanup;
561 }
562
563 mod->netfilter_contexts_len = len - sizeof(uint32_t);
564 mod->netfilter_contexts =
565 (char *)malloc(mod->netfilter_contexts_len);
566 if (!mod->netfilter_contexts) {
567 ERR(file->handle, "out of memory");
568 goto cleanup;
569 }
570 if (read_helper
571 (mod->netfilter_contexts, file,
572 mod->netfilter_contexts_len)) {
573 ERR(file->handle,
574 "invalid netfilter contexts section at section %u",
575 i);
576 free(mod->netfilter_contexts);
577 mod->netfilter_contexts = NULL;
578 goto cleanup;
579 }
580 seen |= SEEN_NETFILTER;
581 break;
582 case POLICYDB_MOD_MAGIC:
583 if (seen & SEEN_MOD) {
584 ERR(file->handle,
585 "found multiple module sections in module package (at section %u)",
586 i);
587 goto cleanup;
588 }
589
590 /* seek back to where the magic number was */
591 if (policy_file_seek(file, offsets[i]))
592 goto cleanup;
593
594 rc = policydb_read(&mod->policy->p, file, verbose);
595 if (rc < 0) {
596 ERR(file->handle,
597 "invalid module in module package (at section %u)",
598 i);
599 goto cleanup;
600 }
601 seen |= SEEN_MOD;
602 break;
603 default:
604 /* unknown section, ignore */
605 ERR(file->handle,
606 "unknown magic number at section %u, offset: %zx, number: %ux ",
607 i, offsets[i], le32_to_cpu(buf[0]));
608 break;
609 }
610 }
611
612 if ((seen & SEEN_MOD) == 0) {
613 ERR(file->handle, "missing module in module package");
614 goto cleanup;
615 }
616
617 free(offsets);
618 return 0;
619
620 cleanup:
621 free(offsets);
622 return -1;
623 }
624
sepol_module_package_info(struct sepol_policy_file * spf,int * type,char ** name,char ** version)625 int sepol_module_package_info(struct sepol_policy_file *spf, int *type,
626 char **name, char **version)
627 {
628 struct policy_file *file = &spf->pf;
629 sepol_module_package_t *mod = NULL;
630 uint32_t buf[5], len, nsec;
631 size_t *offsets = NULL;
632 unsigned i, seen = 0;
633 char *id;
634 int rc;
635
636 if (sepol_module_package_create(&mod))
637 return -1;
638
639 if (module_package_read_offsets(mod, file, &offsets, &nsec)) {
640 goto cleanup;
641 }
642
643 for (i = 0; i < nsec; i++) {
644
645 if (policy_file_seek(file, offsets[i])) {
646 ERR(file->handle, "error seeking to offset "
647 "%zu for module package section %u", offsets[i], i);
648 goto cleanup;
649 }
650
651 len = offsets[i + 1] - offsets[i];
652
653 if (len < sizeof(uint32_t)) {
654 ERR(file->handle,
655 "module package section %u has too small length %u",
656 i, len);
657 goto cleanup;
658 }
659
660 /* read the magic number, so that we know which function to call */
661 rc = next_entry(buf, file, sizeof(uint32_t) * 2);
662 if (rc < 0) {
663 ERR(file->handle,
664 "module package section %u truncated, lacks magic number",
665 i);
666 goto cleanup;
667 }
668
669 switch (le32_to_cpu(buf[0])) {
670 case SEPOL_PACKAGE_SECTION_FC:
671 /* skip file contexts */
672 if (seen & SEEN_FC) {
673 ERR(file->handle,
674 "found multiple file contexts sections in module package (at section %u)",
675 i);
676 goto cleanup;
677 }
678 seen |= SEEN_FC;
679 break;
680 case SEPOL_PACKAGE_SECTION_SEUSER:
681 /* skip seuser */
682 if (seen & SEEN_SEUSER) {
683 ERR(file->handle,
684 "found seuser sections in module package (at section %u)",
685 i);
686 goto cleanup;
687 }
688 seen |= SEEN_SEUSER;
689 break;
690 case SEPOL_PACKAGE_SECTION_USER_EXTRA:
691 /* skip user_extra */
692 if (seen & SEEN_USER_EXTRA) {
693 ERR(file->handle,
694 "found user_extra sections in module package (at section %u)",
695 i);
696 goto cleanup;
697 }
698 seen |= SEEN_USER_EXTRA;
699 break;
700 case SEPOL_PACKAGE_SECTION_NETFILTER:
701 /* skip netfilter contexts */
702 if (seen & SEEN_NETFILTER) {
703 ERR(file->handle,
704 "found multiple netfilter contexts sections in module package (at section %u)",
705 i);
706 goto cleanup;
707 }
708 seen |= SEEN_NETFILTER;
709 break;
710 case POLICYDB_MOD_MAGIC:
711 if (seen & SEEN_MOD) {
712 ERR(file->handle,
713 "found multiple module sections in module package (at section %u)",
714 i);
715 goto cleanup;
716 }
717 len = le32_to_cpu(buf[1]);
718 if (len != strlen(POLICYDB_MOD_STRING)) {
719 ERR(file->handle,
720 "module string length is wrong (at section %u)",
721 i);
722 goto cleanup;
723 }
724
725 /* skip id */
726 id = malloc(len + 1);
727 if (!id) {
728 ERR(file->handle,
729 "out of memory (at section %u)",
730 i);
731 goto cleanup;
732 }
733 rc = next_entry(id, file, len);
734 free(id);
735 if (rc < 0) {
736 ERR(file->handle,
737 "cannot get module string (at section %u)",
738 i);
739 goto cleanup;
740 }
741
742 rc = next_entry(buf, file, sizeof(uint32_t) * 5);
743 if (rc < 0) {
744 ERR(file->handle,
745 "cannot get module header (at section %u)",
746 i);
747 goto cleanup;
748 }
749
750 *type = le32_to_cpu(buf[0]);
751 /* if base - we're done */
752 if (*type == POLICY_BASE) {
753 *name = NULL;
754 *version = NULL;
755 seen |= SEEN_MOD;
756 break;
757 } else if (*type != POLICY_MOD) {
758 ERR(file->handle,
759 "module has invalid type %d (at section %u)",
760 *type, i);
761 goto cleanup;
762 }
763
764 /* read the name and version */
765 rc = next_entry(buf, file, sizeof(uint32_t));
766 if (rc < 0) {
767 ERR(file->handle,
768 "cannot get module name len (at section %u)",
769 i);
770 goto cleanup;
771 }
772 len = le32_to_cpu(buf[0]);
773 *name = malloc(len + 1);
774 if (!*name) {
775 ERR(file->handle, "out of memory");
776 goto cleanup;
777 }
778 rc = next_entry(*name, file, len);
779 if (rc < 0) {
780 ERR(file->handle,
781 "cannot get module name string (at section %u)",
782 i);
783 goto cleanup;
784 }
785 (*name)[len] = '\0';
786 rc = next_entry(buf, file, sizeof(uint32_t));
787 if (rc < 0) {
788 ERR(file->handle,
789 "cannot get module version len (at section %u)",
790 i);
791 goto cleanup;
792 }
793 len = le32_to_cpu(buf[0]);
794 *version = malloc(len + 1);
795 if (!*version) {
796 ERR(file->handle, "out of memory");
797 goto cleanup;
798 }
799 rc = next_entry(*version, file, len);
800 if (rc < 0) {
801 ERR(file->handle,
802 "cannot get module version string (at section %u)",
803 i);
804 goto cleanup;
805 }
806 (*version)[len] = '\0';
807 seen |= SEEN_MOD;
808 break;
809 default:
810 break;
811 }
812
813 }
814
815 if ((seen & SEEN_MOD) == 0) {
816 ERR(file->handle, "missing module in module package");
817 goto cleanup;
818 }
819
820 sepol_module_package_free(mod);
821 free(offsets);
822 return 0;
823
824 cleanup:
825 sepol_module_package_free(mod);
826 free(offsets);
827 return -1;
828 }
829
write_helper(char * data,size_t len,struct policy_file * file)830 static int write_helper(char *data, size_t len, struct policy_file *file)
831 {
832 int idx = 0;
833 size_t len2;
834
835 while (len) {
836 if (len > BUFSIZ)
837 len2 = BUFSIZ;
838 else
839 len2 = len;
840
841 if (put_entry(&data[idx], 1, len2, file) != len2) {
842 return -1;
843 }
844 len -= len2;
845 idx += len2;
846 }
847 return 0;
848 }
849
sepol_module_package_write(sepol_module_package_t * p,struct sepol_policy_file * spf)850 int sepol_module_package_write(sepol_module_package_t * p,
851 struct sepol_policy_file *spf)
852 {
853 struct policy_file *file = &spf->pf;
854 policy_file_t polfile;
855 uint32_t buf[5], offsets[5], len, nsec = 0;
856 int i;
857
858 if (p->policy) {
859 /* compute policy length */
860 policy_file_init(&polfile);
861 polfile.type = PF_LEN;
862 polfile.handle = file->handle;
863 if (policydb_write(&p->policy->p, &polfile))
864 return -1;
865 len = polfile.len;
866 if (!polfile.len)
867 return -1;
868 nsec++;
869
870 } else {
871 /* We don't support writing a package without a module at this point */
872 return -1;
873 }
874
875 /* seusers and user_extra only supported in base at the moment */
876 if ((p->seusers || p->user_extra)
877 && (p->policy->p.policy_type != SEPOL_POLICY_BASE)) {
878 ERR(file->handle,
879 "seuser and user_extra sections only supported in base");
880 return -1;
881 }
882
883 if (p->file_contexts)
884 nsec++;
885
886 if (p->seusers)
887 nsec++;
888
889 if (p->user_extra)
890 nsec++;
891
892 if (p->netfilter_contexts)
893 nsec++;
894
895 buf[0] = cpu_to_le32(SEPOL_MODULE_PACKAGE_MAGIC);
896 buf[1] = cpu_to_le32(p->version);
897 buf[2] = cpu_to_le32(nsec);
898 if (put_entry(buf, sizeof(uint32_t), 3, file) != 3)
899 return -1;
900
901 /* calculate offsets */
902 offsets[0] = (nsec + 3) * sizeof(uint32_t);
903 buf[0] = cpu_to_le32(offsets[0]);
904
905 i = 1;
906 if (p->file_contexts) {
907 offsets[i] = offsets[i - 1] + len;
908 buf[i] = cpu_to_le32(offsets[i]);
909 /* add a uint32_t to compensate for the magic number */
910 len = p->file_contexts_len + sizeof(uint32_t);
911 i++;
912 }
913 if (p->seusers) {
914 offsets[i] = offsets[i - 1] + len;
915 buf[i] = cpu_to_le32(offsets[i]);
916 len = p->seusers_len + sizeof(uint32_t);
917 i++;
918 }
919 if (p->user_extra) {
920 offsets[i] = offsets[i - 1] + len;
921 buf[i] = cpu_to_le32(offsets[i]);
922 len = p->user_extra_len + sizeof(uint32_t);
923 i++;
924 }
925 if (p->netfilter_contexts) {
926 offsets[i] = offsets[i - 1] + len;
927 buf[i] = cpu_to_le32(offsets[i]);
928 len = p->netfilter_contexts_len + sizeof(uint32_t);
929 i++;
930 }
931 if (put_entry(buf, sizeof(uint32_t), nsec, file) != nsec)
932 return -1;
933
934 /* write sections */
935
936 if (policydb_write(&p->policy->p, file))
937 return -1;
938
939 if (p->file_contexts) {
940 buf[0] = cpu_to_le32(SEPOL_PACKAGE_SECTION_FC);
941 if (put_entry(buf, sizeof(uint32_t), 1, file) != 1)
942 return -1;
943 if (write_helper(p->file_contexts, p->file_contexts_len, file))
944 return -1;
945 }
946 if (p->seusers) {
947 buf[0] = cpu_to_le32(SEPOL_PACKAGE_SECTION_SEUSER);
948 if (put_entry(buf, sizeof(uint32_t), 1, file) != 1)
949 return -1;
950 if (write_helper(p->seusers, p->seusers_len, file))
951 return -1;
952
953 }
954 if (p->user_extra) {
955 buf[0] = cpu_to_le32(SEPOL_PACKAGE_SECTION_USER_EXTRA);
956 if (put_entry(buf, sizeof(uint32_t), 1, file) != 1)
957 return -1;
958 if (write_helper(p->user_extra, p->user_extra_len, file))
959 return -1;
960 }
961 if (p->netfilter_contexts) {
962 buf[0] = cpu_to_le32(SEPOL_PACKAGE_SECTION_NETFILTER);
963 if (put_entry(buf, sizeof(uint32_t), 1, file) != 1)
964 return -1;
965 if (write_helper
966 (p->netfilter_contexts, p->netfilter_contexts_len, file))
967 return -1;
968 }
969 return 0;
970 }
971
sepol_link_modules(sepol_handle_t * handle,sepol_policydb_t * base,sepol_policydb_t ** modules,size_t len,int verbose)972 int sepol_link_modules(sepol_handle_t * handle,
973 sepol_policydb_t * base,
974 sepol_policydb_t ** modules, size_t len, int verbose)
975 {
976 return link_modules(handle, &base->p, (policydb_t **) modules, len,
977 verbose);
978 }
979
sepol_expand_module(sepol_handle_t * handle,sepol_policydb_t * base,sepol_policydb_t * out,int verbose,int check)980 int sepol_expand_module(sepol_handle_t * handle,
981 sepol_policydb_t * base,
982 sepol_policydb_t * out, int verbose, int check)
983 {
984 return expand_module(handle, &base->p, &out->p, verbose, check);
985 }
986