1 /* 2 * Copyright 2011 Tresys Technology, LLC. All rights reserved. 3 * 4 * Redistribution and use in source and binary forms, with or without 5 * modification, are permitted provided that the following conditions are met: 6 * 7 * 1. Redistributions of source code must retain the above copyright notice, 8 * this list of conditions and the following disclaimer. 9 * 10 * 2. Redistributions in binary form must reproduce the above copyright notice, 11 * this list of conditions and the following disclaimer in the documentation 12 * and/or other materials provided with the distribution. 13 * 14 * THIS SOFTWARE IS PROVIDED BY TRESYS TECHNOLOGY, LLC ``AS IS'' AND ANY EXPRESS 15 * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 16 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO 17 * EVENT SHALL TRESYS TECHNOLOGY, LLC OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, 18 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 19 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 20 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 21 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE 22 * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF 23 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 24 * 25 * The views and conclusions contained in the software and documentation are those 26 * of the authors and should not be interpreted as representing official policies, 27 * either expressed or implied, of Tresys Technology, LLC. 28 */ 29 30 #include <sepol/policydb/ebitmap.h> 31 32 #include "cil_internal.h" 33 #include "cil_flavor.h" 34 #include "cil_list.h" 35 #include "cil_log.h" 36 #include "cil_symtab.h" 37 38 struct cil_args_find { 39 enum cil_flavor flavor; 40 void *target; 41 struct cil_list *matching; 42 int match_self; 43 }; 44 45 static int cil_type_match_any(struct cil_symtab_datum *d1, struct cil_symtab_datum *d2) 46 { 47 enum cil_flavor f1 = ((struct cil_tree_node*)d1->nodes->head->data)->flavor; 48 enum cil_flavor f2 = ((struct cil_tree_node*)d2->nodes->head->data)->flavor; 49 50 if (f1 != CIL_TYPEATTRIBUTE && f2 != CIL_TYPEATTRIBUTE) { 51 struct cil_type *t1 = (struct cil_type *)d1; 52 struct cil_type *t2 = (struct cil_type *)d2; 53 if (t1->value == t2->value) { 54 return CIL_TRUE; 55 } 56 } else if (f1 == CIL_TYPEATTRIBUTE && f2 != CIL_TYPEATTRIBUTE) { 57 struct cil_typeattribute *a = (struct cil_typeattribute *)d1; 58 struct cil_type *t = (struct cil_type *)d2; 59 if (ebitmap_get_bit(a->types, t->value)) { 60 return CIL_TRUE; 61 } 62 } else if (f1 != CIL_TYPEATTRIBUTE && f2 == CIL_TYPEATTRIBUTE) { 63 struct cil_type *t = (struct cil_type *)d1; 64 struct cil_typeattribute *a = (struct cil_typeattribute *)d2; 65 if (ebitmap_get_bit(a->types, t->value)) { 66 return CIL_TRUE; 67 } 68 } else { 69 /* Both are attributes */ 70 struct cil_typeattribute *a1 = (struct cil_typeattribute *)d1; 71 struct cil_typeattribute *a2 = (struct cil_typeattribute *)d2; 72 if (d1 == d2) { 73 return CIL_TRUE; 74 } else if (ebitmap_match_any(a1->types, a2->types)) { 75 return CIL_TRUE; 76 } 77 } 78 return CIL_FALSE; 79 } 80 81 static int cil_type_matches(ebitmap_t *matches, struct cil_symtab_datum *d1, struct cil_symtab_datum *d2) 82 { 83 int rc = SEPOL_OK; 84 enum cil_flavor f1 = ((struct cil_tree_node*)d1->nodes->head->data)->flavor; 85 enum cil_flavor f2 = ((struct cil_tree_node*)d2->nodes->head->data)->flavor; 86 87 if (f1 != CIL_TYPEATTRIBUTE && f2 != CIL_TYPEATTRIBUTE) { 88 struct cil_type *t1 = (struct cil_type *)d1; 89 struct cil_type *t2 = (struct cil_type *)d2; 90 if (t1->value == t2->value) { 91 ebitmap_set_bit(matches, t1->value, 1); 92 } 93 } else if (f1 == CIL_TYPEATTRIBUTE && f2 != CIL_TYPEATTRIBUTE) { 94 struct cil_typeattribute *a = (struct cil_typeattribute *)d1; 95 struct cil_type *t = (struct cil_type *)d2; 96 if (ebitmap_get_bit(a->types, t->value)) { 97 ebitmap_set_bit(matches, t->value, 1); 98 } 99 } else if (f1 != CIL_TYPEATTRIBUTE && f2 == CIL_TYPEATTRIBUTE) { 100 struct cil_type *t = (struct cil_type *)d1; 101 struct cil_typeattribute *a = (struct cil_typeattribute *)d2; 102 if (ebitmap_get_bit(a->types, t->value)) { 103 ebitmap_set_bit(matches, t->value, 1); 104 } 105 } else { 106 /* Both are attributes */ 107 struct cil_typeattribute *a1 = (struct cil_typeattribute *)d1; 108 struct cil_typeattribute *a2 = (struct cil_typeattribute *)d2; 109 rc = ebitmap_and(matches, a1->types, a2->types); 110 } 111 112 return rc; 113 } 114 115 /* s1 is the src type that is matched with a self 116 * s2, and t2 are the source and type of the other rule 117 */ 118 static int cil_self_match_any(struct cil_symtab_datum *s1, struct cil_symtab_datum *s2, struct cil_symtab_datum *t2) 119 { 120 int rc; 121 struct cil_tree_node *n1 = s1->nodes->head->data; 122 if (n1->flavor != CIL_TYPEATTRIBUTE) { 123 rc = cil_type_match_any(s1, t2); 124 } else { 125 struct cil_typeattribute *a = (struct cil_typeattribute *)s1; 126 ebitmap_t map; 127 ebitmap_init(&map); 128 rc = cil_type_matches(&map, s2, t2); 129 if (rc < 0) { 130 ebitmap_destroy(&map); 131 goto exit; 132 } 133 if (map.node == NULL) { 134 rc = CIL_FALSE; 135 goto exit; 136 } 137 rc = ebitmap_match_any(&map, a->types); 138 ebitmap_destroy(&map); 139 } 140 141 exit: 142 return rc; 143 } 144 145 static int cil_classperms_match_any(struct cil_classperms *cp1, struct cil_classperms *cp2) 146 { 147 struct cil_class *c1 = cp1->class; 148 struct cil_class *c2 = cp2->class; 149 struct cil_list_item *i1, *i2; 150 151 if (&c1->datum != &c2->datum) return CIL_FALSE; 152 153 cil_list_for_each(i1, cp1->perms) { 154 struct cil_perm *p1 = i1->data; 155 cil_list_for_each(i2, cp2->perms) { 156 struct cil_perm *p2 = i2->data; 157 if (&p1->datum == &p2->datum) return CIL_TRUE; 158 } 159 } 160 return CIL_FALSE; 161 } 162 163 static int __cil_classperms_list_match_any(struct cil_classperms *cp1, struct cil_list *cpl2) 164 { 165 int rc; 166 struct cil_list_item *curr; 167 168 cil_list_for_each(curr, cpl2) { 169 if (curr->flavor == CIL_CLASSPERMS) { 170 struct cil_classperms *cp = curr->data; 171 if (FLAVOR(cp->class) == CIL_CLASS) { 172 rc = cil_classperms_match_any(cp1, cp); 173 if (rc == CIL_TRUE) return CIL_TRUE; 174 } else { /* MAP */ 175 struct cil_list_item *i = NULL; 176 cil_list_for_each(i, cp->perms) { 177 struct cil_perm *cmp = i->data; 178 rc = __cil_classperms_list_match_any(cp1, cmp->classperms); 179 if (rc == CIL_TRUE) return CIL_TRUE; 180 } 181 } 182 } else { /* SET */ 183 struct cil_classperms_set *cp_set = curr->data; 184 struct cil_classpermission *cp = cp_set->set; 185 rc = __cil_classperms_list_match_any(cp1, cp->classperms); 186 if (rc == CIL_TRUE) return CIL_TRUE; 187 } 188 } 189 return CIL_FALSE; 190 } 191 192 static int cil_classperms_list_match_any(struct cil_list *cpl1, struct cil_list *cpl2) 193 { 194 int rc; 195 struct cil_list_item *curr; 196 197 cil_list_for_each(curr, cpl1) { 198 if (curr->flavor == CIL_CLASSPERMS) { 199 struct cil_classperms *cp = curr->data; 200 if (FLAVOR(cp->class) == CIL_CLASS) { 201 rc = __cil_classperms_list_match_any(cp, cpl2); 202 if (rc == CIL_TRUE) return CIL_TRUE; 203 } else { /* MAP */ 204 struct cil_list_item *i = NULL; 205 cil_list_for_each(i, cp->perms) { 206 struct cil_perm *cmp = i->data; 207 rc = cil_classperms_list_match_any(cmp->classperms, cpl2); 208 if (rc == CIL_TRUE) return CIL_TRUE; 209 } 210 } 211 } else { /* SET */ 212 struct cil_classperms_set *cp_set = curr->data; 213 struct cil_classpermission *cp = cp_set->set; 214 rc = cil_classperms_list_match_any(cp->classperms, cpl2); 215 if (rc == CIL_TRUE) return CIL_TRUE; 216 } 217 } 218 return CIL_FALSE; 219 } 220 221 static void __add_classes_from_classperms_list(struct cil_list *classperms, struct cil_list *class_list) 222 { 223 struct cil_list_item *curr; 224 225 cil_list_for_each(curr, classperms) { 226 if (curr->flavor == CIL_CLASSPERMS) { 227 struct cil_classperms *cp = curr->data; 228 if (FLAVOR(cp->class) == CIL_CLASS) { 229 cil_list_append(class_list, CIL_CLASS, cp->class); 230 } else { /* MAP */ 231 struct cil_list_item *i = NULL; 232 cil_list_for_each(i, cp->perms) { 233 struct cil_perm *cmp = i->data; 234 __add_classes_from_classperms_list(cmp->classperms, class_list); 235 } 236 } 237 } else { /* SET */ 238 struct cil_classperms_set *cp_set = curr->data; 239 struct cil_classpermission *cp = cp_set->set; 240 __add_classes_from_classperms_list(cp->classperms, class_list); 241 } 242 } 243 } 244 245 static int __add_classes_from_map_perms(__attribute__((unused)) hashtab_key_t k, hashtab_datum_t d, void *args) 246 { 247 struct cil_list *class_list = args; 248 struct cil_perm *cmp = (struct cil_perm *)d; 249 250 __add_classes_from_classperms_list(cmp->classperms, class_list); 251 252 return SEPOL_OK; 253 } 254 255 struct cil_list *cil_expand_class(struct cil_class *class) 256 { 257 struct cil_list *class_list; 258 259 cil_list_init(&class_list, CIL_CLASS); 260 261 if (FLAVOR(class) == CIL_CLASS) { 262 cil_list_append(class_list, CIL_CLASS, class); 263 } else { /* MAP */ 264 cil_symtab_map(&class->perms, __add_classes_from_map_perms, class_list); 265 } 266 267 return class_list; 268 } 269 270 static int cil_permissionx_match_any(struct cil_permissionx *px1, struct cil_permissionx *px2) 271 { 272 int rc = CIL_FALSE; 273 struct cil_list *cl1 = NULL; 274 struct cil_list *cl2 = NULL; 275 276 if (px1->kind != px2->kind) goto exit; 277 278 if (!ebitmap_match_any(px1->perms, px2->perms)) goto exit; 279 280 cl1 = cil_expand_class(px1->obj); 281 cl2 = cil_expand_class(px2->obj); 282 283 if (!cil_list_match_any(cl1, cl2)) goto exit; 284 285 rc = CIL_TRUE; 286 287 exit: 288 cil_list_destroy(&cl1, CIL_FALSE); 289 cil_list_destroy(&cl2, CIL_FALSE); 290 291 return rc; 292 } 293 294 int cil_find_matching_avrule(struct cil_tree_node *node, struct cil_avrule *avrule, struct cil_avrule *target, struct cil_list *matching, int match_self) 295 { 296 int rc = SEPOL_OK; 297 struct cil_symtab_datum *s1 = avrule->src; 298 struct cil_symtab_datum *t1 = avrule->tgt; 299 struct cil_symtab_datum *s2 = target->src; 300 struct cil_symtab_datum *t2 = target->tgt; 301 302 if (match_self != CIL_TRUE && avrule == target) goto exit; 303 304 if (avrule->rule_kind != target->rule_kind) goto exit; 305 306 if (avrule->is_extended != target->is_extended) goto exit; 307 308 if (!cil_type_match_any(s1, s2)) goto exit; 309 310 if (t1->fqn != CIL_KEY_SELF && t2->fqn != CIL_KEY_SELF) { 311 if (!cil_type_match_any(t1, t2)) goto exit; 312 } else { 313 if (t1->fqn == CIL_KEY_SELF && t2->fqn == CIL_KEY_SELF) { 314 /* The earlier check whether s1 and s2 matches is all that is needed */ 315 } else if (t1->fqn == CIL_KEY_SELF) { 316 rc = cil_self_match_any(s1, s2, t2); 317 if (rc < 0) { 318 goto exit; 319 } else if (rc == CIL_FALSE) { 320 rc = SEPOL_OK; 321 goto exit; 322 } 323 } else if (t2->fqn == CIL_KEY_SELF) { 324 rc = cil_self_match_any(s2, s1, t1); 325 if (rc < 0) { 326 goto exit; 327 } else if (rc == CIL_FALSE) { 328 rc = SEPOL_OK; 329 goto exit; 330 } 331 } 332 } 333 334 if (!target->is_extended) { 335 if (cil_classperms_list_match_any(avrule->perms.classperms, target->perms.classperms)) { 336 cil_list_append(matching, CIL_NODE, node); 337 } 338 } else { 339 if (cil_permissionx_match_any(avrule->perms.x.permx, target->perms.x.permx)) { 340 cil_list_append(matching, CIL_NODE, node); 341 } 342 } 343 344 rc = SEPOL_OK; 345 346 exit: 347 return rc; 348 } 349 350 static int __cil_find_matching_avrule_in_ast(struct cil_tree_node *node, uint32_t *finished, void *extra_args) 351 { 352 int rc = SEPOL_OK; 353 struct cil_args_find *args = extra_args; 354 355 if (node->flavor == CIL_BLOCK) { 356 struct cil_block *blk = node->data; 357 if (blk->is_abstract == CIL_TRUE) { 358 *finished = CIL_TREE_SKIP_HEAD; 359 goto exit; 360 } 361 } else if (node->flavor == CIL_MACRO) { 362 *finished = CIL_TREE_SKIP_HEAD; 363 goto exit; 364 } else if (node->flavor == CIL_AVRULE || node->flavor == CIL_AVRULEX) { 365 if (node->flavor == args->flavor) { 366 rc = cil_find_matching_avrule(node, node->data, args->target, args->matching, args->match_self); 367 } 368 } 369 370 exit: 371 return rc; 372 } 373 374 int cil_find_matching_avrule_in_ast(struct cil_tree_node *current, enum cil_flavor flavor, void *target, struct cil_list *matching, int match_self) 375 { 376 int rc; 377 struct cil_args_find args; 378 379 args.flavor = flavor; 380 args.target = target; 381 args.matching = matching; 382 args.match_self = match_self; 383 384 rc = cil_tree_walk(current, __cil_find_matching_avrule_in_ast, NULL, NULL, &args); 385 if (rc) { 386 cil_log(CIL_ERR, "An error occurred while searching for avrule in AST\n"); 387 } 388 389 return rc; 390 } 391