STS test for Android Security CVE-2021-0481
Test: sts-tradefed run sts-engbuild-no-spl-lock -m CtsSecurityBulletinHostTestCases -t android.security.cts.CVE_2021_0481
Bug: 182917454
Bug: 172939189
Change-Id: I5b933bac6a1bdef92686c97de86d028db3647d09
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/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/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..b5d4b57
--- /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" >
+ <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..535c27a
--- /dev/null
+++ b/hostsidetests/securitybulletin/test-apps/CVE-2021-0481/src/android/security/cts/CVE_2021_0481/DeviceTest.java
@@ -0,0 +1,161 @@
+/*
+ * 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 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 "You(Owner)"
+ searchAndClick(mDevice, "You (Owner)", 2000);
+ //in "Profile Info" dialog window showing user silhouette
+ searchAndClick(mDevice, "Select 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 {
+
+ List<UiObject2> objects = mDevice.findObjects(By.clickable(true));
+ boolean clicked = 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(searchAndLog(o, name, ""))
+ {
+ o.click();
+ clicked=true;
+ Log.d(TAG, name + " clicked");
+ SystemClock.sleep(timeOut); //wait for click result to appear onscreen
+ break; //to avoid androidx.test.uiautomator.StaleObjectException
+ }
+ }
+ }
+ if(!clicked) {
+ throw new ClickableNotFound("\"" + name + "\" not found to click on");
+ }
+ }
+
+ //returns true if UiObject2 contains name
+ private boolean searchAndLog(UiObject2 o, String name, String prefix){
+
+ String lname = o.getText();
+ String cname = o.getClassName();
+ String cdesc = o.getContentDescription();
+
+ Log.d(TAG, prefix + "class=" + cname);
+ Log.d(TAG, prefix + "getText()=" + lname);
+ Log.d(TAG, prefix + "getContentDescription()=" + cdesc);
+ Log.d(TAG, prefix + "o.getChildCount()=" + o.getChildCount());
+
+ if(lname != null && lname.equals(name) || cdesc != null && cdesc.equals(name)) {
+ Log.d(TAG, prefix + "found-->" + name);
+ return true;
+ } else {
+ java.util.List<UiObject2> objects2 = o.getChildren();
+ if(objects2 != null && objects2.size() > 0 && prefix.length() < 50) {
+ for (UiObject2 o2 : objects2) {
+ if(searchAndLog(o2, name, prefix + "__")){
+ return true;
+ }
+ }
+ }
+ }
+ return false;
+ }
+
+}
+
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();
+ }
+}