Loading services/core/java/com/android/server/pm/PackageInstallerSession.java +100 −35 Original line number Diff line number Diff line Loading @@ -1088,16 +1088,24 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub { return false; } // Only system installers can have an emergency installer if (PackageManager.PERMISSION_GRANTED != snapshot.checkUidPermission(Manifest.permission.INSTALL_PACKAGES, uid) && PackageManager.PERMISSION_GRANTED != snapshot.checkUidPermission(Manifest.permission.INSTALL_PACKAGE_UPDATES, uid) && PackageManager.PERMISSION_GRANTED != snapshot.checkUidPermission(Manifest.permission.INSTALL_SELF_UPDATES, uid)) { if (!hasSystemInstallerPermissions(snapshot, uid)) { return false; } return (snapshot.checkUidPermission(Manifest.permission.EMERGENCY_INSTALL_PACKAGES, installerUid) == PackageManager.PERMISSION_GRANTED); return hasEmergencyInstallerPermission(snapshot, installerUid); } private static boolean hasSystemInstallerPermissions(Computer snapshot, int uid) { return (PackageManager.PERMISSION_GRANTED == snapshot.checkUidPermission(Manifest.permission.INSTALL_PACKAGES, uid) || PackageManager.PERMISSION_GRANTED == snapshot.checkUidPermission(Manifest.permission.INSTALL_PACKAGE_UPDATES, uid) || PackageManager.PERMISSION_GRANTED == snapshot.checkUidPermission(Manifest.permission.INSTALL_SELF_UPDATES, uid)); } private static boolean hasEmergencyInstallerPermission(Computer snapshot, int installerUid) { return snapshot.checkUidPermission(Manifest.permission.EMERGENCY_INSTALL_PACKAGES, installerUid) == PackageManager.PERMISSION_GRANTED; } private static final int USER_ACTION_NOT_NEEDED = 0; Loading Loading @@ -3123,40 +3131,75 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub { // the emergency bypass. return false; } // Check if app being installed is the verifier itself. if (TextUtils.equals(verifierPackageName, packageName)) { Slog.d(TAG, "Bypassing developer verification because the verifier is being updated"); return true; } // Check if app being installed is the sysconfig-specified update-owner of the verifier. final String updateOwnerPackageName = mPm.getSystemAppUpdateOwnerPackageName( verifierPackageName); if (updateOwnerPackageName == null) { // No sysconfig-specified update-owner for the verifier. No need to check further. // The verifier has not specified an update-owner in sysconfig. return false; } if (TextUtils.equals(updateOwnerPackageName, packageName)) { Slog.d(TAG, "Bypassing verification service because the sysconfig-specified " + "update owner of the verifier is being updated"); return true; final String installerPackageName = getInstallerPackageName(); if (installerPackageName == null) { return false; } // Check if app being installed is the emergency installer of the sysconfig-specified // update-owner of the verifier. if (isEmergencyInstallerEnabled(updateOwnerPackageName, snapshot, userId, ps.getAppId())) { final PackageStateInternal psUpdateOwner = snapshot.getPackageStateInternal( updateOwnerPackageName, Process.SYSTEM_UID); if (psUpdateOwner == null || psUpdateOwner.getPkg() == null) { // Impossible condition, because the if clause above already checked this. // Added to prevent lint warnings. return false; } String emergencyInstallerPackageName = psUpdateOwner.getPkg().getEmergencyInstaller(); if (emergencyInstallerPackageName != null && TextUtils.equals(emergencyInstallerPackageName, packageName)) { Slog.d(TAG, "Bypassing verification service because the " + "emergency installer of the verifier's update owner is being updated"); // Validate the permissions of the sysconfig-specified update-owner if (!hasSystemInstallerPermissions(snapshot, psUpdateOwner.getAppId())) { return false; } // Check if the verifier is being updated, and the installer is the verifier's // sysconfig-specified update-owner. if (TextUtils.equals(verifierPackageName, packageName) && TextUtils.equals(updateOwnerPackageName, installerPackageName)) { Slog.d(TAG, "Bypassing developer verification because the verifier is being updated."); return true; } // Check if the verifier's sysconfig-specified update-owner is being updated, and the // installer is the verifier's sysconfig-specified update-owner. if (TextUtils.equals(updateOwnerPackageName, packageName) && TextUtils.equals(updateOwnerPackageName, installerPackageName)) { Slog.d(TAG, "Bypassing developer verification because the update-owner of the" + " verifier which is specified in the sysconfig is being updated."); return true; } String emergencyInstallerOfUpdateOwner = psUpdateOwner.getPkg().getEmergencyInstaller(); if (emergencyInstallerOfUpdateOwner == null) { // The rest of the bypass checks involve the emergency installer of the update-owner. // If this is no such emergency installer, no need to check further. return false; } final PackageStateInternal psEmergencyInstallerOfUpdateOwner = snapshot.getPackageStateInternal(emergencyInstallerOfUpdateOwner, Process.SYSTEM_UID); if (psEmergencyInstallerOfUpdateOwner == null || psEmergencyInstallerOfUpdateOwner.getPkg() == null) { return false; } // Check the permission of the emergency installer if (!hasEmergencyInstallerPermission( snapshot, psEmergencyInstallerOfUpdateOwner.getAppId())) { return false; } // Check if the emergency installer of the verifier's sysconfig-specified update-owner is // being updated, and the installer is the verifier's sysconfig-specified update-owner. if (TextUtils.equals(emergencyInstallerOfUpdateOwner, packageName) && TextUtils.equals(updateOwnerPackageName, installerPackageName)) { Slog.d(TAG, "Bypassing developer verification because the emergency installer of" + " the update-owner of the verifier which is specified in the sysconfig is" + " being updated."); return true; } // If the app being installed is the sysconfig-specified update-owner, also allow bypassing // if the installer is the app's emergency-installer. if (TextUtils.equals(updateOwnerPackageName, packageName) && TextUtils.equals(emergencyInstallerOfUpdateOwner, installerPackageName)) { Slog.d(TAG, "Bypassing developer verification because the update-owner of the" + " verifier which is specified in the sysconfig is being updated by its" + " emergency installer."); return true; } return false; } Loading Loading @@ -3460,6 +3503,17 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub { resumeVerify(); return; } if (shouldAllowDeveloperVerificationEmergencyBypass( getPackageName(), mPm.snapshotComputer())) { // Bypass verification when critical package is being updated and the // verification result is not verified. synchronized (mMetrics) { mMetrics.onDeveloperVerificationBypassed( DEVELOPER_VERIFICATION_BYPASSED_REASON_EMERGENCY); } resumeVerify(); return; } // Package is blocked. mVerificationUserActionNeededReason = Loading Loading @@ -3495,6 +3549,17 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub { resumeVerify(); return; } if (shouldAllowDeveloperVerificationEmergencyBypass( getPackageName(), mPm.snapshotComputer())) { // Bypass verification when critical package is being updated and the // verification is incomplete. synchronized (mMetrics) { mMetrics.onDeveloperVerificationBypassed( DEVELOPER_VERIFICATION_BYPASSED_REASON_EMERGENCY); } resumeVerify(); return; } StringBuilder sb = new StringBuilder( "Verification cannot be completed because of "); Loading services/tests/PackageManagerServiceTests/server/src/com/android/server/pm/PackageInstallerSessionTest.kt +91 −29 Original line number Diff line number Diff line Loading @@ -17,12 +17,12 @@ package com.android.server.pm import android.content.Context import android.content.pm.PackageInstaller import android.content.pm.PackageInstaller.DEVELOPER_VERIFICATION_POLICY_BLOCK_FAIL_CLOSED import android.content.pm.PackageInstaller.DEVELOPER_VERIFICATION_POLICY_BLOCK_FAIL_OPEN import android.content.pm.PackageInstaller.SessionParams import android.content.pm.PackageInstaller.SessionParams.PERMISSION_STATE_DEFAULT import android.content.pm.PackageInstaller.SessionParams.PERMISSION_STATE_DENIED import android.content.pm.PackageInstaller.SessionParams.PERMISSION_STATE_GRANTED import android.content.pm.PackageInstaller.DEVELOPER_VERIFICATION_POLICY_BLOCK_FAIL_CLOSED import android.content.pm.PackageInstaller.DEVELOPER_VERIFICATION_POLICY_BLOCK_FAIL_OPEN import android.content.pm.PackageManager import android.content.pm.verify.domain.DomainSet import android.os.Parcel Loading Loading @@ -200,14 +200,27 @@ class PackageInstallerSessionTest { @Test fun testShouldAllowDeveloperVerificationEmergencyBypassForVerifier() { val verifierPackageName = "verifierPackageName" val updateOwnerName = "updateOwnerPackageName" val mockPs = mock(PackageStateInternal::class.java) val mockUpdateOwnerPs = mock(PackageStateInternal::class.java) val mockUpdateOwnerPkg = mock(AndroidPackageInternal::class.java) val updateOwnerUid = 10200 whenever(mMockDeveloperVerifierController.verifierPackageName).thenReturn( verifierPackageName) whenever(mockPs.isSystem).thenReturn(true) whenever(mSnapshot.getPackageStateInternal( eq(verifierPackageName), eq(Process.SYSTEM_UID))) .thenReturn(mockPs) val session = createSession() whenever(mMockPackageManagerInternal.getSystemAppUpdateOwnerPackageName( anyString())).thenReturn(updateOwnerName) whenever(mSnapshot.getPackageStateInternal( eq(updateOwnerName), eq(Process.SYSTEM_UID))) .thenReturn(mockUpdateOwnerPs) whenever(mockUpdateOwnerPs.pkg).thenReturn(mockUpdateOwnerPkg) whenever(mockUpdateOwnerPs.appId).thenReturn(updateOwnerUid) whenever(mSnapshot.checkUidPermission(anyString(), eq(updateOwnerUid))) .thenReturn(PackageManager.PERMISSION_GRANTED) val session = createSession(installerPackageName = updateOwnerName) assertThat(session.shouldAllowDeveloperVerificationEmergencyBypass( verifierPackageName, mSnapshot)).isTrue() } Loading @@ -224,8 +237,8 @@ class PackageInstallerSessionTest { eq(updateOwnerName), eq(Process.SYSTEM_UID))) .thenReturn(mockPs) whenever(mMockPackageManagerInternal.getSystemAppUpdateOwnerPackageName( anyString())).thenReturn(null) val session = createSession() eq(verifierPackageName))).thenReturn(null) val session = createSession(installerPackageName = updateOwnerName) assertThat(session.shouldAllowDeveloperVerificationEmergencyBypass( updateOwnerName, mSnapshot)).isFalse() } Loading @@ -234,16 +247,22 @@ class PackageInstallerSessionTest { fun testShouldAllowDeveloperVerificationEmergencyBypassForUpdateOwner() { val verifierPackageName = "verifierPackageName" val updateOwnerName = "updateOwnerPackageName" val mockPs = mock(PackageStateInternal::class.java) val mockUpdateOwnerPs = mock(PackageStateInternal::class.java) val mockUpdateOwnerPkg = mock(AndroidPackageInternal::class.java) val updateOwnerUid = 10200 whenever(mMockDeveloperVerifierController.verifierPackageName).thenReturn( verifierPackageName) whenever(mockPs.isSystem).thenReturn(true) whenever(mockUpdateOwnerPs.isSystem).thenReturn(true) whenever(mSnapshot.getPackageStateInternal( eq(updateOwnerName), eq(Process.SYSTEM_UID))) .thenReturn(mockPs) .thenReturn(mockUpdateOwnerPs) whenever(mMockPackageManagerInternal.getSystemAppUpdateOwnerPackageName( eq(verifierPackageName))).thenReturn(updateOwnerName) val session = createSession() whenever(mockUpdateOwnerPs.pkg).thenReturn(mockUpdateOwnerPkg) whenever(mockUpdateOwnerPs.appId).thenReturn(updateOwnerUid) whenever(mSnapshot.checkUidPermission(anyString(), eq(updateOwnerUid))) .thenReturn(PackageManager.PERMISSION_GRANTED) val session = createSession(installerPackageName = updateOwnerName) assertThat(session.shouldAllowDeveloperVerificationEmergencyBypass( updateOwnerName, mSnapshot)).isTrue() } Loading @@ -253,41 +272,83 @@ class PackageInstallerSessionTest { val verifierPackageName = "verifierPackageName" val updateOwnerName = "updateOwnerPackageName" val emergencyInstallerPackageName = "emergencyInstallerPackageName" val mockPs = mock(PackageStateInternal::class.java) val mockUpdateOwnerPs = mock(PackageStateInternal::class.java) val mockUpdateOwnerPkg = mock(AndroidPackageInternal::class.java) val mockUid = 10001 val mockEmergencyInstallerPs = mock(PackageStateInternal::class.java) val mockEmergencyInstallerPkg = mock(AndroidPackageInternal::class.java) val mockEmergencyInstallerUid = 10001 val mockUpdateOwnerUid = 10200 whenever(mockPs.appId).thenReturn(mockUid) whenever(mockUpdateOwnerPs.appId).thenReturn(mockUpdateOwnerUid) whenever(mockUpdateOwnerPkg.emergencyInstaller).thenReturn( emergencyInstallerPackageName) whenever(mMockDeveloperVerifierController.verifierPackageName).thenReturn( verifierPackageName) whenever(mockPs.isSystem).thenReturn(true) whenever(mockUpdateOwnerPs.isSystem).thenReturn(true) whenever(mMockPackageManagerInternal.getSystemAppUpdateOwnerPackageName( eq(verifierPackageName))).thenReturn(updateOwnerName) whenever(mockUpdateOwnerPs.pkg).thenReturn(mockUpdateOwnerPkg) whenever(mockUpdateOwnerPs.appId).thenReturn(mockUpdateOwnerUid) whenever(mockUpdateOwnerPkg.emergencyInstaller).thenReturn( emergencyInstallerPackageName) whenever(mSnapshot.getPackageStateInternal( eq(updateOwnerName), eq(Process.SYSTEM_UID))) .thenReturn(mockUpdateOwnerPs) whenever(mSnapshot.getPackageStateInternal( eq(updateOwnerName))) .thenReturn(mockUpdateOwnerPs) whenever(mSnapshot.getPackageStateInternal( eq(emergencyInstallerPackageName), eq(Process.SYSTEM_UID))) .thenReturn(mockPs) whenever(mSnapshot.getPackagesForUid(eq(mockUid))).thenReturn( listOf(emergencyInstallerPackageName).toTypedArray()) whenever(mSnapshot.checkUidPermission(anyString(), eq(UserHandle.getUid(USER_ID, mockUpdateOwnerUid)))) .thenReturn(PackageManager.PERMISSION_GRANTED) whenever(mSnapshot.checkUidPermission(anyString(), eq(mockUid))) whenever(mSnapshot.getPackageStateInternal( eq(emergencyInstallerPackageName), eq(Process.SYSTEM_UID))) .thenReturn(mockEmergencyInstallerPs) whenever(mockEmergencyInstallerPs.pkg).thenReturn(mockEmergencyInstallerPkg) whenever(mockEmergencyInstallerPs.appId).thenReturn(mockEmergencyInstallerUid) whenever(mockEmergencyInstallerPs.isSystem).thenReturn(true) whenever(mSnapshot.checkUidPermission(anyString(), eq(mockEmergencyInstallerUid))) .thenReturn(PackageManager.PERMISSION_GRANTED) val session = createSession(installerPackageName = updateOwnerName) assertThat(session.shouldAllowDeveloperVerificationEmergencyBypass( emergencyInstallerPackageName, mSnapshot)).isTrue() } @Test fun testShouldAllowDeveloperVerificationEmergencyBypassForUpdaterOwnerByEmergencyInstaller() { val verifierPackageName = "verifierPackageName" val updateOwnerName = "updateOwnerPackageName" val emergencyInstallerPackageName = "emergencyInstallerPackageName" val mockUpdateOwnerPs = mock(PackageStateInternal::class.java) val mockUpdateOwnerPkg = mock(AndroidPackageInternal::class.java) val mockEmergencyInstallerPs = mock(PackageStateInternal::class.java) val mockEmergencyInstallerPkg = mock(AndroidPackageInternal::class.java) val mockEmergencyInstallerUid = 10001 val mockUpdateOwnerUid = 10200 whenever(mMockDeveloperVerifierController.verifierPackageName).thenReturn( verifierPackageName) whenever(mMockPackageManagerInternal.getSystemAppUpdateOwnerPackageName( eq(verifierPackageName))).thenReturn(updateOwnerName) val session = createSession() whenever(mSnapshot.getPackageStateInternal( eq(updateOwnerName), eq(Process.SYSTEM_UID))) .thenReturn(mockUpdateOwnerPs) whenever(mockUpdateOwnerPs.appId).thenReturn(mockUpdateOwnerUid) whenever(mockUpdateOwnerPs.isSystem).thenReturn(true) whenever(mockUpdateOwnerPs.pkg).thenReturn(mockUpdateOwnerPkg) whenever(mSnapshot.checkUidPermission(anyString(), eq(UserHandle.getUid(USER_ID, mockUpdateOwnerUid)))) .thenReturn(PackageManager.PERMISSION_GRANTED) whenever(mockUpdateOwnerPkg.emergencyInstaller).thenReturn( emergencyInstallerPackageName) whenever(mSnapshot.getPackageStateInternal( eq(emergencyInstallerPackageName), eq(Process.SYSTEM_UID))) .thenReturn(mockEmergencyInstallerPs) whenever(mockEmergencyInstallerPs.pkg).thenReturn(mockEmergencyInstallerPkg) whenever(mockEmergencyInstallerPs.appId).thenReturn(mockEmergencyInstallerUid) whenever(mSnapshot.checkUidPermission(anyString(), eq(mockEmergencyInstallerUid))) .thenReturn(PackageManager.PERMISSION_GRANTED) val session = createSession(installerPackageName = emergencyInstallerPackageName) assertThat(session.shouldAllowDeveloperVerificationEmergencyBypass( emergencyInstallerPackageName, mSnapshot)).isTrue() updateOwnerName, mSnapshot)).isTrue() } private fun createSession( Loading @@ -296,6 +357,7 @@ class PackageInstallerSessionTest { multiPackage: Boolean = false, parentSessionId: Int = PackageInstaller.SessionInfo.INVALID_ID, childSessionIds: List<Int> = emptyList(), installerPackageName: String = "testInstaller", block: (SessionParams) -> Unit = {}, ): PackageInstallerSession { val bundle = PersistableBundle() Loading @@ -309,7 +371,7 @@ class PackageInstallerSessionTest { val installSource = InstallSource.create( "testInstallInitiator", "testInstallOriginator", "testInstaller", -1, "testUpdateOwner", "testInstallOriginator", installerPackageName, -1, "testUpdateOwner", "testAttributionTag", PackageInstaller.PACKAGE_SOURCE_UNSPECIFIED ) Loading Loading
services/core/java/com/android/server/pm/PackageInstallerSession.java +100 −35 Original line number Diff line number Diff line Loading @@ -1088,16 +1088,24 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub { return false; } // Only system installers can have an emergency installer if (PackageManager.PERMISSION_GRANTED != snapshot.checkUidPermission(Manifest.permission.INSTALL_PACKAGES, uid) && PackageManager.PERMISSION_GRANTED != snapshot.checkUidPermission(Manifest.permission.INSTALL_PACKAGE_UPDATES, uid) && PackageManager.PERMISSION_GRANTED != snapshot.checkUidPermission(Manifest.permission.INSTALL_SELF_UPDATES, uid)) { if (!hasSystemInstallerPermissions(snapshot, uid)) { return false; } return (snapshot.checkUidPermission(Manifest.permission.EMERGENCY_INSTALL_PACKAGES, installerUid) == PackageManager.PERMISSION_GRANTED); return hasEmergencyInstallerPermission(snapshot, installerUid); } private static boolean hasSystemInstallerPermissions(Computer snapshot, int uid) { return (PackageManager.PERMISSION_GRANTED == snapshot.checkUidPermission(Manifest.permission.INSTALL_PACKAGES, uid) || PackageManager.PERMISSION_GRANTED == snapshot.checkUidPermission(Manifest.permission.INSTALL_PACKAGE_UPDATES, uid) || PackageManager.PERMISSION_GRANTED == snapshot.checkUidPermission(Manifest.permission.INSTALL_SELF_UPDATES, uid)); } private static boolean hasEmergencyInstallerPermission(Computer snapshot, int installerUid) { return snapshot.checkUidPermission(Manifest.permission.EMERGENCY_INSTALL_PACKAGES, installerUid) == PackageManager.PERMISSION_GRANTED; } private static final int USER_ACTION_NOT_NEEDED = 0; Loading Loading @@ -3123,40 +3131,75 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub { // the emergency bypass. return false; } // Check if app being installed is the verifier itself. if (TextUtils.equals(verifierPackageName, packageName)) { Slog.d(TAG, "Bypassing developer verification because the verifier is being updated"); return true; } // Check if app being installed is the sysconfig-specified update-owner of the verifier. final String updateOwnerPackageName = mPm.getSystemAppUpdateOwnerPackageName( verifierPackageName); if (updateOwnerPackageName == null) { // No sysconfig-specified update-owner for the verifier. No need to check further. // The verifier has not specified an update-owner in sysconfig. return false; } if (TextUtils.equals(updateOwnerPackageName, packageName)) { Slog.d(TAG, "Bypassing verification service because the sysconfig-specified " + "update owner of the verifier is being updated"); return true; final String installerPackageName = getInstallerPackageName(); if (installerPackageName == null) { return false; } // Check if app being installed is the emergency installer of the sysconfig-specified // update-owner of the verifier. if (isEmergencyInstallerEnabled(updateOwnerPackageName, snapshot, userId, ps.getAppId())) { final PackageStateInternal psUpdateOwner = snapshot.getPackageStateInternal( updateOwnerPackageName, Process.SYSTEM_UID); if (psUpdateOwner == null || psUpdateOwner.getPkg() == null) { // Impossible condition, because the if clause above already checked this. // Added to prevent lint warnings. return false; } String emergencyInstallerPackageName = psUpdateOwner.getPkg().getEmergencyInstaller(); if (emergencyInstallerPackageName != null && TextUtils.equals(emergencyInstallerPackageName, packageName)) { Slog.d(TAG, "Bypassing verification service because the " + "emergency installer of the verifier's update owner is being updated"); // Validate the permissions of the sysconfig-specified update-owner if (!hasSystemInstallerPermissions(snapshot, psUpdateOwner.getAppId())) { return false; } // Check if the verifier is being updated, and the installer is the verifier's // sysconfig-specified update-owner. if (TextUtils.equals(verifierPackageName, packageName) && TextUtils.equals(updateOwnerPackageName, installerPackageName)) { Slog.d(TAG, "Bypassing developer verification because the verifier is being updated."); return true; } // Check if the verifier's sysconfig-specified update-owner is being updated, and the // installer is the verifier's sysconfig-specified update-owner. if (TextUtils.equals(updateOwnerPackageName, packageName) && TextUtils.equals(updateOwnerPackageName, installerPackageName)) { Slog.d(TAG, "Bypassing developer verification because the update-owner of the" + " verifier which is specified in the sysconfig is being updated."); return true; } String emergencyInstallerOfUpdateOwner = psUpdateOwner.getPkg().getEmergencyInstaller(); if (emergencyInstallerOfUpdateOwner == null) { // The rest of the bypass checks involve the emergency installer of the update-owner. // If this is no such emergency installer, no need to check further. return false; } final PackageStateInternal psEmergencyInstallerOfUpdateOwner = snapshot.getPackageStateInternal(emergencyInstallerOfUpdateOwner, Process.SYSTEM_UID); if (psEmergencyInstallerOfUpdateOwner == null || psEmergencyInstallerOfUpdateOwner.getPkg() == null) { return false; } // Check the permission of the emergency installer if (!hasEmergencyInstallerPermission( snapshot, psEmergencyInstallerOfUpdateOwner.getAppId())) { return false; } // Check if the emergency installer of the verifier's sysconfig-specified update-owner is // being updated, and the installer is the verifier's sysconfig-specified update-owner. if (TextUtils.equals(emergencyInstallerOfUpdateOwner, packageName) && TextUtils.equals(updateOwnerPackageName, installerPackageName)) { Slog.d(TAG, "Bypassing developer verification because the emergency installer of" + " the update-owner of the verifier which is specified in the sysconfig is" + " being updated."); return true; } // If the app being installed is the sysconfig-specified update-owner, also allow bypassing // if the installer is the app's emergency-installer. if (TextUtils.equals(updateOwnerPackageName, packageName) && TextUtils.equals(emergencyInstallerOfUpdateOwner, installerPackageName)) { Slog.d(TAG, "Bypassing developer verification because the update-owner of the" + " verifier which is specified in the sysconfig is being updated by its" + " emergency installer."); return true; } return false; } Loading Loading @@ -3460,6 +3503,17 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub { resumeVerify(); return; } if (shouldAllowDeveloperVerificationEmergencyBypass( getPackageName(), mPm.snapshotComputer())) { // Bypass verification when critical package is being updated and the // verification result is not verified. synchronized (mMetrics) { mMetrics.onDeveloperVerificationBypassed( DEVELOPER_VERIFICATION_BYPASSED_REASON_EMERGENCY); } resumeVerify(); return; } // Package is blocked. mVerificationUserActionNeededReason = Loading Loading @@ -3495,6 +3549,17 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub { resumeVerify(); return; } if (shouldAllowDeveloperVerificationEmergencyBypass( getPackageName(), mPm.snapshotComputer())) { // Bypass verification when critical package is being updated and the // verification is incomplete. synchronized (mMetrics) { mMetrics.onDeveloperVerificationBypassed( DEVELOPER_VERIFICATION_BYPASSED_REASON_EMERGENCY); } resumeVerify(); return; } StringBuilder sb = new StringBuilder( "Verification cannot be completed because of "); Loading
services/tests/PackageManagerServiceTests/server/src/com/android/server/pm/PackageInstallerSessionTest.kt +91 −29 Original line number Diff line number Diff line Loading @@ -17,12 +17,12 @@ package com.android.server.pm import android.content.Context import android.content.pm.PackageInstaller import android.content.pm.PackageInstaller.DEVELOPER_VERIFICATION_POLICY_BLOCK_FAIL_CLOSED import android.content.pm.PackageInstaller.DEVELOPER_VERIFICATION_POLICY_BLOCK_FAIL_OPEN import android.content.pm.PackageInstaller.SessionParams import android.content.pm.PackageInstaller.SessionParams.PERMISSION_STATE_DEFAULT import android.content.pm.PackageInstaller.SessionParams.PERMISSION_STATE_DENIED import android.content.pm.PackageInstaller.SessionParams.PERMISSION_STATE_GRANTED import android.content.pm.PackageInstaller.DEVELOPER_VERIFICATION_POLICY_BLOCK_FAIL_CLOSED import android.content.pm.PackageInstaller.DEVELOPER_VERIFICATION_POLICY_BLOCK_FAIL_OPEN import android.content.pm.PackageManager import android.content.pm.verify.domain.DomainSet import android.os.Parcel Loading Loading @@ -200,14 +200,27 @@ class PackageInstallerSessionTest { @Test fun testShouldAllowDeveloperVerificationEmergencyBypassForVerifier() { val verifierPackageName = "verifierPackageName" val updateOwnerName = "updateOwnerPackageName" val mockPs = mock(PackageStateInternal::class.java) val mockUpdateOwnerPs = mock(PackageStateInternal::class.java) val mockUpdateOwnerPkg = mock(AndroidPackageInternal::class.java) val updateOwnerUid = 10200 whenever(mMockDeveloperVerifierController.verifierPackageName).thenReturn( verifierPackageName) whenever(mockPs.isSystem).thenReturn(true) whenever(mSnapshot.getPackageStateInternal( eq(verifierPackageName), eq(Process.SYSTEM_UID))) .thenReturn(mockPs) val session = createSession() whenever(mMockPackageManagerInternal.getSystemAppUpdateOwnerPackageName( anyString())).thenReturn(updateOwnerName) whenever(mSnapshot.getPackageStateInternal( eq(updateOwnerName), eq(Process.SYSTEM_UID))) .thenReturn(mockUpdateOwnerPs) whenever(mockUpdateOwnerPs.pkg).thenReturn(mockUpdateOwnerPkg) whenever(mockUpdateOwnerPs.appId).thenReturn(updateOwnerUid) whenever(mSnapshot.checkUidPermission(anyString(), eq(updateOwnerUid))) .thenReturn(PackageManager.PERMISSION_GRANTED) val session = createSession(installerPackageName = updateOwnerName) assertThat(session.shouldAllowDeveloperVerificationEmergencyBypass( verifierPackageName, mSnapshot)).isTrue() } Loading @@ -224,8 +237,8 @@ class PackageInstallerSessionTest { eq(updateOwnerName), eq(Process.SYSTEM_UID))) .thenReturn(mockPs) whenever(mMockPackageManagerInternal.getSystemAppUpdateOwnerPackageName( anyString())).thenReturn(null) val session = createSession() eq(verifierPackageName))).thenReturn(null) val session = createSession(installerPackageName = updateOwnerName) assertThat(session.shouldAllowDeveloperVerificationEmergencyBypass( updateOwnerName, mSnapshot)).isFalse() } Loading @@ -234,16 +247,22 @@ class PackageInstallerSessionTest { fun testShouldAllowDeveloperVerificationEmergencyBypassForUpdateOwner() { val verifierPackageName = "verifierPackageName" val updateOwnerName = "updateOwnerPackageName" val mockPs = mock(PackageStateInternal::class.java) val mockUpdateOwnerPs = mock(PackageStateInternal::class.java) val mockUpdateOwnerPkg = mock(AndroidPackageInternal::class.java) val updateOwnerUid = 10200 whenever(mMockDeveloperVerifierController.verifierPackageName).thenReturn( verifierPackageName) whenever(mockPs.isSystem).thenReturn(true) whenever(mockUpdateOwnerPs.isSystem).thenReturn(true) whenever(mSnapshot.getPackageStateInternal( eq(updateOwnerName), eq(Process.SYSTEM_UID))) .thenReturn(mockPs) .thenReturn(mockUpdateOwnerPs) whenever(mMockPackageManagerInternal.getSystemAppUpdateOwnerPackageName( eq(verifierPackageName))).thenReturn(updateOwnerName) val session = createSession() whenever(mockUpdateOwnerPs.pkg).thenReturn(mockUpdateOwnerPkg) whenever(mockUpdateOwnerPs.appId).thenReturn(updateOwnerUid) whenever(mSnapshot.checkUidPermission(anyString(), eq(updateOwnerUid))) .thenReturn(PackageManager.PERMISSION_GRANTED) val session = createSession(installerPackageName = updateOwnerName) assertThat(session.shouldAllowDeveloperVerificationEmergencyBypass( updateOwnerName, mSnapshot)).isTrue() } Loading @@ -253,41 +272,83 @@ class PackageInstallerSessionTest { val verifierPackageName = "verifierPackageName" val updateOwnerName = "updateOwnerPackageName" val emergencyInstallerPackageName = "emergencyInstallerPackageName" val mockPs = mock(PackageStateInternal::class.java) val mockUpdateOwnerPs = mock(PackageStateInternal::class.java) val mockUpdateOwnerPkg = mock(AndroidPackageInternal::class.java) val mockUid = 10001 val mockEmergencyInstallerPs = mock(PackageStateInternal::class.java) val mockEmergencyInstallerPkg = mock(AndroidPackageInternal::class.java) val mockEmergencyInstallerUid = 10001 val mockUpdateOwnerUid = 10200 whenever(mockPs.appId).thenReturn(mockUid) whenever(mockUpdateOwnerPs.appId).thenReturn(mockUpdateOwnerUid) whenever(mockUpdateOwnerPkg.emergencyInstaller).thenReturn( emergencyInstallerPackageName) whenever(mMockDeveloperVerifierController.verifierPackageName).thenReturn( verifierPackageName) whenever(mockPs.isSystem).thenReturn(true) whenever(mockUpdateOwnerPs.isSystem).thenReturn(true) whenever(mMockPackageManagerInternal.getSystemAppUpdateOwnerPackageName( eq(verifierPackageName))).thenReturn(updateOwnerName) whenever(mockUpdateOwnerPs.pkg).thenReturn(mockUpdateOwnerPkg) whenever(mockUpdateOwnerPs.appId).thenReturn(mockUpdateOwnerUid) whenever(mockUpdateOwnerPkg.emergencyInstaller).thenReturn( emergencyInstallerPackageName) whenever(mSnapshot.getPackageStateInternal( eq(updateOwnerName), eq(Process.SYSTEM_UID))) .thenReturn(mockUpdateOwnerPs) whenever(mSnapshot.getPackageStateInternal( eq(updateOwnerName))) .thenReturn(mockUpdateOwnerPs) whenever(mSnapshot.getPackageStateInternal( eq(emergencyInstallerPackageName), eq(Process.SYSTEM_UID))) .thenReturn(mockPs) whenever(mSnapshot.getPackagesForUid(eq(mockUid))).thenReturn( listOf(emergencyInstallerPackageName).toTypedArray()) whenever(mSnapshot.checkUidPermission(anyString(), eq(UserHandle.getUid(USER_ID, mockUpdateOwnerUid)))) .thenReturn(PackageManager.PERMISSION_GRANTED) whenever(mSnapshot.checkUidPermission(anyString(), eq(mockUid))) whenever(mSnapshot.getPackageStateInternal( eq(emergencyInstallerPackageName), eq(Process.SYSTEM_UID))) .thenReturn(mockEmergencyInstallerPs) whenever(mockEmergencyInstallerPs.pkg).thenReturn(mockEmergencyInstallerPkg) whenever(mockEmergencyInstallerPs.appId).thenReturn(mockEmergencyInstallerUid) whenever(mockEmergencyInstallerPs.isSystem).thenReturn(true) whenever(mSnapshot.checkUidPermission(anyString(), eq(mockEmergencyInstallerUid))) .thenReturn(PackageManager.PERMISSION_GRANTED) val session = createSession(installerPackageName = updateOwnerName) assertThat(session.shouldAllowDeveloperVerificationEmergencyBypass( emergencyInstallerPackageName, mSnapshot)).isTrue() } @Test fun testShouldAllowDeveloperVerificationEmergencyBypassForUpdaterOwnerByEmergencyInstaller() { val verifierPackageName = "verifierPackageName" val updateOwnerName = "updateOwnerPackageName" val emergencyInstallerPackageName = "emergencyInstallerPackageName" val mockUpdateOwnerPs = mock(PackageStateInternal::class.java) val mockUpdateOwnerPkg = mock(AndroidPackageInternal::class.java) val mockEmergencyInstallerPs = mock(PackageStateInternal::class.java) val mockEmergencyInstallerPkg = mock(AndroidPackageInternal::class.java) val mockEmergencyInstallerUid = 10001 val mockUpdateOwnerUid = 10200 whenever(mMockDeveloperVerifierController.verifierPackageName).thenReturn( verifierPackageName) whenever(mMockPackageManagerInternal.getSystemAppUpdateOwnerPackageName( eq(verifierPackageName))).thenReturn(updateOwnerName) val session = createSession() whenever(mSnapshot.getPackageStateInternal( eq(updateOwnerName), eq(Process.SYSTEM_UID))) .thenReturn(mockUpdateOwnerPs) whenever(mockUpdateOwnerPs.appId).thenReturn(mockUpdateOwnerUid) whenever(mockUpdateOwnerPs.isSystem).thenReturn(true) whenever(mockUpdateOwnerPs.pkg).thenReturn(mockUpdateOwnerPkg) whenever(mSnapshot.checkUidPermission(anyString(), eq(UserHandle.getUid(USER_ID, mockUpdateOwnerUid)))) .thenReturn(PackageManager.PERMISSION_GRANTED) whenever(mockUpdateOwnerPkg.emergencyInstaller).thenReturn( emergencyInstallerPackageName) whenever(mSnapshot.getPackageStateInternal( eq(emergencyInstallerPackageName), eq(Process.SYSTEM_UID))) .thenReturn(mockEmergencyInstallerPs) whenever(mockEmergencyInstallerPs.pkg).thenReturn(mockEmergencyInstallerPkg) whenever(mockEmergencyInstallerPs.appId).thenReturn(mockEmergencyInstallerUid) whenever(mSnapshot.checkUidPermission(anyString(), eq(mockEmergencyInstallerUid))) .thenReturn(PackageManager.PERMISSION_GRANTED) val session = createSession(installerPackageName = emergencyInstallerPackageName) assertThat(session.shouldAllowDeveloperVerificationEmergencyBypass( emergencyInstallerPackageName, mSnapshot)).isTrue() updateOwnerName, mSnapshot)).isTrue() } private fun createSession( Loading @@ -296,6 +357,7 @@ class PackageInstallerSessionTest { multiPackage: Boolean = false, parentSessionId: Int = PackageInstaller.SessionInfo.INVALID_ID, childSessionIds: List<Int> = emptyList(), installerPackageName: String = "testInstaller", block: (SessionParams) -> Unit = {}, ): PackageInstallerSession { val bundle = PersistableBundle() Loading @@ -309,7 +371,7 @@ class PackageInstallerSessionTest { val installSource = InstallSource.create( "testInstallInitiator", "testInstallOriginator", "testInstaller", -1, "testUpdateOwner", "testInstallOriginator", installerPackageName, -1, "testUpdateOwner", "testAttributionTag", PackageInstaller.PACKAGE_SOURCE_UNSPECIFIED ) Loading