RESTRICT AUTOMERGE: CTS: Created ResStringPool security tests
Ensures that APKs with malformed ResStringPool data are not successfully
installed.
Bug: 71361168
Bug: 71360999
Test: run cts -m CtsAppSecurityHostTestCases \
-t android.appsecurity.cts.CorruptApkTests
Change-Id: I018f79f33b2f6a9b01dd6d5d35d595d3d70be87b
diff --git a/common/host-side/tradefed/tests/src/com/android/compatibility/common/tradefed/presubmit/ValidateTestsAbi.java b/common/host-side/tradefed/tests/src/com/android/compatibility/common/tradefed/presubmit/ValidateTestsAbi.java
index ebe50a9..297ccfc 100644
--- a/common/host-side/tradefed/tests/src/com/android/compatibility/common/tradefed/presubmit/ValidateTestsAbi.java
+++ b/common/host-side/tradefed/tests/src/com/android/compatibility/common/tradefed/presubmit/ValidateTestsAbi.java
@@ -44,11 +44,19 @@
@RunWith(JUnit4.class)
public class ValidateTestsAbi {
- /**
- * This particular module is shipping all it's dependencies in all abis with prebuilt stuff.
- * Excluding it for now to have the test setup.
- */
- private static final String MODULE_EXCEPTION = "CtsSplitApp";
+ private static final Set<String> MODULE_EXCEPTIONS = new HashSet<>();
+ static {
+ /**
+ * This particular module is shipping all it's dependencies in all abis with prebuilt stuff.
+ * Excluding it for now to have the test setup.
+ */
+ MODULE_EXCEPTIONS.add("CtsSplitApp");
+
+ /**
+ * This module tests for security vulnerabilities when installing attacker-devised APKs.
+ */
+ MODULE_EXCEPTIONS.add("CtsCorruptApkTests");
+ }
private static final Set<String> BINARY_EXCEPTIONS = new HashSet<>();
static {
@@ -74,13 +82,13 @@
File[] listApks = testcases.listFiles(new FilenameFilter() {
@Override
public boolean accept(File dir, String name) {
- if (name.startsWith(MODULE_EXCEPTION)) {
- return false;
+ for (String module : MODULE_EXCEPTIONS) {
+ if (name.startsWith(module)) {
+ return false;
+ }
}
- if (name.endsWith(".apk")) {
- return true;
- }
- return false;
+
+ return name.endsWith(".apk");
}
});
assertTrue(listApks.length > 0);
diff --git a/hostsidetests/appsecurity/Android.mk b/hostsidetests/appsecurity/Android.mk
index 975bcb5..0ef5da3 100644
--- a/hostsidetests/appsecurity/Android.mk
+++ b/hostsidetests/appsecurity/Android.mk
@@ -30,6 +30,10 @@
# tag this module as a cts test artifact
LOCAL_COMPATIBILITY_SUITE := cts vts general-tests
+LOCAL_REQUIRED_MODULES := \
+ CtsCorruptApkTests_b71360999 \
+ CtsCorruptApkTests_b71361168
+
include $(BUILD_CTS_HOST_JAVA_LIBRARY)
# Build the test APKs using their own makefiles
diff --git a/hostsidetests/appsecurity/src/android/appsecurity/cts/CorruptApkTests.java b/hostsidetests/appsecurity/src/android/appsecurity/cts/CorruptApkTests.java
new file mode 100644
index 0000000..bcf67b0
--- /dev/null
+++ b/hostsidetests/appsecurity/src/android/appsecurity/cts/CorruptApkTests.java
@@ -0,0 +1,120 @@
+/*
+ * Copyright (C) 2018 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.appsecurity.cts;
+
+import com.android.compatibility.common.tradefed.build.CompatibilityBuildHelper;
+import com.android.tradefed.build.IBuildInfo;
+import com.android.tradefed.device.ITestDevice;
+import com.android.tradefed.result.InputStreamSource;
+import com.android.tradefed.testtype.DeviceTestCase;
+import com.android.tradefed.testtype.IBuildReceiver;
+import com.android.tradefed.util.FileUtil;
+
+import org.junit.After;
+import org.junit.Before;
+
+import java.io.File;
+
+/**
+ * Set of tests that verify that corrupt APKs are properly rejected by PackageManager and
+ * do not cause the system to crash.
+ */
+public class CorruptApkTests extends DeviceTestCase implements IBuildReceiver {
+ private final String B71360999_PKG = "com.android.appsecurity.b71360999";
+ private final String B71361168_PKG = "com.example.helloworld";
+
+ private IBuildInfo mBuildInfo;
+
+ @Override
+ public void setBuild(IBuildInfo buildInfo) {
+ mBuildInfo = buildInfo;
+ }
+
+ @Before
+ @Override
+ public void setUp() throws Exception {
+ super.setUp();
+ uninstall(B71360999_PKG);
+ uninstall(B71361168_PKG);
+ }
+
+ @After
+ @Override
+ public void tearDown() throws Exception {
+ super.tearDown();
+ uninstall(B71360999_PKG);
+ uninstall(B71361168_PKG);
+ }
+
+ /** Uninstall the apk if the test failed previously. */
+ public void uninstall(String pkg) throws Exception {
+ ITestDevice device = getDevice();
+ if (device.getInstalledPackageNames().contains(pkg)) {
+ device.uninstallPackage(pkg);
+ }
+ }
+
+ /**
+ * Tests that apks described in b/71360999 do not install successfully nor cause
+ */
+ public void testFailToInstallCorruptStringPoolHeader_b71360999() throws Exception {
+ final String APK_PATH = "CtsCorruptApkTests_b71360999.apk";
+ assertFailsToInstall(APK_PATH, B71360999_PKG);
+ }
+
+ /**
+ * Tests that apks described in b/71361168 do not install successfully.
+ */
+ public void testFailToInstallCorruptStringPoolHeader_b71361168() throws Exception {
+ final String APK_PATH = "CtsCorruptApkTests_b71361168.apk";
+ assertFailsToInstall(APK_PATH, B71361168_PKG);
+ }
+
+ /**
+ * Assert that the app fails to install and the reason for failing is not caused by a buffer
+ * overflow nor a out of bounds read.
+ **/
+ private void assertFailsToInstall(String filename, String pkg) throws Exception {
+ ITestDevice device = getDevice();
+ device.clearLogcat();
+
+ final String result = device.installPackage(
+ new CompatibilityBuildHelper(mBuildInfo).getTestFile(filename),
+ true /*reinstall*/);
+
+ assertNotNull(result);
+ assertFalse(result.isEmpty());
+ assertFalse(device.getInstalledPackageNames().contains(pkg));
+
+ // This catches if the device fails to install the app because a segmentation fault
+ // or out of bounds read created by the bug occurs
+ File tmpTxtFile = null;
+ InputStreamSource source = device.getLogcat(200 * 1024);
+ try {
+ assertNotNull(source);
+ tmpTxtFile = FileUtil.createTempFile("logcat", ".txt");
+ FileUtil.writeToFile(source.createInputStream(), tmpTxtFile);
+ String s = FileUtil.readStringFromFile(tmpTxtFile);
+ assertFalse(s.contains("SIGSEGV"));
+ assertFalse(s.contains("==ERROR"));
+ } finally {
+ source.close();
+ if (tmpTxtFile != null) {
+ FileUtil.deleteFile(tmpTxtFile);
+ }
+ }
+ }
+}
diff --git a/hostsidetests/appsecurity/test-apps/CorruptApkTests/Android.mk b/hostsidetests/appsecurity/test-apps/CorruptApkTests/Android.mk
new file mode 100644
index 0000000..feaaa03
--- /dev/null
+++ b/hostsidetests/appsecurity/test-apps/CorruptApkTests/Android.mk
@@ -0,0 +1,31 @@
+# Copyright (C) 2018 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.
+
+LOCAL_PATH := $(call my-dir)
+
+include $(CLEAR_VARS)
+LOCAL_MODULE := CtsCorruptApkTests_b71360999
+LOCAL_MODULE_CLASS := APPS
+LOCAL_SRC_FILES := b71360999.apk
+LOCAL_COMPATIBILITY_SUITE := cts vts general-tests
+LOCAL_CERTIFICATE := PRESIGNED
+include $(BUILD_PREBUILT)
+
+include $(CLEAR_VARS)
+LOCAL_MODULE := CtsCorruptApkTests_b71361168
+LOCAL_MODULE_CLASS := APPS
+LOCAL_SRC_FILES := b71361168.apk
+LOCAL_COMPATIBILITY_SUITE := cts vts general-tests
+LOCAL_CERTIFICATE := PRESIGNED
+include $(BUILD_PREBUILT)
\ No newline at end of file
diff --git a/hostsidetests/appsecurity/test-apps/CorruptApkTests/b71360999.apk b/hostsidetests/appsecurity/test-apps/CorruptApkTests/b71360999.apk
new file mode 100644
index 0000000..55baa66
--- /dev/null
+++ b/hostsidetests/appsecurity/test-apps/CorruptApkTests/b71360999.apk
Binary files differ
diff --git a/hostsidetests/appsecurity/test-apps/CorruptApkTests/b71361168.apk b/hostsidetests/appsecurity/test-apps/CorruptApkTests/b71361168.apk
new file mode 100644
index 0000000..ef1e2bf
--- /dev/null
+++ b/hostsidetests/appsecurity/test-apps/CorruptApkTests/b71361168.apk
Binary files differ