summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorNick Kralevich <nnk@google.com>2013-12-06 16:26:08 +0000
committerAndroid Git Automerger <android-git-automerger@android.com>2013-12-06 16:26:08 +0000
commit6018d01427d7b1676c924e8ccc3bace450991315 (patch)
tree81d0af6797d9729a9c3c2195c4e5712e2494218b
parentc6499939faffe5f25ed8a38cbf4ab75850910698 (diff)
parentbf88b659b6c02143b464c0551d4875f7911ed269 (diff)
downloadframeworks_base-6018d01427d7b1676c924e8ccc3bace450991315.zip
frameworks_base-6018d01427d7b1676c924e8ccc3bace450991315.tar.gz
frameworks_base-6018d01427d7b1676c924e8ccc3bace450991315.tar.bz2
am bf88b659: am 5fa89d55: am 6b8a3a52: am f7422885: Merge "Augment SELinuxMMAC functionality."
* commit 'bf88b659b6c02143b464c0551d4875f7911ed269': Augment SELinuxMMAC functionality.
-rw-r--r--services/java/com/android/server/pm/SELinuxMMAC.java248
1 files changed, 174 insertions, 74 deletions
diff --git a/services/java/com/android/server/pm/SELinuxMMAC.java b/services/java/com/android/server/pm/SELinuxMMAC.java
index 83c5d96..6e12e41 100644
--- a/services/java/com/android/server/pm/SELinuxMMAC.java
+++ b/services/java/com/android/server/pm/SELinuxMMAC.java
@@ -47,12 +47,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 = {
@@ -60,9 +59,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;
}
/**
@@ -86,6 +121,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;
@@ -106,8 +145,6 @@ public final class SELinuxMMAC {
Slog.d(TAG, "Using install policy file " + policyFiles[i].getPath());
- flushInstallPolicy();
-
try {
XmlPullParser parser = Xml.newPullParser();
parser.setInput(policyFile);
@@ -137,63 +174,49 @@ 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) {
- if (DEBUG_POLICY_INSTALL)
- Slog.i(TAG, "<default> tag assigned seinfo=" + seinfo);
-
- // The 'null' signature is the default seinfo value
- sSigSeinfo.put(null, seinfo);
- }
- } else if ("package".equals(tagName)) {
- String pkgName = parser.getAttributeValue(null, "name");
- if (pkgName == null) {
- Slog.w(TAG, "<package> without 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);
+ // 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=" + defaultSeinfo);
- sPackageSeinfo.put(pkgName, 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();
+ // 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) {
- //omit
+ 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 String readSeinfoTag(XmlPullParser parser) throws
+ private static Policy readPolicyTags(XmlPullParser parser) throws
IOException, XmlPullParserException {
int type;
int outerDepth = parser.getDepth();
- String seinfo = null;
+ Policy policy = new Policy();
while ((type=parser.next()) != XmlPullParser.END_DOCUMENT
&& (type != XmlPullParser.END_TAG
|| parser.getDepth() > outerDepth)) {
@@ -204,19 +227,98 @@ public final class SELinuxMMAC {
String tagName = parser.getName();
if ("seinfo".equals(tagName)) {
- String seinfoValue = parser.getAttributeValue(null, "value");
- if (validateValue(seinfoValue)) {
- seinfo = seinfoValue;
- } else {
- Slog.w(TAG, "<seinfo> without valid value at "
+ String seinfo = parseSeinfo(parser);
+ if (seinfo != null) {
+ policy.putSeinfo(seinfo);
+ }
+ XmlUtils.skipCurrentTag(parser);
+ } else if ("package".equals(tagName)) {
+ 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) {
+ policy.putPkg(pkg, seinfo);
}
+ } else {
+ XmlUtils.skipCurrentTag(parser);
+ }
+ }
+ return policy;
+ }
+
+ private static String readSeinfoTag(XmlPullParser parser) throws
+ IOException, XmlPullParserException {
+
+ int type;
+ int outerDepth = parser.getDepth();
+ String seinfo = null;
+ while ((type=parser.next()) != XmlPullParser.END_DOCUMENT
+ && (type != XmlPullParser.END_TAG
+ || parser.getDepth() > outerDepth)) {
+ if (type == XmlPullParser.END_TAG
+ || type == XmlPullParser.TEXT) {
+ continue;
+ }
+
+ 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)) {
+ Slog.w(TAG, "<seinfo> without valid value at "
+ + parser.getPositionDescription());
+ seinfoValue = null;
+ }
+ return seinfoValue;
+ }
+
+ /**
+ * 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;
+ }
+ }
+ if (c == '.') {
+ hasSep = true;
+ front = true;
+ continue;
+ }
+ return false;
+ }
+ return hasSep;
+ }
+
/**
* General validation routine for tag values.
* Returns a boolean indicating if the passed string
@@ -244,10 +346,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
@@ -263,31 +366,28 @@ public final class SELinuxMMAC {
if (s == null)
continue;
- if (sSigSeinfo.containsKey(s)) {
- String seinfo = pkg.applicationInfo.seinfo = sSigSeinfo.get(s);
- if (DEBUG_POLICY_INSTALL)
- Slog.i(TAG, "package (" + pkg.packageName +
- ") labeled with seinfo=" + seinfo);
+ 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);
}
}