class AndroidInitService(object): def __init__(self, service_name, service_args): self.service_class = "default" self.service_groups = [] self.service_name = service_name self.service_args = service_args self.options = [] self.cred = Cred() # default uid/gid is root! self.cred.uid = 0 self.cred.gid = 0 self.disabled = False self.oneshot = False def add_option(self, option, args): if option == "user": self.cred.uid = AID_MAP_INV.get(args[0], 9999) if self.cred.uid == 9999: log.warning("Missing AID definition for user: %s", args[0]) elif option == "capabilities": for cap in args: self.cred.cap.add('ambient', cap) elif option == "group": self.cred.gid = AID_MAP_INV.get(args[0], 9999) if self.cred.gid == 9999: log.warning("Missing AID definition for group: %s", args[0]) for group in args[1:]: try: self.cred.add_group(group) except KeyError: log.debug("Unabled to find AID mapping for group %s", group) elif option == "disabled": self.disabled = True elif option == "class": self.service_class = args[0] if len(args) > 1: self.service_groups = args[1:] elif option == "oneshot": self.oneshot = True elif option == "seclabel": self.cred.sid = SELinuxContext.FromString(args[0]) else: self.options += [[option] + args] def __str__(self): return "<AndroidInitService %s %s>" % (self.service_name, self.cred)
def read_data(data): processes = [] expect_exe = True exe = "" name = "" pid = "" ppid = "" cred = Cred() has_capamb = data.find("CapAmb:") != -1 for line_no, line in enumerate(data.split("\n")): # Ignore comments and blank lines if re.match('^(\s*#)|(\s*$)', line): continue # greedly replace all whitespace with a single space for splitting line = re.sub('\s+', " ", line) # split by spaces, while eliminating empty components components = list(filter(lambda x: len(x) > 0, line.split(" "))) field = components[0][:-1] args = components[1:] if field == "WARN": continue if expect_exe and field != "Exe": raise ValueError("Expected exe") elif not expect_exe and field == "Exe": raise ValueError("Unexpected exe") if field == "Exe": expect_exe = False exe = args[0] elif field == "Sid": cred.sid = SELinuxContext.FromString(args[0]) elif field == "Name": name = args[0] elif field == "Pid": pid = int(args[0]) elif field == "PPid": ppid = int(args[0]) elif field == "Uid": # ignore other UIDs cred.uid = int(args[0]) elif field == "Gid": # ignore other UIDs cred.gid = int(args[0]) elif field == "Groups": for g in args: cred.add_group(int(g)) elif "Cap" in field: capset = field[3:] capv = int(args[0], 16) capbits = [] for i in range(64): if capv & (1 << i): capbits += [i] capvalues = set(list(map(Capabilities.bit_to_name, capbits))) if capset == "Inh": cred.cap.inherited = capvalues elif capset == "Prm": cred.cap.permitted = capvalues elif capset == "Eff": cred.cap.effective = capvalues elif capset == "Bnd": if not has_capamb: expect_exe = True cred.cap.bounding = capvalues elif capset == "Amb": cred.cap.ambient = capvalues expect_exe = True else: raise ValueError("unexpected capset") else: raise ValueError("unk field") if expect_exe: processes += [Process(exe, name, pid, ppid, cred)] exe = "" name = "" pid = "" ppid = "" cred = Cred() # remove rooting tool processes processes = list( filter( lambda x: "magisk" not in (x.exe.lower() + x.name.lower() + str(x.cred.sid).lower()), processes)) return processes