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
+            }
+        }
+    }
+}