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