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