From 0806568d4133e1dc736ebcc45f62655165366a9e Mon Sep 17 00:00:00 2001 From: Winson Date: Thu, 8 Jul 2021 12:07:08 -0700 Subject: [PATCH] Unexport all PackageInstaller receivers All of PackageInstaller's declared receivers receive system broadcasts, so they do not need to be exported. Leaving them exported opens up vulnerabilities for apps to launch them and execute functionality that PackageInstaller includes. Bug: 191283525 Test: manual, verify receivers still work Test: atest com.android.packageinstaller.test.ExportedComponentTest Change-Id: I782fc21c848831a2a4aeab736cd47ad45781b290 --- packages/PackageInstaller/AndroidManifest.xml | 8 +-- packages/PackageInstaller/TEST_MAPPING | 5 +- .../packageinstaller/Android.bp | 39 +++++++++++++++ .../packageinstaller/AndroidManifest.xml | 29 +++++++++++ .../packageinstaller/AndroidTest.xml | 29 +++++++++++ .../test/ExportedComponentTest.kt | 50 +++++++++++++++++++ 6 files changed, 155 insertions(+), 5 deletions(-) create mode 100644 services/tests/PackageManager/packageinstaller/Android.bp create mode 100644 services/tests/PackageManager/packageinstaller/AndroidManifest.xml create mode 100644 services/tests/PackageManager/packageinstaller/AndroidTest.xml create mode 100644 services/tests/PackageManager/packageinstaller/src/com/android/packageinstaller/test/ExportedComponentTest.kt diff --git a/packages/PackageInstaller/AndroidManifest.xml b/packages/PackageInstaller/AndroidManifest.xml index 48cdf1647d869..197b7b2b0eaf8 100644 --- a/packages/PackageInstaller/AndroidManifest.xml +++ b/packages/PackageInstaller/AndroidManifest.xml @@ -31,7 +31,7 @@ android:directBootAware="true"> + android:exported="false"> @@ -76,7 +76,7 @@ + android:exported="false"> @@ -106,14 +106,14 @@ + android:exported="false"> + android:exported="false"> diff --git a/packages/PackageInstaller/TEST_MAPPING b/packages/PackageInstaller/TEST_MAPPING index 5d7b9bb36f751..cef9014ec2298 100644 --- a/packages/PackageInstaller/TEST_MAPPING +++ b/packages/PackageInstaller/TEST_MAPPING @@ -19,6 +19,9 @@ }, { "name": "CtsPackageUninstallTestCases" + }, + { + "name": "PackageInstallerTests" } ] -} \ No newline at end of file +} diff --git a/services/tests/PackageManager/packageinstaller/Android.bp b/services/tests/PackageManager/packageinstaller/Android.bp new file mode 100644 index 0000000000000..35d754b4adc59 --- /dev/null +++ b/services/tests/PackageManager/packageinstaller/Android.bp @@ -0,0 +1,39 @@ +// Copyright (C) 2021 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 { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "frameworks_base_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + default_applicable_licenses: ["frameworks_base_license"], +} + +android_test { + name: "PackageInstallerTests", + srcs: [ + "src/**/*.java", + "src/**/*.kt", + ], + static_libs: [ + "androidx.test.rules", + "androidx.test.runner", + "junit", + "kotlin-test", + "truth-prebuilt", + ], + platform_apis: true, + test_suites: ["device-tests"], +} diff --git a/services/tests/PackageManager/packageinstaller/AndroidManifest.xml b/services/tests/PackageManager/packageinstaller/AndroidManifest.xml new file mode 100644 index 0000000000000..d7062587c4bca --- /dev/null +++ b/services/tests/PackageManager/packageinstaller/AndroidManifest.xml @@ -0,0 +1,29 @@ + + + + + + + + + + + diff --git a/services/tests/PackageManager/packageinstaller/AndroidTest.xml b/services/tests/PackageManager/packageinstaller/AndroidTest.xml new file mode 100644 index 0000000000000..c39285ffca38f --- /dev/null +++ b/services/tests/PackageManager/packageinstaller/AndroidTest.xml @@ -0,0 +1,29 @@ + + + + + diff --git a/services/tests/PackageManager/packageinstaller/src/com/android/packageinstaller/test/ExportedComponentTest.kt b/services/tests/PackageManager/packageinstaller/src/com/android/packageinstaller/test/ExportedComponentTest.kt new file mode 100644 index 0000000000000..d7d2726c15838 --- /dev/null +++ b/services/tests/PackageManager/packageinstaller/src/com/android/packageinstaller/test/ExportedComponentTest.kt @@ -0,0 +1,50 @@ +/* + * Copyright (C) 2021 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.packageinstaller.test + +import android.content.Context +import android.content.Intent +import android.content.pm.PackageManager +import android.net.Uri +import androidx.test.InstrumentationRegistry +import com.google.common.truth.Truth.assertThat +import com.google.common.truth.Truth.assertWithMessage +import org.junit.Test + +class ExportedComponentTest { + + private val context: Context = InstrumentationRegistry.getContext() + + @Test + fun verifyNoExportedReceivers() { + val intent = Intent(Intent.ACTION_INSTALL_PACKAGE).apply { + data = Uri.parse("content://mockForTest") + } + val packageInstallers = context.packageManager.queryIntentActivities(intent, + PackageManager.MATCH_DEFAULT_ONLY or PackageManager.MATCH_DISABLED_COMPONENTS) + .map { it.activityInfo.packageName } + .distinct() + .map { context.packageManager.getPackageInfo(it, PackageManager.GET_RECEIVERS) } + + assertThat(packageInstallers).isNotEmpty() + + packageInstallers.forEach { + val exported = it.receivers.filter { it.exported } + assertWithMessage("Receivers should not be exported").that(exported).isEmpty() + } + } +}