1# Copyright 2021 The Android Open Source Project 2# 3# Licensed under the Apache License, Version 2.0 (the "License"); 4# you may not use this file except in compliance with the License. 5# You may obtain a copy of the License at 6# 7# http://www.apache.org/licenses/LICENSE-2.0 8# 9# Unless required by applicable law or agreed to in writing, software 10# distributed under the License is distributed on an "AS IS" BASIS, 11# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12# See the License for the specific language governing permissions and 13# limitations under the License. 14 15from ctypes import * 16import re 17import os 18import sys 19import platform 20import fc_sort 21 22### 23# Check whether the regex will match a file path starting with the provided 24# prefix 25# 26# Compares regex entries in file_contexts with a path prefix. Regex entries 27# are often more specific than this file prefix. For example, the regex could 28# be /system/bin/foo\.sh and the prefix could be /system. This function 29# loops over the regex removing characters from the end until 30# 1) there is a match - return True or 2) run out of characters - return 31# False. 32# 33COMMON_PREFIXES = { 34 "/(vendor|system/vendor)": ["/vendor", "/system/vendor"], 35 "/(odm|vendor/odm)": ["/odm", "/vendor/odm"], 36 "/(product|system/product)": ["/product", "/system/product"], 37 "/(system_ext|system/system_ext)": ["/system_ext", "/system/system_ext"], 38} 39 40def MatchPathPrefix(pathregex, prefix): 41 # Before running regex compile loop, try two heuristics, because compiling 42 # regex is too expensive. These two can handle more than 90% out of all 43 # MatchPathPrefix calls. 44 45 # Heuristic 1: handle common prefixes for partitions 46 for c in COMMON_PREFIXES: 47 if not pathregex.startswith(c): 48 continue 49 found = False 50 for p in COMMON_PREFIXES[c]: 51 if prefix.startswith(p): 52 found = True 53 prefix = prefix[len(p):] 54 pathregex = pathregex[len(c):] 55 break 56 if not found: 57 return False 58 59 # Heuristic 2: compare normal characters as long as possible 60 idx = 0 61 while idx < len(prefix): 62 if idx == len(pathregex): 63 return False 64 if pathregex[idx] in fc_sort.META_CHARS or pathregex[idx] == '\\': 65 break 66 if pathregex[idx] != prefix[idx]: 67 return False 68 idx += 1 69 if idx == len(prefix): 70 return True 71 72 # Fall back to regex compile loop. 73 for i in range(len(pathregex), 0, -1): 74 try: 75 pattern = re.compile('^' + pathregex[0:i] + "$") 76 except: 77 continue 78 if pattern.match(prefix): 79 return True 80 return False 81 82def MatchPathPrefixes(pathregex, Prefixes): 83 for Prefix in Prefixes: 84 if MatchPathPrefix(pathregex, Prefix): 85 return True 86 return False 87 88class TERule: 89 def __init__(self, rule): 90 data = rule.split(',') 91 self.flavor = data[0] 92 self.sctx = data[1] 93 self.tctx = data[2] 94 self.tclass = data[3] 95 self.perms = set((data[4].strip()).split(' ')) 96 self.rule = rule 97 98class Policy: 99 __ExpandedRules = set() 100 __Rules = set() 101 __FcDict = None 102 __FcSorted = None 103 __GenfsDict = None 104 __libsepolwrap = None 105 __policydbP = None 106 __BUFSIZE = 2048 107 108 def AssertPathTypesDoNotHaveAttr(self, MatchPrefix, DoNotMatchPrefix, Attr, ExcludedTypes = []): 109 # Query policy for the types associated with Attr 110 TypesPol = self.QueryTypeAttribute(Attr, True) - set(ExcludedTypes) 111 # Search file_contexts to find types associated with input paths. 112 PathTypes = self.__GetTypesAndFilesByFilePathPrefix(MatchPrefix, DoNotMatchPrefix) 113 violators = set() 114 for PathType in PathTypes: 115 filepath, filetype = PathType 116 if filetype in TypesPol: 117 violators.add((str(filetype), str(filepath))) 118 119 ret = "" 120 if len(violators) > 0: 121 ret += "The following types on " 122 ret += " ".join(str(x) for x in sorted(MatchPrefix)) 123 ret += " must not be associated with the " 124 ret += "\"" + Attr + "\" attribute.\n" 125 ret += "Violator types and corresponding paths:\n" 126 ret += "\n".join(str(x) for x in sorted(violators)) 127 ret += "\n" 128 return ret 129 130 # Check that all types for "filesystem" have "attribute" associated with them 131 # for types labeled in genfs_contexts. 132 def AssertGenfsFilesystemTypesHaveAttr(self, Filesystem, Attr): 133 TypesPol = self.QueryTypeAttribute(Attr, True) 134 TypesGenfs = self.__GenfsDict[Filesystem] 135 violators = TypesGenfs.difference(TypesPol) 136 137 ret = "" 138 if len(violators) > 0: 139 ret += "The following types in " + Filesystem 140 ret += " must be associated with the " 141 ret += "\"" + Attr + "\" attribute: " 142 ret += " ".join(str(x) for x in sorted(violators)) + "\n" 143 return ret 144 145 # Check that path prefixes that match MatchPrefix, and do not Match 146 # DoNotMatchPrefix have the attribute Attr. 147 # For example assert that all types in /sys, and not in /sys/kernel/debugfs 148 # have the sysfs_type attribute. 149 def AssertPathTypesHaveAttr(self, MatchPrefix, DoNotMatchPrefix, Attr, ExcludedTypes = []): 150 # Query policy for the types associated with Attr 151 TypesPol = self.QueryTypeAttribute(Attr, True) | set(ExcludedTypes) 152 # Search file_contexts to find paths/types that should be associated with 153 # Attr. 154 PathTypes = self.__GetTypesAndFilesByFilePathPrefix(MatchPrefix, DoNotMatchPrefix) 155 violators = set() 156 for PathType in PathTypes: 157 filepath, filetype = PathType 158 if filetype not in TypesPol: 159 violators.add((str(filetype), str(filepath))) 160 161 ret = "" 162 if len(violators) > 0: 163 ret += "The following types on " 164 ret += " ".join(str(x) for x in sorted(MatchPrefix)) 165 ret += " must be associated with the " 166 ret += "\"" + Attr + "\" attribute.\n" 167 ret += "Violator types and corresponding paths:\n" 168 ret += "\n".join(str(x) for x in sorted(violators)) 169 ret += "\n" 170 return ret 171 172 def AssertPropertyOwnersAreExclusive(self): 173 systemProps = self.QueryTypeAttribute('system_property_type', True) 174 vendorProps = self.QueryTypeAttribute('vendor_property_type', True) 175 violators = systemProps.intersection(vendorProps) 176 ret = "" 177 if len(violators) > 0: 178 ret += "The following types have both system_property_type " 179 ret += "and vendor_property_type: " 180 ret += " ".join(str(x) for x in sorted(violators)) + "\n" 181 return ret 182 183 # Return all file_contexts entries that map to the input Type. 184 def QueryFc(self, Type): 185 if Type in self.__FcDict: 186 return self.__FcDict[Type] 187 else: 188 return None 189 190 # Return all attributes associated with a type if IsAttr=False or 191 # all types associated with an attribute if IsAttr=True 192 def QueryTypeAttribute(self, Type, IsAttr): 193 TypeIterP = self.__libsepolwrap.init_type_iter(self.__policydbP, 194 create_string_buffer(Type.encode("ascii")), IsAttr) 195 if (TypeIterP == None): 196 sys.exit("Failed to initialize type iterator") 197 buf = create_string_buffer(self.__BUFSIZE) 198 TypeAttr = set() 199 while True: 200 ret = self.__libsepolwrap.get_type(buf, self.__BUFSIZE, 201 self.__policydbP, TypeIterP) 202 if ret == 0: 203 TypeAttr.add(buf.value.decode("ascii")) 204 continue 205 if ret == 1: 206 break; 207 # We should never get here. 208 sys.exit("Failed to import policy") 209 self.__libsepolwrap.destroy_type_iter(TypeIterP) 210 return TypeAttr 211 212 def __TERuleMatch(self, Rule, **kwargs): 213 # Match source type 214 if ("scontext" in kwargs and 215 len(kwargs['scontext']) > 0 and 216 Rule.sctx not in kwargs['scontext']): 217 return False 218 # Match target type 219 if ("tcontext" in kwargs and 220 len(kwargs['tcontext']) > 0 and 221 Rule.tctx not in kwargs['tcontext']): 222 return False 223 # Match target class 224 if ("tclass" in kwargs and 225 len(kwargs['tclass']) > 0 and 226 not bool(set([Rule.tclass]) & kwargs['tclass'])): 227 return False 228 # Match any perms 229 if ("perms" in kwargs and 230 len(kwargs['perms']) > 0 and 231 not bool(Rule.perms & kwargs['perms'])): 232 return False 233 return True 234 235 # resolve a type to its attributes or 236 # resolve an attribute to its types and attributes 237 # For example if scontext is the domain attribute, then we need to 238 # include all types with the domain attribute such as untrusted_app and 239 # priv_app and all the attributes of those types such as appdomain. 240 def ResolveTypeAttribute(self, Type): 241 types = self.GetAllTypes(False) 242 attributes = self.GetAllTypes(True) 243 244 if Type in types: 245 return self.QueryTypeAttribute(Type, False) 246 elif Type in attributes: 247 TypesAndAttributes = set() 248 Types = self.QueryTypeAttribute(Type, True) 249 TypesAndAttributes |= Types 250 for T in Types: 251 TypesAndAttributes |= self.QueryTypeAttribute(T, False) 252 return TypesAndAttributes 253 else: 254 return set() 255 256 # Return all TERules that match: 257 # (any scontext) or (any tcontext) or (any tclass) or (any perms), 258 # perms. 259 # Any unspecified paramenter will match all. 260 # 261 # Example: QueryTERule(tcontext=["foo", "bar"], perms=["entrypoint"]) 262 # Will return any rule with: 263 # (tcontext="foo" or tcontext="bar") and ("entrypoint" in perms) 264 def QueryTERule(self, **kwargs): 265 if len(self.__Rules) == 0: 266 self.__InitTERules() 267 268 # add any matching types and attributes for scontext and tcontext 269 if ("scontext" in kwargs and len(kwargs['scontext']) > 0): 270 scontext = set() 271 for sctx in kwargs['scontext']: 272 scontext |= self.ResolveTypeAttribute(sctx) 273 if (len(scontext) == 0): 274 return [] 275 kwargs['scontext'] = scontext 276 if ("tcontext" in kwargs and len(kwargs['tcontext']) > 0): 277 tcontext = set() 278 for tctx in kwargs['tcontext']: 279 tcontext |= self.ResolveTypeAttribute(tctx) 280 if (len(tcontext) == 0): 281 return [] 282 kwargs['tcontext'] = tcontext 283 for Rule in self.__Rules: 284 if self.__TERuleMatch(Rule, **kwargs): 285 yield Rule 286 287 # Same as QueryTERule but only using the expanded ruleset. 288 # i.e. all attributes have been expanded to their various types. 289 def QueryExpandedTERule(self, **kwargs): 290 if len(self.__ExpandedRules) == 0: 291 self.__InitExpandedTERules() 292 for Rule in self.__ExpandedRules: 293 if self.__TERuleMatch(Rule, **kwargs): 294 yield Rule 295 296 def GetAllTypes(self, isAttr): 297 TypeIterP = self.__libsepolwrap.init_type_iter(self.__policydbP, None, isAttr) 298 if (TypeIterP == None): 299 sys.exit("Failed to initialize type iterator") 300 buf = create_string_buffer(self.__BUFSIZE) 301 AllTypes = set() 302 while True: 303 ret = self.__libsepolwrap.get_type(buf, self.__BUFSIZE, 304 self.__policydbP, TypeIterP) 305 if ret == 0: 306 AllTypes.add(buf.value.decode("ascii")) 307 continue 308 if ret == 1: 309 break; 310 # We should never get here. 311 sys.exit("Failed to import policy") 312 self.__libsepolwrap.destroy_type_iter(TypeIterP) 313 return AllTypes 314 315 def __ExactMatchPathPrefix(self, pathregex, prefix): 316 pattern = re.compile('^' + pathregex + "$") 317 if pattern.match(prefix): 318 return True 319 return False 320 321 # Return a tuple (prefix, i) where i is the index of the most specific 322 # match of prefix in the sorted file_contexts. This is useful for limiting a 323 # file_contexts search to matches that are more specific and omitting less 324 # specific matches. For example, finding all matches to prefix /data/vendor 325 # should not include /data(/.*)? if /data/vendor(/.*)? is also specified. 326 def __FcSortedIndex(self, prefix): 327 index = 0 328 for i in range(0, len(self.__FcSorted)): 329 if self.__ExactMatchPathPrefix(self.__FcSorted[i].path, prefix): 330 index = i 331 return prefix, index 332 333 # Return a tuple of (path, Type) for all matching paths. Use the sorted 334 # file_contexts and index returned from __FcSortedIndex() to limit results 335 # to results that are more specific than the prefix. 336 def __MatchPathPrefixTypes(self, prefix, index): 337 PathType = [] 338 for i in range(index, len(self.__FcSorted)): 339 if MatchPathPrefix(self.__FcSorted[i].path, prefix): 340 PathType.append((self.__FcSorted[i].path, self.__FcSorted[i].type)) 341 return PathType 342 343 # Return types that match MatchPrefixes but do not match 344 # DoNotMatchPrefixes 345 def __GetTypesAndFilesByFilePathPrefix(self, MatchPrefixes, DoNotMatchPrefixes): 346 ret = [] 347 348 MatchPrefixesWithIndex = [] 349 for MatchPrefix in MatchPrefixes: 350 MatchPrefixesWithIndex.append(self.__FcSortedIndex(MatchPrefix)) 351 352 for MatchPrefixWithIndex in MatchPrefixesWithIndex: 353 PathTypes = self.__MatchPathPrefixTypes(*MatchPrefixWithIndex) 354 for PathType in PathTypes: 355 if MatchPathPrefixes(PathType[0], DoNotMatchPrefixes): 356 continue 357 ret.append(PathType) 358 return ret 359 360 def __GetTERules(self, policydbP, avtabIterP, Rules): 361 if Rules is None: 362 Rules = set() 363 buf = create_string_buffer(self.__BUFSIZE) 364 ret = 0 365 while True: 366 ret = self.__libsepolwrap.get_allow_rule(buf, self.__BUFSIZE, 367 policydbP, avtabIterP) 368 if ret == 0: 369 Rule = TERule(buf.value.decode("ascii")) 370 Rules.add(Rule) 371 continue 372 if ret == 1: 373 break; 374 # We should never get here. 375 sys.exit("Failed to import policy") 376 377 def __InitTERules(self): 378 avtabIterP = self.__libsepolwrap.init_avtab(self.__policydbP) 379 if (avtabIterP == None): 380 sys.exit("Failed to initialize avtab") 381 self.__GetTERules(self.__policydbP, avtabIterP, self.__Rules) 382 self.__libsepolwrap.destroy_avtab(avtabIterP) 383 avtabIterP = self.__libsepolwrap.init_cond_avtab(self.__policydbP) 384 if (avtabIterP == None): 385 sys.exit("Failed to initialize conditional avtab") 386 self.__GetTERules(self.__policydbP, avtabIterP, self.__Rules) 387 self.__libsepolwrap.destroy_avtab(avtabIterP) 388 389 def __InitExpandedTERules(self): 390 avtabIterP = self.__libsepolwrap.init_expanded_avtab(self.__policydbP) 391 if (avtabIterP == None): 392 sys.exit("Failed to initialize avtab") 393 self.__GetTERules(self.__policydbP, avtabIterP, self.__ExpandedRules) 394 self.__libsepolwrap.destroy_expanded_avtab(avtabIterP) 395 avtabIterP = self.__libsepolwrap.init_expanded_cond_avtab(self.__policydbP) 396 if (avtabIterP == None): 397 sys.exit("Failed to initialize conditional avtab") 398 self.__GetTERules(self.__policydbP, avtabIterP, self.__ExpandedRules) 399 self.__libsepolwrap.destroy_expanded_avtab(avtabIterP) 400 401 # load ctypes-ified libsepol wrapper 402 def __InitLibsepolwrap(self, LibPath): 403 lib = CDLL(LibPath) 404 405 # int get_allow_rule(char *out, size_t len, void *policydbp, void *avtab_iterp); 406 lib.get_allow_rule.restype = c_int 407 lib.get_allow_rule.argtypes = [c_char_p, c_size_t, c_void_p, c_void_p]; 408 # void *load_policy(const char *policy_path); 409 lib.load_policy.restype = c_void_p 410 lib.load_policy.argtypes = [c_char_p] 411 # void destroy_policy(void *policydbp); 412 lib.destroy_policy.argtypes = [c_void_p] 413 # void *init_expanded_avtab(void *policydbp); 414 lib.init_expanded_avtab.restype = c_void_p 415 lib.init_expanded_avtab.argtypes = [c_void_p] 416 # void *init_expanded_cond_avtab(void *policydbp); 417 lib.init_expanded_cond_avtab.restype = c_void_p 418 lib.init_expanded_cond_avtab.argtypes = [c_void_p] 419 # void destroy_expanded_avtab(void *avtab_iterp); 420 lib.destroy_expanded_avtab.argtypes = [c_void_p] 421 # void *init_avtab(void *policydbp); 422 lib.init_avtab.restype = c_void_p 423 lib.init_avtab.argtypes = [c_void_p] 424 # void *init_cond_avtab(void *policydbp); 425 lib.init_cond_avtab.restype = c_void_p 426 lib.init_cond_avtab.argtypes = [c_void_p] 427 # void destroy_avtab(void *avtab_iterp); 428 lib.destroy_avtab.argtypes = [c_void_p] 429 # int get_type(char *out, size_t max_size, void *policydbp, void *type_iterp); 430 lib.get_type.restype = c_int 431 lib.get_type.argtypes = [c_char_p, c_size_t, c_void_p, c_void_p] 432 # void *init_type_iter(void *policydbp, const char *type, bool is_attr); 433 lib.init_type_iter.restype = c_void_p 434 lib.init_type_iter.argtypes = [c_void_p, c_char_p, c_bool] 435 # void destroy_type_iter(void *type_iterp); 436 lib.destroy_type_iter.argtypes = [c_void_p] 437 # void *init_genfs_iter(void *policydbp) 438 lib.init_genfs_iter.restype = c_void_p 439 lib.init_genfs_iter.argtypes = [c_void_p] 440 # int get_genfs(char *out, size_t max_size, void *genfs_iterp); 441 lib.get_genfs.restype = c_int 442 lib.get_genfs.argtypes = [c_char_p, c_size_t, c_void_p, c_void_p] 443 # void destroy_genfs_iter(void *genfs_iterp) 444 lib.destroy_genfs_iter.argtypes = [c_void_p] 445 446 self.__libsepolwrap = lib 447 448 def __GenfsDictAdd(self, Dict, buf): 449 fs, buf = buf.split(' ', 1) 450 path, context = buf.rsplit(' ', 1) 451 Type = context.split(":")[2] 452 if not fs in Dict: 453 Dict[fs] = {Type} 454 else: 455 Dict[fs].add(Type) 456 457 def __InitGenfsCon(self): 458 self.__GenfsDict = {} 459 GenfsIterP = self.__libsepolwrap.init_genfs_iter(self.__policydbP) 460 if (GenfsIterP == None): 461 sys.exit("Failed to retreive genfs entries") 462 buf = create_string_buffer(self.__BUFSIZE) 463 while True: 464 ret = self.__libsepolwrap.get_genfs(buf, self.__BUFSIZE, 465 self.__policydbP, GenfsIterP) 466 if ret == 0: 467 self.__GenfsDictAdd(self.__GenfsDict, buf.value.decode("ascii")) 468 continue 469 if ret == 1: 470 self.__GenfsDictAdd(self.__GenfsDict, buf.value.decode("ascii")) 471 break; 472 # We should never get here. 473 sys.exit("Failed to get genfs entries") 474 self.__libsepolwrap.destroy_genfs_iter(GenfsIterP) 475 476 # load file_contexts 477 def __InitFC(self, FcPaths): 478 self.__FcDict = {} 479 if FcPaths is None: 480 return 481 fc = [] 482 for path in FcPaths: 483 if not os.path.exists(path): 484 sys.exit("file_contexts file " + path + " does not exist.") 485 fd = open(path, "r") 486 fc += fd.readlines() 487 fd.close() 488 for i in fc: 489 rec = i.split() 490 try: 491 t = rec[-1].split(":")[2] 492 if t in self.__FcDict: 493 self.__FcDict[t].append(rec[0]) 494 else: 495 self.__FcDict[t] = [rec[0]] 496 except: 497 pass 498 self.__FcSorted = fc_sort.sort(FcPaths) 499 500 # load policy 501 def __InitPolicy(self, PolicyPath): 502 cPolicyPath = create_string_buffer(PolicyPath.encode("ascii")) 503 self.__policydbP = self.__libsepolwrap.load_policy(cPolicyPath) 504 if (self.__policydbP is None): 505 sys.exit("Failed to load policy") 506 507 def __init__(self, PolicyPath, FcPaths, LibPath): 508 self.__InitLibsepolwrap(LibPath) 509 self.__InitFC(FcPaths) 510 self.__InitPolicy(PolicyPath) 511 self.__InitGenfsCon() 512 513 def __del__(self): 514 if self.__policydbP is not None: 515 self.__libsepolwrap.destroy_policy(self.__policydbP) 516 517coredomainAllowlist = { 518 # TODO: how do we make sure vendor_init doesn't have bad coupling with 519 # /vendor? It is the only system process which is not coredomain. 520 'vendor_init', 521 # TODO(b/152813275): need to avoid allowlist for rootdir 522 "modprobe", 523 "slideshow", 524 } 525 526class scontext: 527 def __init__(self): 528 self.fromSystem = False 529 self.fromVendor = False 530 self.coredomain = False 531 self.appdomain = False 532 self.attributes = set() 533 self.entrypoints = [] 534 self.entrypointpaths = [] 535 self.error = "" 536 537class TestPolicy: 538 """A policy loaded in memory with its domains easily accessible.""" 539 540 def __init__(self): 541 self.alldomains = {} 542 self.coredomains = set() 543 self.appdomains = set() 544 self.vendordomains = set() 545 self.pol = None 546 547 # compat vars 548 self.alltypes = set() 549 self.oldalltypes = set() 550 self.compatMapping = None 551 self.pubtypes = set() 552 553 def GetAllDomains(self): 554 for result in self.pol.QueryTypeAttribute("domain", True): 555 self.alldomains[result] = scontext() 556 557 def GetAppDomains(self): 558 for d in self.alldomains: 559 # The application of the "appdomain" attribute is trusted because core 560 # selinux policy contains neverallow rules that enforce that only zygote 561 # and runas spawned processes may transition to processes that have 562 # the appdomain attribute. 563 if "appdomain" in self.alldomains[d].attributes: 564 self.alldomains[d].appdomain = True 565 self.appdomains.add(d) 566 567 def GetCoreDomains(self): 568 for d in self.alldomains: 569 domain = self.alldomains[d] 570 # TestCoredomainViolations will verify if coredomain was incorrectly 571 # applied. 572 if "coredomain" in domain.attributes: 573 domain.coredomain = True 574 self.coredomains.add(d) 575 # check whether domains are executed off of /system or /vendor 576 if d in coredomainAllowlist: 577 continue 578 # TODO(b/153112003): add checks to prevent app domains from being 579 # incorrectly labeled as coredomain. Apps don't have entrypoints as 580 # they're always dynamically transitioned to by zygote. 581 if d in self.appdomains: 582 continue 583 # TODO(b/153112747): need to handle cases where there is a dynamic 584 # transition OR there happens to be no context in AOSP files. 585 if not domain.entrypointpaths: 586 continue 587 588 for path in domain.entrypointpaths: 589 vendor = any(MatchPathPrefix(path, prefix) for prefix in 590 ["/vendor", "/odm"]) 591 system = any(MatchPathPrefix(path, prefix) for prefix in 592 ["/init", "/system_ext", "/product" ]) 593 594 # only mark entrypoint as system if it is not in legacy /system/vendor 595 if MatchPathPrefix(path, "/system/vendor"): 596 vendor = True 597 elif MatchPathPrefix(path, "/system"): 598 system = True 599 600 if not vendor and not system: 601 domain.error += "Unrecognized entrypoint for " + d + " at " + path + "\n" 602 603 domain.fromSystem = domain.fromSystem or system 604 domain.fromVendor = domain.fromVendor or vendor 605 606 ### 607 # Add the entrypoint type and path(s) to each domain. 608 # 609 def GetDomainEntrypoints(self): 610 for x in self.pol.QueryExpandedTERule(tclass=set(["file"]), perms=set(["entrypoint"])): 611 if not x.sctx in self.alldomains: 612 continue 613 self.alldomains[x.sctx].entrypoints.append(str(x.tctx)) 614 # postinstall_file represents a special case specific to A/B OTAs. 615 # Update_engine mounts a partition and relabels it postinstall_file. 616 # There is no file_contexts entry associated with postinstall_file 617 # so skip the lookup. 618 if x.tctx == "postinstall_file": 619 continue 620 entrypointpath = self.pol.QueryFc(x.tctx) 621 if not entrypointpath: 622 continue 623 self.alldomains[x.sctx].entrypointpaths.extend(entrypointpath) 624 625 ### 626 # Get attributes associated with each domain 627 # 628 def GetAttributes(self): 629 for domain in self.alldomains: 630 for result in self.pol.QueryTypeAttribute(domain, False): 631 self.alldomains[domain].attributes.add(result) 632 633 def setup(self, pol): 634 self.pol = pol 635 self.GetAllDomains() 636 self.GetAttributes() 637 self.GetDomainEntrypoints() 638 self.GetAppDomains() 639 self.GetCoreDomains() 640 641 def GetAllTypes(self, basepol, oldpol): 642 self.alltypes = basepol.GetAllTypes(False) 643 self.oldalltypes = oldpol.GetAllTypes(False) 644 645 # setup for the policy compatibility tests 646 def compatSetup(self, basepol, oldpol, mapping, types): 647 self.GetAllTypes(basepol, oldpol) 648 self.compatMapping = mapping 649 self.pubtypes = types 650 651 def DomainsWithAttribute(self, attr): 652 domains = [] 653 for domain in self.alldomains: 654 if attr in self.alldomains[domain].attributes: 655 domains.append(domain) 656 return domains 657 658 def PrintScontexts(self): 659 for d in sorted(self.alldomains.keys()): 660 sctx = self.alldomains[d] 661 print(d) 662 print("\tcoredomain="+str(sctx.coredomain)) 663 print("\tappdomain="+str(sctx.appdomain)) 664 print("\tfromSystem="+str(sctx.fromSystem)) 665 print("\tfromVendor="+str(sctx.fromVendor)) 666 print("\tattributes="+str(sctx.attributes)) 667 print("\tentrypoints="+str(sctx.entrypoints)) 668 print("\tentrypointpaths=") 669 if sctx.entrypointpaths is not None: 670 for path in sctx.entrypointpaths: 671 print("\t\t"+str(path)) 672