From cab3639dcb609b70012744029508f7b19e09c24d Mon Sep 17 00:00:00 2001 From: Jeff Vander Stoep Date: Tue, 6 Mar 2018 15:52:22 -0800 Subject: [PATCH] Revert "Revert "pm: SharedUserId: Assign seinfo using actual targetSdkVersion"" Commit 042f4bb6 'pm: Modify getPackage() to only return non-null packages' prevents the NullPointerException. b/ This reverts commit 00b4fa8b138de801b0caf371a950fcda7b98bb83. Bug: 74214574 Bug: 72290969 Test: Same tests run on original commit. Test: successfully flash and boot from bild 4504078 to ToT master. Change-Id: Ia1e900ebe0eb8f9d10fd0eddbf658f52e1ea79b4 (cherry picked from commit 32ef1c2eb0fe32d8fd02a44bc77b40ab7719c433) --- .../android/content/pm/ApplicationInfo.java | 10 ++-- .../server/pm/PackageManagerService.java | 25 ++++++--- .../com/android/server/pm/SELinuxMMAC.java | 55 ++++++++++++------- .../android/server/pm/SharedUserSetting.java | 31 +++++++++++ 4 files changed, 85 insertions(+), 36 deletions(-) diff --git a/core/java/android/content/pm/ApplicationInfo.java b/core/java/android/content/pm/ApplicationInfo.java index 4a8f61c24a489..efa90d308ee08 100644 --- a/core/java/android/content/pm/ApplicationInfo.java +++ b/core/java/android/content/pm/ApplicationInfo.java @@ -763,15 +763,13 @@ public class ApplicationInfo extends PackageItemInfo implements Parcelable { public String[] resourceDirs; /** - * String retrieved from the seinfo tag found in selinux policy. This value - * can be overridden with a value set through the mac_permissions.xml policy - * construct. This value is useful in setting an SELinux security context on - * the process as well as its data directory. The String default is being used - * here to represent a catchall label when no policy matches. + * String retrieved from the seinfo tag found in selinux policy. This value can be set through + * the mac_permissions.xml policy construct. This value is used for setting an SELinux security + * context on the process as well as its data directory. * * {@hide} */ - public String seInfo = "default"; + public String seInfo; /** * The seinfo tag generated per-user. This value may change based upon the diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java index f12795be658c9..fdba99e9b4c2d 100644 --- a/services/core/java/com/android/server/pm/PackageManagerService.java +++ b/services/core/java/com/android/server/pm/PackageManagerService.java @@ -2980,6 +2980,9 @@ public class PackageManagerService extends IPackageManager.Stub } } } + // Adjust seInfo to ensure apps which share a sharedUserId are placed in the same + // SELinux domain. + setting.fixSeInfoLocked(); } // Now that we know all the packages we are keeping, @@ -10376,20 +10379,24 @@ public class PackageManagerService extends IPackageManager.Stub pkg.applicationInfo.flags |= ApplicationInfo.FLAG_UPDATED_SYSTEM_APP; } - // SELinux sandboxes become more restrictive as targetSdkVersion increases. - // To ensure that apps with sharedUserId are placed in the same selinux domain - // without breaking any assumptions about access, put them into the least - // restrictive targetSdkVersion=25 domain. - // TODO(b/72290969): Base this on the actual targetSdkVersion(s) of the apps within the - // sharedUserSetting, instead of defaulting to the least restrictive domain. - final int targetSdk = (sharedUserSetting != null) ? 25 - : pkg.applicationInfo.targetSdkVersion; + // Apps which share a sharedUserId must be placed in the same selinux domain. If this + // package is the first app installed as this shared user, set seInfoTargetSdkVersion to its + // targetSdkVersion. These are later adjusted in PackageManagerService's constructor to be + // the lowest targetSdkVersion of all apps within the shared user, which corresponds to the + // least restrictive selinux domain. + // NOTE: As new packages are installed / updated, the shared user's seinfoTargetSdkVersion + // will NOT be modified until next boot, even if a lower targetSdkVersion is used. This + // ensures that all packages continue to run in the same selinux domain. + final int targetSdkVersion = + ((sharedUserSetting != null) && (sharedUserSetting.packages.size() != 0)) ? + sharedUserSetting.seInfoTargetSdkVersion : pkg.applicationInfo.targetSdkVersion; // TODO(b/71593002): isPrivileged for sharedUser and appInfo should never be out of sync. // They currently can be if the sharedUser apps are signed with the platform key. final boolean isPrivileged = (sharedUserSetting != null) ? sharedUserSetting.isPrivileged() | pkg.isPrivileged() : pkg.isPrivileged(); - SELinuxMMAC.assignSeInfoValue(pkg, isPrivileged, targetSdk); + pkg.applicationInfo.seInfo = SELinuxMMAC.getSeInfo(pkg, isPrivileged, + pkg.applicationInfo.targetSandboxVersion, targetSdkVersion); pkg.mExtras = pkgSetting; pkg.applicationInfo.processName = fixProcessName( diff --git a/services/core/java/com/android/server/pm/SELinuxMMAC.java b/services/core/java/com/android/server/pm/SELinuxMMAC.java index a9f15282133fd..b47d96622e961 100644 --- a/services/core/java/com/android/server/pm/SELinuxMMAC.java +++ b/services/core/java/com/android/server/pm/SELinuxMMAC.java @@ -64,6 +64,8 @@ public final class SELinuxMMAC { /** Required MAC permissions files */ private static List sMacPermissions = new ArrayList<>(); + private static final String DEFAULT_SEINFO = "default"; + // Append privapp to existing seinfo label private static final String PRIVILEGED_APP_STR = ":privapp"; @@ -307,45 +309,56 @@ public final class SELinuxMMAC { } /** - * 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. + * Selects a security label to a package based on input parameters and the 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' is used. The security label is attached to + * the ApplicationInfo instance of the package. * * @param pkg object representing the package to be labeled. + * @param isPrivileged boolean. + * @param targetSandboxVersion int. + * @param targetSdkVersion int. If this pkg runs as a sharedUser, targetSdkVersion is the + * greater of: lowest targetSdk for all pkgs in the sharedUser, or + * MINIMUM_TARGETSDKVERSION. + * @return String representing the resulting seinfo. */ - public static void assignSeInfoValue(PackageParser.Package pkg, boolean isPrivileged, - int targetSdkVersion) { + public static String getSeInfo(PackageParser.Package pkg, boolean isPrivileged, + int targetSandboxVersion, int targetSdkVersion) { + String seInfo = null; synchronized (sPolicies) { if (!sPolicyRead) { if (DEBUG_POLICY) { Slog.d(TAG, "Policy not read"); } - return; - } - for (Policy policy : sPolicies) { - String seInfo = policy.getMatchedSeInfo(pkg); - if (seInfo != null) { - pkg.applicationInfo.seInfo = seInfo; - break; + } else { + for (Policy policy : sPolicies) { + seInfo = policy.getMatchedSeInfo(pkg); + if (seInfo != null) { + break; + } } } } - if (pkg.applicationInfo.targetSandboxVersion == 2) - pkg.applicationInfo.seInfo += SANDBOX_V2_STR; - - if (isPrivileged) { - pkg.applicationInfo.seInfo += PRIVILEGED_APP_STR; + if (seInfo == null) { + seInfo = DEFAULT_SEINFO; } - pkg.applicationInfo.seInfo += TARGETSDKVERSION_STR + targetSdkVersion; + if (targetSandboxVersion == 2) { + seInfo += SANDBOX_V2_STR; + } + + if (isPrivileged) { + seInfo += PRIVILEGED_APP_STR; + } + + seInfo += TARGETSDKVERSION_STR + targetSdkVersion; if (DEBUG_POLICY_INSTALL) { Slog.i(TAG, "package (" + pkg.packageName + ") labeled with " + - "seinfo=" + pkg.applicationInfo.seInfo); + "seinfo=" + seInfo); } + return seInfo; } } diff --git a/services/core/java/com/android/server/pm/SharedUserSetting.java b/services/core/java/com/android/server/pm/SharedUserSetting.java index 244613180d007..1d9afd9895b4b 100644 --- a/services/core/java/com/android/server/pm/SharedUserSetting.java +++ b/services/core/java/com/android/server/pm/SharedUserSetting.java @@ -39,6 +39,10 @@ public final class SharedUserSetting extends SettingBase { int uidFlags; int uidPrivateFlags; + // The lowest targetSdkVersion of all apps in the sharedUserSetting, used to assign seinfo so + // that all apps within the sharedUser run in the same selinux context. + int seInfoTargetSdkVersion; + final ArraySet packages = new ArraySet(); final PackageSignatures signatures = new PackageSignatures(); @@ -84,6 +88,11 @@ public final class SharedUserSetting extends SettingBase { } void addPackage(PackageSetting packageSetting) { + // If this is the first package added to this shared user, temporarily (until next boot) use + // its targetSdkVersion when assigning seInfo for the shared user. + if ((packages.size() == 0) && (packageSetting.pkg != null)) { + seInfoTargetSdkVersion = packageSetting.pkg.applicationInfo.targetSdkVersion; + } if (packages.add(packageSetting)) { setFlags(this.pkgFlags | packageSetting.pkgFlags); setPrivateFlags(this.pkgPrivateFlags | packageSetting.pkgPrivateFlags); @@ -107,4 +116,26 @@ public final class SharedUserSetting extends SettingBase { public boolean isPrivileged() { return (this.pkgPrivateFlags & ApplicationInfo.PRIVATE_FLAG_PRIVILEGED) != 0; } + + /** + * Determine the targetSdkVersion for a sharedUser and update pkg.applicationInfo.seInfo + * to ensure that all apps within the sharedUser share an SELinux domain. Use the lowest + * targetSdkVersion of all apps within the shared user, which corresponds to the least + * restrictive selinux domain. + */ + public void fixSeInfoLocked() { + final List pkgList = getPackages(); + + for (PackageParser.Package pkg : pkgList) { + if (pkg.applicationInfo.targetSdkVersion < seInfoTargetSdkVersion) { + seInfoTargetSdkVersion = pkg.applicationInfo.targetSdkVersion; + } + } + for (PackageParser.Package pkg : pkgList) { + final boolean isPrivileged = isPrivileged() | pkg.isPrivileged(); + pkg.applicationInfo.seInfo = SELinuxMMAC.getSeInfo(pkg, isPrivileged, + pkg.applicationInfo.targetSandboxVersion, seInfoTargetSdkVersion); + } + } + }