diff options
3 files changed, 94 insertions, 43 deletions
diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java index e322506043b6..b451eaf198f8 100644 --- a/services/core/java/com/android/server/pm/PackageManagerService.java +++ b/services/core/java/com/android/server/pm/PackageManagerService.java @@ -350,6 +350,7 @@ import com.android.server.ServiceThread; import com.android.server.SystemConfig; import com.android.server.SystemServerInitThreadPool; import com.android.server.Watchdog; +import com.android.server.compat.CompatChange; import com.android.server.compat.PlatformCompat; import com.android.server.net.NetworkPolicyManagerInternal; import com.android.server.pm.Installer.InstallerException; @@ -2714,39 +2715,43 @@ public class PackageManagerService extends IPackageManager.Stub PackageManagerService m = new PackageManagerService(injector, onlyCore, factoryTest); t.traceEnd(); // "create package manager" - injector.getCompatibility().registerListener(SELinuxMMAC.SELINUX_LATEST_CHANGES, - packageName -> { - synchronized (m.mInstallLock) { - final AndroidPackage pkg; - final PackageSetting ps; - final SharedUserSetting sharedUser; - final String oldSeInfo; - synchronized (m.mLock) { - ps = m.mSettings.getPackageLPr(packageName); - if (ps == null) { - Slog.e(TAG, "Failed to find package setting " + packageName); - return; - } - pkg = ps.pkg; - sharedUser = ps.getSharedUser(); - oldSeInfo = AndroidPackageUtils.getSeInfo(pkg, ps); - } - - if (pkg == null) { - Slog.e(TAG, "Failed to find package " + packageName); - return; - } - final String newSeInfo = SELinuxMMAC.getSeInfo(pkg, sharedUser, - m.mInjector.getCompatibility()); - - if (!newSeInfo.equals(oldSeInfo)) { - Slog.i(TAG, "Updating seInfo for package " + packageName + " from: " - + oldSeInfo + " to: " + newSeInfo); - ps.getPkgState().setOverrideSeInfo(newSeInfo); - m.prepareAppDataAfterInstallLIF(pkg); - } + final CompatChange.ChangeListener selinuxChangeListener = packageName -> { + synchronized (m.mInstallLock) { + final AndroidPackage pkg; + final PackageSetting ps; + final SharedUserSetting sharedUser; + final String oldSeInfo; + synchronized (m.mLock) { + ps = m.mSettings.getPackageLPr(packageName); + if (ps == null) { + Slog.e(TAG, "Failed to find package setting " + packageName); + return; } - }); + pkg = ps.pkg; + sharedUser = ps.getSharedUser(); + oldSeInfo = AndroidPackageUtils.getSeInfo(pkg, ps); + } + + if (pkg == null) { + Slog.e(TAG, "Failed to find package " + packageName); + return; + } + final String newSeInfo = SELinuxMMAC.getSeInfo(pkg, sharedUser, + m.mInjector.getCompatibility()); + + if (!newSeInfo.equals(oldSeInfo)) { + Slog.i(TAG, "Updating seInfo for package " + packageName + " from: " + + oldSeInfo + " to: " + newSeInfo); + ps.getPkgState().setOverrideSeInfo(newSeInfo); + m.prepareAppDataAfterInstallLIF(pkg); + } + } + }; + + injector.getCompatibility().registerListener(SELinuxMMAC.SELINUX_LATEST_CHANGES, + selinuxChangeListener); + injector.getCompatibility().registerListener(SELinuxMMAC.SELINUX_R_CHANGES, + selinuxChangeListener); m.installWhitelistedSystemPackages(); ServiceManager.addService("package", m); diff --git a/services/core/java/com/android/server/pm/SELinuxMMAC.java b/services/core/java/com/android/server/pm/SELinuxMMAC.java index fdd9636ae7b2..c5fbfba9b049 100644 --- a/services/core/java/com/android/server/pm/SELinuxMMAC.java +++ b/services/core/java/com/android/server/pm/SELinuxMMAC.java @@ -18,6 +18,7 @@ package com.android.server.pm; import android.compat.annotation.ChangeId; import android.compat.annotation.EnabledAfter; +import android.content.pm.ApplicationInfo; import android.content.pm.PackageParser.SigningDetails; import android.content.pm.Signature; import android.os.Environment; @@ -77,9 +78,21 @@ public final class SELinuxMMAC { private static final String TARGETSDKVERSION_STR = ":targetSdkVersion="; /** - * This change gates apps access to untrusted_app_R-targetSDk SELinux domain. Allows opt-in + * Allows opt-in to the latest targetSdkVersion enforced changes without changing target SDK. + * Turning this change off for an app targeting the latest SDK is a no-op. + * + * <p>Has no effect for apps using shared user id. + * + * TODO(b/143539591): Update description with relevant SELINUX changes this opts in to. + */ + @EnabledAfter(targetSdkVersion = android.os.Build.VERSION_CODES.R) + @ChangeId + static final long SELINUX_LATEST_CHANGES = 143539591L; + + /** + * This change gates apps access to untrusted_app_R-targetSDK SELinux domain. Allows opt-in * to R targetSdkVersion enforced changes without changing target SDK. Turning this change - * off for an app targeting R is a no-op. + * off for an app targeting S is a no-op. * * <p>Has no effect for apps using shared user id. * @@ -87,7 +100,7 @@ public final class SELinuxMMAC { */ @EnabledAfter(targetSdkVersion = android.os.Build.VERSION_CODES.Q) @ChangeId - static final long SELINUX_LATEST_CHANGES = 143539591L; + static final long SELINUX_R_CHANGES = 168782947L; // Only initialize sMacPermissions once. static { @@ -349,9 +362,11 @@ public final class SELinuxMMAC { if ((sharedUserSetting != null) && (sharedUserSetting.packages.size() != 0)) { return sharedUserSetting.seInfoTargetSdkVersion; } - if (compatibility.isChangeEnabledInternal(SELINUX_LATEST_CHANGES, - pkg.toAppInfoWithoutState())) { - return android.os.Build.VERSION_CODES.R; + final ApplicationInfo appInfo = pkg.toAppInfoWithoutState(); + if (compatibility.isChangeEnabledInternal(SELINUX_LATEST_CHANGES, appInfo)) { + return android.os.Build.VERSION_CODES.S; + } else if (compatibility.isChangeEnabledInternal(SELINUX_R_CHANGES, appInfo)) { + return Math.max(android.os.Build.VERSION_CODES.R, pkg.getTargetSdkVersion()); } return pkg.getTargetSdkVersion(); diff --git a/services/tests/servicestests/src/com/android/server/pm/SELinuxMMACTest.java b/services/tests/servicestests/src/com/android/server/pm/SELinuxMMACTest.java index a550b27a62a2..f1930d7268d7 100644 --- a/services/tests/servicestests/src/com/android/server/pm/SELinuxMMACTest.java +++ b/services/tests/servicestests/src/com/android/server/pm/SELinuxMMACTest.java @@ -44,7 +44,8 @@ import org.mockito.junit.MockitoJUnitRunner; public class SELinuxMMACTest { private static final String PACKAGE_NAME = "my.package"; - private static final int OPT_IN_VERSION = Build.VERSION_CODES.R; + private static final int LATEST_OPT_IN_VERSION = Build.VERSION_CODES.S; + private static final int R_OPT_IN_VERSION = Build.VERSION_CODES.R; @Mock PlatformCompat mMockCompatibility; @@ -56,7 +57,17 @@ public class SELinuxMMACTest { argThat(argument -> argument.packageName.equals(pkg.getPackageName())))) .thenReturn(true); assertThat(SELinuxMMAC.getSeInfo(pkg, null, mMockCompatibility), - is("default:targetSdkVersion=" + OPT_IN_VERSION)); + is("default:targetSdkVersion=" + LATEST_OPT_IN_VERSION)); + } + + @Test + public void getSeInfoOptInToR() { + AndroidPackage pkg = makePackage(Build.VERSION_CODES.P); + when(mMockCompatibility.isChangeEnabledInternal(eq(SELinuxMMAC.SELINUX_R_CHANGES), + argThat(argument -> argument.packageName.equals(pkg.getPackageName())))) + .thenReturn(true); + assertThat(SELinuxMMAC.getSeInfo(pkg, null, mMockCompatibility), + is("default:targetSdkVersion=" + R_OPT_IN_VERSION)); } @Test @@ -70,13 +81,33 @@ public class SELinuxMMACTest { } @Test - public void getSeInfoNoOptInButAlreadyR() { - AndroidPackage pkg = makePackage(OPT_IN_VERSION); + public void getSeInfoNoOptInButAlreadyLatest() { + AndroidPackage pkg = makePackage(LATEST_OPT_IN_VERSION); when(mMockCompatibility.isChangeEnabledInternal(eq(SELinuxMMAC.SELINUX_LATEST_CHANGES), argThat(argument -> argument.packageName.equals(pkg.getPackageName())))) .thenReturn(false); assertThat(SELinuxMMAC.getSeInfo(pkg, null, mMockCompatibility), - is("default:targetSdkVersion=" + OPT_IN_VERSION)); + is("default:targetSdkVersion=" + LATEST_OPT_IN_VERSION)); + } + + @Test + public void getSeInfoNoOptInButAlreadyR() { + AndroidPackage pkg = makePackage(R_OPT_IN_VERSION); + when(mMockCompatibility.isChangeEnabledInternal(eq(SELinuxMMAC.SELINUX_R_CHANGES), + argThat(argument -> argument.packageName.equals(pkg.getPackageName())))) + .thenReturn(false); + assertThat(SELinuxMMAC.getSeInfo(pkg, null, mMockCompatibility), + is("default:targetSdkVersion=" + R_OPT_IN_VERSION)); + } + + @Test + public void getSeInfoOptInRButLater() { + AndroidPackage pkg = makePackage(R_OPT_IN_VERSION + 1); + when(mMockCompatibility.isChangeEnabledInternal(eq(SELinuxMMAC.SELINUX_R_CHANGES), + argThat(argument -> argument.packageName.equals(pkg.getPackageName())))) + .thenReturn(true); + assertThat(SELinuxMMAC.getSeInfo(pkg, null, mMockCompatibility), + is("default:targetSdkVersion=" + (R_OPT_IN_VERSION + 1))); } private AndroidPackage makePackage(int targetSdkVersion) { |