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