summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndroid Build Coastguard Worker <android-build-coastguard-worker@google.com>2023-05-10 16:06:29 +0000
committerAndroid Build Coastguard Worker <android-build-coastguard-worker@google.com>2023-05-10 16:06:29 +0000
commit59e2afc31c6c2cba73bd6c6834db93c1c07e13ef (patch)
tree3996d3566992a0af741321bbb085681b84cf1552
parent9684881f240024c3d5bf537f03eb74dbc8c237cc (diff)
parentadbe4e46ae2b1c3143847055475d8310bc4ad0b5 (diff)
downloadcts-android10-android13-mainline-tzdata-release.tar.gz
Snap for 10101514 from adbe4e46ae2b1c3143847055475d8310bc4ad0b5 to qt-aml-tzdata-releaseq_tzdata_aml_296200000android10-android13-mainline-tzdata-release
Change-Id: I4bebde50c3f816ce6892886a51da109b9b932c30
-rw-r--r--hostsidetests/appsecurity/Android.mk2
-rw-r--r--hostsidetests/appsecurity/src/android/appsecurity/cts/RoleSecurityTest.java4
-rw-r--r--hostsidetests/securitybulletin/securityPatch/CVE-2021-0484/poc.cpp50
-rw-r--r--hostsidetests/securitybulletin/src/android/security/cts/AdbUtils.java266
-rw-r--r--hostsidetests/securitybulletin/src/android/security/cts/Bug_248251018.java45
-rw-r--r--hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_0484.java10
-rw-r--r--hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_0963.java68
-rw-r--r--hostsidetests/securitybulletin/src/android/security/cts/CVE_2022_20112.java88
-rw-r--r--hostsidetests/securitybulletin/src/android/security/cts/CVE_2022_20197.java32
-rw-r--r--hostsidetests/securitybulletin/src/android/security/cts/CVE_2022_20360.java87
-rw-r--r--hostsidetests/securitybulletin/src/android/security/cts/CVE_2022_20415.java49
-rw-r--r--hostsidetests/securitybulletin/src/android/security/cts/CVE_2023_20913.java (renamed from hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_0642.java)46
-rw-r--r--hostsidetests/securitybulletin/src/android/security/cts/CVE_2023_20918.java57
-rw-r--r--hostsidetests/securitybulletin/test-apps/CVE-2021-0642/src/android/security/cts/cve_2021_0642/DeviceTest.java100
-rw-r--r--hostsidetests/securitybulletin/test-apps/CVE-2021-0963/Android.bp39
-rw-r--r--hostsidetests/securitybulletin/test-apps/CVE-2021-0963/AndroidManifest.xml (renamed from hostsidetests/securitybulletin/test-apps/CVE-2021-0642/AndroidManifest.xml)34
-rw-r--r--hostsidetests/securitybulletin/test-apps/CVE-2021-0963/res/values/integers.xml (renamed from hostsidetests/securitybulletin/test-apps/CVE-2021-0642/res/layout/activity_main.xml)16
-rw-r--r--hostsidetests/securitybulletin/test-apps/CVE-2021-0963/res/values/strings.xml40
-rw-r--r--hostsidetests/securitybulletin/test-apps/CVE-2021-0963/res/xml/device_policies.xml21
-rw-r--r--hostsidetests/securitybulletin/test-apps/CVE-2021-0963/src/android/security/cts/CVE_2021_0963/DeviceTest.java401
-rw-r--r--hostsidetests/securitybulletin/test-apps/CVE-2021-0963/src/android/security/cts/CVE_2021_0963/PocActivity.java56
-rw-r--r--hostsidetests/securitybulletin/test-apps/CVE-2021-0963/src/android/security/cts/CVE_2021_0963/PocDeviceAdminReceiver.java22
-rw-r--r--hostsidetests/securitybulletin/test-apps/CVE-2021-0963/src/android/security/cts/CVE_2021_0963/PocService.java99
-rw-r--r--hostsidetests/securitybulletin/test-apps/CVE-2021-0963/src/android/security/cts/CVE_2021_0963/PocStatus.java35
-rw-r--r--hostsidetests/securitybulletin/test-apps/CVE-2022-20112/Android.bp38
-rw-r--r--hostsidetests/securitybulletin/test-apps/CVE-2022-20112/AndroidManifest.xml22
-rw-r--r--hostsidetests/securitybulletin/test-apps/CVE-2022-20112/res/values/strings.xml24
-rw-r--r--hostsidetests/securitybulletin/test-apps/CVE-2022-20112/src/android/security/cts/CVE_2022_20112/DeviceTest.java90
-rw-r--r--hostsidetests/securitybulletin/test-apps/CVE-2022-20360/Android.bp38
-rw-r--r--hostsidetests/securitybulletin/test-apps/CVE-2022-20360/AndroidManifest.xml23
-rw-r--r--hostsidetests/securitybulletin/test-apps/CVE-2022-20360/res/values/strings.xml27
-rw-r--r--hostsidetests/securitybulletin/test-apps/CVE-2022-20360/src/android/security/cts/CVE_2022_20360/DeviceTest.java119
-rw-r--r--hostsidetests/securitybulletin/test-apps/CVE-2022-20415/Android.bp36
-rw-r--r--hostsidetests/securitybulletin/test-apps/CVE-2022-20415/AndroidManifest.xml31
-rw-r--r--hostsidetests/securitybulletin/test-apps/CVE-2022-20415/res/values/integers.xml23
-rw-r--r--hostsidetests/securitybulletin/test-apps/CVE-2022-20415/res/values/strings.xml27
-rw-r--r--hostsidetests/securitybulletin/test-apps/CVE-2022-20415/src/android/security/cts/CVE_2022_20415/DeviceTest.java134
-rw-r--r--hostsidetests/securitybulletin/test-apps/CVE-2022-20415/src/android/security/cts/CVE_2022_20415/PocActivity.java36
-rw-r--r--hostsidetests/securitybulletin/test-apps/CVE-2023-20913/Android.bp (renamed from hostsidetests/securitybulletin/test-apps/CVE-2021-0642/Android.bp)11
-rw-r--r--hostsidetests/securitybulletin/test-apps/CVE-2023-20913/AndroidManifest.xml27
-rw-r--r--hostsidetests/securitybulletin/test-apps/CVE-2023-20913/res/values/strings.xml35
-rw-r--r--hostsidetests/securitybulletin/test-apps/CVE-2023-20913/src/android/security/cts/CVE_2023_20913/DeviceTest.java161
-rw-r--r--hostsidetests/securitybulletin/test-apps/CVE-2023-20913/src/android/security/cts/CVE_2023_20913/PocService.java75
-rw-r--r--hostsidetests/securitybulletin/test-apps/CVE-2023-20918/attacker-app/Android.bp35
-rw-r--r--hostsidetests/securitybulletin/test-apps/CVE-2023-20918/attacker-app/AndroidManifest.xml23
-rw-r--r--hostsidetests/securitybulletin/test-apps/CVE-2023-20918/attacker-app/res/values/strings.xml27
-rw-r--r--hostsidetests/securitybulletin/test-apps/CVE-2023-20918/attacker-app/src/android/security/cts/CVE_2023_20918_attacker/ExploitActivity.java83
-rw-r--r--hostsidetests/securitybulletin/test-apps/CVE-2023-20918/test-app/Android.bp40
-rw-r--r--hostsidetests/securitybulletin/test-apps/CVE-2023-20918/test-app/AndroidManifest.xml29
-rw-r--r--hostsidetests/securitybulletin/test-apps/CVE-2023-20918/test-app/res/values/strings.xml31
-rw-r--r--hostsidetests/securitybulletin/test-apps/CVE-2023-20918/test-app/res/xml/file_paths.xml20
-rw-r--r--hostsidetests/securitybulletin/test-apps/CVE-2023-20918/test-app/src/android/security/cts/CVE_2023_20918_test/DeviceTest.java118
-rw-r--r--tests/app/AndroidManifest.xml11
-rw-r--r--tests/app/src/android/app/cts/BaseChainedInstrumentation.java92
-rw-r--r--tests/app/src/android/app/cts/ChainedInstrumentationFirst.java30
-rw-r--r--tests/app/src/android/app/cts/ChainedInstrumentationSecond.java27
-rw-r--r--tests/app/src/android/app/cts/InstrumentationHelperService.java83
-rw-r--r--tests/app/src/android/app/cts/InstrumentationTest.java133
-rw-r--r--tests/tests/security/AndroidManifest.xml20
-rw-r--r--tests/tests/security/res/raw/cve_2022_33234.mkvbin0 -> 38048 bytes
-rw-r--r--tests/tests/security/res/values/strings.xml28
-rw-r--r--tests/tests/security/src/android/security/cts/CVE_2021_0642/CVE_2021_0642.java90
-rw-r--r--tests/tests/security/src/android/security/cts/CVE_2021_0642/PocActivity.java (renamed from hostsidetests/securitybulletin/test-apps/CVE-2021-0642/src/android/security/cts/cve_2021_0642/PocActivity.java)2
-rw-r--r--tests/tests/security/src/android/security/cts/CVE_2021_0642/SecondActivity.java22
-rw-r--r--tests/tests/security/src/android/security/cts/CVE_2022_20456.java208
-rw-r--r--tests/tests/security/src/android/security/cts/StagefrightTest.java6
-rw-r--r--tests/tests/security/src/android/security/cts/WorkSourceTest.java67
67 files changed, 3545 insertions, 324 deletions
diff --git a/hostsidetests/appsecurity/Android.mk b/hostsidetests/appsecurity/Android.mk
index da8b8799969..9fc24099e9e 100644
--- a/hostsidetests/appsecurity/Android.mk
+++ b/hostsidetests/appsecurity/Android.mk
@@ -21,7 +21,7 @@ LOCAL_SRC_FILES := $(call all-java-files-under, src)
LOCAL_MODULE := CtsAppSecurityHostTestCases
-LOCAL_JAVA_LIBRARIES := cts-tradefed tradefed compatibility-host-util
+LOCAL_JAVA_LIBRARIES := cts-tradefed tradefed compatibility-host-util sts-host-util
LOCAL_STATIC_JAVA_LIBRARIES := truth-prebuilt-jar
diff --git a/hostsidetests/appsecurity/src/android/appsecurity/cts/RoleSecurityTest.java b/hostsidetests/appsecurity/src/android/appsecurity/cts/RoleSecurityTest.java
index e86aa574897..2e182eb8349 100644
--- a/hostsidetests/appsecurity/src/android/appsecurity/cts/RoleSecurityTest.java
+++ b/hostsidetests/appsecurity/src/android/appsecurity/cts/RoleSecurityTest.java
@@ -21,7 +21,7 @@ import android.platform.test.annotations.AsbSecurityTest;
import com.android.compatibility.common.tradefed.build.CompatibilityBuildHelper;
import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
-import com.android.tradefed.testtype.junit4.BaseHostJUnit4Test;
+import com.android.sts.common.tradefed.testtype.StsExtraBusinessLogicHostTestBase;
import static org.junit.Assert.assertNull;
import static org.junit.Assume.assumeTrue;
@@ -30,7 +30,7 @@ import org.junit.Test;
import org.junit.runner.RunWith;
@RunWith(DeviceJUnit4ClassRunner.class)
-public class RoleSecurityTest extends BaseHostJUnit4Test {
+public class RoleSecurityTest extends StsExtraBusinessLogicHostTestBase {
private static final String ROLE_SECURITY_TEST_APP_APK = "CtsRoleSecurityTestApp.apk";
private static final String ROLE_SECURITY_TEST_APP_PACKAGE = "com.android.cts.rolesecuritytest";
diff --git a/hostsidetests/securitybulletin/securityPatch/CVE-2021-0484/poc.cpp b/hostsidetests/securitybulletin/securityPatch/CVE-2021-0484/poc.cpp
index a2e4ae58bfd..c06db765f0a 100644
--- a/hostsidetests/securitybulletin/securityPatch/CVE-2021-0484/poc.cpp
+++ b/hostsidetests/securitybulletin/securityPatch/CVE-2021-0484/poc.cpp
@@ -1,5 +1,5 @@
/**
- * Copyright (C) 2021 The Android Open Source Project
+ * Copyright (C) 2022 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.
@@ -18,49 +18,37 @@
#include <media/mediaplayer.h>
#include "../includes/common.h"
-#define PREPARE_DRM 38
-
using namespace android;
int main() {
+ constexpr size_t bufferSize = 16;
+ constexpr uint32_t prepareDrm = 38;
+ constexpr uint32_t unknownTrxnCode = prepareDrm + 5;
sp<IServiceManager> serviceManager = defaultServiceManager();
- if (serviceManager == nullptr) {
- return EXIT_FAILURE;
- }
+ FAIL_CHECK(serviceManager != nullptr);
sp<IBinder> mediaPlayerService = serviceManager->getService(String16("media.player"));
- if (mediaPlayerService == nullptr) {
- return EXIT_FAILURE;
- }
+ FAIL_CHECK(mediaPlayerService != nullptr);
sp<IMediaPlayerService> iMediaPlayerService =
IMediaPlayerService::asInterface(mediaPlayerService);
- if (iMediaPlayerService == nullptr) {
- return EXIT_FAILURE;
- }
+ FAIL_CHECK(iMediaPlayerService != nullptr);
- MediaPlayer *mediaPlayer = new MediaPlayer();
- if (mediaPlayer == nullptr) {
- return EXIT_FAILURE;
- }
+ sp<MediaPlayer> mediaPlayer = new MediaPlayer();
+ FAIL_CHECK(mediaPlayer != nullptr);
sp<IMediaPlayer> iMediaPlayer = iMediaPlayerService->create(mediaPlayer);
- if (iMediaPlayer == nullptr) {
- delete (mediaPlayer);
- return EXIT_FAILURE;
- }
+ FAIL_CHECK(iMediaPlayer != nullptr);
Parcel data, reply;
data.writeInterfaceToken(iMediaPlayer->getInterfaceDescriptor());
- const uint8_t arr[16] = {};
- data.write(arr, 16);
- data.writeUint32(2);
- data.writeUnpadded(arr, 1);
-
- IMediaPlayer::asBinder(iMediaPlayer)->transact(PREPARE_DRM, data, &reply);
- uint32_t size = 0;
- reply.readUint32(&size);
-
- delete (mediaPlayer);
- return (size > 0) ? EXIT_VULNERABLE : EXIT_SUCCESS;
+ status_t status = IMediaPlayer::asBinder(iMediaPlayer)->transact(unknownTrxnCode, data, &reply);
+ FAIL_CHECK(status == UNKNOWN_TRANSACTION);
+
+ const uint8_t arr[bufferSize] = {};
+ data.write(arr, bufferSize);
+ data.writeUint32(bufferSize);
+ data.writeUnpadded(arr, bufferSize - 1);
+ status = IMediaPlayer::asBinder(iMediaPlayer)->transact(prepareDrm, data, &reply);
+ return status == OK ? EXIT_VULNERABLE : EXIT_SUCCESS;
}
diff --git a/hostsidetests/securitybulletin/src/android/security/cts/AdbUtils.java b/hostsidetests/securitybulletin/src/android/security/cts/AdbUtils.java
index 17b9b6a7d35..6289a52f39c 100644
--- a/hostsidetests/securitybulletin/src/android/security/cts/AdbUtils.java
+++ b/hostsidetests/securitybulletin/src/android/security/cts/AdbUtils.java
@@ -30,6 +30,11 @@ import com.android.sts.common.tradefed.testtype.SecurityTestCase;
import com.android.tradefed.device.DeviceNotAvailableException;
import com.android.tradefed.device.ITestDevice;
import com.android.tradefed.log.LogUtil.CLog;
+
+import org.json.JSONArray;
+import org.json.JSONException;
+import org.json.JSONObject;
+
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileOutputStream;
@@ -40,13 +45,9 @@ import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.Map;
-import java.util.Scanner;
import java.util.concurrent.TimeUnit;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
-import org.json.JSONArray;
-import org.json.JSONException;
-import org.json.JSONObject;
public class AdbUtils {
@@ -60,6 +61,10 @@ public class AdbUtils {
final static Pattern regexSpecialCharsEscapedPattern =
Pattern.compile("[" + regexSpecialCharsEscaped + "]");
+ /**
+ * @deprecated Use {@link NativePoc} instead.
+ */
+ @Deprecated
public static class pocConfig {
String binaryName;
String arguments;
@@ -76,12 +81,15 @@ public class AdbUtils {
}
}
- /** Runs a commandline on the specified device
+ /**
+ * Runs a commandline on the specified device
*
+ * @deprecated Use {@link CommandUtil} instead.
* @param command the command to be ran
* @param device device for the command to be ran on
* @return the console output from running the command
*/
+ @Deprecated
public static String runCommandLine(String command, ITestDevice device) throws Exception {
if ("reboot".equals(command)) {
throw new IllegalArgumentException(
@@ -93,10 +101,12 @@ public class AdbUtils {
/**
* Pushes and runs a binary to the selected device
*
+ * @deprecated Use {@link NativePoc} instead.
* @param pocName name of the poc binary
* @param device device to be ran on
* @return the console output from the binary
*/
+ @Deprecated
public static String runPoc(String pocName, ITestDevice device) throws Exception {
return runPoc(pocName, device, SecurityTestCase.TIMEOUT_NONDETERMINISTIC);
}
@@ -104,11 +114,13 @@ public class AdbUtils {
/**
* Pushes and runs a binary to the selected device
*
+ * @deprecated Use {@link NativePoc} instead.
* @param pocName name of the poc binary
* @param device device to be ran on
* @param timeout time to wait for output in seconds
* @return the console output from the binary
*/
+ @Deprecated
public static String runPoc(String pocName, ITestDevice device, int timeout) throws Exception {
return runPoc(pocName, device, timeout, null);
}
@@ -116,12 +128,14 @@ public class AdbUtils {
/**
* Pushes and runs a binary to the selected device
*
+ * @deprecated Use {@link NativePoc} instead.
* @param pocName name of the poc binary
* @param device device to be ran on
* @param timeout time to wait for output in seconds
* @param arguments the input arguments for the poc
* @return the console output from the binary
*/
+ @Deprecated
public static String runPoc(String pocName, ITestDevice device, int timeout, String arguments)
throws Exception {
CollectingOutputReceiver receiver = new CollectingOutputReceiver();
@@ -132,48 +146,57 @@ public class AdbUtils {
/**
* Pushes and runs a binary to the selected device and ignores any of its output.
*
+ * @deprecated Use {@link NativePoc} instead.
* @param pocName name of the poc binary
* @param device device to be ran on
* @param timeout time to wait for output in seconds
*/
+ @Deprecated
public static void runPocNoOutput(String pocName, ITestDevice device, int timeout)
throws Exception {
runPocNoOutput(pocName, device, timeout, null);
}
/**
- * Pushes and runs a binary with arguments to the selected device and
- * ignores any of its output.
+ * Pushes and runs a binary with arguments to the selected device and ignores any of its output.
*
+ * @deprecated Use {@link NativePoc} instead.
* @param pocName name of the poc binary
* @param device device to be ran on
* @param timeout time to wait for output in seconds
* @param arguments input arguments for the poc
*/
- public static void runPocNoOutput(String pocName, ITestDevice device, int timeout,
- String arguments) throws Exception {
+ @Deprecated
+ public static void runPocNoOutput(
+ String pocName, ITestDevice device, int timeout, String arguments) throws Exception {
runPoc(pocName, device, timeout, arguments, null);
}
/**
- * Pushes and runs a binary with arguments to the selected device and
- * ignores any of its output.
+ * Pushes and runs a binary with arguments to the selected device and ignores any of its output.
*
+ * @deprecated Use {@link NativePoc} instead.
* @param pocName name of the poc binary
* @param device device to be ran on
* @param timeout time to wait for output in seconds
* @param arguments input arguments for the poc
* @param receiver the type of receiver to run against
*/
- public static int runPoc(String pocName, ITestDevice device, int timeout,
- String arguments, IShellOutputReceiver receiver) throws Exception {
+ @Deprecated
+ public static int runPoc(
+ String pocName,
+ ITestDevice device,
+ int timeout,
+ String arguments,
+ IShellOutputReceiver receiver)
+ throws Exception {
return runPoc(pocName, device, timeout, arguments, null, receiver);
}
/**
- * Pushes and runs a binary with arguments to the selected device and
- * ignores any of its output.
+ * Pushes and runs a binary with arguments to the selected device and ignores any of its output.
*
+ * @deprecated Use {@link NativePoc} instead.
* @param pocName name of the poc binary
* @param device device to be ran on
* @param timeout time to wait for output in seconds
@@ -181,9 +204,15 @@ public class AdbUtils {
* @param envVars run the poc with environment variables
* @param receiver the type of receiver to run against
*/
- public static int runPoc(String pocName, ITestDevice device, int timeout,
- String arguments, Map<String, String> envVars,
- IShellOutputReceiver receiver) throws Exception {
+ @Deprecated
+ public static int runPoc(
+ String pocName,
+ ITestDevice device,
+ int timeout,
+ String arguments,
+ Map<String, String> envVars,
+ IShellOutputReceiver receiver)
+ throws Exception {
String remoteFile = String.format("%s%s", TMP_PATH, pocName);
SecurityTestCase.getPocPusher(device).pushFile(pocName, remoteFile);
@@ -239,9 +268,12 @@ public class AdbUtils {
/**
* Assert the poc is executable
+ *
+ * @deprecated Use {@link NativePoc} instead.
* @param pocName name of the poc binary
* @param device device to be ran on
*/
+ @Deprecated
private static void assertPocExecutable(String pocName, ITestDevice device) throws Exception {
String fullPocPath = TMP_PATH + pocName;
device.executeShellCommand("chmod 777 " + fullPocPath);
@@ -348,7 +380,10 @@ public class AdbUtils {
}
/**
* Utility function to help check the exit code of a shell command
+ *
+ * @deprecated Use {@link CommandUtil} instead.
*/
+ @Deprecated
public static int runCommandGetExitCode(String cmd, ITestDevice device) throws Exception {
long time = System.currentTimeMillis();
String exitStatusString = runCommandLine(
@@ -370,16 +405,17 @@ public class AdbUtils {
}
/**
- * Pushes and runs a binary to the selected device and checks exit code
- * Return code 113 is used to indicate the vulnerability
+ * Pushes and runs a binary to the selected device and checks exit code Return code 113 is used
+ * to indicate the vulnerability
*
+ * @deprecated Use {@link NativePoc} instead.
* @param pocName a string path to poc from the /res folder
* @param device device to be ran on
* @param timeout time to wait for output in seconds
*/
@Deprecated
- public static boolean runPocCheckExitCode(String pocName, ITestDevice device,
- int timeout) throws Exception {
+ public static boolean runPocCheckExitCode(String pocName, ITestDevice device, int timeout)
+ throws Exception {
//Refer to go/asdl-sts-guide Test section for knowing the significance of 113 code
return runPocGetExitStatus(pocName, device, timeout) == 113;
@@ -387,11 +423,13 @@ public class AdbUtils {
/**
* Pushes and runs a binary to the device and returns the exit status.
+ *
+ * @deprecated Use {@link NativePoc} instead.
* @param pocName a string path to poc from the /res folder
* @param device device to be ran on
* @param timeout time to wait for output in seconds
-
*/
+ @Deprecated
public static int runPocGetExitStatus(String pocName, ITestDevice device, int timeout)
throws Exception {
return runPocGetExitStatus(pocName, null, device, timeout);
@@ -399,36 +437,49 @@ public class AdbUtils {
/**
* Pushes and runs a binary to the device and returns the exit status.
+ *
+ * @deprecated Use {@link NativePoc} instead.
* @param pocName a string path to poc from the /res folder
* @param arguments input arguments for the poc
* @param device device to be ran on
* @param timeout time to wait for output in seconds
*/
- public static int runPocGetExitStatus(String pocName, String arguments, ITestDevice device,
- int timeout) throws Exception {
+ @Deprecated
+ public static int runPocGetExitStatus(
+ String pocName, String arguments, ITestDevice device, int timeout) throws Exception {
return runPocGetExitStatus(pocName, arguments, null, device, timeout);
}
/**
* Pushes and runs a binary to the device and returns the exit status.
+ *
+ * @deprecated Use {@link NativePoc} instead.
* @param pocName name of the poc binary
* @param arguments input arguments for the poc
* @param envVars run the poc with environment variables
* @param device device to be run on
* @param timeout time to wait for output in seconds
*/
+ @Deprecated
public static int runPocGetExitStatus(
- String pocName, String arguments, Map<String, String> envVars,
- ITestDevice device, int timeout) throws Exception {
+ String pocName,
+ String arguments,
+ Map<String, String> envVars,
+ ITestDevice device,
+ int timeout)
+ throws Exception {
return runPoc(pocName, device, timeout, arguments, envVars, null);
}
/**
* Pushes and runs a binary and asserts that the exit status isn't 113: vulnerable.
+ *
+ * @deprecated Use {@link NativePoc} instead.
* @param pocName a string path to poc from the /res folder
* @param device device to be ran on
* @param timeout time to wait for output in seconds
*/
+ @Deprecated
public static void runPocAssertExitStatusNotVulnerable(
String pocName, ITestDevice device, int timeout) throws Exception {
runPocAssertExitStatusNotVulnerable(pocName, null, device, timeout);
@@ -436,27 +487,37 @@ public class AdbUtils {
/**
* Pushes and runs a binary and asserts that the exit status isn't 113: vulnerable.
+ *
+ * @deprecated Use {@link NativePoc} instead.
* @param pocName a string path to poc from the /res folder
* @param arguments input arguments for the poc
* @param device device to be ran on
* @param timeout time to wait for output in seconds
*/
- public static void runPocAssertExitStatusNotVulnerable(String pocName, String arguments,
- ITestDevice device, int timeout) throws Exception {
+ @Deprecated
+ public static void runPocAssertExitStatusNotVulnerable(
+ String pocName, String arguments, ITestDevice device, int timeout) throws Exception {
runPocAssertExitStatusNotVulnerable(pocName, arguments, null, device, timeout);
}
/**
* Pushes and runs a binary and asserts that the exit status isn't 113: vulnerable.
+ *
+ * @deprecated Use {@link NativePoc} instead.
* @param pocName name of the poc binary
* @param arguments input arguments for the poc
* @param envVars run the poc with environment variables
* @param device device to be ran on
* @param timeout time to wait for output in seconds
*/
+ @Deprecated
public static void runPocAssertExitStatusNotVulnerable(
- String pocName, String arguments, Map<String, String> envVars,
- ITestDevice device, int timeout) throws Exception {
+ String pocName,
+ String arguments,
+ Map<String, String> envVars,
+ ITestDevice device,
+ int timeout)
+ throws Exception {
assertTrue("PoC returned exit status 113: vulnerable",
runPocGetExitStatus(pocName, arguments, envVars, device, timeout) != 113);
}
@@ -496,12 +557,15 @@ public class AdbUtils {
/**
* Runs the poc binary and asserts that there are no security crashes that match the expected
* process pattern.
+ *
+ * @deprecated Use {@link NativePoc} instead.
* @param pocName a string path to poc from the /res folder
* @param device device to be ran on
* @param processPatternStrings a Pattern string to match the crash tombstone process
*/
- public static void runPocAssertNoCrashes(String pocName, ITestDevice device,
- String... processPatternStrings) throws Exception {
+ @Deprecated
+ public static void runPocAssertNoCrashes(
+ String pocName, ITestDevice device, String... processPatternStrings) throws Exception {
runPocAssertNoCrashes(pocName, device,
new CrashUtils.Config().setProcessPatterns(processPatternStrings));
}
@@ -509,25 +573,32 @@ public class AdbUtils {
/**
* Runs the poc binary and asserts that there are no security crashes that match the expected
* process pattern.
+ *
+ * @deprecated Use {@link NativePoc} instead.
* @param pocName a string path to poc from the /res folder
* @param device device to be ran on
* @param config a crash parser configuration
*/
- public static void runPocAssertNoCrashes(String pocName, ITestDevice device,
- CrashUtils.Config config) throws Exception {
+ @Deprecated
+ public static void runPocAssertNoCrashes(
+ String pocName, ITestDevice device, CrashUtils.Config config) throws Exception {
runPocAssertNoCrashes(pocName, device, null, config);
}
/**
* Runs the poc binary and asserts that there are no security crashes that match the expected
* process pattern, including arguments when running.
+ *
+ * @deprecated Use {@link NativePoc} instead.
* @param pocName a string path to poc from the /res folder
* @param device device to be ran on
* @param arguments input arguments for the poc
* @param config a crash parser configuration
*/
- public static void runPocAssertNoCrashes(String pocName, ITestDevice device, String arguments,
- CrashUtils.Config config) throws Exception {
+ @Deprecated
+ public static void runPocAssertNoCrashes(
+ String pocName, ITestDevice device, String arguments, CrashUtils.Config config)
+ throws Exception {
AdbUtils.runCommandLine("logcat -c", device);
AdbUtils.runPocNoOutput(pocName, device,
SecurityTestCase.TIMEOUT_NONDETERMINISTIC, arguments);
@@ -535,97 +606,115 @@ public class AdbUtils {
}
/**
- * Runs the poc binary and asserts following 2 conditions.
- * 1. There are no security crashes in the binary.
- * 2. The exit status isn't 113 (Code 113 is used to indicate the vulnerability condition).
+ * Runs the poc binary and asserts following 2 conditions. 1. There are no security crashes in
+ * the binary. 2. The exit status isn't 113 (Code 113 is used to indicate the vulnerability
+ * condition).
*
+ * @deprecated Use {@link NativePoc} instead.
* @param binaryName name of the binary
* @param arguments arguments for running the binary
* @param device device to be run on
*/
- public static void runPocAssertNoCrashesNotVulnerable(String binaryName, String arguments,
- ITestDevice device) throws Exception {
+ @Deprecated
+ public static void runPocAssertNoCrashesNotVulnerable(
+ String binaryName, String arguments, ITestDevice device) throws Exception {
runPocAssertNoCrashesNotVulnerable(binaryName, arguments, null, null, device, null);
}
/**
- * Runs the poc binary and asserts following 2 conditions.
- * 1. There are no security crashes in the binary.
- * 2. The exit status isn't 113 (Code 113 is used to indicate the vulnerability condition).
+ * Runs the poc binary and asserts following 2 conditions. 1. There are no security crashes in
+ * the binary. 2. The exit status isn't 113 (Code 113 is used to indicate the vulnerability
+ * condition).
*
+ * @deprecated Use {@link NativePoc} instead.
* @param binaryName name of the binary
* @param arguments arguments for running the binary
* @param device device to be run on
- * @param processPatternStrings a Pattern string to match the crash tombstone
- * process
+ * @param processPatternStrings a Pattern string to match the crash tombstone process
*/
- public static void runPocAssertNoCrashesNotVulnerable(String binaryName, String arguments,
- ITestDevice device, String processPatternStrings[]) throws Exception {
+ @Deprecated
+ public static void runPocAssertNoCrashesNotVulnerable(
+ String binaryName, String arguments, ITestDevice device, String processPatternStrings[])
+ throws Exception {
runPocAssertNoCrashesNotVulnerable(binaryName, arguments, null, null, device,
processPatternStrings);
}
/**
- * Runs the poc binary and asserts following 2 conditions.
- * 1. There are no security crashes in the binary.
- * 2. The exit status isn't 113 (Code 113 is used to indicate the vulnerability condition).
+ * Runs the poc binary and asserts following 2 conditions. 1. There are no security crashes in
+ * the binary. 2. The exit status isn't 113 (Code 113 is used to indicate the vulnerability
+ * condition).
*
+ * @deprecated Use {@link NativePoc} instead.
* @param binaryName name of the binary
* @param arguments arguments for running the binary
* @param inputFiles files required as input
- * @param inputFilesDestination destination directory to which input files are
- * pushed
+ * @param inputFilesDestination destination directory to which input files are pushed
* @param device device to be run on
*/
- public static void runPocAssertNoCrashesNotVulnerable(String binaryName, String arguments,
- String inputFiles[], String inputFilesDestination, ITestDevice device)
+ @Deprecated
+ public static void runPocAssertNoCrashesNotVulnerable(
+ String binaryName,
+ String arguments,
+ String inputFiles[],
+ String inputFilesDestination,
+ ITestDevice device)
throws Exception {
runPocAssertNoCrashesNotVulnerable(binaryName, arguments, inputFiles, inputFilesDestination,
device, null);
}
/**
- * Runs the poc binary and asserts following 3 conditions.
- * 1. There are no security crashes in the binary.
- * 2. There are no security crashes that match the expected process pattern.
- * 3. The exit status isn't 113 (Code 113 is used to indicate the vulnerability condition).
+ * Runs the poc binary and asserts following 3 conditions. 1. There are no security crashes in
+ * the binary. 2. There are no security crashes that match the expected process pattern. 3. The
+ * exit status isn't 113 (Code 113 is used to indicate the vulnerability condition).
*
+ * @deprecated Use {@link NativePoc} instead.
* @param binaryName name of the binary
* @param arguments arguments for running the binary
* @param inputFiles files required as input
- * @param inputFilesDestination destination directory to which input files are
- * pushed
+ * @param inputFilesDestination destination directory to which input files are pushed
* @param device device to be run on
- * @param processPatternStrings a Pattern string to match the crash tombstone
- * process
+ * @param processPatternStrings a Pattern string to match the crash tombstone process
*/
- public static void runPocAssertNoCrashesNotVulnerable(String binaryName, String arguments,
- String inputFiles[], String inputFilesDestination, ITestDevice device,
- String processPatternStrings[]) throws Exception {
+ @Deprecated
+ public static void runPocAssertNoCrashesNotVulnerable(
+ String binaryName,
+ String arguments,
+ String inputFiles[],
+ String inputFilesDestination,
+ ITestDevice device,
+ String processPatternStrings[])
+ throws Exception {
runPocAssertNoCrashesNotVulnerable(binaryName, arguments, null,
inputFiles, inputFilesDestination, device, processPatternStrings);
}
/**
- * Runs the poc binary and asserts following 3 conditions.
- * 1. There are no security crashes in the binary.
- * 2. There are no security crashes that match the expected process pattern.
- * 3. The exit status isn't 113 (Code 113 is used to indicate the vulnerability condition).
+ * Runs the poc binary and asserts following 3 conditions. 1. There are no security crashes in
+ * the binary. 2. There are no security crashes that match the expected process pattern. 3. The
+ * exit status isn't 113 (Code 113 is used to indicate the vulnerability condition).
*
+ * @deprecated Use {@link NativePoc} instead.
* @param binaryName name of the binary
* @param arguments arguments for running the binary
* @param envVars run the poc with environment variables
* @param inputFiles files required as input
- * @param inputFilesDestination destination directory to which input files are
- * pushed
+ * @param inputFilesDestination destination directory to which input files are pushed
* @param device device to be run on
* @param processPatternStrings a Pattern string (other than binary name) to match the crash
- * tombstone process
+ * tombstone process
*/
+ @Deprecated
public static void runPocAssertNoCrashesNotVulnerable(
- String binaryName, String arguments, Map<String, String> envVars,
- String inputFiles[], String inputFilesDestination, ITestDevice device,
- String... processPatternStrings) throws Exception {
+ String binaryName,
+ String arguments,
+ Map<String, String> envVars,
+ String inputFiles[],
+ String inputFilesDestination,
+ ITestDevice device,
+ String... processPatternStrings)
+ throws Exception {
pocConfig testConfig = new pocConfig(binaryName, device);
testConfig.arguments = arguments;
testConfig.envVars = envVars;
@@ -649,13 +738,14 @@ public class AdbUtils {
}
/**
- * Runs the poc binary and asserts following 3 conditions.
- * 1. There are no security crashes in the binary.
- * 2. There are no security crashes that match the expected process pattern.
- * 3. The exit status isn't 113 (Code 113 is used to indicate the vulnerability condition).
+ * Runs the poc binary and asserts following 3 conditions. 1. There are no security crashes in
+ * the binary. 2. There are no security crashes that match the expected process pattern. 3. The
+ * exit status isn't 113 (Code 113 is used to indicate the vulnerability condition).
*
+ * @deprecated Use {@link NativePoc} instead.
* @param testConfig test configuration
*/
+ @Deprecated
public static void runPocAssertNoCrashesNotVulnerable(pocConfig testConfig) throws Exception {
String[] inputFiles = null;
if(!testConfig.inputFiles.isEmpty()) {
@@ -689,11 +779,14 @@ public class AdbUtils {
/**
* Dumps logcat and asserts that there are no security crashes that match the expected process.
- * By default, checks min crash addresses
- * pattern. Ensure that adb logcat -c is called beforehand.
+ * By default, checks min crash addresses pattern. Ensure that adb logcat -c is called
+ * beforehand.
+ *
+ * @deprecated Use {@link TombstoneUtils} instead.
* @param device device to be ran on
* @param processPatternStrings a Pattern string to match the crash tombstone process
*/
+ @Deprecated
public static void assertNoCrashes(ITestDevice device, String... processPatternStrings)
throws Exception {
assertNoCrashes(device, new CrashUtils.Config().setProcessPatterns(processPatternStrings));
@@ -702,11 +795,14 @@ public class AdbUtils {
/**
* Dumps logcat and asserts that there are no security crashes that match the expected process
* pattern. Ensure that adb logcat -c is called beforehand.
+ *
* @param device device to be ran on
* @param config a crash parser configuration
+ * @deprecated Use {@link TombstoneUtils} instead.
*/
- public static void assertNoCrashes(ITestDevice device,
- CrashUtils.Config config) throws Exception {
+ @Deprecated
+ public static void assertNoCrashes(ITestDevice device, CrashUtils.Config config)
+ throws Exception {
String logcat = AdbUtils.runCommandLine("logcat -d *:S DEBUG:V", device);
JSONArray crashes = CrashUtils.addAllCrashes(logcat, new JSONArray());
diff --git a/hostsidetests/securitybulletin/src/android/security/cts/Bug_248251018.java b/hostsidetests/securitybulletin/src/android/security/cts/Bug_248251018.java
new file mode 100644
index 00000000000..4b8389e7103
--- /dev/null
+++ b/hostsidetests/securitybulletin/src/android/security/cts/Bug_248251018.java
@@ -0,0 +1,45 @@
+/*
+ * Copyright (C) 2020 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.Assert.*;
+
+import android.platform.test.annotations.AsbSecurityTest;
+import com.android.sts.common.tradefed.testtype.NonRootSecurityTestCase;
+import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+@RunWith(DeviceJUnit4ClassRunner.class)
+public class Bug_248251018 extends NonRootSecurityTestCase {
+
+ @Test
+ @AsbSecurityTest(cveBugId = 248251018)
+ public void testEmergencyInfo_cannotInteractAcrossUsers() throws Exception {
+ String packageList =
+ getDevice()
+ .executeShellV2Command("pm list package com.android.emergency")
+ .getStdout();
+ if (!packageList.isEmpty()) {
+ String result =
+ getDevice()
+ .executeShellV2Command("dumpsys package com.android.emergency")
+ .getStdout();
+ assertFalse(result.contains("android.permission.INTERACT_ACROSS_USERS_FULL"));
+ }
+ }
+}
diff --git a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_0484.java b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_0484.java
index c98dc5e2153..c47c5bea32b 100644
--- a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_0484.java
+++ b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_0484.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2021 The Android Open Source Project
+ * Copyright (C) 2022 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.
@@ -17,8 +17,10 @@
package android.security.cts;
import android.platform.test.annotations.AsbSecurityTest;
+
import com.android.sts.common.tradefed.testtype.NonRootSecurityTestCase;
import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
+
import org.junit.Test;
import org.junit.runner.RunWith;
@@ -28,12 +30,12 @@ public class CVE_2021_0484 extends NonRootSecurityTestCase {
/**
* b/173720767
* Vulnerability Behavior: EXIT_VULNERABLE (113)
+ * Vulnerable library : libmedia
+ * Is Play managed : No
*/
@Test
@AsbSecurityTest(cveBugId = 173720767)
public void testPocCVE_2021_0484() throws Exception {
- AdbUtils.pocConfig testConfig = new AdbUtils.pocConfig("CVE-2021-0484", getDevice());
- testConfig.checkCrash = false;
- AdbUtils.runPocAssertNoCrashesNotVulnerable(testConfig);
+ AdbUtils.runPocAssertExitStatusNotVulnerable("CVE-2021-0484", getDevice(), 300);
}
}
diff --git a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_0963.java b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_0963.java
new file mode 100644
index 00000000000..90d8196c3f6
--- /dev/null
+++ b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_0963.java
@@ -0,0 +1,68 @@
+/*
+ * Copyright (C) 2022 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.assumeNoException;
+
+import android.platform.test.annotations.AsbSecurityTest;
+
+import com.android.sts.common.tradefed.testtype.StsExtraBusinessLogicHostTestBase;
+import com.android.tradefed.device.ITestDevice;
+import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+@RunWith(DeviceJUnit4ClassRunner.class)
+public class CVE_2021_0963 extends StsExtraBusinessLogicHostTestBase {
+ static final String TEST_PKG = "android.security.cts.CVE_2021_0963";
+
+ /**
+ * b/199754277
+ * Vulnerable app : KeyChain.apk
+ * Vulnerable module : com.android.keychain
+ * Is Play managed : No
+ */
+ @AsbSecurityTest(cveBugId = 199754277)
+ @Test
+ public void testPocCVE_2021_0963() {
+ try {
+ ITestDevice device = getDevice();
+
+ /* Wake up the device */
+ AdbUtils.runCommandLine("input keyevent KEYCODE_WAKEUP", device);
+ AdbUtils.runCommandLine("input keyevent KEYCODE_MENU", device);
+ AdbUtils.runCommandLine("input keyevent KEYCODE_HOME", device);
+
+ /* Install the application */
+ installPackage("CVE-2021-0963.apk");
+
+ /*
+ * Set device as owner. After the test is completed, this change is reverted in the
+ * DeviceTest.java's tearDown() method by calling clearDeviceOwnerApp() on an instance
+ * of DevicePolicyManager.
+ */
+ AdbUtils.runCommandLine("dpm set-device-owner --user 0 '" + TEST_PKG + "/" + TEST_PKG
+ + ".PocDeviceAdminReceiver" + "'", device);
+
+ /* Run the device test "testOverlayButtonPresence" */
+ runDeviceTests(TEST_PKG, TEST_PKG + "." + "DeviceTest", "testOverlayButtonPresence");
+ } catch (Exception e) {
+ assumeNoException(e);
+ }
+ }
+}
diff --git a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2022_20112.java b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2022_20112.java
new file mode 100644
index 00000000000..cc9d347c8f7
--- /dev/null
+++ b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2022_20112.java
@@ -0,0 +1,88 @@
+/*
+ * Copyright (C) 2022 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.assumeNoException;
+import static org.junit.Assume.assumeTrue;
+
+import android.platform.test.annotations.AsbSecurityTest;
+
+import com.android.sts.common.tradefed.testtype.RootSecurityTestCase;
+import com.android.tradefed.device.ITestDevice;
+import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+@RunWith(DeviceJUnit4ClassRunner.class)
+public class CVE_2022_20112 extends RootSecurityTestCase {
+
+ // b/206987762
+ // Vulnerable module : com.android.settings
+ // Vulnerable apk : Settings.apk
+ // Is play managed : No
+ @AsbSecurityTest(cveBugId = 206987762)
+ @Test
+ public void testPocCVE_2022_20112() {
+ final String testPkg = "android.security.cts.CVE_2022_20112";
+ ITestDevice device = null;
+ int currentUser = -1;
+ int newUser = -1;
+ try {
+ device = getDevice();
+
+ // Device wakeup and unlock
+ AdbUtils.runCommandLine("input keyevent KEYCODE_WAKEUP", device);
+ AdbUtils.runCommandLine("wm dismiss-keyguard", device);
+
+ // Get current user
+ currentUser = device.getCurrentUser();
+
+ // Create new guest user 'CTSUser' for test
+ newUser = device.createUser("CTSUser", true, false);
+
+ // Start new guest user 'CTSUser'
+ assumeTrue("Unable to create new guest user", device.startUser(newUser, true));
+
+ // Switch to new user 'CTSUser'
+ assumeTrue("Unable to switch to guest user", device.switchUser(newUser));
+
+ // Install PoC application
+ installPackage("CVE-2022-20112.apk");
+
+ runDeviceTests(testPkg, testPkg + ".DeviceTest", "testprivateDnsPreferenceController");
+ } catch (Exception e) {
+ assumeNoException(e);
+ } finally {
+ try {
+ if (currentUser != -1) {
+ // Switch back to previous user
+ device.switchUser(currentUser);
+ }
+ if (newUser != -1) {
+ // Stop user 'CTSUser'
+ device.stopUser(newUser);
+
+ // Remove user 'CTSUser'
+ device.removeUser(newUser);
+ }
+ } catch (Exception e) {
+ // Ignore exception here
+ }
+ }
+ }
+}
diff --git a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2022_20197.java b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2022_20197.java
index 3d31cee17c7..98befd4884a 100644
--- a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2022_20197.java
+++ b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2022_20197.java
@@ -16,18 +16,18 @@
package android.security.cts;
+import static com.android.sts.common.SystemUtil.withSetting;
+
import static org.junit.Assume.assumeNoException;
import android.platform.test.annotations.AsbSecurityTest;
import com.android.sts.common.tradefed.testtype.NonRootSecurityTestCase;
-import com.android.tradefed.device.ITestDevice;
import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
import org.junit.Test;
import org.junit.runner.RunWith;
-
@RunWith(DeviceJUnit4ClassRunner.class)
public class CVE_2022_20197 extends NonRootSecurityTestCase {
private static final String TEST_PKG = "android.security.cts.CVE_2022_20197";
@@ -35,37 +35,11 @@ public class CVE_2022_20197 extends NonRootSecurityTestCase {
@AsbSecurityTest(cveBugId = 208279300)
@Test
public void testPocCVE_2022_20197() {
- ITestDevice device = null;
- boolean isPolicyPresent = true;
- boolean isHiddenApiEnabled = true;
- String status = "";
- try {
- device = getDevice();
+ try (AutoCloseable a = withSetting(getDevice(), "global", "hidden_api_policy", "1")) {
installPackage("CVE-2022-20197.apk");
-
- status = AdbUtils.runCommandLine("settings get global hidden_api_policy", device);
- if (status.toLowerCase().contains("null")) {
- isPolicyPresent = false;
- } else if (!status.toLowerCase().contains("1")) {
- isHiddenApiEnabled = false;
- }
- if (!isPolicyPresent || !isHiddenApiEnabled) {
- AdbUtils.runCommandLine("settings put global hidden_api_policy 1", device);
- }
runDeviceTests(TEST_PKG, TEST_PKG + ".DeviceTest", "testParcel");
} catch (Exception e) {
assumeNoException(e);
- } finally {
- try {
- if (!isPolicyPresent) {
- AdbUtils.runCommandLine("settings delete global hidden_api_policy", device);
- } else if (!isHiddenApiEnabled) {
- AdbUtils.runCommandLine("settings put global hidden_api_policy " + status,
- device);
- }
- } catch (Exception e) {
- // ignore all exceptions.
- }
}
}
}
diff --git a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2022_20360.java b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2022_20360.java
new file mode 100644
index 00000000000..0568740ce20
--- /dev/null
+++ b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2022_20360.java
@@ -0,0 +1,87 @@
+/*
+ * Copyright (C) 2022 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.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.testtype.DeviceJUnit4ClassRunner;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+@RunWith(DeviceJUnit4ClassRunner.class)
+public class CVE_2022_20360 extends NonRootSecurityTestCase {
+
+ // b/228314987
+ // Vulnerable apk : Settings.apk
+ // Vulnerable module : com.android.settings
+ // Is Play managed : No
+ @AsbSecurityTest(cveBugId = 228314987)
+ @Test
+ public void testPocCVE_2022_20360() {
+ final String testPkg = "android.security.cts.CVE_2022_20360";
+ ITestDevice device = null;
+ int currentUser = -1;
+ int newUser = -1;
+ try {
+ device = getDevice();
+
+ // Check if device supports nfc
+ assumeTrue("Device does not support nfc", device.hasFeature("android.hardware.nfc"));
+
+ // Get current user
+ currentUser = device.getCurrentUser();
+
+ // Create new guest user 'CTSUser' for test
+ newUser = device.createUser("CTSUser", true, false);
+
+ // Start new guest user 'CTSUser'
+ assumeTrue("Unable to create new guest user", device.startUser(newUser, true));
+
+ // Switch to new user 'CTSUser'
+ assumeTrue("Unable to switch to guest user", device.switchUser(newUser));
+
+ // Install test-app
+ installPackage("CVE-2022-20360.apk", "--user " + newUser);
+
+ runDeviceTests(testPkg, testPkg + ".DeviceTest", "testSecureNfcPreferenceController");
+ } catch (Exception e) {
+ assumeNoException(e);
+ } finally {
+ try {
+ if (currentUser != -1) {
+ // Switch back to previous user
+ device.switchUser(currentUser);
+ }
+ if (newUser != -1) {
+ // Stop user 'CTSUser'
+ device.stopUser(newUser);
+
+ // Remove user 'CTSUser'
+ device.removeUser(newUser);
+ }
+ } catch (Exception e) {
+ // Ignore exception here
+ }
+ }
+ }
+}
diff --git a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2022_20415.java b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2022_20415.java
new file mode 100644
index 00000000000..511cbd4ac45
--- /dev/null
+++ b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2022_20415.java
@@ -0,0 +1,49 @@
+/*
+ * 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.assumeNoException;
+
+import android.platform.test.annotations.AsbSecurityTest;
+
+import com.android.sts.common.tradefed.testtype.NonRootSecurityTestCase;
+import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+@RunWith(DeviceJUnit4ClassRunner.class)
+public class CVE_2022_20415 extends NonRootSecurityTestCase {
+
+ // b/231322873
+ // Vulnerable app : SystemUI.apk
+ // Vulnerable module : com.android.systemui
+ // Is Play managed : No
+ @AsbSecurityTest(cveBugId = 231322873)
+ @Test
+ public void testPocCVE_2022_20415() {
+ try {
+ final String testPkg = "android.security.cts.CVE_2022_20415";
+
+ // Install the test-app
+ installPackage("CVE-2022-20415.apk");
+ runDeviceTests(testPkg, testPkg + "." + "DeviceTest", "testFullScreenIntent");
+ } catch (Exception e) {
+ assumeNoException(e);
+ }
+ }
+}
diff --git a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_0642.java b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2023_20913.java
index 2e1ddda5360..5e4da6900af 100644
--- a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_0642.java
+++ b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2023_20913.java
@@ -1,4 +1,4 @@
-/**
+/*
* Copyright (C) 2022 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
@@ -16,41 +16,37 @@
package android.security.cts;
-import android.platform.test.annotations.AppModeFull;
+import static org.junit.Assume.assumeNoException;
+
import android.platform.test.annotations.AsbSecurityTest;
import com.android.sts.common.tradefed.testtype.NonRootSecurityTestCase;
import com.android.tradefed.device.ITestDevice;
import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
-import org.junit.Assert;
-import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
@RunWith(DeviceJUnit4ClassRunner.class)
-public class CVE_2021_0642 extends NonRootSecurityTestCase {
- static final String TEST_APP = "CVE-2021-0642.apk";
- static final String TEST_PKG = "android.security.cts.cve_2021_0642";
- static final String TEST_CLASS = TEST_PKG + "." + "DeviceTest";
-
- @Before
- public void setUp() throws Exception {
- ITestDevice device = getDevice();
- AdbUtils.runCommandLine("input keyevent KEYCODE_WAKEUP", device);
- AdbUtils.runCommandLine("input keyevent KEYCODE_MENU", device);
- AdbUtils.runCommandLine("input keyevent KEYCODE_HOME", device);
- uninstallPackage(device, TEST_PKG);
- }
+public class CVE_2023_20913 extends NonRootSecurityTestCase {
- /**
- * b/185126149
- */
- @AppModeFull
- @AsbSecurityTest(cveBugId = 185126149)
+ // b/246933785
+ // Vulnerable app : Telephony.apk
+ // Vulnerable module : com.android.phone
+ // Is Play managed : No
+ @AsbSecurityTest(cveBugId = 246933785)
@Test
- public void testPocCVE_2021_0642() throws Exception {
- installPackage(TEST_APP);
- Assert.assertTrue(runDeviceTests(TEST_PKG, TEST_CLASS, "testCVE_2021_0642"));
+ public void testPocCVE_2023_20913() {
+ try {
+ final String testPkg = "android.security.cts.CVE_2023_20913";
+ ITestDevice device = getDevice();
+ installPackage("CVE-2023-20913.apk");
+
+ AdbUtils.runCommandLine(
+ "pm grant " + testPkg + " android.permission.SYSTEM_ALERT_WINDOW", device);
+ runDeviceTests(testPkg, testPkg + ".DeviceTest", "testOverlayButtonPresence");
+ } catch (Exception e) {
+ assumeNoException(e);
+ }
}
}
diff --git a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2023_20918.java b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2023_20918.java
new file mode 100644
index 00000000000..659c002d83f
--- /dev/null
+++ b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2023_20918.java
@@ -0,0 +1,57 @@
+/*
+ * Copyright (C) 2022 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.assumeNoException;
+
+import android.platform.test.annotations.AsbSecurityTest;
+
+import com.android.sts.common.SystemUtil;
+import com.android.sts.common.tradefed.testtype.NonRootSecurityTestCase;
+import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+@RunWith(DeviceJUnit4ClassRunner.class)
+public class CVE_2023_20918 extends NonRootSecurityTestCase {
+
+ // b/243794108
+ // Vulnerable library : services.jar
+ // Vulnerable module : Not applicable
+ // Is Play Managed : No
+ @AsbSecurityTest(cveBugId = 243794108)
+ @Test
+ public void testPocCVE_2023_20918() {
+ try {
+ final String testPkg = "android.security.cts.CVE_2023_20918_test";
+
+ // Install the test and attacker apps
+ installPackage("CVE-2023-20918-test.apk");
+ installPackage("CVE-2023-20918-attacker.apk");
+
+ // Allow access to hidden api "ActivityOptions#setPendingIntentLaunchFlags()"
+ try (AutoCloseable closable =
+ SystemUtil.withSetting(getDevice(), "global", "hidden_api_policy", "1")) {
+ // Run the test "testCVE_2023_20918"
+ runDeviceTests(testPkg, testPkg + ".DeviceTest", "testCVE_2023_20918");
+ }
+ } catch (Exception e) {
+ assumeNoException(e);
+ }
+ }
+}
diff --git a/hostsidetests/securitybulletin/test-apps/CVE-2021-0642/src/android/security/cts/cve_2021_0642/DeviceTest.java b/hostsidetests/securitybulletin/test-apps/CVE-2021-0642/src/android/security/cts/cve_2021_0642/DeviceTest.java
deleted file mode 100644
index 8fc235ba9da..00000000000
--- a/hostsidetests/securitybulletin/test-apps/CVE-2021-0642/src/android/security/cts/cve_2021_0642/DeviceTest.java
+++ /dev/null
@@ -1,100 +0,0 @@
-/*
- * Copyright (C) 2022 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_2021_0642;
-
-import static androidx.test.core.app.ApplicationProvider.getApplicationContext;
-import static androidx.test.platform.app.InstrumentationRegistry.getInstrumentation;
-import static org.hamcrest.CoreMatchers.notNullValue;
-import static org.junit.Assert.assertThat;
-import static org.junit.Assert.assertTrue;
-import static org.junit.Assume.assumeNoException;
-import static org.junit.Assume.assumeTrue;
-
-import android.content.ActivityNotFoundException;
-import android.content.Context;
-import android.content.Intent;
-import android.content.pm.PackageManager;
-import android.telephony.TelephonyManager;
-
-import androidx.test.runner.AndroidJUnit4;
-import androidx.test.uiautomator.By;
-import androidx.test.uiautomator.BySelector;
-import androidx.test.uiautomator.UiDevice;
-import androidx.test.uiautomator.UiObject2;
-import androidx.test.uiautomator.Until;
-
-import java.util.List;
-
-import org.junit.Test;
-import org.junit.runner.RunWith;
-
-@RunWith(AndroidJUnit4.class)
-public class DeviceTest {
- static final String APP_TITLE = "CVE-2021-0642";
- static final String PACKAGE_NAME = "com.android.phone";
- static final int LAUNCH_TIMEOUT_MS = 20000;
-
- @Test
- public void testCVE_2021_0642() {
- UiDevice device = UiDevice.getInstance(getInstrumentation());
- Context context = getApplicationContext();
- assertThat(context, notNullValue());
- PackageManager packageManager = context.getPackageManager();
- assertThat(packageManager, notNullValue());
- assumeTrue(packageManager.hasSystemFeature(PackageManager.FEATURE_TELEPHONY));
- final Intent intent = new Intent(TelephonyManager.ACTION_CONFIGURE_VOICEMAIL);
- intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK);
- intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
- try {
- context.startActivity(intent);
- } catch (ActivityNotFoundException e) {
- assumeNoException(e);
- }
-
- // Check if "com.android.phone" exists on the system
- try {
- packageManager.getPackageUid(PACKAGE_NAME, 0);
- } catch (PackageManager.NameNotFoundException e) {
- assumeNoException(e);
- }
-
- // Wait for activity (which is part of package "com.android.phone") that
- // handles ACTION_CONFIGURE_VOICEMAIL to get launched
- boolean isVoicemailVisible =
- device.wait(Until.hasObject(By.pkg(PACKAGE_NAME)), LAUNCH_TIMEOUT_MS);
-
- // To check if PocActivity was launched
- BySelector selector = By.enabled(true);
- List<UiObject2> objects = device.findObjects(selector);
- boolean isPocActivityVisible = false;
- for (UiObject2 o : objects) {
- String visibleText = o.getText();
- if ((visibleText != null) && (visibleText.equalsIgnoreCase(APP_TITLE))) {
- isPocActivityVisible = true;
- break;
- }
- }
- device.pressHome();
-
- assumeTrue(isVoicemailVisible || isPocActivityVisible);
-
- String outputMsg = "Device is vulnerable to b/185126149 "
- + "hence sensitive Iccid could be sniffed by intercepting "
- + "ACTION_CONFIGURE_VOICEMAIL implicit intent";
- assertTrue(outputMsg, ((isVoicemailVisible) && (!isPocActivityVisible)));
- }
-}
diff --git a/hostsidetests/securitybulletin/test-apps/CVE-2021-0963/Android.bp b/hostsidetests/securitybulletin/test-apps/CVE-2021-0963/Android.bp
new file mode 100644
index 00000000000..ea39e68b2be
--- /dev/null
+++ b/hostsidetests/securitybulletin/test-apps/CVE-2021-0963/Android.bp
@@ -0,0 +1,39 @@
+/*
+ * Copyright (C) 2022 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-2021-0963",
+ defaults: [
+ "cts_defaults",
+ ],
+ srcs: [
+ "src/**/*.java",
+ ],
+ test_suites: [
+ "sts",
+ ],
+ static_libs: [
+ "androidx.test.core",
+ "androidx.test.rules",
+ "androidx.test.uiautomator_uiautomator",
+ ],
+ platform_apis: true,
+}
diff --git a/hostsidetests/securitybulletin/test-apps/CVE-2021-0642/AndroidManifest.xml b/hostsidetests/securitybulletin/test-apps/CVE-2021-0963/AndroidManifest.xml
index fadda577403..ae0d4160fcb 100644
--- a/hostsidetests/securitybulletin/test-apps/CVE-2021-0642/AndroidManifest.xml
+++ b/hostsidetests/securitybulletin/test-apps/CVE-2021-0963/AndroidManifest.xml
@@ -14,31 +14,29 @@
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_2021_0642"
- android:versionCode="1"
- android:versionName="1.0">
- <uses-permission android:name="android.permission.BLUETOOTH_ADMIN" />
- <application
- android:allowBackup="true"
- android:label="CVE-2021-0642"
- android:supportsRtl="true">
- <activity
- android:name=".PocActivity"
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ package="android.security.cts.CVE_2021_0963">
+ <uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW" />
+ <application>
+ <activity android:name=".PocActivity"
android:exported="true">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
+ </activity>
+ <receiver android:name=".PocDeviceAdminReceiver"
+ android:exported="true"
+ android:permission="android.permission.BIND_DEVICE_ADMIN">
+ <meta-data android:name="android.app.device_admin"
+ android:resource="@xml/device_policies" />
<intent-filter>
- <action android:name="android.telephony.action.CONFIGURE_VOICEMAIL" />
- <category android:name="android.intent.category.DEFAULT" />
+ <action android:name="android.app.action.DEVICE_ADMIN_ENABLED" />
</intent-filter>
- </activity>
+ </receiver>
+ <service android:name=".PocService" />
</application>
-
- <instrumentation
- android:name="androidx.test.runner.AndroidJUnitRunner"
- android:targetPackage="android.security.cts.cve_2021_0642" />
+ <instrumentation android:name="androidx.test.runner.AndroidJUnitRunner"
+ android:targetPackage="android.security.cts.CVE_2021_0963" />
</manifest>
diff --git a/hostsidetests/securitybulletin/test-apps/CVE-2021-0642/res/layout/activity_main.xml b/hostsidetests/securitybulletin/test-apps/CVE-2021-0963/res/values/integers.xml
index 7460b96ae6b..6a14b4a8240 100644
--- a/hostsidetests/securitybulletin/test-apps/CVE-2021-0642/res/layout/activity_main.xml
+++ b/hostsidetests/securitybulletin/test-apps/CVE-2021-0963/res/values/integers.xml
@@ -14,13 +14,9 @@
See the License for the specific language governing permissions and
limitations under the License.
-->
-<LinearLayout
- xmlns:android="http://schemas.android.com/apk/res/android"
- android:orientation="vertical"
- android:layout_width="match_parent"
- android:layout_height="match_parent">
- <View
- android:id="@+id/drawableview"
- android:layout_width="match_parent"
- android:layout_height="300dp" />
-</LinearLayout>
+
+<resources>
+ <integer name="assumptionFailure">-1</integer>
+ <integer name="noException">0</integer>
+ <integer name="timeoutMs">10000</integer>
+</resources>
diff --git a/hostsidetests/securitybulletin/test-apps/CVE-2021-0963/res/values/strings.xml b/hostsidetests/securitybulletin/test-apps/CVE-2021-0963/res/values/strings.xml
new file mode 100644
index 00000000000..1da84fe3711
--- /dev/null
+++ b/hostsidetests/securitybulletin/test-apps/CVE-2021-0963/res/values/strings.xml
@@ -0,0 +1,40 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright 2022 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.
+ -->
+
+<resources>
+ <string name="actionKeychainActivity">com.android.keychain.CHOOSER</string>
+ <string name="activityNotFoundMsg">The activity with intent was not found : </string>
+ <string name="activityNotStartedException">Unable to start the activity with intent : </string>
+ <string name="alias">Client</string>
+ <string name="callbackKey">callback</string>
+ <string name="canNotDrawOverlaysMsg">The application cannot draw overlays</string>
+ <string name="certType">X.509</string>
+ <string name="dumpsysActivity">dumpsys activity %1$s</string>
+ <string name="dumpsysActivityNotStartedException">Could not execute dumpsys activity command
+ </string>
+ <string name="errorMessage">Device is vulnerable to b/199754277 hence any app with
+ "SYSTEM_ALERT_WINDOW can overlay the %1$s screen</string>
+ <string name="keyType">RSA</string>
+ <string name="mResumedTrue">mResumed=true</string>
+ <string name="messageKey">message</string>
+ <string name="overlayButtonText">OverlayButton</string>
+ <string name="overlayServiceNotStartedException">Unable to start the overlay service</string>
+ <string name="overlayUiScreenError">Overlay UI did not appear on the screen</string>
+ <string name="statusKey">status</string>
+ <string name="vulActivityNotRunningError">The activity %1$s is not currently running
+ on the device</string>
+</resources>
diff --git a/hostsidetests/securitybulletin/test-apps/CVE-2021-0963/res/xml/device_policies.xml b/hostsidetests/securitybulletin/test-apps/CVE-2021-0963/res/xml/device_policies.xml
new file mode 100644
index 00000000000..a826e80f531
--- /dev/null
+++ b/hostsidetests/securitybulletin/test-apps/CVE-2021-0963/res/xml/device_policies.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright 2022 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.
+ -->
+
+<device-admin>
+ <uses-policies>
+ </uses-policies>
+</device-admin>
diff --git a/hostsidetests/securitybulletin/test-apps/CVE-2021-0963/src/android/security/cts/CVE_2021_0963/DeviceTest.java b/hostsidetests/securitybulletin/test-apps/CVE-2021-0963/src/android/security/cts/CVE_2021_0963/DeviceTest.java
new file mode 100644
index 00000000000..3d1c0df2131
--- /dev/null
+++ b/hostsidetests/securitybulletin/test-apps/CVE-2021-0963/src/android/security/cts/CVE_2021_0963/DeviceTest.java
@@ -0,0 +1,401 @@
+/*
+ * Copyright (C) 2022 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_2021_0963;
+
+import static androidx.test.platform.app.InstrumentationRegistry.getInstrumentation;
+
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assume.assumeNoException;
+import static org.junit.Assume.assumeTrue;
+
+import android.app.admin.DevicePolicyManager;
+import android.content.ComponentName;
+import android.content.Context;
+import android.content.Intent;
+import android.content.pm.PackageManager;
+import android.content.pm.ResolveInfo;
+import android.content.res.Resources;
+import android.os.Bundle;
+import android.os.RemoteCallback;
+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 org.junit.After;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import java.io.ByteArrayInputStream;
+import java.security.KeyFactory;
+import java.security.PrivateKey;
+import java.security.cert.Certificate;
+import java.security.cert.CertificateFactory;
+import java.security.spec.PKCS8EncodedKeySpec;
+import java.util.concurrent.CompletableFuture;
+import java.util.concurrent.TimeUnit;
+import java.util.regex.Pattern;
+
+@RunWith(AndroidJUnit4.class)
+public class DeviceTest {
+ private DevicePolicyManager mDevicePolicyManager;
+ private ComponentName mComponentName;
+ Context mContext;
+
+ /**
+ * Generated from above and converted with:
+ *
+ * openssl pkcs8 -topk8 -outform d -in userkey.pem -nocrypt | xxd -i | sed 's/0x/(byte) 0x/g'
+ */
+ private static final byte[] PRIVATE_KEY =
+ new byte[] {(byte) 0x30, (byte) 0x82, (byte) 0x02, (byte) 0x76, (byte) 0x02,
+ (byte) 0x01, (byte) 0x00, (byte) 0x30, (byte) 0x0d, (byte) 0x06, (byte) 0x09,
+ (byte) 0x2a, (byte) 0x86, (byte) 0x48, (byte) 0x86, (byte) 0xf7, (byte) 0x0d,
+ (byte) 0x01, (byte) 0x01, (byte) 0x01, (byte) 0x05, (byte) 0x00, (byte) 0x04,
+ (byte) 0x82, (byte) 0x02, (byte) 0x60, (byte) 0x30, (byte) 0x82, (byte) 0x02,
+ (byte) 0x5c, (byte) 0x02, (byte) 0x01, (byte) 0x00, (byte) 0x02, (byte) 0x81,
+ (byte) 0x81, (byte) 0x00, (byte) 0xee, (byte) 0x6e, (byte) 0x51, (byte) 0xa8,
+ (byte) 0xc4, (byte) 0x44, (byte) 0xd9, (byte) 0xb7, (byte) 0x53, (byte) 0xf1,
+ (byte) 0xb9, (byte) 0x1b, (byte) 0x9d, (byte) 0x8d, (byte) 0x7c, (byte) 0x9f,
+ (byte) 0x06, (byte) 0xe7, (byte) 0xed, (byte) 0xa8, (byte) 0x05, (byte) 0xb8,
+ (byte) 0xaa, (byte) 0x0a, (byte) 0x2d, (byte) 0x74, (byte) 0x05, (byte) 0x8b,
+ (byte) 0xad, (byte) 0xfe, (byte) 0xd3, (byte) 0x3e, (byte) 0x08, (byte) 0x9d,
+ (byte) 0xc9, (byte) 0xf5, (byte) 0xf7, (byte) 0x81, (byte) 0x90, (byte) 0xf1,
+ (byte) 0xcc, (byte) 0x3f, (byte) 0x91, (byte) 0xda, (byte) 0xcb, (byte) 0x67,
+ (byte) 0x6a, (byte) 0xe8, (byte) 0x4a, (byte) 0xa0, (byte) 0xc3, (byte) 0x8a,
+ (byte) 0x53, (byte) 0xd9, (byte) 0xf0, (byte) 0x17, (byte) 0xbe, (byte) 0x90,
+ (byte) 0xbb, (byte) 0x95, (byte) 0x29, (byte) 0x01, (byte) 0xce, (byte) 0x32,
+ (byte) 0xce, (byte) 0xf8, (byte) 0x02, (byte) 0xfe, (byte) 0xe8, (byte) 0x19,
+ (byte) 0x91, (byte) 0x29, (byte) 0x46, (byte) 0xf7, (byte) 0x67, (byte) 0xd1,
+ (byte) 0xcb, (byte) 0xa7, (byte) 0x20, (byte) 0x8b, (byte) 0x85, (byte) 0x8a,
+ (byte) 0x0c, (byte) 0x07, (byte) 0xf8, (byte) 0xfe, (byte) 0xf4, (byte) 0x5d,
+ (byte) 0x08, (byte) 0xf4, (byte) 0x63, (byte) 0x4a, (byte) 0x69, (byte) 0x66,
+ (byte) 0x28, (byte) 0xcb, (byte) 0x0d, (byte) 0x1c, (byte) 0x7f, (byte) 0x7f,
+ (byte) 0x7e, (byte) 0x83, (byte) 0x49, (byte) 0x66, (byte) 0x6c, (byte) 0x83,
+ (byte) 0x2d, (byte) 0xa0, (byte) 0x51, (byte) 0xf6, (byte) 0x14, (byte) 0x68,
+ (byte) 0x47, (byte) 0x31, (byte) 0x72, (byte) 0x4d, (byte) 0xe9, (byte) 0x1e,
+ (byte) 0x12, (byte) 0x1b, (byte) 0xd0, (byte) 0xe6, (byte) 0x21, (byte) 0xd8,
+ (byte) 0x84, (byte) 0x5f, (byte) 0xe3, (byte) 0xef, (byte) 0x02, (byte) 0x03,
+ (byte) 0x01, (byte) 0x00, (byte) 0x01, (byte) 0x02, (byte) 0x81, (byte) 0x80,
+ (byte) 0x24, (byte) 0x95, (byte) 0xb8, (byte) 0xe1, (byte) 0xf4, (byte) 0x7b,
+ (byte) 0xbc, (byte) 0x0c, (byte) 0x6d, (byte) 0x4d, (byte) 0x01, (byte) 0xe2,
+ (byte) 0x42, (byte) 0xe2, (byte) 0x9a, (byte) 0xe4, (byte) 0xab, (byte) 0xe2,
+ (byte) 0x9a, (byte) 0x8c, (byte) 0xd5, (byte) 0x93, (byte) 0xe8, (byte) 0x43,
+ (byte) 0x77, (byte) 0x85, (byte) 0xfd, (byte) 0xf3, (byte) 0xd8, (byte) 0xd6,
+ (byte) 0xe9, (byte) 0x02, (byte) 0xf3, (byte) 0xbf, (byte) 0x82, (byte) 0x65,
+ (byte) 0xc3, (byte) 0x7c, (byte) 0x96, (byte) 0x09, (byte) 0x04, (byte) 0x16,
+ (byte) 0x1d, (byte) 0x03, (byte) 0x3d, (byte) 0x82, (byte) 0xb8, (byte) 0xdc,
+ (byte) 0xbb, (byte) 0xd6, (byte) 0xbf, (byte) 0x2a, (byte) 0x52, (byte) 0x83,
+ (byte) 0x76, (byte) 0x5b, (byte) 0xae, (byte) 0x59, (byte) 0xf6, (byte) 0xee,
+ (byte) 0x84, (byte) 0x44, (byte) 0x4a, (byte) 0xa7, (byte) 0x25, (byte) 0x50,
+ (byte) 0x89, (byte) 0x63, (byte) 0x43, (byte) 0x0b, (byte) 0xc8, (byte) 0xd5,
+ (byte) 0x17, (byte) 0x9d, (byte) 0x8b, (byte) 0x62, (byte) 0xd5, (byte) 0xf1,
+ (byte) 0xde, (byte) 0x45, (byte) 0xe6, (byte) 0x35, (byte) 0x10, (byte) 0xba,
+ (byte) 0x58, (byte) 0x18, (byte) 0x44, (byte) 0xc1, (byte) 0x6d, (byte) 0xb6,
+ (byte) 0x1d, (byte) 0x2f, (byte) 0x53, (byte) 0xb6, (byte) 0x5a, (byte) 0xf1,
+ (byte) 0x66, (byte) 0xbc, (byte) 0x0e, (byte) 0x63, (byte) 0xa7, (byte) 0x0f,
+ (byte) 0x81, (byte) 0x4b, (byte) 0x07, (byte) 0x31, (byte) 0xa5, (byte) 0x70,
+ (byte) 0xec, (byte) 0x30, (byte) 0x57, (byte) 0xc4, (byte) 0x14, (byte) 0xb2,
+ (byte) 0x8b, (byte) 0x6f, (byte) 0x26, (byte) 0x7e, (byte) 0x55, (byte) 0x60,
+ (byte) 0x63, (byte) 0x7d, (byte) 0x90, (byte) 0xd7, (byte) 0x5f, (byte) 0xef,
+ (byte) 0x7d, (byte) 0xc1, (byte) 0x02, (byte) 0x41, (byte) 0x00, (byte) 0xfe,
+ (byte) 0x92, (byte) 0xa9, (byte) 0xf1, (byte) 0x29, (byte) 0x1e, (byte) 0xd4,
+ (byte) 0x72, (byte) 0xd3, (byte) 0x3f, (byte) 0x9d, (byte) 0xd6, (byte) 0x3d,
+ (byte) 0xe9, (byte) 0xcf, (byte) 0x3e, (byte) 0x06, (byte) 0xdc, (byte) 0x65,
+ (byte) 0x8f, (byte) 0xc0, (byte) 0x81, (byte) 0xc2, (byte) 0x66, (byte) 0xc1,
+ (byte) 0x5c, (byte) 0x2c, (byte) 0xfa, (byte) 0x08, (byte) 0x65, (byte) 0xb6,
+ (byte) 0x47, (byte) 0xc5, (byte) 0x14, (byte) 0x8d, (byte) 0x69, (byte) 0xe9,
+ (byte) 0xaf, (byte) 0x42, (byte) 0x02, (byte) 0x53, (byte) 0x04, (byte) 0x63,
+ (byte) 0x47, (byte) 0xaf, (byte) 0xcc, (byte) 0xae, (byte) 0x08, (byte) 0x31,
+ (byte) 0xba, (byte) 0xea, (byte) 0x85, (byte) 0xda, (byte) 0xd6, (byte) 0xb2,
+ (byte) 0xe7, (byte) 0x4c, (byte) 0xda, (byte) 0xad, (byte) 0x52, (byte) 0x76,
+ (byte) 0x48, (byte) 0x16, (byte) 0xeb, (byte) 0x02, (byte) 0x41, (byte) 0x00,
+ (byte) 0xef, (byte) 0xc4, (byte) 0x7d, (byte) 0x69, (byte) 0x7b, (byte) 0xcb,
+ (byte) 0xcb, (byte) 0xf7, (byte) 0x00, (byte) 0x2d, (byte) 0x05, (byte) 0x3c,
+ (byte) 0xe4, (byte) 0xfd, (byte) 0x5c, (byte) 0xea, (byte) 0xcf, (byte) 0x40,
+ (byte) 0x84, (byte) 0x10, (byte) 0xf1, (byte) 0xc0, (byte) 0xaf, (byte) 0xc7,
+ (byte) 0xc8, (byte) 0x51, (byte) 0xac, (byte) 0x18, (byte) 0x25, (byte) 0x63,
+ (byte) 0x75, (byte) 0xc7, (byte) 0x0e, (byte) 0xa9, (byte) 0xed, (byte) 0x9c,
+ (byte) 0x78, (byte) 0x08, (byte) 0x28, (byte) 0x1d, (byte) 0x9e, (byte) 0xfa,
+ (byte) 0x17, (byte) 0x0f, (byte) 0x7a, (byte) 0x6a, (byte) 0x78, (byte) 0x63,
+ (byte) 0x6e, (byte) 0xb3, (byte) 0x6b, (byte) 0xd6, (byte) 0x43, (byte) 0x4b,
+ (byte) 0x58, (byte) 0xb8, (byte) 0x77, (byte) 0x10, (byte) 0x07, (byte) 0x70,
+ (byte) 0xa6, (byte) 0xa9, (byte) 0xae, (byte) 0x0d, (byte) 0x02, (byte) 0x41,
+ (byte) 0x00, (byte) 0x92, (byte) 0x4c, (byte) 0x79, (byte) 0x0b, (byte) 0x95,
+ (byte) 0xc5, (byte) 0x18, (byte) 0xf4, (byte) 0x90, (byte) 0x40, (byte) 0x8c,
+ (byte) 0x15, (byte) 0x96, (byte) 0x69, (byte) 0x2a, (byte) 0xe7, (byte) 0x8b,
+ (byte) 0x8b, (byte) 0xd7, (byte) 0x76, (byte) 0x00, (byte) 0x7c, (byte) 0xd1,
+ (byte) 0xda, (byte) 0xb9, (byte) 0x9e, (byte) 0x9e, (byte) 0x5e, (byte) 0x66,
+ (byte) 0xbb, (byte) 0x05, (byte) 0x41, (byte) 0x43, (byte) 0x9a, (byte) 0x67,
+ (byte) 0x16, (byte) 0x89, (byte) 0xec, (byte) 0x65, (byte) 0x33, (byte) 0xee,
+ (byte) 0xbf, (byte) 0xa3, (byte) 0xca, (byte) 0x8b, (byte) 0xd6, (byte) 0x45,
+ (byte) 0xe1, (byte) 0x81, (byte) 0xaa, (byte) 0xd8, (byte) 0xa2, (byte) 0x6a,
+ (byte) 0x3c, (byte) 0x5e, (byte) 0x7e, (byte) 0x1c, (byte) 0xa5, (byte) 0xc3,
+ (byte) 0x5b, (byte) 0x93, (byte) 0x8c, (byte) 0x24, (byte) 0x57, (byte) 0x02,
+ (byte) 0x40, (byte) 0x0a, (byte) 0x6d, (byte) 0x3f, (byte) 0x0e, (byte) 0xf1,
+ (byte) 0x45, (byte) 0x41, (byte) 0x8f, (byte) 0x72, (byte) 0x40, (byte) 0x82,
+ (byte) 0xf3, (byte) 0xcc, (byte) 0xf9, (byte) 0x7f, (byte) 0xaa, (byte) 0xee,
+ (byte) 0x6c, (byte) 0x5d, (byte) 0xd1, (byte) 0xe6, (byte) 0xd1, (byte) 0x7c,
+ (byte) 0x53, (byte) 0x71, (byte) 0xd0, (byte) 0xab, (byte) 0x6d, (byte) 0x39,
+ (byte) 0x63, (byte) 0x03, (byte) 0xe2, (byte) 0x2e, (byte) 0x2f, (byte) 0x11,
+ (byte) 0x98, (byte) 0x36, (byte) 0x58, (byte) 0x14, (byte) 0x76, (byte) 0x85,
+ (byte) 0x4d, (byte) 0x56, (byte) 0xe7, (byte) 0x63, (byte) 0x69, (byte) 0x71,
+ (byte) 0xe6, (byte) 0xd1, (byte) 0x0f, (byte) 0x98, (byte) 0x66, (byte) 0xee,
+ (byte) 0xf2, (byte) 0x3d, (byte) 0xdf, (byte) 0x77, (byte) 0xbe, (byte) 0x08,
+ (byte) 0xb4, (byte) 0xcb, (byte) 0x6a, (byte) 0xa1, (byte) 0x99, (byte) 0x02,
+ (byte) 0x40, (byte) 0x52, (byte) 0x01, (byte) 0xde, (byte) 0x62, (byte) 0xc2,
+ (byte) 0x25, (byte) 0xbf, (byte) 0x5d, (byte) 0x77, (byte) 0xe4, (byte) 0x6b,
+ (byte) 0xb6, (byte) 0xd7, (byte) 0x8f, (byte) 0x89, (byte) 0x2c, (byte) 0xe6,
+ (byte) 0x8d, (byte) 0xe5, (byte) 0xad, (byte) 0x39, (byte) 0x17, (byte) 0x54,
+ (byte) 0x2b, (byte) 0x35, (byte) 0x53, (byte) 0xd1, (byte) 0xa1, (byte) 0xef,
+ (byte) 0x48, (byte) 0xbc, (byte) 0x95, (byte) 0x48, (byte) 0xcf, (byte) 0x62,
+ (byte) 0xf4, (byte) 0x33, (byte) 0xcf, (byte) 0x37, (byte) 0x78, (byte) 0xeb,
+ (byte) 0x17, (byte) 0xb4, (byte) 0x0b, (byte) 0x83, (byte) 0x4f, (byte) 0xb6,
+ (byte) 0xab, (byte) 0x7d, (byte) 0x67, (byte) 0x3e, (byte) 0x4e, (byte) 0x44,
+ (byte) 0x4a, (byte) 0x55, (byte) 0x2e, (byte) 0x34, (byte) 0x12, (byte) 0x0b,
+ (byte) 0x59, (byte) 0xb3, (byte) 0xb1, (byte) 0x1e, (byte) 0x3d};
+
+
+ /**
+ * Generated from above and converted with:
+ *
+ * openssl x509 -outform d -in usercert.pem | xxd -i | sed 's/0x/(byte) 0x/g'
+ */
+ private static final byte[] USER_CERT =
+ {(byte) 0x30, (byte) 0x82, (byte) 0x02, (byte) 0xd8, (byte) 0x30, (byte) 0x82,
+ (byte) 0x01, (byte) 0xc0, (byte) 0xa0, (byte) 0x03, (byte) 0x02, (byte) 0x01,
+ (byte) 0x02, (byte) 0x02, (byte) 0x01, (byte) 0x01, (byte) 0x30, (byte) 0x0d,
+ (byte) 0x06, (byte) 0x09, (byte) 0x2a, (byte) 0x86, (byte) 0x48, (byte) 0x86,
+ (byte) 0xf7, (byte) 0x0d, (byte) 0x01, (byte) 0x01, (byte) 0x0b, (byte) 0x05,
+ (byte) 0x00, (byte) 0x30, (byte) 0x33, (byte) 0x31, (byte) 0x0b, (byte) 0x30,
+ (byte) 0x09, (byte) 0x06, (byte) 0x03, (byte) 0x55, (byte) 0x04, (byte) 0x06,
+ (byte) 0x13, (byte) 0x02, (byte) 0x41, (byte) 0x55, (byte) 0x31, (byte) 0x13,
+ (byte) 0x30, (byte) 0x11, (byte) 0x06, (byte) 0x03, (byte) 0x55, (byte) 0x04,
+ (byte) 0x08, (byte) 0x0c, (byte) 0x0a, (byte) 0x53, (byte) 0x6f, (byte) 0x6d,
+ (byte) 0x65, (byte) 0x2d, (byte) 0x53, (byte) 0x74, (byte) 0x61, (byte) 0x74,
+ (byte) 0x65, (byte) 0x31, (byte) 0x0f, (byte) 0x30, (byte) 0x0d, (byte) 0x06,
+ (byte) 0x03, (byte) 0x55, (byte) 0x04, (byte) 0x0a, (byte) 0x0c, (byte) 0x06,
+ (byte) 0x47, (byte) 0x6f, (byte) 0x6f, (byte) 0x67, (byte) 0x6c, (byte) 0x65,
+ (byte) 0x30, (byte) 0x1e, (byte) 0x17, (byte) 0x0d, (byte) 0x32, (byte) 0x32,
+ (byte) 0x30, (byte) 0x33, (byte) 0x32, (byte) 0x35, (byte) 0x30, (byte) 0x37,
+ (byte) 0x32, (byte) 0x30, (byte) 0x31, (byte) 0x32, (byte) 0x5a, (byte) 0x17,
+ (byte) 0x0d, (byte) 0x33, (byte) 0x32, (byte) 0x30, (byte) 0x33, (byte) 0x32,
+ (byte) 0x32, (byte) 0x30, (byte) 0x37, (byte) 0x32, (byte) 0x30, (byte) 0x31,
+ (byte) 0x32, (byte) 0x5a, (byte) 0x30, (byte) 0x33, (byte) 0x31, (byte) 0x0b,
+ (byte) 0x30, (byte) 0x09, (byte) 0x06, (byte) 0x03, (byte) 0x55, (byte) 0x04,
+ (byte) 0x06, (byte) 0x13, (byte) 0x02, (byte) 0x41, (byte) 0x55, (byte) 0x31,
+ (byte) 0x13, (byte) 0x30, (byte) 0x11, (byte) 0x06, (byte) 0x03, (byte) 0x55,
+ (byte) 0x04, (byte) 0x08, (byte) 0x0c, (byte) 0x0a, (byte) 0x53, (byte) 0x6f,
+ (byte) 0x6d, (byte) 0x65, (byte) 0x2d, (byte) 0x53, (byte) 0x74, (byte) 0x61,
+ (byte) 0x74, (byte) 0x65, (byte) 0x31, (byte) 0x0f, (byte) 0x30, (byte) 0x0d,
+ (byte) 0x06, (byte) 0x03, (byte) 0x55, (byte) 0x04, (byte) 0x0a, (byte) 0x0c,
+ (byte) 0x06, (byte) 0x47, (byte) 0x6f, (byte) 0x6f, (byte) 0x67, (byte) 0x6c,
+ (byte) 0x65, (byte) 0x30, (byte) 0x81, (byte) 0x9f, (byte) 0x30, (byte) 0x0d,
+ (byte) 0x06, (byte) 0x09, (byte) 0x2a, (byte) 0x86, (byte) 0x48, (byte) 0x86,
+ (byte) 0xf7, (byte) 0x0d, (byte) 0x01, (byte) 0x01, (byte) 0x01, (byte) 0x05,
+ (byte) 0x00, (byte) 0x03, (byte) 0x81, (byte) 0x8d, (byte) 0x00, (byte) 0x30,
+ (byte) 0x81, (byte) 0x89, (byte) 0x02, (byte) 0x81, (byte) 0x81, (byte) 0x00,
+ (byte) 0xee, (byte) 0x6e, (byte) 0x51, (byte) 0xa8, (byte) 0xc4, (byte) 0x44,
+ (byte) 0xd9, (byte) 0xb7, (byte) 0x53, (byte) 0xf1, (byte) 0xb9, (byte) 0x1b,
+ (byte) 0x9d, (byte) 0x8d, (byte) 0x7c, (byte) 0x9f, (byte) 0x06, (byte) 0xe7,
+ (byte) 0xed, (byte) 0xa8, (byte) 0x05, (byte) 0xb8, (byte) 0xaa, (byte) 0x0a,
+ (byte) 0x2d, (byte) 0x74, (byte) 0x05, (byte) 0x8b, (byte) 0xad, (byte) 0xfe,
+ (byte) 0xd3, (byte) 0x3e, (byte) 0x08, (byte) 0x9d, (byte) 0xc9, (byte) 0xf5,
+ (byte) 0xf7, (byte) 0x81, (byte) 0x90, (byte) 0xf1, (byte) 0xcc, (byte) 0x3f,
+ (byte) 0x91, (byte) 0xda, (byte) 0xcb, (byte) 0x67, (byte) 0x6a, (byte) 0xe8,
+ (byte) 0x4a, (byte) 0xa0, (byte) 0xc3, (byte) 0x8a, (byte) 0x53, (byte) 0xd9,
+ (byte) 0xf0, (byte) 0x17, (byte) 0xbe, (byte) 0x90, (byte) 0xbb, (byte) 0x95,
+ (byte) 0x29, (byte) 0x01, (byte) 0xce, (byte) 0x32, (byte) 0xce, (byte) 0xf8,
+ (byte) 0x02, (byte) 0xfe, (byte) 0xe8, (byte) 0x19, (byte) 0x91, (byte) 0x29,
+ (byte) 0x46, (byte) 0xf7, (byte) 0x67, (byte) 0xd1, (byte) 0xcb, (byte) 0xa7,
+ (byte) 0x20, (byte) 0x8b, (byte) 0x85, (byte) 0x8a, (byte) 0x0c, (byte) 0x07,
+ (byte) 0xf8, (byte) 0xfe, (byte) 0xf4, (byte) 0x5d, (byte) 0x08, (byte) 0xf4,
+ (byte) 0x63, (byte) 0x4a, (byte) 0x69, (byte) 0x66, (byte) 0x28, (byte) 0xcb,
+ (byte) 0x0d, (byte) 0x1c, (byte) 0x7f, (byte) 0x7f, (byte) 0x7e, (byte) 0x83,
+ (byte) 0x49, (byte) 0x66, (byte) 0x6c, (byte) 0x83, (byte) 0x2d, (byte) 0xa0,
+ (byte) 0x51, (byte) 0xf6, (byte) 0x14, (byte) 0x68, (byte) 0x47, (byte) 0x31,
+ (byte) 0x72, (byte) 0x4d, (byte) 0xe9, (byte) 0x1e, (byte) 0x12, (byte) 0x1b,
+ (byte) 0xd0, (byte) 0xe6, (byte) 0x21, (byte) 0xd8, (byte) 0x84, (byte) 0x5f,
+ (byte) 0xe3, (byte) 0xef, (byte) 0x02, (byte) 0x03, (byte) 0x01, (byte) 0x00,
+ (byte) 0x01, (byte) 0xa3, (byte) 0x7b, (byte) 0x30, (byte) 0x79, (byte) 0x30,
+ (byte) 0x09, (byte) 0x06, (byte) 0x03, (byte) 0x55, (byte) 0x1d, (byte) 0x13,
+ (byte) 0x04, (byte) 0x02, (byte) 0x30, (byte) 0x00, (byte) 0x30, (byte) 0x2c,
+ (byte) 0x06, (byte) 0x09, (byte) 0x60, (byte) 0x86, (byte) 0x48, (byte) 0x01,
+ (byte) 0x86, (byte) 0xf8, (byte) 0x42, (byte) 0x01, (byte) 0x0d, (byte) 0x04,
+ (byte) 0x1f, (byte) 0x16, (byte) 0x1d, (byte) 0x4f, (byte) 0x70, (byte) 0x65,
+ (byte) 0x6e, (byte) 0x53, (byte) 0x53, (byte) 0x4c, (byte) 0x20, (byte) 0x47,
+ (byte) 0x65, (byte) 0x6e, (byte) 0x65, (byte) 0x72, (byte) 0x61, (byte) 0x74,
+ (byte) 0x65, (byte) 0x64, (byte) 0x20, (byte) 0x43, (byte) 0x65, (byte) 0x72,
+ (byte) 0x74, (byte) 0x69, (byte) 0x66, (byte) 0x69, (byte) 0x63, (byte) 0x61,
+ (byte) 0x74, (byte) 0x65, (byte) 0x30, (byte) 0x1d, (byte) 0x06, (byte) 0x03,
+ (byte) 0x55, (byte) 0x1d, (byte) 0x0e, (byte) 0x04, (byte) 0x16, (byte) 0x04,
+ (byte) 0x14, (byte) 0xee, (byte) 0xec, (byte) 0x08, (byte) 0xcc, (byte) 0xdd,
+ (byte) 0xa3, (byte) 0x29, (byte) 0x6e, (byte) 0x2b, (byte) 0x78, (byte) 0x23,
+ (byte) 0xb3, (byte) 0xf0, (byte) 0xb8, (byte) 0x9d, (byte) 0x53, (byte) 0x41,
+ (byte) 0x2e, (byte) 0x3c, (byte) 0x61, (byte) 0x30, (byte) 0x1f, (byte) 0x06,
+ (byte) 0x03, (byte) 0x55, (byte) 0x1d, (byte) 0x23, (byte) 0x04, (byte) 0x18,
+ (byte) 0x30, (byte) 0x16, (byte) 0x80, (byte) 0x14, (byte) 0x86, (byte) 0xdb,
+ (byte) 0xa5, (byte) 0x5e, (byte) 0x0e, (byte) 0x03, (byte) 0xbc, (byte) 0xe4,
+ (byte) 0xc1, (byte) 0xc8, (byte) 0xf3, (byte) 0xed, (byte) 0x24, (byte) 0x48,
+ (byte) 0xb1, (byte) 0x37, (byte) 0x3a, (byte) 0x52, (byte) 0x10, (byte) 0x57,
+ (byte) 0x30, (byte) 0x0d, (byte) 0x06, (byte) 0x09, (byte) 0x2a, (byte) 0x86,
+ (byte) 0x48, (byte) 0x86, (byte) 0xf7, (byte) 0x0d, (byte) 0x01, (byte) 0x01,
+ (byte) 0x0b, (byte) 0x05, (byte) 0x00, (byte) 0x03, (byte) 0x82, (byte) 0x01,
+ (byte) 0x01, (byte) 0x00, (byte) 0x15, (byte) 0x5a, (byte) 0x5c, (byte) 0x08,
+ (byte) 0xe4, (byte) 0x0e, (byte) 0x28, (byte) 0x4c, (byte) 0xa9, (byte) 0x0e,
+ (byte) 0x35, (byte) 0xbe, (byte) 0xe3, (byte) 0xd5, (byte) 0xd1, (byte) 0xb4,
+ (byte) 0x47, (byte) 0x87, (byte) 0x63, (byte) 0xd2, (byte) 0x5e, (byte) 0x7e,
+ (byte) 0xf6, (byte) 0xd8, (byte) 0xce, (byte) 0xdf, (byte) 0x10, (byte) 0x15,
+ (byte) 0x61, (byte) 0xc4, (byte) 0x9a, (byte) 0xf1, (byte) 0xba, (byte) 0x33,
+ (byte) 0xf2, (byte) 0xc2, (byte) 0x01, (byte) 0x95, (byte) 0xa7, (byte) 0x74,
+ (byte) 0x97, (byte) 0xc1, (byte) 0x43, (byte) 0x68, (byte) 0x92, (byte) 0xbe,
+ (byte) 0x9a, (byte) 0x6f, (byte) 0x38, (byte) 0xcb, (byte) 0xa0, (byte) 0xcf,
+ (byte) 0x1e, (byte) 0x5b, (byte) 0x03, (byte) 0xde, (byte) 0x45, (byte) 0x6d,
+ (byte) 0xea, (byte) 0xf0, (byte) 0x46, (byte) 0x4d, (byte) 0xb6, (byte) 0x4b,
+ (byte) 0x88, (byte) 0xc7, (byte) 0xb8, (byte) 0xe3, (byte) 0x9f, (byte) 0x58,
+ (byte) 0x8b, (byte) 0x2d, (byte) 0xbf, (byte) 0x4b, (byte) 0x3f, (byte) 0x54,
+ (byte) 0x2d, (byte) 0xa8, (byte) 0x27, (byte) 0x72, (byte) 0x5e, (byte) 0x36,
+ (byte) 0x67, (byte) 0x5c, (byte) 0x6e, (byte) 0x9a, (byte) 0x67, (byte) 0x73,
+ (byte) 0x44, (byte) 0xaf, (byte) 0x46, (byte) 0x7f, (byte) 0xd6, (byte) 0x2b,
+ (byte) 0x9d, (byte) 0x28, (byte) 0xb1, (byte) 0xc4, (byte) 0xc4, (byte) 0x72,
+ (byte) 0x3d, (byte) 0x6d, (byte) 0x7d, (byte) 0x28, (byte) 0x40, (byte) 0x62,
+ (byte) 0x40, (byte) 0x21, (byte) 0x52, (byte) 0xb5, (byte) 0x0b, (byte) 0xf3,
+ (byte) 0xcc, (byte) 0x36, (byte) 0x03, (byte) 0x10, (byte) 0x19, (byte) 0xe3,
+ (byte) 0xc2, (byte) 0xfe, (byte) 0xe9, (byte) 0x08, (byte) 0x0d, (byte) 0xd4,
+ (byte) 0x8b, (byte) 0x12, (byte) 0xd6, (byte) 0x3d, (byte) 0xc5, (byte) 0xb8,
+ (byte) 0x8c, (byte) 0xbd, (byte) 0xa5, (byte) 0xcd, (byte) 0xb3, (byte) 0xe4,
+ (byte) 0xd1, (byte) 0xd8, (byte) 0x4c, (byte) 0x32, (byte) 0x44, (byte) 0x3f,
+ (byte) 0x63, (byte) 0x32, (byte) 0x09, (byte) 0xdb, (byte) 0x8b, (byte) 0x7b,
+ (byte) 0x30, (byte) 0x58, (byte) 0xc7, (byte) 0xcf, (byte) 0xc3, (byte) 0x44,
+ (byte) 0xd9, (byte) 0xff, (byte) 0x63, (byte) 0x91, (byte) 0x74, (byte) 0xd8,
+ (byte) 0x62, (byte) 0x2b, (byte) 0x52, (byte) 0xc8, (byte) 0x82, (byte) 0x9f,
+ (byte) 0xeb, (byte) 0x22, (byte) 0x5c, (byte) 0xa2, (byte) 0x26, (byte) 0xfe,
+ (byte) 0x04, (byte) 0x31, (byte) 0x53, (byte) 0x09, (byte) 0xa7, (byte) 0x23,
+ (byte) 0xe3, (byte) 0x0f, (byte) 0xf8, (byte) 0xe9, (byte) 0x99, (byte) 0xad,
+ (byte) 0x4b, (byte) 0x23, (byte) 0x07, (byte) 0xfb, (byte) 0xfa, (byte) 0xc3,
+ (byte) 0x55, (byte) 0x59, (byte) 0xdb, (byte) 0x6b, (byte) 0x71, (byte) 0xdf,
+ (byte) 0x25, (byte) 0x0f, (byte) 0xaa, (byte) 0xa2, (byte) 0xfa, (byte) 0x28,
+ (byte) 0x49, (byte) 0x65, (byte) 0x7e, (byte) 0x0b, (byte) 0x74, (byte) 0x30,
+ (byte) 0xd9, (byte) 0x9a, (byte) 0xfe, (byte) 0x2c, (byte) 0x8c, (byte) 0x67,
+ (byte) 0x50, (byte) 0x0c, (byte) 0x6d, (byte) 0x4c, (byte) 0xba, (byte) 0x34,
+ (byte) 0x3b, (byte) 0x0d, (byte) 0x16, (byte) 0x45, (byte) 0x63, (byte) 0x73,
+ (byte) 0xc2, (byte) 0x9f, (byte) 0xb4, (byte) 0xdd, (byte) 0x6f, (byte) 0xde,
+ (byte) 0x9d, (byte) 0x71, (byte) 0xbf, (byte) 0x8d, (byte) 0x1b, (byte) 0x79,
+ (byte) 0xa0, (byte) 0x0a, (byte) 0x66, (byte) 0x7e, (byte) 0x56, (byte) 0x83,
+ (byte) 0x8f, (byte) 0x3f, (byte) 0x7d, (byte) 0x93, (byte) 0xf6, (byte) 0xc9,
+ (byte) 0x42, (byte) 0xfc, (byte) 0xc5, (byte) 0xf2, (byte) 0x49, (byte) 0xec};
+
+ @After
+ public void tearDown() {
+ try {
+ mDevicePolicyManager.removeKeyPair(mComponentName, mContext.getString(R.string.alias));
+ mDevicePolicyManager.clearDeviceOwnerApp(mContext.getPackageName());
+ } catch (Exception e) {
+ // ignore all exceptions as the test is already complete
+ }
+ }
+
+ @Test
+ public void testOverlayButtonPresence() {
+ try {
+ /* Install key pair required to launch KeyChainActivity dialog */
+ mContext = getInstrumentation().getContext();
+ Resources resources = mContext.getResources();
+ KeyFactory kf = KeyFactory.getInstance(mContext.getString(R.string.keyType));
+ PrivateKey privKey = kf.generatePrivate(new PKCS8EncodedKeySpec(PRIVATE_KEY));
+ CertificateFactory cf =
+ CertificateFactory.getInstance(mContext.getString(R.string.certType));
+ Certificate cert = cf.generateCertificate(new ByteArrayInputStream(USER_CERT));
+ mDevicePolicyManager = mContext.getSystemService(DevicePolicyManager.class);
+ mComponentName = new ComponentName(PocDeviceAdminReceiver.class.getPackage().getName(),
+ PocDeviceAdminReceiver.class.getName());
+ assumeTrue(mDevicePolicyManager.installKeyPair(mComponentName, privKey, cert,
+ mContext.getString(R.string.alias)));
+
+ /* Start the overlay service */
+ Intent intent = new Intent(mContext, PocService.class);
+ assumeTrue(mContext.getString(R.string.canNotDrawOverlaysMsg),
+ Settings.canDrawOverlays(mContext));
+ CompletableFuture<PocStatus> callbackReturn = new CompletableFuture<>();
+ RemoteCallback cb = new RemoteCallback((Bundle result) -> {
+ PocStatus pocStatus =
+ new PocStatus(result.getInt(mContext.getString(R.string.statusKey)),
+ result.getString(mContext.getString(R.string.messageKey)));
+ callbackReturn.complete(pocStatus);
+ });
+ intent.putExtra(mContext.getString(R.string.callbackKey), cb);
+ mContext.startService(intent);
+ PocStatus result = callbackReturn.get(resources.getInteger(R.integer.timeoutMs),
+ TimeUnit.MILLISECONDS);
+ assumeTrue(result.getErrorMessage(),
+ result.getStatusCode() != resources.getInteger(R.integer.assumptionFailure));
+
+ /* Wait for the overlay window */
+ Pattern overlayTextPattern = Pattern.compile(
+ mContext.getString(R.string.overlayButtonText), Pattern.CASE_INSENSITIVE);
+ UiDevice device = UiDevice.getInstance(getInstrumentation());
+ assumeTrue(mContext.getString(R.string.overlayUiScreenError),
+ device.wait(Until.hasObject(By.text(overlayTextPattern)),
+ mContext.getResources().getInteger(R.integer.timeoutMs)));
+
+ /* Start PocActivity which starts the vulnerable activity */
+ intent = new Intent(mContext, PocActivity.class);
+ intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+ CompletableFuture<PocStatus> pocActivityReturn = new CompletableFuture<>();
+ RemoteCallback pocActivityCb = new RemoteCallback((Bundle pocActivityResult) -> {
+ PocStatus pocStatus = new PocStatus(
+ pocActivityResult.getInt(mContext.getString(R.string.statusKey)),
+ pocActivityResult.getString(mContext.getString(R.string.messageKey)));
+ pocActivityReturn.complete(pocStatus);
+ });
+ intent.putExtra(mContext.getString(R.string.callbackKey), pocActivityCb);
+ mContext.startActivity(intent);
+ result = pocActivityReturn.get(resources.getInteger(R.integer.timeoutMs),
+ TimeUnit.MILLISECONDS);
+ assumeTrue(result.getErrorMessage(),
+ result.getStatusCode() != resources.getInteger(R.integer.assumptionFailure));
+
+ /* Get the vulnerable activity name by using an alternative intent */
+ Intent vulIntent = new Intent(mContext.getString(R.string.actionKeychainActivity));
+ ResolveInfo ri = mContext.getPackageManager().resolveActivity(vulIntent,
+ PackageManager.MATCH_DEFAULT_ONLY);
+ String vulnerableActivityName = ri.activityInfo.name;
+
+ /* Wait until the object of launcher activity is gone */
+ boolean overlayDisallowed = device.wait(Until.gone(By.pkg(mContext.getPackageName())),
+ mContext.getResources().getInteger(R.integer.timeoutMs));
+
+ /* Check if the currently running activity is the vulnerable activity */
+ String activityDump = "";
+ activityDump = device.executeShellCommand(
+ mContext.getString(R.string.dumpsysActivity, vulnerableActivityName));
+ Pattern activityPattern = Pattern.compile(mContext.getString(R.string.mResumedTrue),
+ Pattern.CASE_INSENSITIVE);
+ assumeTrue(
+ mContext.getString(R.string.vulActivityNotRunningError, vulnerableActivityName),
+ activityPattern.matcher(activityDump).find());
+
+ /* Failing the test as fix is not present */
+ assertTrue(mContext.getString(R.string.errorMessage, vulnerableActivityName),
+ overlayDisallowed);
+ } catch (Exception e) {
+ assumeNoException(e);
+ }
+ }
+}
diff --git a/hostsidetests/securitybulletin/test-apps/CVE-2021-0963/src/android/security/cts/CVE_2021_0963/PocActivity.java b/hostsidetests/securitybulletin/test-apps/CVE-2021-0963/src/android/security/cts/CVE_2021_0963/PocActivity.java
new file mode 100644
index 00000000000..ac8ea15c6e0
--- /dev/null
+++ b/hostsidetests/securitybulletin/test-apps/CVE-2021-0963/src/android/security/cts/CVE_2021_0963/PocActivity.java
@@ -0,0 +1,56 @@
+/*
+ * Copyright (C) 2022 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_2021_0963;
+
+import android.app.Activity;
+import android.os.Bundle;
+import android.os.RemoteCallback;
+import android.security.KeyChain;
+import android.security.KeyChainAliasCallback;
+
+import androidx.annotation.Nullable;
+
+public class PocActivity extends Activity {
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ try {
+ super.onCreate(savedInstanceState);
+ KeyChainAliasCallback callback = new KeyChainAliasCallback() {
+ @Override
+ public void alias(@Nullable String alias) {}
+ };
+ KeyChain.choosePrivateKeyAlias(this, callback, null, null, null, -1, null);
+ sendTestResult(getResources().getInteger(R.integer.noException), "");
+ } catch (Exception e) {
+ sendTestResult(getResources().getInteger(R.integer.assumptionFailure), e.getMessage());
+ }
+ }
+
+ void sendTestResult(int status, String message) {
+ try {
+ RemoteCallback cb =
+ (RemoteCallback) getIntent().getExtras().get(getString(R.string.callbackKey));
+ Bundle res = new Bundle();
+ res.putString(getString(R.string.messageKey), message);
+ res.putInt(getString(R.string.statusKey), status);
+ cb.sendResult(res);
+ } catch (Exception e) {
+ // ignore all exceptions
+ }
+ }
+}
diff --git a/hostsidetests/securitybulletin/test-apps/CVE-2021-0963/src/android/security/cts/CVE_2021_0963/PocDeviceAdminReceiver.java b/hostsidetests/securitybulletin/test-apps/CVE-2021-0963/src/android/security/cts/CVE_2021_0963/PocDeviceAdminReceiver.java
new file mode 100644
index 00000000000..5592323071b
--- /dev/null
+++ b/hostsidetests/securitybulletin/test-apps/CVE-2021-0963/src/android/security/cts/CVE_2021_0963/PocDeviceAdminReceiver.java
@@ -0,0 +1,22 @@
+/*
+ * Copyright (C) 2022 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_2021_0963;
+
+import android.app.admin.DeviceAdminReceiver;
+
+public class PocDeviceAdminReceiver extends DeviceAdminReceiver {
+}
diff --git a/hostsidetests/securitybulletin/test-apps/CVE-2021-0963/src/android/security/cts/CVE_2021_0963/PocService.java b/hostsidetests/securitybulletin/test-apps/CVE-2021-0963/src/android/security/cts/CVE_2021_0963/PocService.java
new file mode 100644
index 00000000000..b83e8247d54
--- /dev/null
+++ b/hostsidetests/securitybulletin/test-apps/CVE-2021-0963/src/android/security/cts/CVE_2021_0963/PocService.java
@@ -0,0 +1,99 @@
+/*
+ * Copyright (C) 2022 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_2021_0963;
+
+import android.app.Service;
+import android.content.Context;
+import android.content.Intent;
+import android.content.res.Resources;
+import android.graphics.PixelFormat;
+import android.os.Bundle;
+import android.os.IBinder;
+import android.os.RemoteCallback;
+import android.view.Gravity;
+import android.view.WindowManager;
+import android.view.WindowManager.LayoutParams;
+import android.widget.Button;
+
+public class PocService extends Service {
+ Button mButton;
+ WindowManager mWindowManager;
+ LayoutParams mLayoutParams;
+ Intent mIntent;
+
+ private static int getScreenWidth() {
+ return Resources.getSystem().getDisplayMetrics().widthPixels;
+ }
+
+ private static int getScreenHeight() {
+ return Resources.getSystem().getDisplayMetrics().heightPixels;
+ }
+
+ @Override
+ public IBinder onBind(Intent intent) {
+ return null;
+ }
+
+ @Override
+ public int onStartCommand(Intent intent, int flags, int startId) {
+ try {
+ mIntent = intent;
+ mWindowManager = getSystemService(WindowManager.class);
+ mLayoutParams = new LayoutParams();
+ mLayoutParams.type = LayoutParams.TYPE_APPLICATION_OVERLAY;
+ mLayoutParams.flags = LayoutParams.FLAG_NOT_TOUCH_MODAL |
+ LayoutParams.FLAG_NOT_FOCUSABLE;
+ mLayoutParams.format = PixelFormat.OPAQUE;
+ mLayoutParams.gravity = Gravity.LEFT | Gravity.TOP;
+ mLayoutParams.width = getScreenWidth();
+ mLayoutParams.height = getScreenHeight();
+ mLayoutParams.x = getScreenWidth() / 2;
+ mLayoutParams.y = getScreenHeight() / 2;
+ Context context = getApplicationContext();
+ mButton = new Button(context);
+ mButton.setText(context.getString(R.string.overlayButtonText));
+ mWindowManager.addView(mButton, mLayoutParams);
+ sendTestResult(getResources().getInteger(R.integer.noException), "");
+ } catch (Exception e) {
+ sendTestResult(getResources().getInteger(R.integer.assumptionFailure), e.getMessage());
+ }
+ return super.onStartCommand(intent, flags, startId);
+ }
+
+ @Override
+ public void onDestroy() {
+ try {
+ mWindowManager.removeView(mButton);
+ } catch (Exception e) {
+ sendTestResult(getResources().getInteger(R.integer.assumptionFailure), e.getMessage());
+ }
+ super.onDestroy();
+ }
+
+ void sendTestResult(int status, String message) {
+ try {
+ RemoteCallback cb =
+ (RemoteCallback) mIntent.getExtras().get(getString(R.string.callbackKey));
+ Bundle res = new Bundle();
+ res.putString(getString(R.string.messageKey), message);
+ res.putInt(getString(R.string.statusKey), status);
+ cb.sendResult(res);
+ } catch (Exception e) {
+ // ignore exception here
+ }
+ }
+}
diff --git a/hostsidetests/securitybulletin/test-apps/CVE-2021-0963/src/android/security/cts/CVE_2021_0963/PocStatus.java b/hostsidetests/securitybulletin/test-apps/CVE-2021-0963/src/android/security/cts/CVE_2021_0963/PocStatus.java
new file mode 100644
index 00000000000..de67f0ff104
--- /dev/null
+++ b/hostsidetests/securitybulletin/test-apps/CVE-2021-0963/src/android/security/cts/CVE_2021_0963/PocStatus.java
@@ -0,0 +1,35 @@
+/*
+ * Copyright (C) 2022 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_2021_0963;
+
+public class PocStatus {
+ int statusCode;
+ String errorMessage;
+
+ public PocStatus(int status, String message) {
+ statusCode = status;
+ errorMessage = message;
+ }
+
+ public int getStatusCode() {
+ return statusCode;
+ }
+
+ public String getErrorMessage() {
+ return errorMessage;
+ }
+}
diff --git a/hostsidetests/securitybulletin/test-apps/CVE-2022-20112/Android.bp b/hostsidetests/securitybulletin/test-apps/CVE-2022-20112/Android.bp
new file mode 100644
index 00000000000..cf3b7e26fb0
--- /dev/null
+++ b/hostsidetests/securitybulletin/test-apps/CVE-2022-20112/Android.bp
@@ -0,0 +1,38 @@
+/*
+ * Copyright (C) 2022 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-2022-20112",
+ defaults: [
+ "cts_support_defaults"
+ ],
+ srcs: [
+ "src/**/*.java"
+ ],
+ test_suites: [
+ "sts",
+ ],
+ static_libs: [
+ "androidx.test.core",
+ "androidx.test.rules",
+ ],
+ platform_apis: true,
+}
diff --git a/hostsidetests/securitybulletin/test-apps/CVE-2022-20112/AndroidManifest.xml b/hostsidetests/securitybulletin/test-apps/CVE-2022-20112/AndroidManifest.xml
new file mode 100644
index 00000000000..052a711b31e
--- /dev/null
+++ b/hostsidetests/securitybulletin/test-apps/CVE-2022-20112/AndroidManifest.xml
@@ -0,0 +1,22 @@
+<!--
+ Copyright 2022 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_2022_20112">
+ <instrumentation
+ android:name="androidx.test.runner.AndroidJUnitRunner"
+ android:targetPackage="android.security.cts.CVE_2022_20112" />
+</manifest>
diff --git a/hostsidetests/securitybulletin/test-apps/CVE-2022-20112/res/values/strings.xml b/hostsidetests/securitybulletin/test-apps/CVE-2022-20112/res/values/strings.xml
new file mode 100644
index 00000000000..af458479c47
--- /dev/null
+++ b/hostsidetests/securitybulletin/test-apps/CVE-2022-20112/res/values/strings.xml
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright (C) 2022 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.
+-->
+<resources>
+ <string name="defaultSettingsPkg">com.android.settings</string>
+ <string name="getAvailabilityStatusMethodName">getAvailabilityStatus</string>
+ <string name="privateDnsPreferenceControllerClassName">.network.PrivateDnsPreferenceController
+ </string>
+ <string name="testFailMsg">Device is vulnerable to b/206987762!! Private DNS can be modified in
+ guest mode</string>
+</resources>
diff --git a/hostsidetests/securitybulletin/test-apps/CVE-2022-20112/src/android/security/cts/CVE_2022_20112/DeviceTest.java b/hostsidetests/securitybulletin/test-apps/CVE-2022-20112/src/android/security/cts/CVE_2022_20112/DeviceTest.java
new file mode 100644
index 00000000000..96cb205134f
--- /dev/null
+++ b/hostsidetests/securitybulletin/test-apps/CVE-2022-20112/src/android/security/cts/CVE_2022_20112/DeviceTest.java
@@ -0,0 +1,90 @@
+/*
+ * Copyright (C) 2022 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_2022_20112;
+
+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.UiAutomation;
+import android.content.ComponentName;
+import android.content.Context;
+import android.content.Intent;
+import android.os.UserManager;
+import android.provider.Settings;
+
+import androidx.test.runner.AndroidJUnit4;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import java.lang.reflect.Constructor;
+import java.lang.reflect.Method;
+
+@RunWith(AndroidJUnit4.class)
+public class DeviceTest {
+
+ @Test
+ public void testprivateDnsPreferenceController() {
+ UiAutomation uiAutomation = null;
+ try {
+ Context context = getInstrumentation().getTargetContext();
+
+ // Retrieve settings package name dynamically
+ Intent settingsIntent = new Intent(Settings.ACTION_SETTINGS);
+ ComponentName settingsComponent =
+ settingsIntent.resolveActivity(context.getPackageManager());
+ String settingsPkgName = settingsComponent != null ? settingsComponent.getPackageName()
+ : context.getString(R.string.defaultSettingsPkg);
+
+ // Get vulnerable method 'getAvailabilityStatus' using reflection
+ Context settingsContext = context.createPackageContext(settingsPkgName,
+ Context.CONTEXT_INCLUDE_CODE | Context.CONTEXT_IGNORE_SECURITY);
+ ClassLoader settingsClassLoader = settingsContext.getClassLoader();
+ Class<?> privateDnsPreferenceControllerClass =
+ settingsClassLoader.loadClass(settingsPkgName
+ + context.getString(R.string.privateDnsPreferenceControllerClassName));
+ Constructor<?> privateDnsPreferenceControllerCstr =
+ privateDnsPreferenceControllerClass.getConstructor(Context.class);
+ Object privateDnsPreferenceControllerObject =
+ privateDnsPreferenceControllerCstr.newInstance(settingsContext);
+ Method getAvailabilityStatusMethod = privateDnsPreferenceControllerClass
+ .getDeclaredMethod(context.getString(R.string.getAvailabilityStatusMethodName));
+ getAvailabilityStatusMethod.setAccessible(true);
+
+ // Check if current user is guest user
+ uiAutomation = getInstrumentation().getUiAutomation();
+ uiAutomation.adoptShellPermissionIdentity(android.Manifest.permission.CREATE_USERS);
+ final UserManager userManager = context.getSystemService(UserManager.class);
+ assumeTrue(userManager.isGuestUser());
+
+ // Invoke vulnerable method 'getAvailabilityStatus'
+ int status =
+ (int) getAvailabilityStatusMethod.invoke(privateDnsPreferenceControllerObject);
+ assertFalse(context.getString(R.string.testFailMsg), status == 0 /* AVAILABLE */);
+ } catch (Exception e) {
+ assumeNoException(e);
+ } finally {
+ try {
+ uiAutomation.dropShellPermissionIdentity();
+ } catch (Exception ignored) {
+ // Ignore exception here
+ }
+ }
+ }
+}
diff --git a/hostsidetests/securitybulletin/test-apps/CVE-2022-20360/Android.bp b/hostsidetests/securitybulletin/test-apps/CVE-2022-20360/Android.bp
new file mode 100644
index 00000000000..d9f8554c32d
--- /dev/null
+++ b/hostsidetests/securitybulletin/test-apps/CVE-2022-20360/Android.bp
@@ -0,0 +1,38 @@
+/*
+ * Copyright (C) 2022 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-2022-20360",
+ defaults: [
+ "cts_support_defaults"
+ ],
+ srcs: [
+ "src/**/*.java"
+ ],
+ test_suites: [
+ "sts",
+ ],
+ static_libs: [
+ "androidx.test.core",
+ "androidx.test.rules",
+ ],
+ platform_apis: true,
+}
diff --git a/hostsidetests/securitybulletin/test-apps/CVE-2022-20360/AndroidManifest.xml b/hostsidetests/securitybulletin/test-apps/CVE-2022-20360/AndroidManifest.xml
new file mode 100644
index 00000000000..9e2361a9750
--- /dev/null
+++ b/hostsidetests/securitybulletin/test-apps/CVE-2022-20360/AndroidManifest.xml
@@ -0,0 +1,23 @@
+<!--
+ Copyright 2022 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_2022_20360">
+ <uses-permission android:name="android.permission.WRITE_SECURE_SETTINGS" />
+ <instrumentation
+ android:name="androidx.test.runner.AndroidJUnitRunner"
+ android:targetPackage="android.security.cts.CVE_2022_20360" />
+</manifest>
diff --git a/hostsidetests/securitybulletin/test-apps/CVE-2022-20360/res/values/strings.xml b/hostsidetests/securitybulletin/test-apps/CVE-2022-20360/res/values/strings.xml
new file mode 100644
index 00000000000..9476f7af344
--- /dev/null
+++ b/hostsidetests/securitybulletin/test-apps/CVE-2022-20360/res/values/strings.xml
@@ -0,0 +1,27 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright (C) 2022 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.
+-->
+<resources>
+ <string name="defaultSettingsPkg">com.android.settings</string>
+ <string name="disableSecureNfcFailed">Disabling secure NFC failed</string>
+ <string name="key">key</string>
+ <string name="msgDeviceLocked">Device is in sleep or locked mode</string>
+ <string name="msgTestFail"> Device is vulnerable to b/228314987!! Secure nfc can be disabled in
+ guest user via SettingsSlice</string>
+ <string name="secureNfcPreferenceControllerClassName">.nfc.SecureNfcPreferenceController
+ </string>
+ <string name="setCheckedMethod">setChecked</string>
+</resources>
diff --git a/hostsidetests/securitybulletin/test-apps/CVE-2022-20360/src/android/security/cts/CVE_2022_20360/DeviceTest.java b/hostsidetests/securitybulletin/test-apps/CVE-2022-20360/src/android/security/cts/CVE_2022_20360/DeviceTest.java
new file mode 100644
index 00000000000..9e73804e1b7
--- /dev/null
+++ b/hostsidetests/securitybulletin/test-apps/CVE-2022-20360/src/android/security/cts/CVE_2022_20360/DeviceTest.java
@@ -0,0 +1,119 @@
+/*
+ * Copyright (C) 2022 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_2022_20360;
+
+import static androidx.test.core.app.ApplicationProvider.getApplicationContext;
+import static androidx.test.platform.app.InstrumentationRegistry.getInstrumentation;
+
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assume.assumeFalse;
+import static org.junit.Assume.assumeNoException;
+import static org.junit.Assume.assumeTrue;
+
+import android.app.KeyguardManager;
+import android.app.UiAutomation;
+import android.content.ComponentName;
+import android.content.Context;
+import android.content.Intent;
+import android.nfc.NfcAdapter;
+import android.nfc.NfcManager;
+import android.os.PowerManager;
+import android.os.UserManager;
+import android.provider.Settings;
+
+import androidx.test.runner.AndroidJUnit4;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import java.lang.reflect.Constructor;
+import java.lang.reflect.Method;
+
+@RunWith(AndroidJUnit4.class)
+public class DeviceTest {
+
+ @Test
+ public void testSecureNfcPreferenceController() {
+ boolean secureNfcEnabled = false;
+ NfcAdapter nfcAdapter = null;
+ UiAutomation uiAutomation = null;
+ try {
+ Context context = getApplicationContext();
+ NfcManager nfcManager = context.getSystemService(NfcManager.class);
+ nfcAdapter = nfcManager.getDefaultAdapter();
+ uiAutomation = getInstrumentation().getUiAutomation();
+
+ // Secure NFC APIs require device to be unlocked hence check if device is unlocked
+ PowerManager powerManager = context.getSystemService(PowerManager.class);
+ KeyguardManager keyguardManager = context.getSystemService(KeyguardManager.class);
+ assumeTrue(context.getString(R.string.msgDeviceLocked),
+ powerManager.isInteractive() && !keyguardManager.isKeyguardLocked());
+
+
+ // Save secure NFC state(enabled/disabled) and disable secure NFC for test
+ secureNfcEnabled = nfcAdapter.isSecureNfcEnabled();
+ if (secureNfcEnabled) {
+ nfcAdapter.enableSecureNfc(false);
+ }
+ assumeFalse(context.getString(R.string.disableSecureNfcFailed),
+ nfcAdapter.isSecureNfcEnabled());
+
+ // Retrieve settings package name dynamically
+ Intent settingsIntent = new Intent(Settings.ACTION_SETTINGS);
+ ComponentName settingsComponent =
+ settingsIntent.resolveActivity(context.getPackageManager());
+ String settingsPkgName = settingsComponent != null ? settingsComponent.getPackageName()
+ : context.getString(R.string.defaultSettingsPkg);
+
+ // Get vulnerable method 'setChecked' using reflection
+ Context settingsContext = context.createPackageContext(settingsPkgName,
+ Context.CONTEXT_INCLUDE_CODE | Context.CONTEXT_IGNORE_SECURITY);
+ ClassLoader settingsClassLoader = settingsContext.getClassLoader();
+ Class<?> targetClass = settingsClassLoader.loadClass(settingsPkgName
+ + context.getString(R.string.secureNfcPreferenceControllerClassName));
+ Constructor<?> targetClassCstr =
+ targetClass.getConstructor(Context.class, String.class);
+ Object targetClassobject =
+ targetClassCstr.newInstance(context, context.getString(R.string.key));
+ Method setCheckedMethod = targetClass
+ .getDeclaredMethod(context.getString(R.string.setCheckedMethod), boolean.class);
+ setCheckedMethod.setAccessible(true);
+
+ // Check if current user is guest user
+ uiAutomation.adoptShellPermissionIdentity(android.Manifest.permission.CREATE_USERS);
+ UserManager userManager = context.getSystemService(UserManager.class);
+ assumeTrue(userManager.isGuestUser());
+
+ // Invoke vulnerable method 'setChecked'
+ boolean retVal = (boolean) setCheckedMethod.invoke(targetClassobject, true);
+ assertFalse(context.getString(R.string.msgTestFail), retVal);
+ } catch (Exception e) {
+ assumeNoException(e);
+ } finally {
+ try {
+ // Disable secure NFC if it was disabled before the test
+ if (!secureNfcEnabled) {
+ nfcAdapter.enableSecureNfc(false);
+ }
+ } catch (Exception ignored) {
+ // Ignore any exception here
+ } finally {
+ uiAutomation.dropShellPermissionIdentity();
+ }
+ }
+ }
+}
diff --git a/hostsidetests/securitybulletin/test-apps/CVE-2022-20415/Android.bp b/hostsidetests/securitybulletin/test-apps/CVE-2022-20415/Android.bp
new file mode 100644
index 00000000000..1ba587fb4aa
--- /dev/null
+++ b/hostsidetests/securitybulletin/test-apps/CVE-2022-20415/Android.bp
@@ -0,0 +1,36 @@
+/*
+ * 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-2022-20415",
+ defaults: ["cts_support_defaults"],
+ srcs: [
+ "src/**/*.java",
+ ],
+ test_suites: [
+ "sts",
+ ],
+ static_libs: [
+ "androidx.test.core",
+ "androidx.test.rules",
+ ],
+ sdk_version: "current",
+}
diff --git a/hostsidetests/securitybulletin/test-apps/CVE-2022-20415/AndroidManifest.xml b/hostsidetests/securitybulletin/test-apps/CVE-2022-20415/AndroidManifest.xml
new file mode 100644
index 00000000000..476cf0b26e6
--- /dev/null
+++ b/hostsidetests/securitybulletin/test-apps/CVE-2022-20415/AndroidManifest.xml
@@ -0,0 +1,31 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ 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_2022_20415">
+ <uses-permission android:name="android.permission.USE_FULL_SCREEN_INTENT" />
+ <uses-permission android:name="android.permission.POST_NOTIFICATIONS" />
+ <application>
+ <activity
+ android:name=".PocActivity"
+ android:exported="true">
+ </activity>
+ </application>
+ <instrumentation
+ android:name="androidx.test.runner.AndroidJUnitRunner"
+ android:targetPackage="android.security.cts.CVE_2022_20415" />
+</manifest>
diff --git a/hostsidetests/securitybulletin/test-apps/CVE-2022-20415/res/values/integers.xml b/hostsidetests/securitybulletin/test-apps/CVE-2022-20415/res/values/integers.xml
new file mode 100644
index 00000000000..f2cba3d0623
--- /dev/null
+++ b/hostsidetests/securitybulletin/test-apps/CVE-2022-20415/res/values/integers.xml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ 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.
+ -->
+<resources>
+ <integer name="height">50</integer>
+ <integer name="idSummaryNotification">0</integer>
+ <integer name="idTestNotification">1</integer>
+ <integer name="requestCodeIntent">0</integer>
+ <integer name="width">50</integer>
+</resources>
diff --git a/hostsidetests/securitybulletin/test-apps/CVE-2022-20415/res/values/strings.xml b/hostsidetests/securitybulletin/test-apps/CVE-2022-20415/res/values/strings.xml
new file mode 100644
index 00000000000..195d69661fe
--- /dev/null
+++ b/hostsidetests/securitybulletin/test-apps/CVE-2022-20415/res/values/strings.xml
@@ -0,0 +1,27 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ 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.
+ -->
+
+<resources>
+ <string name="idNotificationChannel">testId</string>
+ <string name="msgFailure">Device is vulnerable to b/231322873 !!</string>
+ <string name="nameBroadcastActionString">CVE_2022_20415_action</string>
+ <string name="nameNotificationChannel">b/231322873 notification</string>
+ <string name="tagNotify">NOTIFY_TAG</string>
+ <string name="textSummaryNotification">Summary Content</string>
+ <string name="titlePocNotification">PoC</string>
+ <string name="titleSummaryNotification">Summary Title</string>
+</resources>
diff --git a/hostsidetests/securitybulletin/test-apps/CVE-2022-20415/src/android/security/cts/CVE_2022_20415/DeviceTest.java b/hostsidetests/securitybulletin/test-apps/CVE-2022-20415/src/android/security/cts/CVE_2022_20415/DeviceTest.java
new file mode 100644
index 00000000000..687235100c6
--- /dev/null
+++ b/hostsidetests/securitybulletin/test-apps/CVE-2022-20415/src/android/security/cts/CVE_2022_20415/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_2022_20415;
+
+import static androidx.test.platform.app.InstrumentationRegistry.getInstrumentation;
+
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assume.assumeNoException;
+
+import android.app.Notification;
+import android.app.NotificationChannel;
+import android.app.NotificationManager;
+import android.app.PendingIntent;
+import android.content.BroadcastReceiver;
+import android.content.Context;
+import android.content.Intent;
+import android.content.IntentFilter;
+import android.content.res.Resources;
+import android.graphics.Bitmap;
+import android.graphics.Canvas;
+import android.graphics.Color;
+import android.graphics.drawable.Icon;
+
+import androidx.test.runner.AndroidJUnit4;
+
+import java.util.concurrent.Semaphore;
+import java.util.concurrent.TimeUnit;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+@RunWith(AndroidJUnit4.class)
+public class DeviceTest {
+ private Context mContext;
+ private NotificationManager mNotificationManager;
+ private Resources mResources;
+
+ Icon createNotificationIcon() {
+ Bitmap testBitmap = Bitmap.createBitmap(mResources.getInteger(R.integer.width),
+ mResources.getInteger(R.integer.height), Bitmap.Config.ARGB_8888);
+ final Canvas canvas = new Canvas(testBitmap);
+ canvas.drawColor(Color.BLUE);
+ return Icon.createWithBitmap(testBitmap);
+ }
+
+ public void tryNotificationStart() throws Exception {
+ Icon icon = createNotificationIcon();
+ PendingIntent pendingIntent = PendingIntent.getActivity(mContext,
+ mResources.getInteger(R.integer.requestCodeIntent),
+ new Intent(mContext, PocActivity.class), PendingIntent.FLAG_IMMUTABLE);
+ NotificationChannel notificationChannel =
+ new NotificationChannel(mContext.getString(R.string.idNotificationChannel),
+ mContext.getString(R.string.nameNotificationChannel),
+ NotificationManager.IMPORTANCE_MAX);
+ notificationChannel.setDescription(mContext.getString(R.string.nameNotificationChannel));
+ mNotificationManager.createNotificationChannel(notificationChannel);
+ Notification summaryNotification = new Notification.Builder(mContext,
+ mContext.getString(R.string.idNotificationChannel))
+ .setContentTitle(mContext.getString(R.string.titleSummaryNotification))
+ .setContentText(mContext.getString(R.string.textSummaryNotification))
+ .setSmallIcon(icon).setGroup(mContext.getPackageName())
+ .setGroupSummary(true /* make summaryNotification a group summary */)
+ .build();
+ Notification pocNotification = new Notification.Builder(mContext,
+ mContext.getString(R.string.idNotificationChannel)).setSmallIcon(icon)
+ .setContentTitle(mContext.getString(R.string.titlePocNotification))
+ .setGroupAlertBehavior(Notification.GROUP_ALERT_SUMMARY)
+ .setGroup(mContext.getPackageName())
+ .setFullScreenIntent(pendingIntent, true /* high priority */).build();
+
+ mNotificationManager.notify(mContext.getString(R.string.tagNotify),
+ mResources.getInteger(R.integer.idTestNotification), pocNotification);
+ mNotificationManager.notify(mResources.getInteger(R.integer.idSummaryNotification),
+ summaryNotification);
+ }
+
+ @Test
+ public void testFullScreenIntent() {
+ try {
+ mContext = getInstrumentation().getTargetContext();
+ mNotificationManager = mContext.getSystemService(NotificationManager.class);
+ mResources = mContext.getResources();
+ Semaphore mBroadcastReceived = new Semaphore(0);
+ int timeoutMs = 20000;
+
+ // Register a broadcast receiver to receive broadcast from PocActivity indicating
+ // presence of vulnerability
+ BroadcastReceiver broadcastReceiver = new BroadcastReceiver() {
+ @Override
+ public void onReceive(Context context, Intent intent) {
+ try {
+ if (intent.getAction()
+ .equals(mContext.getString(R.string.nameBroadcastActionString))) {
+ mBroadcastReceived.release();
+ }
+ } catch (Exception ignored) {
+ // ignore any exceptions
+ }
+ }
+ };
+ IntentFilter filter =
+ new IntentFilter(mContext.getString(R.string.nameBroadcastActionString));
+ mContext.registerReceiver(broadcastReceiver, filter);
+
+ tryNotificationStart();
+ assertFalse(mContext.getString(R.string.msgFailure),
+ mBroadcastReceived.tryAcquire(timeoutMs, TimeUnit.MILLISECONDS));
+ } catch (Exception e) {
+ assumeNoException(e);
+ } finally {
+ try {
+ mNotificationManager.cancel(mResources.getInteger(R.integer.idSummaryNotification));
+ mNotificationManager.cancel(mContext.getString(R.string.tagNotify),
+ mResources.getInteger(R.integer.idTestNotification));
+ } catch (Exception e) {
+ // ignore this exception
+ }
+ }
+ }
+}
diff --git a/hostsidetests/securitybulletin/test-apps/CVE-2022-20415/src/android/security/cts/CVE_2022_20415/PocActivity.java b/hostsidetests/securitybulletin/test-apps/CVE-2022-20415/src/android/security/cts/CVE_2022_20415/PocActivity.java
new file mode 100644
index 00000000000..5afa1914562
--- /dev/null
+++ b/hostsidetests/securitybulletin/test-apps/CVE-2022-20415/src/android/security/cts/CVE_2022_20415/PocActivity.java
@@ -0,0 +1,36 @@
+/*
+ * 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_2022_20415;
+
+import android.app.Activity;
+import android.content.Intent;
+import android.os.Bundle;
+
+public class PocActivity extends Activity {
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ try {
+ super.onCreate(savedInstanceState);
+ // PocActivity has been launched successfully, this indicates presence of vulnerability
+ // so broadcasting it to DeviceTest.
+ sendBroadcast(new Intent(getString(R.string.nameBroadcastActionString)));
+ } catch (Exception e) {
+ // ignore any exceptions
+ }
+ }
+}
diff --git a/hostsidetests/securitybulletin/test-apps/CVE-2021-0642/Android.bp b/hostsidetests/securitybulletin/test-apps/CVE-2023-20913/Android.bp
index 770b5a2089e..81ce65dffbd 100644
--- a/hostsidetests/securitybulletin/test-apps/CVE-2021-0642/Android.bp
+++ b/hostsidetests/securitybulletin/test-apps/CVE-2023-20913/Android.bp
@@ -15,12 +15,18 @@
*
*/
+package {
+ default_applicable_licenses: ["Android-Apache-2.0"],
+}
+
android_test_helper_app {
- name: "CVE-2021-0642",
+ name: "CVE-2023-20913",
defaults: [
"cts_support_defaults",
],
- srcs: ["src/**/*.java"],
+ srcs: [
+ "src/**/*.java",
+ ],
test_suites: [
"sts",
],
@@ -29,5 +35,4 @@ android_test_helper_app {
"androidx.test.rules",
"androidx.test.uiautomator_uiautomator",
],
- sdk_version: "current",
}
diff --git a/hostsidetests/securitybulletin/test-apps/CVE-2023-20913/AndroidManifest.xml b/hostsidetests/securitybulletin/test-apps/CVE-2023-20913/AndroidManifest.xml
new file mode 100644
index 00000000000..5617874ad3d
--- /dev/null
+++ b/hostsidetests/securitybulletin/test-apps/CVE-2023-20913/AndroidManifest.xml
@@ -0,0 +1,27 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright 2022 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_20913">
+ <uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW" />
+ <application>
+ <service android:name=".PocService" />
+ </application>
+ <instrumentation
+ android:name="androidx.test.runner.AndroidJUnitRunner"
+ android:targetPackage="android.security.cts.CVE_2023_20913" />
+</manifest>
diff --git a/hostsidetests/securitybulletin/test-apps/CVE-2023-20913/res/values/strings.xml b/hostsidetests/securitybulletin/test-apps/CVE-2023-20913/res/values/strings.xml
new file mode 100644
index 00000000000..dc0aa2a5932
--- /dev/null
+++ b/hostsidetests/securitybulletin/test-apps/CVE-2023-20913/res/values/strings.xml
@@ -0,0 +1,35 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright (C) 2022 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.
+-->
+
+<resources>
+ <string name="activityAccessibilitySettings">.settings.AccessibilitySettingsActivity</string>
+ <string name="activityPhoneAccountSettings">.settings.PhoneAccountSettingsActivity</string>
+ <string name="activityVoicemailSettings">.settings.VoicemailSettingsActivity</string>
+ <string name="dumpsysActivityCmd">dumpsys activity %1$s</string>
+ <string name="mResumedTrue">mResumed=true</string>
+ <string name="msgActivityNotFound">The activity with intent %1$s was not found</string>
+ <string name="msgAssumptionFailure">Following assumption failures occurred: </string>
+ <string name="msgCannotDrawOverlays">The application cannot draw overlays</string>
+ <string name="msgDeviceLocked">Device is in sleep or locked mode</string>
+ <string name="msgOverlayError">Device is vulnerable to b/246933785 hence any app with
+ "SYSTEM_ALERT_WINDOW permission" can overlay the following activities: </string>
+ <string name="overlayUiScreenError">Overlay UI did not appear on the screen</string>
+ <string name="pkgDefaultTelephony">com.android.phone</string>
+ <string name="textOverlayButton">b_246933785 OverlayButton</string>
+ <string name="vulActivityNotRunningError">The %1$s is not currently running on the device
+ </string>
+</resources>
diff --git a/hostsidetests/securitybulletin/test-apps/CVE-2023-20913/src/android/security/cts/CVE_2023_20913/DeviceTest.java b/hostsidetests/securitybulletin/test-apps/CVE-2023-20913/src/android/security/cts/CVE_2023_20913/DeviceTest.java
new file mode 100644
index 00000000000..49b26be5911
--- /dev/null
+++ b/hostsidetests/securitybulletin/test-apps/CVE-2023-20913/src/android/security/cts/CVE_2023_20913/DeviceTest.java
@@ -0,0 +1,161 @@
+/*
+ * Copyright (C) 2022 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_20913;
+
+import static androidx.test.platform.app.InstrumentationRegistry.getInstrumentation;
+
+import static org.junit.Assert.fail;
+import static org.junit.Assume.assumeNoException;
+import static org.junit.Assume.assumeTrue;
+
+import android.app.KeyguardManager;
+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.PowerManager;
+import android.os.UserHandle;
+import android.provider.Settings;
+import android.telecom.TelecomManager;
+
+import androidx.test.runner.AndroidJUnit4;
+import androidx.test.uiautomator.By;
+import androidx.test.uiautomator.UiDevice;
+import androidx.test.uiautomator.Until;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.regex.Pattern;
+
+@RunWith(AndroidJUnit4.class)
+public class DeviceTest {
+ private Context mContext = null;
+ private List<String> mViolations;
+ private List<String> mVulnerabilities;
+ PackageManager mPackageManager = null;
+
+ private String getTelephonyPackageName() {
+ UiAutomation ui = getInstrumentation().getUiAutomation();
+ String name = mContext.getString(R.string.pkgDefaultTelephony);
+ try {
+ ui.adoptShellPermissionIdentity(android.Manifest.permission.INTERACT_ACROSS_USERS);
+ Intent intent = new Intent(TelecomManager.ACTION_CHANGE_PHONE_ACCOUNTS);
+ ResolveInfo info = mPackageManager.resolveActivityAsUser(intent,
+ PackageManager.MATCH_SYSTEM_ONLY, UserHandle.USER_SYSTEM);
+ name = info.activityInfo.packageName;
+ } catch (Exception e) {
+ assumeNoException(e);
+ } finally {
+ ui.dropShellPermissionIdentity();
+ }
+ return name;
+ }
+
+ public void testActivity(String cls) throws Exception {
+ UiDevice device = null;
+ try {
+ mPackageManager = mContext.getPackageManager();
+ device = UiDevice.getInstance(getInstrumentation());
+
+ // Start the overlay service
+ Intent serviceIntent = new Intent(mContext, PocService.class);
+ assumeTrue(mContext.getString(R.string.msgCannotDrawOverlays),
+ Settings.canDrawOverlays(mContext));
+ mContext.startService(serviceIntent);
+
+ // Wait for the overlay window
+ Pattern overlayTextPattern = Pattern.compile(
+ mContext.getString(R.string.textOverlayButton), Pattern.CASE_INSENSITIVE);
+ final long launchTimeoutMs = 20_000L;
+ if (!device.wait(Until.hasObject(By.text(overlayTextPattern)), launchTimeoutMs)) {
+ mViolations.add(cls + mContext.getString(R.string.overlayUiScreenError));
+ return;
+ }
+
+ // Start the vulnerable activity
+ String pkg = getTelephonyPackageName();
+ Intent intent = new Intent();
+ String vulActivity = pkg + cls;
+ intent.setClassName(pkg, vulActivity);
+ ResolveInfo ri =
+ mPackageManager.resolveActivity(intent, PackageManager.MATCH_DEFAULT_ONLY);
+ if (ri == null) {
+ mViolations.add(cls + mContext.getString(R.string.msgActivityNotFound, intent));
+ return;
+ }
+ intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK);
+ mContext.startActivity(intent);
+
+ // Wait until overlay window is gone
+ boolean overlayDisallowed =
+ device.wait(Until.gone(By.text(overlayTextPattern)), launchTimeoutMs);
+
+ // Check if the currently running activity is the vulnerable activity
+ String activityDump = device.executeShellCommand(
+ mContext.getString(R.string.dumpsysActivityCmd, vulActivity));
+ Pattern activityPattern = Pattern.compile(mContext.getString(R.string.mResumedTrue),
+ Pattern.CASE_INSENSITIVE);
+ if (!(activityPattern.matcher(activityDump).find())) {
+ mViolations.add(
+ cls + mContext.getString(R.string.vulActivityNotRunningError, vulActivity));
+ return;
+ }
+
+ // If overlayDisallowed is not true then add the class name to mVulnerabilities
+ if (!overlayDisallowed) {
+ mVulnerabilities.add(cls);
+ }
+ } catch (Exception e) {
+ mViolations.add(e.getMessage());
+ } finally {
+ try {
+ // To exit current activity so that new activity starts
+ device.pressHome();
+ } catch (Exception e) {
+ // Ignoring exceptions here since any exception caught here is unrelated to test
+ }
+ }
+ }
+
+ @Test
+ public void testOverlayButtonPresence() {
+ try {
+ mContext = getInstrumentation().getTargetContext();
+ KeyguardManager keyguardManager = mContext.getSystemService(KeyguardManager.class);
+ PowerManager powerManager = mContext.getSystemService(PowerManager.class);
+ assumeTrue(mContext.getString(R.string.msgDeviceLocked),
+ powerManager.isInteractive() && !keyguardManager.isKeyguardLocked());
+ mViolations = new ArrayList<String>();
+ mVulnerabilities = new ArrayList<String>();
+ testActivity(mContext.getString(R.string.activityAccessibilitySettings));
+ testActivity(mContext.getString(R.string.activityPhoneAccountSettings));
+ testActivity(mContext.getString(R.string.activityVoicemailSettings));
+ if (mVulnerabilities.isEmpty()) {
+ assumeTrue(mContext.getString(R.string.msgAssumptionFailure) + mViolations,
+ mViolations.isEmpty());
+ } else {
+ fail(mContext.getString(R.string.msgOverlayError) + mVulnerabilities);
+ }
+ } catch (Exception e) {
+ assumeNoException(e);
+ }
+ }
+}
diff --git a/hostsidetests/securitybulletin/test-apps/CVE-2023-20913/src/android/security/cts/CVE_2023_20913/PocService.java b/hostsidetests/securitybulletin/test-apps/CVE-2023-20913/src/android/security/cts/CVE_2023_20913/PocService.java
new file mode 100644
index 00000000000..6ac55d98cff
--- /dev/null
+++ b/hostsidetests/securitybulletin/test-apps/CVE-2023-20913/src/android/security/cts/CVE_2023_20913/PocService.java
@@ -0,0 +1,75 @@
+/*
+ * Copyright (C) 2022 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_20913;
+
+import android.app.Service;
+import android.content.Intent;
+import android.content.res.Resources;
+import android.graphics.PixelFormat;
+import android.os.IBinder;
+import android.util.DisplayMetrics;
+import android.view.Gravity;
+import android.view.WindowManager;
+import android.view.WindowManager.LayoutParams;
+import android.widget.Button;
+
+public class PocService extends Service {
+ private Button mButton;
+ private WindowManager mWindowManager;
+
+ @Override
+ public void onCreate() {
+ try {
+ super.onCreate();
+ mWindowManager = getSystemService(WindowManager.class);
+ LayoutParams layoutParams = new LayoutParams();
+ layoutParams.type = LayoutParams.TYPE_APPLICATION_OVERLAY;
+ layoutParams.flags =
+ LayoutParams.FLAG_NOT_TOUCH_MODAL | LayoutParams.FLAG_NOT_FOCUSABLE;
+ layoutParams.format = PixelFormat.OPAQUE;
+ layoutParams.gravity = Gravity.LEFT | Gravity.TOP;
+ DisplayMetrics displayMetrics = Resources.getSystem().getDisplayMetrics();
+ layoutParams.width = displayMetrics.widthPixels;
+ layoutParams.height = displayMetrics.heightPixels;
+ layoutParams.x = displayMetrics.widthPixels / 2;
+ layoutParams.y = displayMetrics.heightPixels / 2;
+
+ // Show the floating window
+ mButton = new Button(this);
+ mButton.setText(getString(R.string.textOverlayButton));
+ mWindowManager.addView(mButton, layoutParams);
+ } catch (Exception ignored) {
+ // In case of occurrence of an exception overlay won't appear on display which results
+ // in assumption failure in device test. Hence ignoring this exception here.
+ }
+ }
+
+ @Override
+ public IBinder onBind(Intent intent) {
+ return null;
+ }
+
+ @Override
+ public void onDestroy() {
+ try {
+ mWindowManager.removeView(mButton);
+ super.onDestroy();
+ } catch (Exception ignored) {
+ // Ignoring unintended exceptions
+ }
+ }
+}
diff --git a/hostsidetests/securitybulletin/test-apps/CVE-2023-20918/attacker-app/Android.bp b/hostsidetests/securitybulletin/test-apps/CVE-2023-20918/attacker-app/Android.bp
new file mode 100644
index 00000000000..af4ad21c319
--- /dev/null
+++ b/hostsidetests/securitybulletin/test-apps/CVE-2023-20918/attacker-app/Android.bp
@@ -0,0 +1,35 @@
+/*
+ * Copyright (C) 2022 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-20918-attacker",
+ defaults: [
+ "cts_support_defaults",
+ ],
+ srcs: [
+ "src/**/*.java",
+ ],
+ test_suites: [
+ "sts",
+ ],
+ // platform_apis set to true here to access hidden method setPendingIntentLaunchFlags
+ platform_apis: true,
+}
diff --git a/hostsidetests/securitybulletin/test-apps/CVE-2023-20918/attacker-app/AndroidManifest.xml b/hostsidetests/securitybulletin/test-apps/CVE-2023-20918/attacker-app/AndroidManifest.xml
new file mode 100644
index 00000000000..bcc3ad1373a
--- /dev/null
+++ b/hostsidetests/securitybulletin/test-apps/CVE-2023-20918/attacker-app/AndroidManifest.xml
@@ -0,0 +1,23 @@
+<!--
+ Copyright 2022 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_20918_attacker">
+ <application>
+ <activity android:name=".ExploitActivity"
+ android:exported="true" />
+ </application>
+</manifest>
diff --git a/hostsidetests/securitybulletin/test-apps/CVE-2023-20918/attacker-app/res/values/strings.xml b/hostsidetests/securitybulletin/test-apps/CVE-2023-20918/attacker-app/res/values/strings.xml
new file mode 100644
index 00000000000..9523eca2ace
--- /dev/null
+++ b/hostsidetests/securitybulletin/test-apps/CVE-2023-20918/attacker-app/res/values/strings.xml
@@ -0,0 +1,27 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright 2022 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.
+ -->
+
+<resources>
+ <string name="bcastActionTestAssumeFail">CVE_2023_20918_assume_fail_action</string>
+ <string name="bcastActionTestFail">CVE_2023_20918_test_fail_action</string>
+ <string name="bcastActionTestPass">CVE_2023_20918_test_pass_action</string>
+ <string name="contentUri">content://authority_CVE_2023_20918_test/file_path/poc.txt</string>
+ <string name="expActivityExploit">Got an exception in ExploitActivity with message: %1$s
+ </string>
+ <string name="keyMsgAssumeFail">msg</string>
+ <string name="keyPendingIntent">pi</string>
+</resources>
diff --git a/hostsidetests/securitybulletin/test-apps/CVE-2023-20918/attacker-app/src/android/security/cts/CVE_2023_20918_attacker/ExploitActivity.java b/hostsidetests/securitybulletin/test-apps/CVE-2023-20918/attacker-app/src/android/security/cts/CVE_2023_20918_attacker/ExploitActivity.java
new file mode 100644
index 00000000000..1693cac7b68
--- /dev/null
+++ b/hostsidetests/securitybulletin/test-apps/CVE-2023-20918/attacker-app/src/android/security/cts/CVE_2023_20918_attacker/ExploitActivity.java
@@ -0,0 +1,83 @@
+/*
+ * Copyright (C) 2022 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_20918_attacker;
+
+import android.app.Activity;
+import android.app.ActivityOptions;
+import android.app.PendingIntent;
+import android.content.Intent;
+import android.net.Uri;
+import android.os.Bundle;
+
+public class ExploitActivity extends Activity {
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ try {
+ super.onCreate(savedInstanceState);
+ Intent intent = getIntent();
+ final String keyPendingIntent = getString(R.string.keyPendingIntent);
+
+ // If intent contains 'keyPendingIntent', then this activity is launched again using
+ // the custom intent that the extra 'keyPendingIntent' holds.
+ if (intent.hasExtra(keyPendingIntent)) {
+ PendingIntent activity = intent.getParcelableExtra(keyPendingIntent);
+ ActivityOptions options = ActivityOptions.makeBasic();
+ options.setPendingIntentLaunchFlags(Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
+ activity.send(this, 0, null, null, null, "", options.toBundle());
+ } else if (intent.getData() != null) {
+ // Control goes in this block when the activity is launched again. Attempting to
+ // open uri data received from the intent.
+ Uri data = intent.getData();
+ getContentResolver().openOutputStream(data);
+
+ // If control reaches here, then it means that openOutputStream() did not raise an
+ // exception, this indicates that FLAG_GRANT_WRITE_URI_PERMISSION has been granted
+ // so sending a broadcast to DeviceTest with the test_fail status.
+ sendBroadcastToTestApp(getString(R.string.bcastActionTestFail));
+ }
+ } catch (Exception e) {
+ if (e instanceof SecurityException
+ && e.getMessage().contains(getString(R.string.keyPendingIntent))) {
+ // ignoring this exception since it occurs with fix
+ sendBroadcastToTestApp(getString(R.string.bcastActionTestPass));
+ return;
+ }
+
+ // Sending a broadcast to DeviceTest to indicate assumption failure status,
+ // since an exception was raised unrelated to the vulnerability
+ sendBroadcastToTestApp(getString(R.string.bcastActionTestAssumeFail),
+ getString(R.string.expActivityExploit, e.getMessage()));
+ }
+ }
+
+ public void sendBroadcastToTestApp(String action) {
+ sendBroadcastToTestApp(action, null);
+ }
+
+ public void sendBroadcastToTestApp(String action, String assumeFailMsg) {
+ try {
+ Intent intent = new Intent(action);
+ if (assumeFailMsg != null) {
+ intent.putExtra(getString(R.string.keyMsgAssumeFail), assumeFailMsg);
+ }
+ sendBroadcast(intent);
+ } catch (Exception ignored) {
+ // ignore the exceptions
+ }
+ }
+}
diff --git a/hostsidetests/securitybulletin/test-apps/CVE-2023-20918/test-app/Android.bp b/hostsidetests/securitybulletin/test-apps/CVE-2023-20918/test-app/Android.bp
new file mode 100644
index 00000000000..a32ae6c9dee
--- /dev/null
+++ b/hostsidetests/securitybulletin/test-apps/CVE-2023-20918/test-app/Android.bp
@@ -0,0 +1,40 @@
+/*
+ * Copyright (C) 2022 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-20918-test",
+ defaults: [
+ "cts_support_defaults",
+ ],
+ srcs: [
+ "src/**/*.java",
+ ],
+ test_suites: [
+ "sts",
+ ],
+ static_libs: [
+ "androidx.test.core",
+ "androidx.test.rules",
+ // including this to use androidx.core.content.FileProvider
+ "androidx.legacy_legacy-support-v4",
+ ],
+ sdk_version: "current",
+}
diff --git a/hostsidetests/securitybulletin/test-apps/CVE-2023-20918/test-app/AndroidManifest.xml b/hostsidetests/securitybulletin/test-apps/CVE-2023-20918/test-app/AndroidManifest.xml
new file mode 100644
index 00000000000..b95b6d7a52c
--- /dev/null
+++ b/hostsidetests/securitybulletin/test-apps/CVE-2023-20918/test-app/AndroidManifest.xml
@@ -0,0 +1,29 @@
+<!--
+ Copyright 2022 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_20918_test">
+ <application>
+ <provider android:name="androidx.core.content.FileProvider"
+ android:authorities="authority_CVE_2023_20918_test"
+ android:grantUriPermissions="true">
+ <meta-data android:name="android.support.FILE_PROVIDER_PATHS"
+ android:resource="@xml/file_paths" />
+ </provider>
+ </application>
+ <instrumentation android:name="androidx.test.runner.AndroidJUnitRunner"
+ android:targetPackage="android.security.cts.CVE_2023_20918_test" />
+</manifest>
diff --git a/hostsidetests/securitybulletin/test-apps/CVE-2023-20918/test-app/res/values/strings.xml b/hostsidetests/securitybulletin/test-apps/CVE-2023-20918/test-app/res/values/strings.xml
new file mode 100644
index 00000000000..40b8d361140
--- /dev/null
+++ b/hostsidetests/securitybulletin/test-apps/CVE-2023-20918/test-app/res/values/strings.xml
@@ -0,0 +1,31 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright 2022 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.
+ -->
+
+<resources>
+ <string name="activityExploit">android.security.cts.CVE_2023_20918_attacker.ExploitActivity
+ </string>
+ <string name="bcastActionTestAssumeFail">CVE_2023_20918_assume_fail_action</string>
+ <string name="bcastActionTestFail">CVE_2023_20918_test_fail_action</string>
+ <string name="bcastActionTestPass">CVE_2023_20918_test_pass_action</string>
+ <string name="contentUri">content://authority_CVE_2023_20918_test/file_path/poc.txt</string>
+ <string name="fileContents">This is a read only file\n</string>
+ <string name="keyMsgAssumeFail">msg</string>
+ <string name="keyPendingIntent">pi</string>
+ <string name="msgAssumeFailDefault">Got an exception in DeviceTest.java</string>
+ <string name="msgFail">Device is vulnerable to b/243794108 !!</string>
+ <string name="pkgAttacker">android.security.cts.CVE_2023_20918_attacker</string>
+</resources>
diff --git a/hostsidetests/securitybulletin/test-apps/CVE-2023-20918/test-app/res/xml/file_paths.xml b/hostsidetests/securitybulletin/test-apps/CVE-2023-20918/test-app/res/xml/file_paths.xml
new file mode 100644
index 00000000000..dd4259b19db
--- /dev/null
+++ b/hostsidetests/securitybulletin/test-apps/CVE-2023-20918/test-app/res/xml/file_paths.xml
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright 2022 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.
+ -->
+
+<paths>
+ <files-path name="file_path" path="./" />
+</paths>
diff --git a/hostsidetests/securitybulletin/test-apps/CVE-2023-20918/test-app/src/android/security/cts/CVE_2023_20918_test/DeviceTest.java b/hostsidetests/securitybulletin/test-apps/CVE-2023-20918/test-app/src/android/security/cts/CVE_2023_20918_test/DeviceTest.java
new file mode 100644
index 00000000000..e677938d6ba
--- /dev/null
+++ b/hostsidetests/securitybulletin/test-apps/CVE-2023-20918/test-app/src/android/security/cts/CVE_2023_20918_test/DeviceTest.java
@@ -0,0 +1,118 @@
+/*
+ * Copyright (C) 2022 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_20918_test;
+
+import static androidx.test.core.app.ApplicationProvider.getApplicationContext;
+
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assume.assumeNoException;
+
+import android.app.PendingIntent;
+import android.content.BroadcastReceiver;
+import android.content.Context;
+import android.content.Intent;
+import android.content.IntentFilter;
+import android.net.Uri;
+
+import androidx.test.runner.AndroidJUnit4;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import java.io.OutputStream;
+import java.nio.charset.StandardCharsets;
+import java.util.concurrent.CompletableFuture;
+import java.util.concurrent.TimeUnit;
+
+@RunWith(AndroidJUnit4.class)
+public class DeviceTest {
+ private static final long TIMEOUT_MS = 10_000L;
+ private String mAssumeFailMsg;
+
+ @Test
+ public void testCVE_2023_20918() {
+ try {
+ Context context = getApplicationContext();
+ mAssumeFailMsg = context.getString(R.string.msgAssumeFailDefault);
+ final CompletableFuture<Boolean> exploitActivityReturn = new CompletableFuture<>();
+ final String bcastActionFail = context.getString(R.string.bcastActionTestFail);
+ final String bcastActionPass = context.getString(R.string.bcastActionTestPass);
+ final String bcastActionAssumeFail =
+ context.getString(R.string.bcastActionTestAssumeFail);
+
+ // Register a broadcast receiver to receive broadcast from ExploitActivity indicating
+ // presence of vulnerability
+ BroadcastReceiver broadcastReceiver = new BroadcastReceiver() {
+ @Override
+ public void onReceive(Context context, Intent intent) {
+ try {
+ if (intent.getAction().equals(bcastActionFail)) {
+ exploitActivityReturn.complete(true);
+ } else if (intent.getAction().equals(bcastActionPass)) {
+ exploitActivityReturn.complete(false);
+ } else if (intent.getAction().equals(bcastActionAssumeFail)) {
+ // mAssumeFailMsg set here is used in assumeNoException() triggered
+ // when exploitActivityReturn.get() raises a timeout exception
+ mAssumeFailMsg = intent
+ .getStringExtra(context.getString(R.string.keyMsgAssumeFail));
+ }
+ } catch (Exception ignored) {
+ // ignore the exceptions
+ }
+ }
+ };
+ IntentFilter filter = new IntentFilter();
+ filter.addAction(bcastActionFail);
+ filter.addAction(bcastActionPass);
+ filter.addAction(bcastActionAssumeFail);
+ context.registerReceiver(broadcastReceiver, filter);
+
+ // Write some data to the Uri content://authority/file_path/poc.txt
+ final String uriString = context.getString(R.string.contentUri);
+ try (OutputStream outputStream =
+ context.getContentResolver().openOutputStream(Uri.parse(uriString));) {
+ outputStream.write(
+ context.getString(R.string.fileContents).getBytes(StandardCharsets.UTF_8));
+ }
+
+ // Creating an intent to launch ExploitActivity
+ Intent intent = new Intent();
+ final String attackerPkg = context.getString(R.string.pkgAttacker);
+ final String exploitActivity = context.getString(R.string.activityExploit);
+ intent.setClassName(attackerPkg, exploitActivity);
+ intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+
+ // Creating the inner intent for PendingIntent
+ Intent innerIntent = new Intent(Intent.ACTION_MAIN, Uri.parse(uriString));
+ innerIntent.setClassName(attackerPkg, exploitActivity);
+ innerIntent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
+ innerIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+
+ // Launch the ExploitActivity passing PendingIntent as data
+ intent.putExtra(context.getString(R.string.keyPendingIntent), PendingIntent
+ .getActivity(context, 0, innerIntent, PendingIntent.FLAG_IMMUTABLE));
+ context.startActivity(intent);
+
+ // On vulnerable device, the PendingIntent launchIntentFlags will be added even though
+ // it is immutable, so the test should fail if the flags are found to take effect.
+ assertFalse(context.getString(R.string.msgFail),
+ exploitActivityReturn.get(TIMEOUT_MS, TimeUnit.MILLISECONDS));
+ } catch (Exception e) {
+ assumeNoException(mAssumeFailMsg, e);
+ }
+ }
+}
diff --git a/tests/app/AndroidManifest.xml b/tests/app/AndroidManifest.xml
index 4ff6cb27df2..97e6fd649f3 100644
--- a/tests/app/AndroidManifest.xml
+++ b/tests/app/AndroidManifest.xml
@@ -27,6 +27,10 @@
<application android:usesCleartextTraffic="true">
<uses-library android:name="android.test.runner" />
<uses-library android:name="org.apache.http.legacy" android:required="false" />
+
+ <service android:name=".InstrumentationHelperService"
+ android:exported="true"
+ android:process=":helper" />
</application>
<instrumentation android:name="androidx.test.runner.AndroidJUnitRunner"
@@ -55,4 +59,11 @@
android:targetProcesses="com.android.cts.launcherapps.simpleapp:other,com.android.cts.launcherapps.simpleapp">
</instrumentation>
+ <instrumentation android:name=".ChainedInstrumentationFirst"
+ android:targetPackage="com.android.test.cantsavestate1" >
+ </instrumentation>
+
+ <instrumentation android:name=".ChainedInstrumentationSecond"
+ android:targetPackage="com.android.test.cantsavestate2" >
+ </instrumentation>
</manifest>
diff --git a/tests/app/src/android/app/cts/BaseChainedInstrumentation.java b/tests/app/src/android/app/cts/BaseChainedInstrumentation.java
new file mode 100644
index 00000000000..d265263dc4d
--- /dev/null
+++ b/tests/app/src/android/app/cts/BaseChainedInstrumentation.java
@@ -0,0 +1,92 @@
+/*
+ * Copyright (C) 2022 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.app.cts;
+
+import android.app.Activity;
+import android.app.Application;
+import android.app.Instrumentation;
+import android.content.ComponentName;
+import android.os.Bundle;
+import android.os.Handler;
+import android.os.Looper;
+import android.os.Message;
+import android.os.Messenger;
+import android.os.RemoteException;
+
+/**
+ * Base class supporting "chained" instrumentation: start another instrumentation while
+ * running the current instrumentation.
+ */
+public class BaseChainedInstrumentation extends Instrumentation {
+ static final String EXTRA_MESSENGER = "messenger";
+
+ final ComponentName mNestedInstrComp;
+
+ /** Constructor */
+ public BaseChainedInstrumentation(ComponentName nestedInstrComp) {
+ mNestedInstrComp = nestedInstrComp;
+ }
+
+ @Override
+ public void onCreate(Bundle arguments) {
+ super.onCreate(arguments);
+ final String proc = getProcessName();
+ final String appProc = Application.getProcessName();
+ if (!proc.equals(appProc)) {
+ throw new RuntimeException(String.format(
+ "getProcessName()s mismatch. Instr=%s App=%s", proc, appProc));
+ }
+ final Bundle result = new Bundle();
+ result.putBoolean(proc, true);
+ if (mNestedInstrComp != null) {
+ // We're in the main process.
+ // Because the Context#startInstrumentation doesn't support result watcher,
+ // we'd have to craft a private way to relay the result back.
+ final Handler handler = new Handler(Looper.myLooper(), msg -> {
+ final Bundle nestedResult = (Bundle) msg.obj;
+ result.putAll(nestedResult);
+ finish(Activity.RESULT_OK, result);
+ return true;
+ });
+ final Messenger messenger = new Messenger(handler);
+ final Bundle extras = new Bundle();
+ extras.putParcelable(EXTRA_MESSENGER, messenger);
+ getContext().startInstrumentation(mNestedInstrComp, null, extras);
+ scheduleTimeoutCleanup();
+ } else {
+ final Messenger messenger = arguments.getParcelable(EXTRA_MESSENGER);
+ final Message msg = Message.obtain();
+ try {
+ msg.obj = result;
+ messenger.send(msg);
+ } catch (RemoteException e) {
+ } finally {
+ msg.recycle();
+ }
+ finish(Activity.RESULT_OK, result);
+ }
+ }
+
+ private void scheduleTimeoutCleanup() {
+ new Handler(Looper.myLooper()).postDelayed(() -> {
+ Bundle result = new Bundle();
+ result.putString("FAILURE",
+ "Timed out waiting for sub-instrumentation to complete");
+ finish(Activity.RESULT_CANCELED, result);
+ }, 20 * 1000);
+ }
+}
diff --git a/tests/app/src/android/app/cts/ChainedInstrumentationFirst.java b/tests/app/src/android/app/cts/ChainedInstrumentationFirst.java
new file mode 100644
index 00000000000..0fd22b06cbf
--- /dev/null
+++ b/tests/app/src/android/app/cts/ChainedInstrumentationFirst.java
@@ -0,0 +1,30 @@
+/*
+ * Copyright (C) 2022 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.app.cts;
+
+import android.content.ComponentName;
+
+/**
+ * Chained instrumentation test class.
+ */
+public final class ChainedInstrumentationFirst extends BaseChainedInstrumentation {
+ static final String PACKAGE_NAME = "android.app.cts";
+ /** Constructor */
+ public ChainedInstrumentationFirst() {
+ super(new ComponentName(PACKAGE_NAME, PACKAGE_NAME + ".ChainedInstrumentationSecond"));
+ }
+}
diff --git a/tests/app/src/android/app/cts/ChainedInstrumentationSecond.java b/tests/app/src/android/app/cts/ChainedInstrumentationSecond.java
new file mode 100644
index 00000000000..ebed475c0c0
--- /dev/null
+++ b/tests/app/src/android/app/cts/ChainedInstrumentationSecond.java
@@ -0,0 +1,27 @@
+/*
+ * Copyright (C) 2022 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.app.cts;
+
+/**
+ * Chained instrumentation test class.
+ */
+public final class ChainedInstrumentationSecond extends BaseChainedInstrumentation {
+ /** Constructor */
+ public ChainedInstrumentationSecond() {
+ super(null);
+ }
+}
diff --git a/tests/app/src/android/app/cts/InstrumentationHelperService.java b/tests/app/src/android/app/cts/InstrumentationHelperService.java
new file mode 100644
index 00000000000..0c4f48d626a
--- /dev/null
+++ b/tests/app/src/android/app/cts/InstrumentationHelperService.java
@@ -0,0 +1,83 @@
+/*
+ * Copyright (C) 2022 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.app.cts;
+
+import android.app.Service;
+import android.content.ComponentName;
+import android.content.Context;
+import android.content.Intent;
+import android.os.Bundle;
+import android.os.IBinder;
+import android.os.ResultReceiver;
+
+import java.util.concurrent.CountDownLatch;
+
+/**
+ * The helper class to start an instrumentation from a different process.
+ */
+public class InstrumentationHelperService extends Service {
+ private static final String ACTION_START_INSTRUMENTATION =
+ "android.app.cts.ACTION_START_INSTRUMENTATION";
+ private static final String EXTRA_INSTRUMENTATIION_NAME = "instrumentation_name";
+
+ @Override
+ public IBinder onBind(Intent intent) {
+ return null;
+ }
+
+ @Override
+ public int onStartCommand(Intent intent, int flags, int startId) {
+ final String action = intent.getAction();
+ if (ACTION_START_INSTRUMENTATION.equals(action)) {
+ final String instrumentationName = intent.getStringExtra(EXTRA_INSTRUMENTATIION_NAME);
+ final ResultReceiver r = intent.getParcelableExtra(Intent.EXTRA_RESULT_RECEIVER);
+
+ boolean result = false;
+ try {
+ startInstrumentation(
+ ComponentName.unflattenFromString(instrumentationName), null, null);
+ result = true;
+ } catch (SecurityException e) {
+ }
+ r.send(result ? 1 : 0, null);
+ }
+ return START_NOT_STICKY;
+ }
+
+ /**
+ * Start the given instrumentation from this service and return result.
+ */
+ static boolean startInstrumentation(Context context, String instrumentationName)
+ throws InterruptedException {
+ final Intent intent = new Intent(ACTION_START_INSTRUMENTATION);
+ final boolean[] resultHolder = new boolean[1];
+ final CountDownLatch latch = new CountDownLatch(1);
+ final ResultReceiver r = new ResultReceiver(null) {
+ @Override
+ protected void onReceiveResult(int resultCode, Bundle resultData) {
+ resultHolder[0] = resultCode == 1;
+ latch.countDown();
+ }
+ };
+ intent.putExtra(EXTRA_INSTRUMENTATIION_NAME, instrumentationName);
+ intent.putExtra(Intent.EXTRA_RESULT_RECEIVER, r);
+ intent.setClassName("android.app.cts", "android.app.cts.InstrumentationHelperService");
+ context.startService(intent);
+ latch.await();
+ return resultHolder[0];
+ }
+}
diff --git a/tests/app/src/android/app/cts/InstrumentationTest.java b/tests/app/src/android/app/cts/InstrumentationTest.java
index 396c20d5a72..0a2c071deb3 100644
--- a/tests/app/src/android/app/cts/InstrumentationTest.java
+++ b/tests/app/src/android/app/cts/InstrumentationTest.java
@@ -16,6 +16,15 @@
package android.app.cts;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertNotSame;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertSame;
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assume.assumeFalse;
+
import android.app.Activity;
import android.app.Application;
import android.app.Instrumentation;
@@ -32,10 +41,11 @@ import android.content.res.Configuration;
import android.graphics.Point;
import android.graphics.drawable.Drawable;
import android.net.Uri;
+import android.os.Build;
import android.os.Bundle;
import android.os.Debug;
import android.os.SystemClock;
-import android.test.InstrumentationTestCase;
+import android.os.SystemProperties;
import android.test.UiThreadTest;
import android.view.InputQueue;
import android.view.KeyCharacterMap;
@@ -47,16 +57,24 @@ import android.view.View;
import android.view.ViewGroup.LayoutParams;
import android.view.Window;
-import java.util.List;
-
import android.app.stubs.R;
import com.android.compatibility.common.util.PollingCheck;
import com.android.compatibility.common.util.SystemUtil;
import androidx.test.filters.FlakyTest;
+import androidx.test.InstrumentationRegistry;
+import androidx.test.runner.AndroidJUnit4;
-public class InstrumentationTest extends InstrumentationTestCase {
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import java.util.List;
+
+@RunWith(AndroidJUnit4.class)
+public class InstrumentationTest {
private static final int WAIT_TIME = 1000;
@@ -70,10 +88,9 @@ public class InstrumentationTest extends InstrumentationTestCase {
private Context mContext;
private MockActivity mMockActivity;
- @Override
- protected void setUp() throws Exception {
- super.setUp();
- mInstrumentation = getInstrumentation();
+ @Before
+ public void setUp() throws Exception {
+ mInstrumentation = InstrumentationRegistry.getInstrumentation();
mContext = mInstrumentation.getTargetContext();
mIntent = new Intent(mContext, InstrumentationTestActivity.class);
mIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
@@ -81,47 +98,87 @@ public class InstrumentationTest extends InstrumentationTestCase {
PollingCheck.waitFor(mActivity::hasWindowFocus);
}
- protected void tearDown() throws Exception {
+ @After
+ public void tearDown() throws Exception {
mInstrumentation = null;
mIntent = null;
if (mActivity != null) {
mActivity.finish();
mActivity = null;
}
- super.tearDown();
}
+ @Test
public void testDefaultProcessInstrumentation() throws Exception {
String cmd = "am instrument -w android.app.cts/.DefaultProcessInstrumentation";
- String result = SystemUtil.runShellCommand(getInstrumentation(), cmd);
+ String result = SystemUtil.runShellCommand(mInstrumentation, cmd);
assertEquals("INSTRUMENTATION_RESULT: " + SIMPLE_PACKAGE_NAME + "=true" +
"\nINSTRUMENTATION_CODE: -1\n", result);
}
+ @Test
public void testAltProcessInstrumentation() throws Exception {
String cmd = "am instrument -w android.app.cts/.AltProcessInstrumentation";
- String result = SystemUtil.runShellCommand(getInstrumentation(), cmd);
+ String result = SystemUtil.runShellCommand(mInstrumentation, cmd);
assertEquals("INSTRUMENTATION_RESULT: " + SIMPLE_PACKAGE_NAME + ":other=true" +
"\nINSTRUMENTATION_CODE: -1\n", result);
}
@FlakyTest(bugId = 133760851)
+ @Test
public void testWildcardProcessInstrumentation() throws Exception {
String cmd = "am instrument -w android.app.cts/.WildcardProcessInstrumentation";
- String result = SystemUtil.runShellCommand(getInstrumentation(), cmd);
+ String result = SystemUtil.runShellCommand(mInstrumentation, cmd);
assertEquals("INSTRUMENTATION_RESULT: " + SIMPLE_PACKAGE_NAME + "=true" +
"\nINSTRUMENTATION_RESULT: " + SIMPLE_PACKAGE_NAME + ":receiver=true" +
"\nINSTRUMENTATION_CODE: -1\n", result);
}
+ @Test
public void testMultiProcessInstrumentation() throws Exception {
String cmd = "am instrument -w android.app.cts/.MultiProcessInstrumentation";
- String result = SystemUtil.runShellCommand(getInstrumentation(), cmd);
+ String result = SystemUtil.runShellCommand(mInstrumentation, cmd);
assertEquals("INSTRUMENTATION_RESULT: " + SIMPLE_PACKAGE_NAME + "=true" +
"\nINSTRUMENTATION_RESULT: " + SIMPLE_PACKAGE_NAME + ":other=true" +
"\nINSTRUMENTATION_CODE: -1\n", result);
}
+ @Test
+ public void testEnforceStartFromShell() throws Exception {
+ assumeFalse(SystemProperties.getBoolean("ro.debuggable", false));
+ // Start the instrumentation from shell, it should succeed.
+ final String defaultInstrumentationName = "android.app.cts/.DefaultProcessInstrumentation";
+ String cmd = "am instrument -w " + defaultInstrumentationName;
+ String result = SystemUtil.runShellCommand(mInstrumentation, cmd);
+ assertEquals("INSTRUMENTATION_RESULT: " + SIMPLE_PACKAGE_NAME + "=true"
+ + "\nINSTRUMENTATION_CODE: -1\n", result);
+ // Start the instrumentation by ourselves, it should succeed (chained instrumentation).
+ mContext.startInstrumentation(
+ ComponentName.unflattenFromString(defaultInstrumentationName), null, null);
+ // Start the instrumentation from another process, this time it should fail.
+ SystemUtil.runShellCommand(mInstrumentation,
+ "cmd deviceidle tempwhitelist android.app.cts");
+ try {
+ assertFalse(InstrumentationHelperService.startInstrumentation(
+ mContext, defaultInstrumentationName));
+ } finally {
+ SystemUtil.runShellCommand(mInstrumentation,
+ "cmd deviceidle tempwhitelist -r android.app.cts");
+ }
+ }
+
+ @Test
+ public void testChainedInstrumentation() throws Exception {
+ final String testPkg1 = "com.android.test.cantsavestate1";
+ final String testPkg2 = "com.android.test.cantsavestate2";
+ String cmd = "am instrument -w android.app.cts/.ChainedInstrumentationFirst";
+ String result = SystemUtil.runShellCommand(mInstrumentation, cmd);
+ assertEquals("INSTRUMENTATION_RESULT: " + testPkg1 + "=true"
+ + "\nINSTRUMENTATION_RESULT: " + testPkg2 + "=true"
+ + "\nINSTRUMENTATION_CODE: -1\n", result);
+ }
+
+ @Test
public void testMonitor() throws Exception {
if (mActivity != null)
mActivity.finish();
@@ -162,6 +219,7 @@ public class InstrumentationTest extends InstrumentationTestCase {
mInstrumentation.removeMonitor(am);
}
+ @Test
public void testCallActivityOnCreate() throws Throwable {
mActivity.setOnCreateCalled(false);
runTestOnUiThread(new Runnable() {
@@ -173,6 +231,7 @@ public class InstrumentationTest extends InstrumentationTestCase {
assertTrue(mActivity.isOnCreateCalled());
}
+ @Test
public void testAllocCounting() throws Exception {
mInstrumentation.startAllocCounting();
@@ -208,6 +267,7 @@ public class InstrumentationTest extends InstrumentationTestCase {
}
@FlakyTest(bugId = 133760851)
+ @Test
public void testSendTrackballEventSync() throws Exception {
long now = SystemClock.uptimeMillis();
MotionEvent orig = MotionEvent.obtain(now, now, MotionEvent.ACTION_DOWN,
@@ -222,6 +282,7 @@ public class InstrumentationTest extends InstrumentationTestCase {
}
@FlakyTest(bugId = 133760851)
+ @Test
public void testCallApplicationOnCreate() throws Exception {
InstrumentationTestStub ca = new InstrumentationTestStub();
mInstrumentation.callApplicationOnCreate(ca);
@@ -229,12 +290,14 @@ public class InstrumentationTest extends InstrumentationTestCase {
}
@FlakyTest(bugId = 133760851)
+ @Test
public void testContext() throws Exception {
Context c1 = mInstrumentation.getContext();
Context c2 = mInstrumentation.getTargetContext();
assertNotSame(c1.getPackageName(), c2.getPackageName());
}
+ @Test
public void testInvokeMenuActionSync() throws Exception {
final int resId = R.id.goto_menu_id;
if (mActivity.getWindow().hasFeature(Window.FEATURE_OPTIONS_PANEL)) {
@@ -245,6 +308,7 @@ public class InstrumentationTest extends InstrumentationTestCase {
}
}
+ @Test
public void testCallActivityOnPostCreate() throws Throwable {
mActivity.setOnPostCreate(false);
runTestOnUiThread(new Runnable() {
@@ -256,6 +320,7 @@ public class InstrumentationTest extends InstrumentationTestCase {
assertTrue(mActivity.isOnPostCreate());
}
+ @Test
public void testCallActivityOnNewIntent() throws Throwable {
mActivity.setOnNewIntentCalled(false);
runTestOnUiThread(new Runnable() {
@@ -269,6 +334,7 @@ public class InstrumentationTest extends InstrumentationTestCase {
}
@FlakyTest(bugId = 133760851)
+ @Test
public void testCallActivityOnResume() throws Throwable {
mActivity.setOnResume(false);
runTestOnUiThread(new Runnable() {
@@ -280,15 +346,18 @@ public class InstrumentationTest extends InstrumentationTestCase {
assertTrue(mActivity.isOnResume());
}
+ @Test
public void testMisc() throws Exception {
}
+ @Test
public void testPerformanceSnapshot() throws Exception {
mInstrumentation.setAutomaticPerformanceSnapshots();
mInstrumentation.startPerformanceSnapshot();
mInstrumentation.endPerformanceSnapshot();
}
+ @Test
public void testProfiling() throws Exception {
// by default, profiling was disabled. but after set the handleProfiling attribute in the
// manifest file for this Instrumentation to true, the profiling was also disabled.
@@ -298,6 +367,7 @@ public class InstrumentationTest extends InstrumentationTestCase {
mInstrumentation.stopProfiling();
}
+ @Test
public void testInvokeContextMenuAction() throws Exception {
mActivity.runOnUiThread(new Runnable() {
public void run() {
@@ -314,6 +384,7 @@ public class InstrumentationTest extends InstrumentationTestCase {
assertEquals(flag, mMockActivity.mWindow.mFlags);
}
+ @Test
public void testSendStringSync() {
final String text = "abcd";
mInstrumentation.sendStringSync(text);
@@ -335,6 +406,7 @@ public class InstrumentationTest extends InstrumentationTestCase {
}
@FlakyTest(bugId = 133760851)
+ @Test
public void testCallActivityOnSaveInstanceState() throws Throwable {
final Bundle bundle = new Bundle();
mActivity.setOnSaveInstanceState(false);
@@ -349,6 +421,7 @@ public class InstrumentationTest extends InstrumentationTestCase {
assertSame(bundle, mActivity.getBundle());
}
+ @Test
public void testSendPointerSync() throws Exception {
mInstrumentation.waitForIdleSync();
mInstrumentation.setInTouchMode(true);
@@ -371,13 +444,15 @@ public class InstrumentationTest extends InstrumentationTestCase {
mActivity.setOnTouchEventCalled(false);
}
+ @Test
public void testGetComponentName() throws Exception {
- ComponentName com = getInstrumentation().getComponentName();
+ ComponentName com = mInstrumentation.getComponentName();
assertNotNull(com.getPackageName());
assertNotNull(com.getClassName());
assertNotNull(com.getShortClassName());
}
+ @Test
public void testNewApplication() throws Exception {
final String className = "android.app.stubs.MockApplication";
ClassLoader cl = getClass().getClassLoader();
@@ -389,6 +464,7 @@ public class InstrumentationTest extends InstrumentationTestCase {
assertEquals(className, app.getClass().getName());
}
+ @Test
public void testRunOnMainSync() throws Exception {
mRunOnMainSyncResult = false;
mInstrumentation.runOnMainSync(new Runnable() {
@@ -400,6 +476,7 @@ public class InstrumentationTest extends InstrumentationTestCase {
assertTrue(mRunOnMainSyncResult);
}
+ @Test
public void testCallActivityOnPause() throws Throwable {
mActivity.setOnPauseCalled(false);
runTestOnUiThread(() -> {
@@ -409,6 +486,7 @@ public class InstrumentationTest extends InstrumentationTestCase {
assertTrue(mActivity.isOnPauseCalled());
}
+ @Test
public void testSendKeyDownUpSync() throws Exception {
mInstrumentation.sendKeyDownUpSync(KeyEvent.KEYCODE_0);
mInstrumentation.waitForIdleSync();
@@ -419,6 +497,7 @@ public class InstrumentationTest extends InstrumentationTestCase {
}
@FlakyTest(bugId = 133760851)
+ @Test
@UiThreadTest
public void testNewActivity() throws Exception {
Intent intent = new Intent();
@@ -446,6 +525,7 @@ public class InstrumentationTest extends InstrumentationTestCase {
activity.finish();
}
+ @Test
public void testCallActivityOnStart() throws Exception {
mActivity.setOnStart(false);
mInstrumentation.callActivityOnStart(mActivity);
@@ -453,6 +533,7 @@ public class InstrumentationTest extends InstrumentationTestCase {
assertTrue(mActivity.isOnStart());
}
+ @Test
public void testWaitForIdle() throws Exception {
MockRunnable mr = new MockRunnable();
assertFalse(mr.isRunCalled());
@@ -461,6 +542,7 @@ public class InstrumentationTest extends InstrumentationTestCase {
assertTrue(mr.isRunCalled());
}
+ @Test
public void testSendCharacterSync() throws Exception {
mInstrumentation.sendCharacterSync(KeyEvent.KEYCODE_0);
mInstrumentation.waitForIdleSync();
@@ -469,6 +551,7 @@ public class InstrumentationTest extends InstrumentationTestCase {
}
@FlakyTest(bugId = 133760851)
+ @Test
public void testCallActivityOnRestart() throws Exception {
mActivity.setOnRestart(false);
mInstrumentation.callActivityOnRestart(mActivity);
@@ -476,6 +559,7 @@ public class InstrumentationTest extends InstrumentationTestCase {
assertTrue(mActivity.isOnRestart());
}
+ @Test
public void testCallActivityOnStop() throws Exception {
mActivity.setOnStop(false);
mInstrumentation.callActivityOnStop(mActivity);
@@ -484,6 +568,7 @@ public class InstrumentationTest extends InstrumentationTestCase {
}
@FlakyTest(bugId = 133760851)
+ @Test
public void testCallActivityOnUserLeaving() throws Exception {
assertFalse(mActivity.isOnLeave());
mInstrumentation.callActivityOnUserLeaving(mActivity);
@@ -491,6 +576,7 @@ public class InstrumentationTest extends InstrumentationTestCase {
assertTrue(mActivity.isOnLeave());
}
+ @Test
public void testCallActivityOnRestoreInstanceState() throws Exception {
mActivity.setOnRestoreInstanceState(false);
mInstrumentation.callActivityOnRestoreInstanceState(mActivity, new Bundle());
@@ -498,6 +584,7 @@ public class InstrumentationTest extends InstrumentationTestCase {
assertTrue(mActivity.isOnRestoreInstanceState());
}
+ @Test
public void testSendKeySync() throws Exception {
KeyEvent key = new KeyEvent(KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_0);
mInstrumentation.sendKeySync(key);
@@ -761,4 +848,20 @@ public class InstrumentationTest extends InstrumentationTestCase {
mIsOnCreateCalled = true;
}
}
+
+ private void runTestOnUiThread(final Runnable r) throws Throwable {
+ final Throwable[] exceptions = new Throwable[1];
+ mInstrumentation.runOnMainSync(new Runnable() {
+ public void run() {
+ try {
+ r.run();
+ } catch (Throwable throwable) {
+ exceptions[0] = throwable;
+ }
+ }
+ });
+ if (exceptions[0] != null) {
+ throw exceptions[0];
+ }
+ }
}
diff --git a/tests/tests/security/AndroidManifest.xml b/tests/tests/security/AndroidManifest.xml
index c6d60bc12f6..ce2035827b8 100644
--- a/tests/tests/security/AndroidManifest.xml
+++ b/tests/tests/security/AndroidManifest.xml
@@ -179,6 +179,26 @@
android:resource="@xml/syncadapter" />
</service>
+ <activity android:name="android.security.cts.CVE_2021_0642.PocActivity"
+ android:exported="true">
+ <intent-filter>
+ <action android:name="android.telephony.action.CONFIGURE_VOICEMAIL" />
+ <category android:name="android.intent.category.DEFAULT" />
+ </intent-filter>
+ <intent-filter>
+ <action android:name="CVE_2021_0642_ACTION" />
+ <category android:name="android.intent.category.DEFAULT" />
+ </intent-filter>
+ </activity>
+
+ <activity android:name="android.security.cts.CVE_2021_0642.SecondActivity"
+ android:exported="true">
+ <intent-filter>
+ <action android:name="CVE_2021_0642_ACTION" />
+ <category android:name="android.intent.category.DEFAULT" />
+ </intent-filter>
+ </activity>
+
</application>
<instrumentation android:name="androidx.test.runner.AndroidJUnitRunner"
diff --git a/tests/tests/security/res/raw/cve_2022_33234.mkv b/tests/tests/security/res/raw/cve_2022_33234.mkv
new file mode 100644
index 00000000000..752e3cd749b
--- /dev/null
+++ b/tests/tests/security/res/raw/cve_2022_33234.mkv
Binary files differ
diff --git a/tests/tests/security/res/values/strings.xml b/tests/tests/security/res/values/strings.xml
new file mode 100644
index 00000000000..73dd5b93d2c
--- /dev/null
+++ b/tests/tests/security/res/values/strings.xml
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright 2022 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.
+ -->
+
+<resources>
+ <!-- CVE-2021-0642 -->
+ <string name="cve_2021_0642_action">CVE_2021_0642_ACTION</string>
+ <string name="cve_2021_0642_pkgPhone">com.android.phone</string>
+ <string name="cve_2021_0642_failMsg">Device is vulnerable to b/185126149 !!</string>
+ <string name="cve_2021_0642_msgResolveErrorVoicemail">The intent with action
+ ACTION_CONFIGURE_VOICEMAIL should resolve to either ResolverActivity or
+ VoicemailSettingsActivity</string>
+ <string name="cve_2021_0642_msgResolveErrorPocAction">The intent with action
+ CVE_2021_0642_ACTION should not be resolved to test package</string>
+</resources>
diff --git a/tests/tests/security/src/android/security/cts/CVE_2021_0642/CVE_2021_0642.java b/tests/tests/security/src/android/security/cts/CVE_2021_0642/CVE_2021_0642.java
new file mode 100644
index 00000000000..b40c06b221c
--- /dev/null
+++ b/tests/tests/security/src/android/security/cts/CVE_2021_0642/CVE_2021_0642.java
@@ -0,0 +1,90 @@
+/*
+ * Copyright (C) 2022 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_2021_0642;
+
+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.content.Context;
+import android.content.Intent;
+import android.content.pm.PackageManager;
+import android.content.pm.ResolveInfo;
+import android.platform.test.annotations.AsbSecurityTest;
+import android.security.cts.R;
+import android.telephony.TelephonyManager;
+
+import androidx.test.runner.AndroidJUnit4;
+
+import com.android.sts.common.util.StsExtraBusinessLogicTestCase;
+
+import java.util.List;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+@RunWith(AndroidJUnit4.class)
+public class CVE_2021_0642 extends StsExtraBusinessLogicTestCase {
+
+ // b/185126149
+ // Vulnerable app : TeleService.apk
+ // Vulnerable module : com.android.phone
+ // Is Play managed : No
+ @AsbSecurityTest(cveBugId = 185126149)
+ @Test
+ public void testCVE_2021_0642() {
+ try {
+ // This test requires the device to have Telephony feature.
+ Context context = getInstrumentation().getTargetContext();
+ PackageManager pm = context.getPackageManager();
+ assumeTrue(pm.hasSystemFeature(PackageManager.FEATURE_TELEPHONY));
+
+ // Get ResolverActivity's name and package name
+ Intent customIntent = new Intent(context.getString(R.string.cve_2021_0642_action));
+ ResolveInfo riCustomAction =
+ pm.resolveActivity(customIntent, PackageManager.MATCH_DEFAULT_ONLY);
+ assumeTrue(context.getString(R.string.cve_2021_0642_msgResolveErrorPocAction),
+ !riCustomAction.activityInfo.packageName.equals(context.getPackageName()));
+ final String resolverPkgName = riCustomAction.activityInfo.packageName;
+ final String resolverActivityName = riCustomAction.activityInfo.name;
+
+ // Resolving intent with action "ACTION_CONFIGURE_VOICEMAIL"
+ Intent intent = new Intent(TelephonyManager.ACTION_CONFIGURE_VOICEMAIL);
+ ResolveInfo ri = pm.resolveActivity(intent, PackageManager.MATCH_DEFAULT_ONLY);
+ final String resolvedPkgName = ri.activityInfo.packageName;
+ final String resolvedActivityName = ri.activityInfo.name;
+
+ // Check if intent resolves to either VoicemailActivity or ResolverActivity
+ boolean isVoicemailActivity =
+ resolvedPkgName.equals(context.getString(R.string.cve_2021_0642_pkgPhone));
+ boolean isResolverActivity = resolvedPkgName.equals(resolverPkgName)
+ && resolvedActivityName.equals(resolverActivityName);
+
+ assumeTrue(context.getString(R.string.cve_2021_0642_msgResolveErrorVoicemail),
+ isVoicemailActivity || isResolverActivity);
+
+ // If vulnerability is present, the intent with action ACTION_CONFIGURE_VOICEMAIL
+ // would resolve to the IntentResolver i.e. ResolverActivity, the test would fail in
+ // this case.
+ assertFalse(context.getString(R.string.cve_2021_0642_failMsg), isResolverActivity);
+ } catch (Exception e) {
+ assumeNoException(e);
+ }
+ }
+}
diff --git a/hostsidetests/securitybulletin/test-apps/CVE-2021-0642/src/android/security/cts/cve_2021_0642/PocActivity.java b/tests/tests/security/src/android/security/cts/CVE_2021_0642/PocActivity.java
index 1a335c76444..ae73b016d76 100644
--- a/hostsidetests/securitybulletin/test-apps/CVE-2021-0642/src/android/security/cts/cve_2021_0642/PocActivity.java
+++ b/tests/tests/security/src/android/security/cts/CVE_2021_0642/PocActivity.java
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package android.security.cts.cve_2021_0642;
+package android.security.cts.CVE_2021_0642;
import android.app.Activity;
diff --git a/tests/tests/security/src/android/security/cts/CVE_2021_0642/SecondActivity.java b/tests/tests/security/src/android/security/cts/CVE_2021_0642/SecondActivity.java
new file mode 100644
index 00000000000..4c0caeedc2c
--- /dev/null
+++ b/tests/tests/security/src/android/security/cts/CVE_2021_0642/SecondActivity.java
@@ -0,0 +1,22 @@
+/*
+ * Copyright (C) 2022 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_2021_0642;
+
+import android.app.Activity;
+
+public class SecondActivity extends Activity {
+}
diff --git a/tests/tests/security/src/android/security/cts/CVE_2022_20456.java b/tests/tests/security/src/android/security/cts/CVE_2022_20456.java
new file mode 100644
index 00000000000..26434336a3e
--- /dev/null
+++ b/tests/tests/security/src/android/security/cts/CVE_2022_20456.java
@@ -0,0 +1,208 @@
+/*
+ * Copyright (C) 2022 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 android.app.NotificationManager.INTERRUPTION_FILTER_UNKNOWN;
+
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assume.assumeNoException;
+
+import android.app.AutomaticZenRule;
+import android.content.ComponentName;
+import android.net.Uri;
+import android.os.Parcel;
+import android.platform.test.annotations.AsbSecurityTest;
+
+import androidx.test.runner.AndroidJUnit4;
+
+import com.android.sts.common.util.StsExtraBusinessLogicTestCase;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import java.lang.reflect.Field;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+
+
+// This CTS test has been created taking reference from the tests present in
+// frameworks/base/core/tests/coretests/src/android/app/AutomaticZenRuleTest.java
+@RunWith(AndroidJUnit4.class)
+public class CVE_2022_20456 extends StsExtraBusinessLogicTestCase {
+ private static final int INPUT_STRING_LENGTH = 2000; // 2 * 'MAX_STRING_LENGTH'
+ private static final String CLASS_NAME = "className";
+ private static final String PACKAGE_NAME = "packageName";
+ private static final String URI_STRING = "condition://android";
+ private static final String ZEN_RULE_NAME = "ZenRuleName";
+ private ComponentName mComponentNameWithLongFields;
+ private ComponentName mValidComponentName;
+ private String mLongString;
+ private Uri mLongUri;
+ private Uri mValidUri;
+ private List<String> mViolations;
+
+ private void checkFields(AutomaticZenRule rule, boolean ownerFlag, boolean configActivityFlag,
+ String tag) {
+ // Check all fields
+ if (INPUT_STRING_LENGTH <= rule.getName().length()) {
+ mViolations.add(tag + "input string length <= rule name length");
+ }
+ if (mLongUri.toString().length() <= rule.getConditionId().toString().length()) {
+ mViolations.add(tag + "input uri length <= rule conditionId length");
+ }
+ if (ownerFlag) {
+ if (INPUT_STRING_LENGTH <= rule.getOwner().getPackageName().length()) {
+ mViolations.add(tag + "input string length <= rule owner package name length");
+ }
+ if (INPUT_STRING_LENGTH <= rule.getOwner().getClassName().length()) {
+ mViolations.add(tag + "input string length <= rule owner class name length");
+ }
+ }
+ if (configActivityFlag) {
+ if (INPUT_STRING_LENGTH <= rule.getConfigurationActivity().getPackageName().length()) {
+ mViolations.add(tag
+ + "input string length <= rule configurationActivity package name length");
+ }
+ if (INPUT_STRING_LENGTH <= rule.getConfigurationActivity().getClassName().length()) {
+ mViolations.add(tag
+ + "input string length <= rule configurationActivity class name length");
+ }
+ }
+ }
+
+ private void checkConstructor(boolean ownerFlag, boolean configActivityFlag) {
+ ComponentName owner = ownerFlag ? mComponentNameWithLongFields : null;
+ ComponentName configActivity = configActivityFlag ? mComponentNameWithLongFields : null;
+ AutomaticZenRule rule = new AutomaticZenRule(mLongString, owner, configActivity, mLongUri,
+ null, INTERRUPTION_FILTER_UNKNOWN, /* enabled */ true);
+ checkFields(rule, ownerFlag, configActivityFlag, "\ncheckConstructor (owner=" + ownerFlag
+ + ", configActivity=" + configActivityFlag + "): ");
+ }
+
+ private void testIsConstructorVulnerable() {
+ // Check all three variants i.e. with owner, with configuration activity and with both
+ // owner and configuration activity. Although third case is mostly redundant, adding it to
+ // complete checks on all possible variants.
+ checkConstructor(/* ownerFlag */ true, /* configActivityFlag */ false);
+ checkConstructor(/* ownerFlag */ false, /* configActivityFlag */ true);
+ checkConstructor(/* ownerFlag */ true, /* configActivityFlag */ true);
+ }
+
+ private void checkFieldSetters(boolean ownerFlag, boolean configActivityFlag) {
+ ComponentName owner = ownerFlag ? mValidComponentName : null;
+ ComponentName configActivity = configActivityFlag ? mValidComponentName : null;
+ AutomaticZenRule rule = new AutomaticZenRule(ZEN_RULE_NAME, owner, configActivity,
+ mValidUri, null, INTERRUPTION_FILTER_UNKNOWN, /* enabled */ true);
+
+ // Check all fields that can be set via setter methods of AutomaticZenRule class
+ rule.setName(mLongString);
+ rule.setConditionId(mLongUri);
+ rule.setConfigurationActivity(mComponentNameWithLongFields);
+ checkFields(rule, /* ownerFlag */ false, /* configActivityFlag */ true,
+ "\ncheckFieldSetters (owner=" + ownerFlag + ", configActivity=" + configActivityFlag
+ + "): ");
+ }
+
+ private void testIsFieldSetterVulnerable() {
+ checkFieldSetters(/* ownerFlag */ true, /* configActivityFlag */ false);
+ checkFieldSetters(/* ownerFlag */ false, /* configActivityFlag */ true);
+ checkFieldSetters(/* ownerFlag */ true, /* configActivityFlag */ true);
+ }
+
+ private void checkParcelInput(boolean ownerFlag, boolean configActivityFlag)
+ throws ClassNotFoundException, IllegalAccessException, NoSuchFieldException {
+ ComponentName owner = ownerFlag ? mValidComponentName : null;
+ ComponentName configActivity = configActivityFlag ? mValidComponentName : null;
+ AutomaticZenRule rule = new AutomaticZenRule(ZEN_RULE_NAME, owner, configActivity,
+ mValidUri, null, INTERRUPTION_FILTER_UNKNOWN, /* enabled */ true);
+
+ // Create rules with long fields set directly via reflection so that we can confirm that a
+ // rule with too-long fields that comes in via a parcel has its fields truncated directly.
+ Class automaticZenRuleClass = Class.forName("android.app.AutomaticZenRule");
+ Field fieldName = automaticZenRuleClass.getDeclaredField("name");
+ fieldName.setAccessible(/* flag */ true);
+ fieldName.set(rule, mLongString);
+ Field fieldConditionId = automaticZenRuleClass.getDeclaredField("conditionId");
+ fieldConditionId.setAccessible(/* flag */ true);
+ fieldConditionId.set(rule, mLongUri);
+ if (ownerFlag) {
+ Field fieldOwner = automaticZenRuleClass.getDeclaredField("owner");
+ fieldOwner.setAccessible(/* flag */ true);
+ fieldOwner.set(rule, mComponentNameWithLongFields);
+ }
+ if (configActivityFlag) {
+ Field fieldConfigActivity =
+ automaticZenRuleClass.getDeclaredField("configurationActivity");
+ fieldConfigActivity.setAccessible(/* flag */ true);
+ fieldConfigActivity.set(rule, mComponentNameWithLongFields);
+ }
+
+ // Write AutomaticZenRule object to parcel
+ Parcel parcel = Parcel.obtain();
+ rule.writeToParcel(parcel, 0);
+ parcel.setDataPosition(0);
+
+ // Instantiate AutomaticZenRule object using parcel
+ AutomaticZenRule ruleFromParcel = new AutomaticZenRule(parcel);
+
+ checkFields(ruleFromParcel, ownerFlag, configActivityFlag, "\ncheckParcelInput (owner="
+ + ownerFlag + ", configActivity=" + configActivityFlag + "): ");
+ }
+
+ private void testIsInputFromParcelVulnerable()
+ throws ClassNotFoundException, IllegalAccessException, NoSuchFieldException {
+ checkParcelInput(/* ownerFlag */ true, /* configActivityFlag */ false);
+ checkParcelInput(/* ownerFlag */ false, /* configActivityFlag */ true);
+ checkParcelInput(/* ownerFlag */ true, /* configActivityFlag */ true);
+ }
+
+ // b/242703460, b/242703505, b/242703780, b/242704043, b/243794204
+ // Vulnerable library : framework.jar
+ // Vulnerable module : Not applicable
+ // Is Play managed : No
+ @AsbSecurityTest(cveBugId = {242703460, 242703505, 242703780, 242704043, 243794204})
+ @Test
+ public void testPocCVE_2022_20456() {
+ try {
+ mLongString = String.join("", Collections.nCopies(INPUT_STRING_LENGTH, "A"));
+ mComponentNameWithLongFields = new ComponentName(mLongString, mLongString);
+ mValidComponentName = new ComponentName(PACKAGE_NAME, CLASS_NAME);
+ mLongUri = Uri.parse("condition://" + mLongString);
+ mValidUri = Uri.parse(URI_STRING);
+ mViolations = new ArrayList<String>();
+
+ // Check AutomaticZenRule constructor
+ testIsConstructorVulnerable();
+
+ // Check AutomaticZenRule field setters
+ testIsFieldSetterVulnerable();
+
+ // Check AutomaticZenRule constructor using parcel input
+ testIsInputFromParcelVulnerable();
+
+ assertTrue("Device is vulnerable to at least one of the following vulnerabilities : "
+ + "b/242703460(CVE-2022-20489), b/242703505(CVE-2022-20490), b/242703780"
+ + "(CVE-2022-20456), b/242704043(CVE-2022-20492), b/243794204(CVE-2022-20494)"
+ + " due to these violations where input string length=" + INPUT_STRING_LENGTH
+ + " and input uri length=" + mLongUri.toString().length() + ":" + mViolations,
+ mViolations.isEmpty());
+ } catch (Exception e) {
+ assumeNoException(e);
+ }
+ }
+}
diff --git a/tests/tests/security/src/android/security/cts/StagefrightTest.java b/tests/tests/security/src/android/security/cts/StagefrightTest.java
index 4e1b4afb3b3..8a4c0fc968d 100644
--- a/tests/tests/security/src/android/security/cts/StagefrightTest.java
+++ b/tests/tests/security/src/android/security/cts/StagefrightTest.java
@@ -1808,6 +1808,12 @@ public class StagefrightTest extends StsExtraBusinessLogicTestCase {
before any existing test methods
***********************************************************/
@Test
+ @AsbSecurityTest(cveBugId = 240971780)
+ public void testStagefright_cve_2022_33234() throws Exception {
+ doStagefrightTest(R.raw.cve_2022_33234);
+ }
+
+ @Test
@AsbSecurityTest(cveBugId = 235102508)
public void testStagefright_cve_2022_25669() throws Exception {
doStagefrightTest(R.raw.cve_2022_25669);
diff --git a/tests/tests/security/src/android/security/cts/WorkSourceTest.java b/tests/tests/security/src/android/security/cts/WorkSourceTest.java
new file mode 100644
index 00000000000..1438b29d1d6
--- /dev/null
+++ b/tests/tests/security/src/android/security/cts/WorkSourceTest.java
@@ -0,0 +1,67 @@
+/*
+ * Copyright (C) 2022 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.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertTrue;
+
+import android.os.Parcel;
+import android.os.WorkSource;
+import android.platform.test.annotations.AsbSecurityTest;
+
+import androidx.test.runner.AndroidJUnit4;
+
+import com.android.sts.common.util.StsExtraBusinessLogicTestCase;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+@RunWith(AndroidJUnit4.class)
+public class WorkSourceTest extends StsExtraBusinessLogicTestCase {
+ private static final int TEST_PID = 6512;
+ private static final String TEST_PACKAGE_NAME = "android.security.cts";
+
+ @Test
+ @AsbSecurityTest(cveBugId = 220302519)
+ public void testWorkChainParceling() {
+ WorkSource ws = new WorkSource(TEST_PID, TEST_PACKAGE_NAME);
+ // Create a WorkChain so the mChains becomes non-null
+ ws.createWorkChain();
+ assertNotNull("WorkChains must be non-null in order to properly test parceling",
+ ws.getWorkChains());
+ // Then clear it so it's an empty list.
+ ws.getWorkChains().clear();
+ assertTrue("WorkChains must be empty in order to properly test parceling",
+ ws.getWorkChains().isEmpty());
+
+ Parcel p = Parcel.obtain();
+ ws.writeToParcel(p, 0);
+ p.setDataPosition(0);
+
+ // Read the Parcel back out and validate the two Parcels are identical
+ WorkSource readWs = WorkSource.CREATOR.createFromParcel(p);
+ assertNotNull(readWs.getWorkChains());
+ assertTrue(readWs.getWorkChains().isEmpty());
+ assertEquals(ws, readWs);
+
+ // Assert that we've read every byte out of the Parcel.
+ assertEquals(p.dataSize(), p.dataPosition());
+
+ p.recycle();
+ }
+}