CTS test for Android Security b/268193384
Bug: 268193384
Bug: 280641507
Test: Ran the new testcase on android-13.0.0_r7 with/without patch
Change-Id: I7e4db88429f1ac3c1299b78baf30aadba5edee71
diff --git a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2023_21256.java b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2023_21256.java
new file mode 100644
index 0000000..b367055
--- /dev/null
+++ b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2023_21256.java
@@ -0,0 +1,85 @@
+/*
+ * Copyright (C) 2023 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 android.security.cts;
+
+import static org.junit.Assume.assumeFalse;
+import static org.junit.Assume.assumeNoException;
+import static org.junit.Assume.assumeTrue;
+
+import android.platform.test.annotations.AsbSecurityTest;
+
+import com.android.sts.common.tradefed.testtype.NonRootSecurityTestCase;
+import com.android.tradefed.device.ITestDevice;
+import com.android.tradefed.device.UserInfo;
+import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
+import com.android.tradefed.testtype.junit4.DeviceTestRunOptions;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import java.util.Map;
+
+@RunWith(DeviceJUnit4ClassRunner.class)
+public class CVE_2023_21256 extends NonRootSecurityTestCase {
+
+ @AsbSecurityTest(cveBugId = 268193384)
+ @Test
+ public void testPocCVE_2023_21256() {
+ ITestDevice device = null;
+ int workUserId = -1;
+ try {
+ final String testPkg = "android.security.cts.CVE_2023_21256";
+ device = getDevice();
+
+ assumeTrue(device.isMultiUserSupported());
+
+ AdbUtils.runCommandLine(
+ "pm create-user --profileOf 0 --managed CVE_2023_21256_work_user", device);
+
+ Map<Integer, UserInfo> mapOfUserInfos = device.getUserInfos();
+ for (UserInfo userInfo : mapOfUserInfos.values()) {
+ if (userInfo.userName().equals("CVE_2023_21256_work_user")) {
+ workUserId = userInfo.userId();
+ }
+ }
+ assumeFalse(workUserId == -1);
+
+ assumeTrue(device.startUser(workUserId, true /* waitFlag */));
+
+ // Install the test app in work profile
+ installPackage("CVE-2023-21256.apk", "--user " + workUserId);
+
+ runDeviceTests(
+ new DeviceTestRunOptions(testPkg)
+ .setDevice(device)
+ .setTestClassName(testPkg + ".DeviceTest")
+ .setTestMethodName("testSettingsHomePageActivityFromWorkProfile")
+ .setUserId(workUserId));
+ } catch (Exception e) {
+ assumeNoException(e);
+ } finally {
+ if (workUserId != -1) {
+ try {
+ device.stopUser(workUserId, true /* waitFlag */, true /* forceFlag */);
+ device.removeUser(workUserId);
+ } catch (Exception e) {
+ // Ignore exceptions as the test has finished
+ }
+ }
+ }
+ }
+}
diff --git a/hostsidetests/securitybulletin/test-apps/CVE-2023-21256/Android.bp b/hostsidetests/securitybulletin/test-apps/CVE-2023-21256/Android.bp
new file mode 100644
index 0000000..1f7e5c2
--- /dev/null
+++ b/hostsidetests/securitybulletin/test-apps/CVE-2023-21256/Android.bp
@@ -0,0 +1,40 @@
+/*
+ * Copyright (C) 2023 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 {
+ default_applicable_licenses: ["Android-Apache-2.0"],
+}
+
+android_test_helper_app {
+ name: "CVE-2023-21256",
+ defaults: [
+ "cts_support_defaults",
+ ],
+ srcs: [
+ "src/**/*.java",
+ ],
+ test_suites: [
+ "sts",
+ ],
+ static_libs: [
+ "Nene",
+ "androidx.test.core",
+ "androidx.test.rules",
+ "androidx.test.uiautomator_uiautomator",
+ ],
+ platform_apis: true,
+}
diff --git a/hostsidetests/securitybulletin/test-apps/CVE-2023-21256/AndroidManifest.xml b/hostsidetests/securitybulletin/test-apps/CVE-2023-21256/AndroidManifest.xml
new file mode 100644
index 0000000..b6cdbca
--- /dev/null
+++ b/hostsidetests/securitybulletin/test-apps/CVE-2023-21256/AndroidManifest.xml
@@ -0,0 +1,22 @@
+<!--
+ Copyright 2023 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.
+ -->
+
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ package="android.security.cts.CVE_2023_21256">
+
+ <instrumentation android:name="androidx.test.runner.AndroidJUnitRunner"
+ android:targetPackage="android.security.cts.CVE_2023_21256" />
+</manifest>
diff --git a/hostsidetests/securitybulletin/test-apps/CVE-2023-21256/src/android/security/cts/CVE_2023_21256/DeviceTest.java b/hostsidetests/securitybulletin/test-apps/CVE-2023-21256/src/android/security/cts/CVE_2023_21256/DeviceTest.java
new file mode 100644
index 0000000..31d153f
--- /dev/null
+++ b/hostsidetests/securitybulletin/test-apps/CVE-2023-21256/src/android/security/cts/CVE_2023_21256/DeviceTest.java
@@ -0,0 +1,134 @@
+/*
+ * Copyright (C) 2023 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 android.security.cts.CVE_2023_21256;
+
+import static androidx.test.platform.app.InstrumentationRegistry.getInstrumentation;
+
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assume.assumeNoException;
+import static org.junit.Assume.assumeTrue;
+
+import android.app.Instrumentation;
+import android.app.UiAutomation;
+import android.content.Context;
+import android.content.Intent;
+import android.content.pm.PackageManager;
+import android.content.pm.ResolveInfo;
+import android.os.UserHandle;
+import android.provider.Settings;
+
+import androidx.test.runner.AndroidJUnit4;
+import androidx.test.uiautomator.By;
+import androidx.test.uiautomator.UiDevice;
+import androidx.test.uiautomator.Until;
+
+import com.android.bedstead.nene.utils.Poll;
+import com.android.internal.app.PlatLogoActivity;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import java.time.Duration;
+import java.util.regex.Pattern;
+
+@RunWith(AndroidJUnit4.class)
+public class DeviceTest {
+ private UiDevice mUiDevice;
+
+ @Test
+ public void testSettingsHomePageActivityFromWorkProfile() {
+ UiAutomation uiAutomation = null;
+ try {
+ final long timeoutMs = 10_000L;
+ Instrumentation instrumentation = getInstrumentation();
+ uiAutomation = instrumentation.getUiAutomation();
+ mUiDevice = UiDevice.getInstance(instrumentation);
+ Context context = instrumentation.getContext();
+ String defaultSettingsPkg = "com.android.settings";
+ String platLogoActivityName = PlatLogoActivity.class.getName();
+ String dumpsysActivityCmd = "dumpsys activity " + platLogoActivityName;
+
+ // Retrieve Settings app's package name
+ uiAutomation.adoptShellPermissionIdentity(
+ android.Manifest.permission.INTERACT_ACROSS_USERS);
+ ResolveInfo info =
+ context.getPackageManager()
+ .resolveActivityAsUser(
+ new Intent(Settings.ACTION_SETTINGS),
+ PackageManager.MATCH_SYSTEM_ONLY,
+ UserHandle.USER_SYSTEM);
+ if (info != null && info.activityInfo != null) {
+ defaultSettingsPkg = info.activityInfo.packageName;
+ }
+
+ // Attempt to launch PlatLogoActivity using Settings app
+ Intent intent =
+ Intent.createChooser(
+ new Intent(Settings.ACTION_SETTINGS_EMBED_DEEP_LINK_ACTIVITY)
+ .setClassName(
+ defaultSettingsPkg,
+ defaultSettingsPkg
+ + ".homepage.SettingsHomepageActivity")
+ .putExtra(
+ Settings.EXTRA_SETTINGS_EMBEDDED_DEEP_LINK_INTENT_URI,
+ new Intent(Intent.ACTION_CHOOSER)
+ .toUri(Intent.URI_INTENT_SCHEME))
+ .putExtra(
+ Intent.EXTRA_INTENT,
+ new Intent()
+ .setClassName("android", platLogoActivityName))
+ .addFlags(Intent.FLAG_ACTIVITY_NEW_TASK),
+ "chooserTitle");
+ context.startActivity(intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK));
+
+ // Click Settings from ChooserActivity
+ String settingsText = "Settings";
+ assumeTrue(mUiDevice.wait(Until.hasObject(By.text(settingsText)), timeoutMs));
+ mUiDevice.findObject(By.text(settingsText)).click();
+
+ Pattern resumedTruePattern =
+ Pattern.compile(".*mResumed=true.*", Pattern.CASE_INSENSITIVE);
+
+ // Wait for dumpsys result to update
+ Poll.forValue(
+ () ->
+ resumedTruePattern
+ .matcher(mUiDevice.executeShellCommand(dumpsysActivityCmd))
+ .find())
+ .toBeEqualTo(true)
+ .timeout(Duration.ofMillis(timeoutMs))
+ .await();
+
+ // Fail test if PlatLogoActivity was launched
+ assertFalse(
+ "Device is vulnerable to b/250589026, Unexported activities can be launched"
+ + "using ACTION_SETTINGS_EMBED_DEEP_LINK_ACTIVITY from a workProfile",
+ resumedTruePattern
+ .matcher(mUiDevice.executeShellCommand(dumpsysActivityCmd))
+ .find());
+ } catch (Exception e) {
+ assumeNoException(e);
+ } finally {
+ try {
+ uiAutomation.dropShellPermissionIdentity();
+ mUiDevice.pressHome();
+ } catch (Exception e) {
+ // Ignore exceptions as the test has finished
+ }
+ }
+ }
+}