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