Loading services/java/com/android/server/pm/SELinuxMMAC.java +174 −74 Original line number Diff line number Diff line Loading @@ -48,12 +48,11 @@ public final class SELinuxMMAC { private static final boolean DEBUG_POLICY_INSTALL = DEBUG_POLICY || false; // Signature seinfo values read from policy. private static final HashMap<Signature, String> sSigSeinfo = new HashMap<Signature, String>(); private static HashMap<Signature, Policy> sSigSeinfo = new HashMap<Signature, Policy>(); // Package name seinfo values read from policy. private static final HashMap<String, String> sPackageSeinfo = new HashMap<String, String>(); // Default seinfo read from policy. private static String sDefaultSeinfo = null; // Locations of potential install policy files. private static final File[] INSTALL_POLICY_FILE = { Loading @@ -61,9 +60,45 @@ public final class SELinuxMMAC { new File(Environment.getRootDirectory(), "etc/security/mac_permissions.xml"), null}; // Signature policy stanzas static class Policy { private String seinfo; private final HashMap<String, String> pkgMap; Policy() { seinfo = null; pkgMap = new HashMap<String, String>(); } void putSeinfo(String seinfoValue) { seinfo = seinfoValue; } void putPkg(String pkg, String seinfoValue) { pkgMap.put(pkg, seinfoValue); } // Valid policy stanza means there exists a global // seinfo value or at least one package policy. boolean isValid() { return (seinfo != null) || (!pkgMap.isEmpty()); } String checkPolicy(String pkgName) { // Check for package name seinfo value first. String seinfoValue = pkgMap.get(pkgName); if (seinfoValue != null) { return seinfoValue; } // Return the global seinfo value. return seinfo; } } private static void flushInstallPolicy() { sSigSeinfo.clear(); sPackageSeinfo.clear(); sDefaultSeinfo = null; } /** Loading @@ -87,6 +122,10 @@ public final class SELinuxMMAC { } private static boolean readInstallPolicy(File[] policyFiles) { // Temp structures to hold the rules while we parse the xml file. // We add all the rules together once we know there's no structural problems. HashMap<Signature, Policy> sigSeinfo = new HashMap<Signature, Policy>(); String defaultSeinfo = null; FileReader policyFile = null; int i = 0; Loading @@ -107,8 +146,6 @@ public final class SELinuxMMAC { Slog.d(TAG, "Using install policy file " + policyFiles[i].getPath()); flushInstallPolicy(); try { XmlPullParser parser = Xml.newPullParser(); parser.setInput(policyFile); Loading Loading @@ -138,55 +175,82 @@ public final class SELinuxMMAC { XmlUtils.skipCurrentTag(parser); continue; } String seinfo = readSeinfoTag(parser); if (seinfo != null) { if (DEBUG_POLICY_INSTALL) Slog.i(TAG, "<signer> tag: (" + cert + ") assigned seinfo=" + seinfo); sSigSeinfo.put(signature, seinfo); Policy policy = readPolicyTags(parser); if (policy.isValid()) { sigSeinfo.put(signature, policy); } } else if ("default".equals(tagName)) { String seinfo = readSeinfoTag(parser); if (seinfo != null) { // Value is null if default tag is absent or seinfo tag is malformed. defaultSeinfo = readSeinfoTag(parser); if (DEBUG_POLICY_INSTALL) Slog.i(TAG, "<default> tag assigned seinfo=" + seinfo); Slog.i(TAG, "<default> tag assigned seinfo=" + defaultSeinfo); } else { XmlUtils.skipCurrentTag(parser); } } } catch (XmlPullParserException e) { // An error outside of a stanza means a structural problem // with the xml file. So ignore it. Slog.w(TAG, "Got exception parsing ", e); return false; } catch (IOException e) { Slog.w(TAG, "Got exception parsing ", e); return false; } finally { try { policyFile.close(); } catch (IOException e) { //omit } } flushInstallPolicy(); sSigSeinfo = sigSeinfo; sDefaultSeinfo = defaultSeinfo; return true; } private static Policy readPolicyTags(XmlPullParser parser) throws IOException, XmlPullParserException { int type; int outerDepth = parser.getDepth(); Policy policy = new Policy(); while ((type=parser.next()) != XmlPullParser.END_DOCUMENT && (type != XmlPullParser.END_TAG || parser.getDepth() > outerDepth)) { if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) { continue; } // The 'null' signature is the default seinfo value sSigSeinfo.put(null, seinfo); String tagName = parser.getName(); if ("seinfo".equals(tagName)) { String seinfo = parseSeinfo(parser); if (seinfo != null) { policy.putSeinfo(seinfo); } XmlUtils.skipCurrentTag(parser); } else if ("package".equals(tagName)) { String pkgName = parser.getAttributeValue(null, "name"); if (pkgName == null) { Slog.w(TAG, "<package> without name at " String pkg = parser.getAttributeValue(null, "name"); if (!validatePackageName(pkg)) { Slog.w(TAG, "<package> without valid name at " + parser.getPositionDescription()); XmlUtils.skipCurrentTag(parser); continue; } String seinfo = readSeinfoTag(parser); if (seinfo != null) { if (DEBUG_POLICY_INSTALL) Slog.i(TAG, "<package> tag: (" + pkgName + ") assigned seinfo=" + seinfo); sPackageSeinfo.put(pkgName, seinfo); policy.putPkg(pkg, seinfo); } } else { XmlUtils.skipCurrentTag(parser); continue; } } } catch (XmlPullParserException e) { Slog.w(TAG, "Got execption parsing ", e); } catch (IOException e) { Slog.w(TAG, "Got execption parsing ", e); } try { policyFile.close(); } catch (IOException e) { //omit } return true; return policy; } private static String readSeinfoTag(XmlPullParser parser) throws Loading @@ -205,17 +269,55 @@ public final class SELinuxMMAC { String tagName = parser.getName(); if ("seinfo".equals(tagName)) { seinfo = parseSeinfo(parser); } XmlUtils.skipCurrentTag(parser); } return seinfo; } private static String parseSeinfo(XmlPullParser parser) { String seinfoValue = parser.getAttributeValue(null, "value"); if (validateValue(seinfoValue)) { seinfo = seinfoValue; } else { if (!validateValue(seinfoValue)) { Slog.w(TAG, "<seinfo> without valid value at " + parser.getPositionDescription()); seinfoValue = null; } return seinfoValue; } XmlUtils.skipCurrentTag(parser); /** * General validation routine for package names. * Returns a boolean indicating if the passed string * is a valid android package name. */ private static boolean validatePackageName(String name) { if (name == null) return false; final int N = name.length(); boolean hasSep = false; boolean front = true; for (int i=0; i<N; i++) { final char c = name.charAt(i); if ((c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z')) { front = false; continue; } if (!front) { if ((c >= '0' && c <= '9') || c == '_') { continue; } return seinfo; } if (c == '.') { hasSep = true; front = true; continue; } return false; } return hasSep; } /** Loading Loading @@ -245,10 +347,11 @@ public final class SELinuxMMAC { * The label is attached to the ApplicationInfo instance of the package. * @param PackageParser.Package object representing the package * to labeled. * @return String holding the value of the seinfo label that was assigned. * Value may be null which indicates no seinfo label was assigned. * @return boolean which determines whether a non null seinfo label * was assigned to the package. A null value simply meaning that * no policy matched. */ public static void assignSeinfoValue(PackageParser.Package pkg) { public static boolean assignSeinfoValue(PackageParser.Package pkg) { /* * Non system installed apps should be treated the same. This Loading @@ -264,31 +367,28 @@ public final class SELinuxMMAC { if (s == null) continue; if (sSigSeinfo.containsKey(s)) { String seinfo = pkg.applicationInfo.seinfo = sSigSeinfo.get(s); Policy policy = sSigSeinfo.get(s); if (policy != null) { String seinfo = policy.checkPolicy(pkg.packageName); if (seinfo != null) { pkg.applicationInfo.seinfo = seinfo; if (DEBUG_POLICY_INSTALL) Slog.i(TAG, "package (" + pkg.packageName + ") labeled with seinfo=" + seinfo); return; return true; } } // Check for seinfo labeled by package. if (sPackageSeinfo.containsKey(pkg.packageName)) { String seinfo = pkg.applicationInfo.seinfo = sPackageSeinfo.get(pkg.packageName); if (DEBUG_POLICY_INSTALL) Slog.i(TAG, "package (" + pkg.packageName + ") labeled with seinfo=" + seinfo); return; } } // If we have a default seinfo value then great, otherwise // we set a null object and that is what we started with. String seinfo = pkg.applicationInfo.seinfo = sSigSeinfo.get(null); pkg.applicationInfo.seinfo = sDefaultSeinfo; if (DEBUG_POLICY_INSTALL) Slog.i(TAG, "package (" + pkg.packageName + ") labeled with seinfo=" + (seinfo == null ? "null" : seinfo)); Slog.i(TAG, "package (" + pkg.packageName + ") labeled with seinfo=" + (sDefaultSeinfo == null ? "null" : sDefaultSeinfo)); return (sDefaultSeinfo != null); } } Loading
services/java/com/android/server/pm/SELinuxMMAC.java +174 −74 Original line number Diff line number Diff line Loading @@ -48,12 +48,11 @@ public final class SELinuxMMAC { private static final boolean DEBUG_POLICY_INSTALL = DEBUG_POLICY || false; // Signature seinfo values read from policy. private static final HashMap<Signature, String> sSigSeinfo = new HashMap<Signature, String>(); private static HashMap<Signature, Policy> sSigSeinfo = new HashMap<Signature, Policy>(); // Package name seinfo values read from policy. private static final HashMap<String, String> sPackageSeinfo = new HashMap<String, String>(); // Default seinfo read from policy. private static String sDefaultSeinfo = null; // Locations of potential install policy files. private static final File[] INSTALL_POLICY_FILE = { Loading @@ -61,9 +60,45 @@ public final class SELinuxMMAC { new File(Environment.getRootDirectory(), "etc/security/mac_permissions.xml"), null}; // Signature policy stanzas static class Policy { private String seinfo; private final HashMap<String, String> pkgMap; Policy() { seinfo = null; pkgMap = new HashMap<String, String>(); } void putSeinfo(String seinfoValue) { seinfo = seinfoValue; } void putPkg(String pkg, String seinfoValue) { pkgMap.put(pkg, seinfoValue); } // Valid policy stanza means there exists a global // seinfo value or at least one package policy. boolean isValid() { return (seinfo != null) || (!pkgMap.isEmpty()); } String checkPolicy(String pkgName) { // Check for package name seinfo value first. String seinfoValue = pkgMap.get(pkgName); if (seinfoValue != null) { return seinfoValue; } // Return the global seinfo value. return seinfo; } } private static void flushInstallPolicy() { sSigSeinfo.clear(); sPackageSeinfo.clear(); sDefaultSeinfo = null; } /** Loading @@ -87,6 +122,10 @@ public final class SELinuxMMAC { } private static boolean readInstallPolicy(File[] policyFiles) { // Temp structures to hold the rules while we parse the xml file. // We add all the rules together once we know there's no structural problems. HashMap<Signature, Policy> sigSeinfo = new HashMap<Signature, Policy>(); String defaultSeinfo = null; FileReader policyFile = null; int i = 0; Loading @@ -107,8 +146,6 @@ public final class SELinuxMMAC { Slog.d(TAG, "Using install policy file " + policyFiles[i].getPath()); flushInstallPolicy(); try { XmlPullParser parser = Xml.newPullParser(); parser.setInput(policyFile); Loading Loading @@ -138,55 +175,82 @@ public final class SELinuxMMAC { XmlUtils.skipCurrentTag(parser); continue; } String seinfo = readSeinfoTag(parser); if (seinfo != null) { if (DEBUG_POLICY_INSTALL) Slog.i(TAG, "<signer> tag: (" + cert + ") assigned seinfo=" + seinfo); sSigSeinfo.put(signature, seinfo); Policy policy = readPolicyTags(parser); if (policy.isValid()) { sigSeinfo.put(signature, policy); } } else if ("default".equals(tagName)) { String seinfo = readSeinfoTag(parser); if (seinfo != null) { // Value is null if default tag is absent or seinfo tag is malformed. defaultSeinfo = readSeinfoTag(parser); if (DEBUG_POLICY_INSTALL) Slog.i(TAG, "<default> tag assigned seinfo=" + seinfo); Slog.i(TAG, "<default> tag assigned seinfo=" + defaultSeinfo); } else { XmlUtils.skipCurrentTag(parser); } } } catch (XmlPullParserException e) { // An error outside of a stanza means a structural problem // with the xml file. So ignore it. Slog.w(TAG, "Got exception parsing ", e); return false; } catch (IOException e) { Slog.w(TAG, "Got exception parsing ", e); return false; } finally { try { policyFile.close(); } catch (IOException e) { //omit } } flushInstallPolicy(); sSigSeinfo = sigSeinfo; sDefaultSeinfo = defaultSeinfo; return true; } private static Policy readPolicyTags(XmlPullParser parser) throws IOException, XmlPullParserException { int type; int outerDepth = parser.getDepth(); Policy policy = new Policy(); while ((type=parser.next()) != XmlPullParser.END_DOCUMENT && (type != XmlPullParser.END_TAG || parser.getDepth() > outerDepth)) { if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) { continue; } // The 'null' signature is the default seinfo value sSigSeinfo.put(null, seinfo); String tagName = parser.getName(); if ("seinfo".equals(tagName)) { String seinfo = parseSeinfo(parser); if (seinfo != null) { policy.putSeinfo(seinfo); } XmlUtils.skipCurrentTag(parser); } else if ("package".equals(tagName)) { String pkgName = parser.getAttributeValue(null, "name"); if (pkgName == null) { Slog.w(TAG, "<package> without name at " String pkg = parser.getAttributeValue(null, "name"); if (!validatePackageName(pkg)) { Slog.w(TAG, "<package> without valid name at " + parser.getPositionDescription()); XmlUtils.skipCurrentTag(parser); continue; } String seinfo = readSeinfoTag(parser); if (seinfo != null) { if (DEBUG_POLICY_INSTALL) Slog.i(TAG, "<package> tag: (" + pkgName + ") assigned seinfo=" + seinfo); sPackageSeinfo.put(pkgName, seinfo); policy.putPkg(pkg, seinfo); } } else { XmlUtils.skipCurrentTag(parser); continue; } } } catch (XmlPullParserException e) { Slog.w(TAG, "Got execption parsing ", e); } catch (IOException e) { Slog.w(TAG, "Got execption parsing ", e); } try { policyFile.close(); } catch (IOException e) { //omit } return true; return policy; } private static String readSeinfoTag(XmlPullParser parser) throws Loading @@ -205,17 +269,55 @@ public final class SELinuxMMAC { String tagName = parser.getName(); if ("seinfo".equals(tagName)) { seinfo = parseSeinfo(parser); } XmlUtils.skipCurrentTag(parser); } return seinfo; } private static String parseSeinfo(XmlPullParser parser) { String seinfoValue = parser.getAttributeValue(null, "value"); if (validateValue(seinfoValue)) { seinfo = seinfoValue; } else { if (!validateValue(seinfoValue)) { Slog.w(TAG, "<seinfo> without valid value at " + parser.getPositionDescription()); seinfoValue = null; } return seinfoValue; } XmlUtils.skipCurrentTag(parser); /** * General validation routine for package names. * Returns a boolean indicating if the passed string * is a valid android package name. */ private static boolean validatePackageName(String name) { if (name == null) return false; final int N = name.length(); boolean hasSep = false; boolean front = true; for (int i=0; i<N; i++) { final char c = name.charAt(i); if ((c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z')) { front = false; continue; } if (!front) { if ((c >= '0' && c <= '9') || c == '_') { continue; } return seinfo; } if (c == '.') { hasSep = true; front = true; continue; } return false; } return hasSep; } /** Loading Loading @@ -245,10 +347,11 @@ public final class SELinuxMMAC { * The label is attached to the ApplicationInfo instance of the package. * @param PackageParser.Package object representing the package * to labeled. * @return String holding the value of the seinfo label that was assigned. * Value may be null which indicates no seinfo label was assigned. * @return boolean which determines whether a non null seinfo label * was assigned to the package. A null value simply meaning that * no policy matched. */ public static void assignSeinfoValue(PackageParser.Package pkg) { public static boolean assignSeinfoValue(PackageParser.Package pkg) { /* * Non system installed apps should be treated the same. This Loading @@ -264,31 +367,28 @@ public final class SELinuxMMAC { if (s == null) continue; if (sSigSeinfo.containsKey(s)) { String seinfo = pkg.applicationInfo.seinfo = sSigSeinfo.get(s); Policy policy = sSigSeinfo.get(s); if (policy != null) { String seinfo = policy.checkPolicy(pkg.packageName); if (seinfo != null) { pkg.applicationInfo.seinfo = seinfo; if (DEBUG_POLICY_INSTALL) Slog.i(TAG, "package (" + pkg.packageName + ") labeled with seinfo=" + seinfo); return; return true; } } // Check for seinfo labeled by package. if (sPackageSeinfo.containsKey(pkg.packageName)) { String seinfo = pkg.applicationInfo.seinfo = sPackageSeinfo.get(pkg.packageName); if (DEBUG_POLICY_INSTALL) Slog.i(TAG, "package (" + pkg.packageName + ") labeled with seinfo=" + seinfo); return; } } // If we have a default seinfo value then great, otherwise // we set a null object and that is what we started with. String seinfo = pkg.applicationInfo.seinfo = sSigSeinfo.get(null); pkg.applicationInfo.seinfo = sDefaultSeinfo; if (DEBUG_POLICY_INSTALL) Slog.i(TAG, "package (" + pkg.packageName + ") labeled with seinfo=" + (seinfo == null ? "null" : seinfo)); Slog.i(TAG, "package (" + pkg.packageName + ") labeled with seinfo=" + (sDefaultSeinfo == null ? "null" : sDefaultSeinfo)); return (sDefaultSeinfo != null); } }