@Override public int compare(Policy p1, Policy p2) { // Give precedence to stanzas with inner package mappings if (p1.hasInnerPackages() != p2.hasInnerPackages()) { return p1.hasInnerPackages() ? -1 : 1; } // Check for duplicate entries if (p1.getSignatures().equals(p2.getSignatures())) { // Checks if signer w/o inner package names if (p1.hasGlobalSeinfo()) { duplicateFound = true; Slog.e(SELinuxMMAC.TAG, "Duplicate policy entry: " + p1.toString()); } // Look for common inner package name mappings final Map<String, String> p1Packages = p1.getInnerPackages(); final Map<String, String> p2Packages = p2.getInnerPackages(); if (!Collections.disjoint(p1Packages.keySet(), p2Packages.keySet())) { duplicateFound = true; Slog.e(SELinuxMMAC.TAG, "Duplicate policy entry: " + p1.toString()); } } return 0; }
/** * Applies a security label to a package based on an seinfo tag taken from a matched policy. All * signature based policy stanzas are consulted and, if no match is found, the default seinfo * label of 'default' (set in ApplicationInfo object) is used. The security label is attached to * the ApplicationInfo instance of the package in the event that a matching policy was found. * * @param pkg object representing the package to be labeled. */ public static void assignSeinfoValue(PackageParser.Package pkg) { synchronized (sPolicies) { for (Policy policy : sPolicies) { String seinfo = policy.getMatchedSeinfo(pkg); if (seinfo != null) { pkg.applicationInfo.seinfo = seinfo; break; } } } if (pkg.applicationInfo.isAutoPlayApp()) pkg.applicationInfo.seinfo += AUTOPLAY_APP_STR; if (pkg.applicationInfo.isPrivilegedApp()) pkg.applicationInfo.seinfo += PRIVILEGED_APP_STR; if (DEBUG_POLICY_INSTALL) { Slog.i( TAG, "package (" + pkg.packageName + ") labeled with " + "seinfo=" + pkg.applicationInfo.seinfo); } }
/** * Load the mac_permissions.xml file containing all seinfo assignments used to label apps. The * loaded mac_permissions.xml file is determined by the MAC_PERMISSIONS class variable which is * set at class load time which itself is based on the USE_OVERRIDE_POLICY class variable. For * further guidance on the proper structure of a mac_permissions.xml file consult the source code * located at system/sepolicy/mac_permissions.xml. * * @return boolean indicating if policy was correctly loaded. A value of false typically indicates * a structural problem with the xml or incorrectly constructed policy stanzas. A value of * true means that all stanzas were loaded successfully; no partial loading is possible. */ public static boolean readInstallPolicy() { // Temp structure to hold the rules while we parse the xml file List<Policy> policies = new ArrayList<>(); FileReader policyFile = null; XmlPullParser parser = Xml.newPullParser(); try { policyFile = new FileReader(MAC_PERMISSIONS); Slog.d(TAG, "Using policy file " + MAC_PERMISSIONS); parser.setInput(policyFile); parser.nextTag(); parser.require(XmlPullParser.START_TAG, null, "policy"); while (parser.next() != XmlPullParser.END_TAG) { if (parser.getEventType() != XmlPullParser.START_TAG) { continue; } switch (parser.getName()) { case "signer": policies.add(readSignerOrThrow(parser)); break; default: skip(parser); } } } catch (IllegalStateException | IllegalArgumentException | XmlPullParserException ex) { StringBuilder sb = new StringBuilder("Exception @"); sb.append(parser.getPositionDescription()); sb.append(" while parsing "); sb.append(MAC_PERMISSIONS); sb.append(":"); sb.append(ex); Slog.w(TAG, sb.toString()); return false; } catch (IOException ioe) { Slog.w(TAG, "Exception parsing " + MAC_PERMISSIONS, ioe); return false; } finally { IoUtils.closeQuietly(policyFile); } // Now sort the policy stanzas PolicyComparator policySort = new PolicyComparator(); Collections.sort(policies, policySort); if (policySort.foundDuplicate()) { Slog.w(TAG, "ERROR! Duplicate entries found parsing " + MAC_PERMISSIONS); return false; } synchronized (sPolicies) { sPolicies = policies; if (DEBUG_POLICY_ORDER) { for (Policy policy : sPolicies) { Slog.d(TAG, "Policy: " + policy.toString()); } } } return true; }