summaryrefslogtreecommitdiff
path: root/hostsidetests/securitybulletin/test-apps/CVE-2023-20944/test-app/src/android/security/cts/CVE_2023_20944_test/DeviceTest.java
diff options
context:
space:
mode:
Diffstat (limited to 'hostsidetests/securitybulletin/test-apps/CVE-2023-20944/test-app/src/android/security/cts/CVE_2023_20944_test/DeviceTest.java')
-rw-r--r--hostsidetests/securitybulletin/test-apps/CVE-2023-20944/test-app/src/android/security/cts/CVE_2023_20944_test/DeviceTest.java126
1 files changed, 126 insertions, 0 deletions
diff --git a/hostsidetests/securitybulletin/test-apps/CVE-2023-20944/test-app/src/android/security/cts/CVE_2023_20944_test/DeviceTest.java b/hostsidetests/securitybulletin/test-apps/CVE-2023-20944/test-app/src/android/security/cts/CVE_2023_20944_test/DeviceTest.java
new file mode 100644
index 00000000000..a0c7a241de5
--- /dev/null
+++ b/hostsidetests/securitybulletin/test-apps/CVE-2023-20944/test-app/src/android/security/cts/CVE_2023_20944_test/DeviceTest.java
@@ -0,0 +1,126 @@
+/*
+ * 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_20944_test;
+
+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.ActivityTaskManager;
+import android.app.IActivityTaskManager;
+import android.app.UiAutomation;
+import android.content.BroadcastReceiver;
+import android.content.Context;
+import android.content.Intent;
+import android.content.IntentFilter;
+import android.os.ServiceManager;
+
+import androidx.test.runner.AndroidJUnit4;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import java.util.concurrent.Semaphore;
+import java.util.concurrent.TimeUnit;
+import java.util.List;
+
+@RunWith(AndroidJUnit4.class)
+public class DeviceTest {
+ private String mPocActivityStatus;
+ private int mTaskId;
+
+ @Test
+ public void testCVE_2023_20944() {
+ try {
+ final int waitMs = 5000;
+ final int waitPerIter = 200;
+ Context context = getInstrumentation().getContext();
+ UiAutomation uiAutomation = getInstrumentation().getUiAutomation();
+ uiAutomation.adoptShellPermissionIdentity();
+
+ // Registering a receiver here to wait for a broadcast from TargetActivity
+ final Semaphore targetReturn = new Semaphore(0);
+ final Semaphore pocReturn = new Semaphore(0);
+ BroadcastReceiver broadcastReceiver = new BroadcastReceiver() {
+ @Override
+ public void onReceive(Context context, Intent intent) {
+ try {
+ if ((intent.getBooleanExtra(context.getString(R.string.actionTarget), false)
+ && (mTaskId = intent.getIntExtra(context.getString(R.string.taskId),
+ -1)) != -1)) {
+ targetReturn.release();
+ }
+ if ((mPocActivityStatus = intent
+ .getStringExtra(context.getString(R.string.status))) != null) {
+ pocReturn.release();
+ }
+ } catch (Exception ignored) {
+ // ignore any exceptions
+ }
+ }
+ };
+ IntentFilter filter = new IntentFilter(context.getString(R.string.bcastActionTarget));
+ context.registerReceiver(broadcastReceiver, filter);
+
+ // Start TargetActivity
+ Intent targetIntent = new Intent(Intent.ACTION_MAIN);
+ final String pkgTarget = context.getString(R.string.pkgTarget);
+ targetIntent.setClassName(pkgTarget, context.getString(R.string.activityTarget));
+ targetIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+ context.startActivity(targetIntent);
+ assumeTrue(context.getString(R.string.targetFailMsg),
+ targetReturn.tryAcquire(waitMs, TimeUnit.MILLISECONDS));
+
+ // Start PocActivity which in turn starts the ChooseTypeAndAccountActivity
+ Intent intent = new Intent(context, PocActivity.class);
+ intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+ context.startActivity(intent);
+ assumeTrue(context.getString(R.string.pocFailedMsg),
+ pocReturn.tryAcquire(waitMs, TimeUnit.MILLISECONDS));
+ assumeTrue(context.getString(R.string.pocCrashedMsg, mPocActivityStatus),
+ mPocActivityStatus.equals(context.getString(R.string.noExceptionMsg)));
+
+ // Failing the test if the taskId received from the target activity matches with the
+ // list of running taskId and topActivity has HijackActivity in the same taskId.
+ IActivityTaskManager iActivityTaskManager = IActivityTaskManager.Stub
+ .asInterface(ServiceManager.getService(Context.ACTIVITY_TASK_SERVICE));
+ long start = System.currentTimeMillis();
+ while (!(iActivityTaskManager.getAllRootTaskInfos().toString()
+ .contains(HijackActivity.class.getName()))
+ && System.currentTimeMillis() - start < waitMs) {
+ Thread.sleep(waitPerIter);
+ }
+ boolean isDeviceVulnerable = false;
+ List<ActivityTaskManager.RootTaskInfo> runningTasks =
+ iActivityTaskManager.getAllRootTaskInfos();
+ for (ActivityTaskManager.RootTaskInfo runningTaskInfo : runningTasks) {
+ for (int i = 0; i < runningTaskInfo.childTaskIds.length; ++i) {
+ if (mTaskId == runningTaskInfo.childTaskIds[i] && runningTaskInfo.topActivity
+ .getClassName().equals(HijackActivity.class.getName())) {
+ isDeviceVulnerable = true;
+ break;
+ }
+ }
+ }
+ assertFalse(context.getString(R.string.msgFail), isDeviceVulnerable);
+ } catch (Exception e) {
+ assumeNoException(e);
+ }
+ }
+}