1 /* 2 * Copyright (C) 2018 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); you may not 5 * use this file except in compliance with the License. You may obtain a copy 6 * of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 12 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 13 * License for the specific language governing permissions and limitations 14 * under the License. 15 */ 16 package android.appsecurity.cts; 17 18 import static org.junit.Assert.assertFalse; 19 import static org.junit.Assert.assertNotEquals; 20 import static org.junit.Assert.assertNotNull; 21 import static org.junit.Assert.fail; 22 23 import android.platform.test.annotations.AppModeFull; 24 import com.android.ddmlib.Log.LogLevel; 25 import com.android.compatibility.common.tradefed.build.CompatibilityBuildHelper; 26 import com.android.tradefed.build.IBuildInfo; 27 import com.android.tradefed.device.DeviceNotAvailableException; 28 import com.android.tradefed.device.ITestDevice; 29 import com.android.tradefed.log.LogUtil.CLog; 30 import com.android.tradefed.testtype.DeviceTestCase; 31 import com.android.tradefed.testtype.IBuildReceiver; 32 import com.android.tradefed.util.FileUtil; 33 34 import org.junit.After; 35 import org.junit.Assert; 36 import org.junit.Before; 37 38 import java.io.File; 39 40 /** 41 * Set of tests that verify that corrupt APKs are properly rejected by PackageManager and 42 * do not cause the system to crash. 43 */ 44 @AppModeFull(reason = "the corrupt APKs were provided as-is and we cannot modify them to comply with instant mode") 45 public class CorruptApkTests extends DeviceTestCase implements IBuildReceiver { 46 47 private IBuildInfo mBuildInfo; 48 49 /** A container for information about the system_server process. */ 50 private class SystemServerInformation { 51 final long mPid; 52 final long mStartTime; 53 SystemServerInformation(long pid, long startTime)54 SystemServerInformation(long pid, long startTime) { 55 this.mPid = pid; 56 this.mStartTime = startTime; 57 } 58 59 @Override equals(Object actual)60 public boolean equals(Object actual) { 61 return (actual instanceof SystemServerInformation) 62 && mPid == ((SystemServerInformation) actual).mPid 63 && mStartTime == ((SystemServerInformation) actual).mStartTime; 64 } 65 } 66 67 /** Retrieves the process id and elapsed run time of system_server. */ retrieveInfo()68 private SystemServerInformation retrieveInfo() throws DeviceNotAvailableException { 69 ITestDevice device = getDevice(); 70 71 // Retrieve the process id of system_server 72 String pidResult = device.executeShellCommand("pidof system_server").trim(); 73 assertNotNull("Failed to retrieve pid of system_server", pidResult); 74 long pid = 0; 75 try { 76 pid = Long.parseLong(pidResult); 77 } catch (NumberFormatException | IndexOutOfBoundsException e) { 78 fail("Unable to parse pid of system_server '" + pidResult + "'"); 79 } 80 81 // Retrieve the start time of system_server 82 long startTime = 0; 83 String pidStats = device.executeShellCommand("cat /proc/" + pid + "/stat"); 84 assertNotNull("Failed to retrieve stat of system_server with pid '" + pid + "'", pidStats); 85 try { 86 String startTimeJiffies = pidStats.split("\\s+")[21]; 87 startTime = Long.parseLong(startTimeJiffies); 88 } catch (NumberFormatException | IndexOutOfBoundsException e) { 89 fail("Unable to parse system_server stat file '" + pidStats + "'"); 90 } 91 92 return new SystemServerInformation(pid, startTime); 93 } 94 95 @Override setBuild(IBuildInfo buildInfo)96 public void setBuild(IBuildInfo buildInfo) { 97 mBuildInfo = buildInfo; 98 } 99 100 /** Uninstall any test APKs already present on device. */ uninstallApks()101 private void uninstallApks() throws DeviceNotAvailableException { 102 ITestDevice device = getDevice(); 103 device.uninstallPackage("com.android.appsecurity.b71360999"); 104 device.uninstallPackage("com.android.appsecurity.b71361168"); 105 device.uninstallPackage("com.android.appsecurity.b79488511"); 106 } 107 108 @Before 109 @Override setUp()110 public void setUp() throws Exception { 111 super.setUp(); 112 uninstallApks(); 113 } 114 115 @After 116 @Override tearDown()117 public void tearDown() throws Exception { 118 super.tearDown(); 119 uninstallApks(); 120 } 121 122 /** 123 * Asserts that installing the application does not cause a native error causing system_server 124 * to crash (typically the result of a buffer overflow or an out-of-bounds read). 125 */ assertInstallDoesNotCrashSystem(String apk)126 private void assertInstallDoesNotCrashSystem(String apk) throws Exception { 127 SystemServerInformation beforeInfo = retrieveInfo(); 128 129 final String result = getDevice().installPackage( 130 new CompatibilityBuildHelper(mBuildInfo).getTestFile(apk), 131 false /*reinstall*/); 132 CLog.logAndDisplay(LogLevel.INFO, "Result: '" + result + "'"); 133 if (result != null) { 134 assertFalse("Install package segmentation faulted", 135 result.toLowerCase().contains("segmentation fault")); 136 } 137 138 assertEquals("system_server restarted", beforeInfo, retrieveInfo()); 139 } 140 141 /** Tests that installing the APK described in b/71360999 does not crash the device. */ testSafeInstallOfCorruptAPK_b71360999()142 public void testSafeInstallOfCorruptAPK_b71360999() throws Exception { 143 assertInstallDoesNotCrashSystem("CtsCorruptApkTests_b71360999.apk"); 144 } 145 146 /** Tests that installing the APK described in b/71361168 does not crash the device. */ testSafeInstallOfCorruptAPK_b71361168()147 public void testSafeInstallOfCorruptAPK_b71361168() throws Exception { 148 assertInstallDoesNotCrashSystem("CtsCorruptApkTests_b71361168.apk"); 149 } 150 151 /** Tests that installing the APK described in b/79488511 does not crash the device. */ testSafeInstallOfCorruptAPK_b79488511()152 public void testSafeInstallOfCorruptAPK_b79488511() throws Exception { 153 assertInstallDoesNotCrashSystem("CtsCorruptApkTests_b79488511.apk"); 154 } 155 }