113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle/* Authors: Karl MacMillan <kmacmillan@tresys.com> 213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle * Joshua Brindle <jbrindle@tresys.com> 313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle * 413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle * Copyright (C) 2004 Tresys Technology, LLC 513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle * This program is free software; you can redistribute it and/or modify 613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle * it under the terms of the GNU General Public License as published by 713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle * the Free Software Foundation, version 2. 813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle */ 913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle 1013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle#include <sepol/policydb.h> 1113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle#include <sepol/module.h> 1213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle 1313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle#include <getopt.h> 1413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle#include <fcntl.h> 1513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle#include <stdio.h> 1613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle#include <errno.h> 1713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle#include <sys/mman.h> 1813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle#include <sys/types.h> 1913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle#include <sys/stat.h> 2013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle#include <stdlib.h> 2113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle#include <unistd.h> 2213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle#include <string.h> 2313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle 2413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindleextern char *optarg; 2513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindleextern int optind; 2613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle 2713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindleint policyvers = 0; 2813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle 2913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle#define EXPANDPOLICY_VERSION "1.0" 3013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle 3113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindlestatic void usage(char *program_name) 3213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle{ 3313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle printf("usage: %s [-V -a -c [version]] basemodpkg outputfile\n", 3413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle program_name); 3513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle exit(1); 3613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle} 3713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle 3813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindleint main(int argc, char **argv) 3913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle{ 4013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle char *basename, *outname; 4113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle int ch, ret, show_version = 0, verbose = 0; 4213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle struct sepol_policy_file *pf; 4313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle sepol_module_package_t *base; 4413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle sepol_policydb_t *out, *p; 4513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle FILE *fp, *outfile; 4613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle int check_assertions = 1; 4713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle sepol_handle_t *handle; 4813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle 4913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle while ((ch = getopt(argc, argv, "c:Vva")) != EOF) { 5013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle switch (ch) { 5113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle case 'V': 5213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle show_version = 1; 5313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle break; 5413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle case 'v': 5513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle verbose = 1; 5613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle break; 5713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle case 'c':{ 5813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle long int n = strtol(optarg, NULL, 10); 5913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle if (errno) { 6013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle fprintf(stderr, 6113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle "%s: Invalid policyvers specified: %s\n", 6213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle argv[0], optarg); 6313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle usage(argv[0]); 6413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle exit(1); 6513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle } 6613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle if (n < sepol_policy_kern_vers_min() 6713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle || n > sepol_policy_kern_vers_max()) { 6813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle fprintf(stderr, 6913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle "%s: policyvers value %ld not in range %d-%d\n", 7013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle argv[0], n, 7113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle sepol_policy_kern_vers_min(), 7213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle sepol_policy_kern_vers_max()); 7313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle usage(argv[0]); 7413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle exit(1); 7513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle } 7613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle policyvers = n; 7713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle break; 7813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle } 7913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle case 'a':{ 8013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle check_assertions = 0; 8113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle break; 8213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle } 8313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle default: 8413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle usage(argv[0]); 8513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle } 8613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle } 8713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle 8813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle if (verbose) { 8913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle if (policyvers) 9013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle printf("Building version %d policy\n", policyvers); 9113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle } 9213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle 9313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle if (show_version) { 9413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle printf("%s\n", EXPANDPOLICY_VERSION); 9513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle exit(0); 9613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle } 9713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle 9813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle /* check args */ 9913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle if (argc < 3 || !(optind != (argc - 1))) { 10013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle fprintf(stderr, 10113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle "%s: You must provide the base module package and output filename\n", 10213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle argv[0]); 10313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle usage(argv[0]); 10413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle } 10513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle 10613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle basename = argv[optind++]; 10713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle outname = argv[optind]; 10813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle 10913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle handle = sepol_handle_create(); 11013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle if (!handle) 11113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle exit(1); 11213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle 11313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle if (sepol_policy_file_create(&pf)) { 11413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle fprintf(stderr, "%s: Out of memory\n", argv[0]); 11513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle exit(1); 11613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle } 11713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle 11813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle /* read the base module */ 11913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle if (sepol_module_package_create(&base)) { 12013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle fprintf(stderr, "%s: Out of memory\n", argv[0]); 12113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle exit(1); 12213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle } 12313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle fp = fopen(basename, "r"); 12413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle if (!fp) { 12513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle fprintf(stderr, "%s: Can't open '%s': %s\n", 12613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle argv[0], basename, strerror(errno)); 12713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle exit(1); 12813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle } 12913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle sepol_policy_file_set_fp(pf, fp); 13013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle ret = sepol_module_package_read(base, pf, 0); 13113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle if (ret) { 13213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle fprintf(stderr, "%s: Error in reading package from %s\n", 13313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle argv[0], basename); 13413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle exit(1); 13513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle } 13613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle fclose(fp); 13713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle 13813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle /* linking the base takes care of enabling optional avrules */ 13913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle p = sepol_module_package_get_policy(base); 14013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle if (sepol_link_modules(handle, p, NULL, 0, 0)) { 14113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle fprintf(stderr, "%s: Error while enabling avrules\n", argv[0]); 14213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle exit(1); 14313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle } 14413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle 14513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle /* create the output policy */ 14613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle 14713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle if (sepol_policydb_create(&out)) { 14813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle fprintf(stderr, "%s: Out of memory\n", argv[0]); 14913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle exit(1); 15013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle } 15113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle 15213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle sepol_set_expand_consume_base(handle, 1); 15313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle 15413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle if (sepol_expand_module(handle, p, out, verbose, check_assertions)) { 15513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle fprintf(stderr, "%s: Error while expanding policy\n", argv[0]); 15613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle exit(1); 15713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle } 15813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle 15913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle if (policyvers) { 16013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle if (sepol_policydb_set_vers(out, policyvers)) { 16113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle fprintf(stderr, "%s: Invalid version %d\n", argv[0], 16213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle policyvers); 16313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle exit(1); 16413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle } 16513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle } 16613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle 16713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle sepol_module_package_free(base); 16813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle 16913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle outfile = fopen(outname, "w"); 17013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle if (!outfile) { 17113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle perror(outname); 17213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle exit(1); 17313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle } 17413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle 17513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle sepol_policy_file_set_fp(pf, outfile); 17613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle ret = sepol_policydb_write(out, pf); 17713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle if (ret) { 17813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle fprintf(stderr, 17913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle "%s: Error while writing expanded policy to %s\n", 18013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle argv[0], outname); 18113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle exit(1); 18213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle } 18313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle fclose(outfile); 18413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle sepol_handle_destroy(handle); 18513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle sepol_policydb_free(out); 18613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle sepol_policy_file_free(pf); 18713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle 18813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle return 0; 18913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle} 190