1 /* 2 * Authors: Joshua Brindle <jbrindle (at) tresys.com> 3 * Karl MacMillan <kmacmillan (at) tresys.com> 4 * Jason Tang <jtang (at) tresys.com> 5 * 6 * 7 * Copyright (C) 2004-5 Tresys Technology, LLC 8 * This program is free software; you can redistribute it and/or modify 9 * it under the terms of the GNU General Public License as published by 10 * the Free Software Foundation, version 2. 11 */ 12 13 #include <getopt.h> 14 #include <unistd.h> 15 #include <stdlib.h> 16 #include <sys/types.h> 17 #include <sys/stat.h> 18 #include <fcntl.h> 19 #include <stdio.h> 20 #include <errno.h> 21 #include <sys/mman.h> 22 23 #include <sepol/module_to_cil.h> 24 #include <sepol/policydb/policydb.h> 25 #include <sepol/policydb/services.h> 26 #include <sepol/policydb/conditional.h> 27 #include <sepol/policydb/flask.h> 28 #include <sepol/policydb/hierarchy.h> 29 #include <sepol/policydb/expand.h> 30 #include <sepol/policydb/link.h> 31 #include <sepol/policydb/sidtab.h> 32 33 #include "queue.h" 34 #include "checkpolicy.h" 35 #include "parse_util.h" 36 37 extern char *optarg; 38 extern int optind; 39 40 static sidtab_t sidtab; 41 42 extern int mlspol; 43 44 static int handle_unknown = SEPOL_DENY_UNKNOWN; 45 static const char *txtfile = "policy.conf"; 46 static const char *binfile = "policy"; 47 48 unsigned int policy_type = POLICY_BASE; 49 unsigned int policyvers = MOD_POLICYDB_VERSION_MAX; 50 51 static int read_binary_policy(policydb_t * p, const char *file, const char *progname) 52 { 53 int fd; 54 struct stat sb; 55 void *map; 56 struct policy_file f, *fp; 57 58 fd = open(file, O_RDONLY); 59 if (fd < 0) { 60 fprintf(stderr, "Can't open '%s': %s\n", 61 file, strerror(errno)); 62 return -1; 63 } 64 if (fstat(fd, &sb) < 0) { 65 fprintf(stderr, "Can't stat '%s': %s\n", 66 file, strerror(errno)); 67 close(fd); 68 return -1; 69 } 70 map = 71 mmap(NULL, sb.st_size, PROT_READ | PROT_WRITE, MAP_PRIVATE, fd, 0); 72 close(fd); 73 if (map == MAP_FAILED) { 74 fprintf(stderr, "Can't map '%s': %s\n", file, strerror(errno)); 75 return -1; 76 } 77 policy_file_init(&f); 78 f.type = PF_USE_MEMORY; 79 f.data = map; 80 f.len = sb.st_size; 81 fp = &f; 82 83 if (policydb_init(p)) { 84 fprintf(stderr, "%s: policydb_init: Out of memory!\n", 85 progname); 86 return -1; 87 } 88 if (policydb_read(p, fp, 1)) { 89 fprintf(stderr, 90 "%s: error(s) encountered while parsing configuration\n", 91 progname); 92 return -1; 93 } 94 95 /* Check Policy Consistency */ 96 if (p->mls) { 97 if (!mlspol) { 98 fprintf(stderr, "%s: MLS policy, but non-MLS" 99 " is specified\n", progname); 100 return -1; 101 } 102 } else { 103 if (mlspol) { 104 fprintf(stderr, "%s: non-MLS policy, but MLS" 105 " is specified\n", progname); 106 return -1; 107 } 108 } 109 return 0; 110 } 111 112 static int write_binary_policy(policydb_t * p, FILE *outfp) 113 { 114 struct policy_file pf; 115 116 p->policy_type = policy_type; 117 p->policyvers = policyvers; 118 p->handle_unknown = handle_unknown; 119 120 policy_file_init(&pf); 121 pf.type = PF_USE_STDIO; 122 pf.fp = outfp; 123 return policydb_write(p, &pf); 124 } 125 126 static void usage(char *progname) 127 { 128 printf("usage: %s [-h] [-V] [-b] [-C] [-U handle_unknown] [-m] [-M] [-o FILE] [INPUT]\n", progname); 129 printf("Build base and policy modules.\n"); 130 printf("Options:\n"); 131 printf(" INPUT build module from INPUT (else read from \"%s\")\n", 132 txtfile); 133 printf(" -V show policy versions created by this program\n"); 134 printf(" -b treat input as a binary policy file\n"); 135 printf(" -C output CIL policy instead of binary policy\n"); 136 printf(" -h print usage\n"); 137 printf(" -U OPTION How to handle unknown classes and permissions\n"); 138 printf(" deny: Deny unknown kernel checks\n"); 139 printf(" reject: Reject loading of policy with unknowns\n"); 140 printf(" allow: Allow unknown kernel checks\n"); 141 printf(" -m build a policy module instead of a base module\n"); 142 printf(" -M enable MLS policy\n"); 143 printf(" -o FILE write module to FILE (else just check syntax)\n"); 144 exit(1); 145 } 146 147 int main(int argc, char **argv) 148 { 149 const char *file = txtfile, *outfile = NULL; 150 unsigned int binary = 0, cil = 0; 151 int ch; 152 int show_version = 0; 153 policydb_t modpolicydb; 154 struct option long_options[] = { 155 {"help", no_argument, NULL, 'h'}, 156 {"output", required_argument, NULL, 'o'}, 157 {"binary", no_argument, NULL, 'b'}, 158 {"version", no_argument, NULL, 'V'}, 159 {"handle-unknown", required_argument, NULL, 'U'}, 160 {"mls", no_argument, NULL, 'M'}, 161 {"cil", no_argument, NULL, 'C'}, 162 {NULL, 0, NULL, 0} 163 }; 164 165 while ((ch = getopt_long(argc, argv, "ho:bVU:mMC", long_options, NULL)) != -1) { 166 switch (ch) { 167 case 'h': 168 usage(argv[0]); 169 break; 170 case 'o': 171 outfile = optarg; 172 break; 173 case 'b': 174 binary = 1; 175 file = binfile; 176 break; 177 case 'V': 178 show_version = 1; 179 break; 180 case 'U': 181 if (!strcasecmp(optarg, "deny")) { 182 handle_unknown = DENY_UNKNOWN; 183 break; 184 } 185 if (!strcasecmp(optarg, "reject")) { 186 handle_unknown = REJECT_UNKNOWN; 187 break; 188 } 189 if (!strcasecmp(optarg, "allow")) { 190 handle_unknown = ALLOW_UNKNOWN; 191 break; 192 } 193 usage(argv[0]); 194 case 'm': 195 policy_type = POLICY_MOD; 196 policyvers = MOD_POLICYDB_VERSION_MAX; 197 break; 198 case 'M': 199 mlspol = 1; 200 break; 201 case 'C': 202 cil = 1; 203 break; 204 default: 205 usage(argv[0]); 206 } 207 } 208 209 if (show_version) { 210 printf("Module versions %d-%d\n", 211 MOD_POLICYDB_VERSION_MIN, MOD_POLICYDB_VERSION_MAX); 212 exit(0); 213 } 214 215 if (handle_unknown && (policy_type != POLICY_BASE)) { 216 fprintf(stderr, "%s: Handling of unknown classes and permissions is only valid in the base module.\n", argv[0]); 217 exit(1); 218 } 219 220 if (binary && (policy_type != POLICY_BASE)) { 221 fprintf(stderr, "%s: -b and -m are incompatible with each other.\n", argv[0]); 222 exit(1); 223 } 224 225 if (optind != argc) { 226 file = argv[optind++]; 227 if (optind != argc) 228 usage(argv[0]); 229 } 230 printf("%s: loading policy configuration from %s\n", argv[0], file); 231 232 /* Set policydb and sidtab used by libsepol service functions 233 to my structures, so that I can directly populate and 234 manipulate them. */ 235 sepol_set_policydb(&modpolicydb); 236 sepol_set_sidtab(&sidtab); 237 238 if (binary) { 239 if (read_binary_policy(&modpolicydb, file, argv[0]) == -1) { 240 exit(1); 241 } 242 } else { 243 if (policydb_init(&modpolicydb)) { 244 fprintf(stderr, "%s: out of memory!\n", argv[0]); 245 return -1; 246 } 247 248 modpolicydb.policy_type = policy_type; 249 modpolicydb.mls = mlspol; 250 modpolicydb.handle_unknown = handle_unknown; 251 252 if (read_source_policy(&modpolicydb, file, argv[0]) == -1) { 253 exit(1); 254 } 255 256 if (hierarchy_check_constraints(NULL, &modpolicydb)) { 257 return -1; 258 } 259 } 260 261 if (modpolicydb.policy_type == POLICY_BASE && !cil) { 262 /* Verify that we can successfully expand the base module. */ 263 policydb_t kernpolicydb; 264 265 if (policydb_init(&kernpolicydb)) { 266 fprintf(stderr, "%s: policydb_init failed\n", argv[0]); 267 exit(1); 268 } 269 if (link_modules(NULL, &modpolicydb, NULL, 0, 0)) { 270 fprintf(stderr, "%s: link modules failed\n", argv[0]); 271 exit(1); 272 } 273 if (expand_module(NULL, &modpolicydb, &kernpolicydb, 0, 1)) { 274 fprintf(stderr, "%s: expand module failed\n", argv[0]); 275 exit(1); 276 } 277 policydb_destroy(&kernpolicydb); 278 } 279 280 if (policydb_load_isids(&modpolicydb, &sidtab)) 281 exit(1); 282 283 sepol_sidtab_destroy(&sidtab); 284 285 printf("%s: policy configuration loaded\n", argv[0]); 286 287 if (outfile) { 288 FILE *outfp = fopen(outfile, "w"); 289 290 if (!outfp) { 291 perror(outfile); 292 exit(1); 293 } 294 295 if (!cil) { 296 printf("%s: writing binary representation (version %d) to %s\n", 297 argv[0], policyvers, file); 298 299 if (write_binary_policy(&modpolicydb, outfp) != 0) { 300 fprintf(stderr, "%s: error writing %s\n", argv[0], outfile); 301 exit(1); 302 } 303 } else { 304 printf("%s: writing CIL to %s\n",argv[0], outfile); 305 306 if (sepol_module_policydb_to_cil(outfp, &modpolicydb, 0) != 0) { 307 fprintf(stderr, "%s: error writing %s\n", argv[0], outfile); 308 exit(1); 309 } 310 } 311 312 fclose(outfp); 313 } else if (cil) { 314 fprintf(stderr, "%s: No file to write CIL was specified\n", argv[0]); 315 exit(1); 316 } 317 318 policydb_destroy(&modpolicydb); 319 320 return 0; 321 } 322 323 /* FLASK */ 324