Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit d8f738dc authored by Rhed Jao's avatar Rhed Jao
Browse files

Fix side channel leakage from the api of overrideLabelAndIcon

- The package information is disclosed from the different exceptions
  thrown by the api of IPackageManager#overrideLabelAndIcon.

- Fix the PackageManagerComponentOverrideTests breakage.

- Add non-existent package tests in the
  PackageManagerComponentOverrideTests. Verify that the api should
  throw security exception if the package does not exist.

Bug: 184851840
Bug: 190596162
Test: atest PackageManagerComponentOverrideTests
Change-Id: I77a9cc0f87413913bbcb93674f16c311574654dd
parent d52baf86
Loading
Loading
Loading
Loading
+4 −5
Original line number Diff line number Diff line
@@ -23531,11 +23531,6 @@ public class PackageManagerService extends IPackageManager.Stub
            throw new IllegalArgumentException("Must specify a component");
        }
        boolean componentExists = mComponentResolver.componentExists(componentName);
        if (!componentExists) {
            throw new IllegalArgumentException("Component " + componentName + " not found");
        }
        int callingUid = Binder.getCallingUid();
        String componentPkgName = componentName.getPackageName();
@@ -23567,6 +23562,10 @@ public class PackageManagerService extends IPackageManager.Stub
                        "Changing the label is not allowed for " + componentName);
            }
            if (!mComponentResolver.componentExists(componentName)) {
                throw new IllegalArgumentException("Component " + componentName + " not found");
            }
            if (!pkgSetting.overrideNonLocalizedLabelAndIcon(componentName, nonLocalizedLabel,
                    icon, userId)) {
                // Nothing changed
+41 −18
Original line number Diff line number Diff line
@@ -16,6 +16,7 @@

package com.android.server.pm.test.override

import android.app.PropertyInvalidatedCache
import android.content.ComponentName
import android.content.Context
import android.content.pm.PackageManager
@@ -26,8 +27,10 @@ import android.util.ArrayMap
import com.android.server.pm.AppsFilter
import com.android.server.pm.ComponentResolver
import com.android.server.pm.PackageManagerService
import com.android.server.pm.PackageManagerTracedLock
import com.android.server.pm.PackageSetting
import com.android.server.pm.Settings
import com.android.server.pm.UserManagerInternal
import com.android.server.pm.UserManagerService
import com.android.server.pm.parsing.pkg.AndroidPackage
import com.android.server.pm.parsing.pkg.PackageImpl
@@ -42,6 +45,7 @@ import com.android.server.wm.ActivityTaskManagerInternal
import com.google.common.truth.Truth.assertThat
import org.junit.After
import org.junit.Before
import org.junit.BeforeClass
import org.junit.Test
import org.junit.runner.RunWith
import org.junit.runners.Parameterized
@@ -63,6 +67,7 @@ class PackageManagerComponentLabelIconOverrideTest {
        private const val VALID_PKG = "com.android.server.pm.test.override"
        private const val SHARED_PKG = "com.android.server.pm.test.override.shared"
        private const val INVALID_PKG = "com.android.server.pm.test.override.invalid"
        private const val NON_EXISTENT_PKG = "com.android.server.pm.test.override.nonexistent"

        private const val SEND_PENDING_BROADCAST = 1 // PackageManagerService.SEND_PENDING_BROADCAST

@@ -94,7 +99,8 @@ class PackageManagerComponentLabelIconOverrideTest {
                // Start with an array of the simplest known inputs and expected outputs
                Params(VALID_PKG, AppType.SYSTEM_APP, Result.Changed),
                Params(SHARED_PKG, AppType.SYSTEM_APP, Result.Changed),
                Params(INVALID_PKG, AppType.SYSTEM_APP, SecurityException::class.java)
                Params(INVALID_PKG, AppType.SYSTEM_APP, SecurityException::class.java),
                Params(NON_EXISTENT_PKG, AppType.SYSTEM_APP, SecurityException::class.java)
        )
                .flatMap { param ->
                    mutableListOf(param).apply {
@@ -120,6 +126,13 @@ class PackageManagerComponentLabelIconOverrideTest {
                    }
                }

        @BeforeClass
        @JvmStatic
        fun disablePropertyInvalidatedCache() {
            // Disable binder caches in this process.
            PropertyInvalidatedCache.disableForTestMode()
        }

        data class Params(
            val pkgName: String,
            private val appType: AppType,
@@ -210,10 +223,12 @@ class PackageManagerComponentLabelIconOverrideTest {
    fun verifyExpectedResult() {
        if (params.componentName != null) {
            val activityInfo = service.getActivityInfo(params.componentName, 0, userId)
            if (activityInfo != null) {
                assertThat(activityInfo.nonLocalizedLabel).isEqualTo(params.expectedLabel)
                assertThat(activityInfo.icon).isEqualTo(params.expectedIcon)
            }
        }
    }

    @After
    fun verifyDifferentUserUnchanged() {
@@ -294,15 +309,18 @@ class PackageManagerComponentLabelIconOverrideTest {
                SHARED_PKG to makePkg(SHARED_PKG) { uid = Binder.getCallingUid() },
                INVALID_PKG to makePkg(INVALID_PKG) { uid = Binder.getCallingUid() + 1 }
        )
        val mockedPkgSettings = mapOf(
        val mockedPkgSettings = mutableMapOf(
                VALID_PKG to makePkgSetting(VALID_PKG),
                SHARED_PKG to makePkgSetting(SHARED_PKG),
                INVALID_PKG to makePkgSetting(INVALID_PKG)
        )

        var mockActivity: ParsedActivity? = null
        if (mockedPkgSettings.containsKey(params.pkgName)) {
            // Add pkgSetting under test so its attributes override the defaults added above
                .plus(params.pkgName to mockPkgSetting)
            mockedPkgSettings.put(params.pkgName, mockPkgSetting)

        val mockActivity: ParsedActivity = mock {
            mockActivity = mock<ParsedActivity> {
                whenever(this.packageName) { params.pkgName }
                whenever(this.nonLocalizedLabel) { DEFAULT_LABEL }
                whenever(this.icon) { DEFAULT_ICON }
@@ -311,17 +329,21 @@ class PackageManagerComponentLabelIconOverrideTest {
                whenever(this.isEnabled) { true }
                whenever(this.isDirectBootAware) { params.isSystem }
            }
        }

        val mockSettings = Settings(mockedPkgSettings)
        val mockComponentResolver: ComponentResolver = mockThrowOnUnmocked {
            params.componentName?.let {
                whenever(this.componentExists(same(it))) { true }
                whenever(this.componentExists(same(it))) { mockActivity != null }
                whenever(this.getActivity(same(it))) { mockActivity }
            }
        }
        val mockUserManagerService: UserManagerService = mockThrowOnUnmocked {
            val matcher: (Int) -> Boolean = { it == userId || it == userIdDifferent }
            whenever(this.exists(intThat(matcher))) { true }
        }
        val mockUserManagerInternal: UserManagerInternal = mockThrowOnUnmocked {
            val matcher: (Int) -> Boolean = { it == userId || it == userIdDifferent }
            whenever(this.isUserUnlockingOrUnlocked(intThat(matcher))) { true }
        }
        val mockActivityTaskManager: ActivityTaskManagerInternal = mockThrowOnUnmocked {
@@ -340,18 +362,19 @@ class PackageManagerComponentLabelIconOverrideTest {
            }
        }
        val mockInjector: PackageManagerService.Injector = mock {
            whenever(this.lock) { Object() }
            whenever(this.lock) { PackageManagerTracedLock() }
            whenever(this.componentResolver) { mockComponentResolver }
            whenever(this.userManagerService) { mockUserManagerService }
            whenever(this.getUserManagerInternal()) { mockUserManagerInternal }
            whenever(this.settings) { mockSettings }
            whenever(this.getLocalService(ActivityTaskManagerInternal::class.java)) {
                mockActivityTaskManager
            }
            whenever(this.appsFilter) { mockAppsFilter }
            whenever(this.context) { mockContext }
            whenever(this.getHandler()) { testHandler }
        }
        val testParams = PackageManagerService.TestParams().apply {
            this.handler = testHandler
            this.pendingPackageBroadcasts = mockPendingBroadcasts
            this.resolveComponentName = ComponentName("android", ".Test")
            this.packages = ArrayMap<String, AndroidPackage>().apply { putAll(mockedPkgs) }