1 #include <getopt.h> 2 #include <unistd.h> 3 #include <stdlib.h> 4 #include <sys/mman.h> 5 #include <sys/types.h> 6 #include <sys/stat.h> 7 #include <fcntl.h> 8 #include <stdio.h> 9 #include <sepol/policydb/policydb.h> 10 #include <sepol/policydb/services.h> 11 #include <sepol/policydb/expand.h> 12 13 #define EQUALS 0 14 #define NOT 1 15 #define ANY 2 16 17 void usage(char *arg0) { 18 fprintf(stderr, "%s -s <source> -t <target> -c <class> -p <perm> -P <policy file>\n", arg0); 19 exit(1); 20 } 21 22 void *cmalloc(size_t s) { 23 void *t = malloc(s); 24 if (t == NULL) { 25 fprintf(stderr, "Out of memory\n"); 26 exit(1); 27 } 28 return t; 29 } 30 31 int parse_ops(char **arg) { 32 switch (*arg[0]) { 33 case '-': 34 *arg = *arg + 1; 35 return NOT; 36 case '*': 37 return ANY; 38 default: 39 return EQUALS; 40 } 41 } 42 43 int check(int op, uint16_t arg1, uint16_t arg2) { 44 switch (op) { 45 case EQUALS: 46 return arg1 == arg2; 47 case NOT: 48 return arg1 != arg2; 49 case ANY: 50 return 1; 51 default: 52 fprintf(stderr, "Bad op while checking!"); 53 return 2; 54 } 55 } 56 57 int check_perm(avtab_ptr_t current, perm_datum_t *perm) { 58 uint16_t perm_bitmask = 1U << (perm->s.value - 1); 59 return (current->datum.data & perm_bitmask) != 0; 60 } 61 62 63 int expand_and_check(int s_op, uint32_t source_type, 64 int t_op, uint32_t target_type, 65 int c_op, uint32_t target_class, 66 perm_datum_t *perm, policydb_t *policy, avtab_t *avtab) { 67 avtab_t exp_avtab; 68 avtab_ptr_t cur; 69 unsigned int i; 70 int match; 71 72 if (avtab_init(&exp_avtab)) { 73 fputs("out of memory\n", stderr); 74 return -1; 75 } 76 77 if (expand_avtab(policy, avtab, &exp_avtab)) { 78 fputs("out of memory\n", stderr); 79 avtab_destroy(&exp_avtab); 80 return -1; 81 } 82 83 for (i = 0; i < exp_avtab.nslot; i++) { 84 for (cur = exp_avtab.htable[i]; cur; cur = cur->next) { 85 match = 1; 86 match &= check(s_op, source_type, cur->key.source_type); 87 match &= check(t_op, target_type, cur->key.target_type); 88 match &= check(c_op, target_class, cur->key.target_class); 89 match &= check_perm(cur, perm); 90 if (match) { 91 avtab_destroy(&exp_avtab); 92 return 1; 93 } 94 } 95 } 96 97 avtab_destroy(&exp_avtab); 98 return 0; 99 } 100 101 /* 102 * Checks to see if a rule matching the given arguments already exists. 103 * 104 * The format for the arguments is as follows: 105 * 106 * - A bare string is treated as a literal and will be matched by equality. 107 * - A string starting with "-" will be matched by inequality. 108 * - A string starting with "*" will be treated as a wildcard. 109 * 110 * The return codes for this function are as follows: 111 * 112 * - 0 indicates a successful return without a match 113 * - 1 indicates a successful return with a match 114 * - -1 indicates an error 115 */ 116 int check_rule(char *s, char *t, char *c, char *p, policydb_t *policy) { 117 type_datum_t *src = NULL; 118 type_datum_t *tgt = NULL; 119 class_datum_t *cls = NULL; 120 perm_datum_t *perm = NULL; 121 int s_op = parse_ops(&s); 122 int t_op = parse_ops(&t); 123 int c_op = parse_ops(&c); 124 int p_op = parse_ops(&p); 125 avtab_key_t key; 126 int match; 127 128 key.source_type = key.target_type = key.target_class = 0; 129 130 if (s_op != ANY) { 131 src = hashtab_search(policy->p_types.table, s); 132 if (src == NULL) { 133 fprintf(stderr, "source type %s does not exist\n", s); 134 return -1; 135 } 136 } 137 if (t_op != ANY) { 138 tgt = hashtab_search(policy->p_types.table, t); 139 if (tgt == NULL) { 140 fprintf(stderr, "target type %s does not exist\n", t); 141 return -1; 142 } 143 } 144 if (c_op != ANY) { 145 cls = hashtab_search(policy->p_classes.table, c); 146 if (cls == NULL) { 147 fprintf(stderr, "class %s does not exist\n", c); 148 return -1; 149 } 150 } 151 if (p_op != ANY) { 152 perm = hashtab_search(cls->permissions.table, p); 153 if (perm == NULL) { 154 if (cls->comdatum == NULL) { 155 fprintf(stderr, "perm %s does not exist in class %s\n", p, c); 156 return -1; 157 } 158 perm = hashtab_search(cls->comdatum->permissions.table, p); 159 if (perm == NULL) { 160 fprintf(stderr, "perm %s does not exist in class %s\n", p, c); 161 return -1; 162 } 163 } 164 } 165 166 if (s_op != ANY) 167 key.source_type = src->s.value; 168 if (t_op != ANY) 169 key.target_type = tgt->s.value; 170 if (c_op != ANY) 171 key.target_class = cls->s.value; 172 173 /* Check unconditional rules after attribute expansion. */ 174 match = expand_and_check(s_op, key.source_type, 175 t_op, key.target_type, 176 c_op, key.target_class, 177 perm, policy, &policy->te_avtab); 178 if (match) 179 return match; 180 181 /* Check conditional rules after attribute expansion. */ 182 return expand_and_check(s_op, key.source_type, 183 t_op, key.target_type, 184 c_op, key.target_class, 185 perm, policy, &policy->te_cond_avtab); 186 } 187 188 int load_policy(char *filename, policydb_t *policydb, struct policy_file *pf) { 189 int fd; 190 struct stat sb; 191 void *map; 192 int ret; 193 194 fd = open(filename, O_RDONLY); 195 if (fd < 0) { 196 fprintf(stderr, "Can't open '%s': %s\n", filename, strerror(errno)); 197 return 1; 198 } 199 if (fstat(fd, &sb) < 0) { 200 fprintf(stderr, "Can't stat '%s': %s\n", filename, strerror(errno)); 201 close(fd); 202 return 1; 203 } 204 map = mmap(NULL, sb.st_size, PROT_READ | PROT_WRITE, MAP_PRIVATE, fd, 0); 205 if (map == MAP_FAILED) { 206 fprintf(stderr, "Can't mmap '%s': %s\n", filename, strerror(errno)); 207 close(fd); 208 return 1; 209 } 210 211 policy_file_init(pf); 212 pf->type = PF_USE_MEMORY; 213 pf->data = map; 214 pf->len = sb.st_size; 215 if (policydb_init(policydb)) { 216 fprintf(stderr, "Could not initialize policydb!\n"); 217 close(fd); 218 munmap(map, sb.st_size); 219 return 1; 220 } 221 ret = policydb_read(policydb, pf, 0); 222 if (ret) { 223 fprintf(stderr, "error(s) encountered while parsing configuration\n"); 224 close(fd); 225 munmap(map, sb.st_size); 226 return 1; 227 } 228 229 return 0; 230 } 231 232 233 int main(int argc, char **argv) 234 { 235 char *policy = NULL, *source = NULL, *target = NULL, *class = NULL, *perm = NULL; 236 policydb_t policydb; 237 struct policy_file pf; 238 sidtab_t sidtab; 239 char ch; 240 int match = 1; 241 242 struct option long_options[] = { 243 {"source", required_argument, NULL, 's'}, 244 {"target", required_argument, NULL, 't'}, 245 {"class", required_argument, NULL, 'c'}, 246 {"perm", required_argument, NULL, 'p'}, 247 {"policy", required_argument, NULL, 'P'}, 248 {NULL, 0, NULL, 0} 249 }; 250 251 while ((ch = getopt_long(argc, argv, "s:t:c:p:P:", long_options, NULL)) != -1) { 252 switch (ch) { 253 case 's': 254 source = optarg; 255 break; 256 case 't': 257 target = optarg; 258 break; 259 case 'c': 260 class = optarg; 261 break; 262 case 'p': 263 perm = optarg; 264 break; 265 case 'P': 266 policy = optarg; 267 break; 268 default: 269 usage(argv[0]); 270 } 271 } 272 273 if (!source || !target || !class || !perm || !policy) 274 usage(argv[0]); 275 276 sepol_set_policydb(&policydb); 277 sepol_set_sidtab(&sidtab); 278 279 if (load_policy(policy, &policydb, &pf)) 280 goto out; 281 282 match = check_rule(source, target, class, perm, &policydb); 283 if (match < 0) { 284 fprintf(stderr, "Error checking rules!\n"); 285 goto out; 286 } else if (match > 0) { 287 printf("Match found!\n"); 288 goto out; 289 } 290 291 match = 0; 292 293 out: 294 policydb_destroy(&policydb); 295 return match; 296 } 297