diff options
Diffstat (limited to 'services/java')
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)); + } +} |