summaryrefslogtreecommitdiffstats
path: root/services/java
diff options
context:
space:
mode:
Diffstat (limited to 'services/java')
-rw-r--r--services/java/com/android/server/am/ActivityManagerService.java2
-rw-r--r--services/java/com/android/server/pm/Installer.java4
-rw-r--r--services/java/com/android/server/pm/PackageManagerService.java19
-rw-r--r--services/java/com/android/server/pm/SELinuxMMAC.java272
4 files changed, 291 insertions, 6 deletions
diff --git a/services/java/com/android/server/am/ActivityManagerService.java b/services/java/com/android/server/am/ActivityManagerService.java
index 6e81e9d..c6efe15b 100644
--- a/services/java/com/android/server/am/ActivityManagerService.java
+++ b/services/java/com/android/server/am/ActivityManagerService.java
@@ -2171,7 +2171,7 @@ public final class ActivityManagerService extends ActivityManagerNative
// the PID of the new process, or else throw a RuntimeException.
Process.ProcessStartResult startResult = Process.start("android.app.ActivityThread",
app.processName, uid, uid, gids, debugFlags, mountExternal,
- app.info.targetSdkVersion, null, null);
+ app.info.targetSdkVersion, app.info.seinfo, null);
BatteryStatsImpl bs = app.batteryStats.getBatteryStats();
synchronized (bs) {
diff --git a/services/java/com/android/server/pm/Installer.java b/services/java/com/android/server/pm/Installer.java
index 71a6a01..ddb0d0b 100644
--- a/services/java/com/android/server/pm/Installer.java
+++ b/services/java/com/android/server/pm/Installer.java
@@ -188,7 +188,7 @@ public final class Installer {
}
}
- public int install(String name, int uid, int gid) {
+ public int install(String name, int uid, int gid, String seinfo) {
StringBuilder builder = new StringBuilder("install");
builder.append(' ');
builder.append(name);
@@ -196,6 +196,8 @@ public final class Installer {
builder.append(uid);
builder.append(' ');
builder.append(gid);
+ builder.append(' ');
+ builder.append(seinfo != null ? seinfo : "!");
return execute(builder.toString());
}
diff --git a/services/java/com/android/server/pm/PackageManagerService.java b/services/java/com/android/server/pm/PackageManagerService.java
index 2238f17..8102f2b 100644
--- a/services/java/com/android/server/pm/PackageManagerService.java
+++ b/services/java/com/android/server/pm/PackageManagerService.java
@@ -352,6 +352,9 @@ public class PackageManagerService extends IPackageManager.Stub {
final HashMap<String, FeatureInfo> mAvailableFeatures =
new HashMap<String, FeatureInfo>();
+ // If mac_permissions.xml was found for seinfo labeling.
+ boolean mFoundPolicyFile;
+
// All available activities, for your resolving pleasure.
final ActivityIntentResolver mActivities =
new ActivityIntentResolver();
@@ -1020,6 +1023,8 @@ public class PackageManagerService extends IPackageManager.Stub {
readPermissions();
+ mFoundPolicyFile = SELinuxMMAC.readInstallPolicy();
+
mRestoredSettings = mSettings.readLPw(sUserManager.getUsers(false),
mSdkVersion, mOnlyCore);
long startTime = SystemClock.uptimeMillis();
@@ -3582,9 +3587,9 @@ public class PackageManagerService extends IPackageManager.Stub {
}
}
- private int createDataDirsLI(String packageName, int uid) {
+ private int createDataDirsLI(String packageName, int uid, String seinfo) {
int[] users = sUserManager.getUserIds();
- int res = mInstaller.install(packageName, uid, uid);
+ int res = mInstaller.install(packageName, uid, uid, seinfo);
if (res < 0) {
return res;
}
@@ -3847,6 +3852,10 @@ public class PackageManagerService extends IPackageManager.Stub {
pkg.applicationInfo.flags |= ApplicationInfo.FLAG_UPDATED_SYSTEM_APP;
}
+ if (mFoundPolicyFile) {
+ SELinuxMMAC.assignSeinfoValue(pkg);
+ }
+
pkg.applicationInfo.uid = pkgSetting.appId;
pkg.mExtras = pkgSetting;
@@ -3985,7 +3994,8 @@ public class PackageManagerService extends IPackageManager.Stub {
recovered = true;
// And now re-install the app.
- ret = createDataDirsLI(pkgName, pkg.applicationInfo.uid);
+ ret = createDataDirsLI(pkgName, pkg.applicationInfo.uid,
+ pkg.applicationInfo.seinfo);
if (ret == -1) {
// Ack should not happen!
msg = prefix + pkg.packageName
@@ -4031,7 +4041,8 @@ public class PackageManagerService extends IPackageManager.Stub {
Log.v(TAG, "Want this data dir: " + dataPath);
}
//invoke installer to do the actual installation
- int ret = createDataDirsLI(pkgName, pkg.applicationInfo.uid);
+ int ret = createDataDirsLI(pkgName, pkg.applicationInfo.uid,
+ pkg.applicationInfo.seinfo);
if (ret < 0) {
// Error from installer
mLastScanError = PackageManager.INSTALL_FAILED_INSUFFICIENT_STORAGE;
diff --git a/services/java/com/android/server/pm/SELinuxMMAC.java b/services/java/com/android/server/pm/SELinuxMMAC.java
new file mode 100644
index 0000000..15d2a5a
--- /dev/null
+++ b/services/java/com/android/server/pm/SELinuxMMAC.java
@@ -0,0 +1,272 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.pm;
+
+import android.content.pm.ApplicationInfo;
+import android.content.pm.PackageParser;
+import android.content.pm.Signature;
+import android.os.Environment;
+import android.util.Slog;
+import android.util.Xml;
+
+import com.android.internal.util.XmlUtils;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileNotFoundException;
+import java.io.FileReader;
+import java.io.IOException;
+
+import java.util.HashMap;
+
+import org.xmlpull.v1.XmlPullParser;
+import org.xmlpull.v1.XmlPullParserException;
+
+/**
+ * Centralized access to SELinux MMAC (middleware MAC) implementation.
+ * {@hide}
+ */
+public final class SELinuxMMAC {
+
+ private static final String TAG = "SELinuxMMAC";
+
+ private static final boolean DEBUG_POLICY = false;
+ 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>();
+
+ // Package name seinfo values read from policy.
+ private static final HashMap<String, String> sPackageSeinfo =
+ new HashMap<String, String>();
+
+ // Locations of potential install policy files.
+ private static final File[] INSTALL_POLICY_FILE = {
+ new File(Environment.getDataDirectory(), "system/mac_permissions.xml"),
+ new File(Environment.getRootDirectory(), "etc/security/mac_permissions.xml"),
+ null};
+
+ private static void flushInstallPolicy() {
+ sSigSeinfo.clear();
+ sPackageSeinfo.clear();
+ }
+
+ /**
+ * Parses an MMAC install policy from a predefined list of locations.
+ * @param none
+ * @return boolean indicating whether an install policy was correctly parsed.
+ */
+ public static boolean readInstallPolicy() {
+
+ return readInstallPolicy(INSTALL_POLICY_FILE);
+ }
+
+ /**
+ * Parses an MMAC install policy given as an argument.
+ * @param File object representing the path of the policy.
+ * @return boolean indicating whether the install policy was correctly parsed.
+ */
+ public static boolean readInstallPolicy(File policyFile) {
+
+ return readInstallPolicy(new File[]{policyFile,null});
+ }
+
+ private static boolean readInstallPolicy(File[] policyFiles) {
+
+ FileReader policyFile = null;
+ int i = 0;
+ while (policyFile == null && policyFiles != null && policyFiles[i] != null) {
+ try {
+ policyFile = new FileReader(policyFiles[i]);
+ break;
+ } catch (FileNotFoundException e) {
+ Slog.d(TAG,"Couldn't find install policy " + policyFiles[i].getPath());
+ }
+ i++;
+ }
+
+ if (policyFile == null) {
+ Slog.d(TAG, "No policy file found. All seinfo values will be null.");
+ return false;
+ }
+
+ Slog.d(TAG, "Using install policy file " + policyFiles[i].getPath());
+
+ flushInstallPolicy();
+
+ try {
+ XmlPullParser parser = Xml.newPullParser();
+ parser.setInput(policyFile);
+
+ XmlUtils.beginDocument(parser, "policy");
+ while (true) {
+ XmlUtils.nextElement(parser);
+ if (parser.getEventType() == XmlPullParser.END_DOCUMENT) {
+ break;
+ }
+
+ String tagName = parser.getName();
+ if ("signer".equals(tagName)) {
+ String cert = parser.getAttributeValue(null, "signature");
+ if (cert == null) {
+ Slog.w(TAG, "<signer> without signature at "
+ + parser.getPositionDescription());
+ XmlUtils.skipCurrentTag(parser);
+ continue;
+ }
+ Signature signature;
+ try {
+ signature = new Signature(cert);
+ } catch (IllegalArgumentException e) {
+ Slog.w(TAG, "<signer> with bad signature at "
+ + parser.getPositionDescription(), e);
+ 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);
+ }
+ } 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);
+
+ 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();
+ } catch (IOException e) {
+ //omit
+ }
+ return true;
+ }
+
+ 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)) {
+ String seinfoValue = parser.getAttributeValue(null, "value");
+ if (seinfoValue != null) {
+ seinfo = seinfoValue;
+ } else {
+ Slog.w(TAG, "<seinfo> without value at "
+ + parser.getPositionDescription());
+ }
+ }
+ XmlUtils.skipCurrentTag(parser);
+ }
+ return seinfo;
+ }
+
+ /**
+ * Labels a package based on an seinfo tag from install policy.
+ * 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.
+ */
+ public static void assignSeinfoValue(PackageParser.Package pkg) {
+
+ /*
+ * Non system installed apps should be treated the same. This
+ * means that any post-loaded apk will be assigned the default
+ * tag, if one exists in the policy, else null, without respect
+ * to the signing key.
+ */
+ if (((pkg.applicationInfo.flags & ApplicationInfo.FLAG_SYSTEM) != 0) ||
+ ((pkg.applicationInfo.flags & ApplicationInfo.FLAG_UPDATED_SYSTEM_APP) != 0)) {
+
+ // We just want one of the signatures to match.
+ for (Signature s : pkg.mSignatures) {
+ 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);
+
+ return;
+ }
+ }
+
+ // 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);
+ if (DEBUG_POLICY_INSTALL)
+ Slog.i(TAG, "package (" + pkg.packageName +
+ ") labeled with seinfo=" + (seinfo == null ? "null" : seinfo));
+ }
+}