From dc11b7ea38af99595103cc1e0a1550331ec7cae6 Mon Sep 17 00:00:00 2001 From: Shikha Panwar Date: Thu, 15 Dec 2022 12:24:11 +0000 Subject: [PATCH] Test for checking persistence of encryptedstore Test#encryptedStorageIsPersistent creates a VM, writes an example string into a file backed by encryptedstore. Then it stops the VM, re-runs it (this will reuse the instance image & backing storage). Then it reads the file & checks that the content is the same as the string before. Test: atest MicrodroidTests#encryptedStorageIsPersistent Bug: 260084116 Change-Id: I9a0694de07175c1a29d37fd16488d1523eb13fed --- .../microdroid/testservice/ITestService.aidl | 6 +++ .../test/device/MicrodroidDeviceTestBase.java | 6 +++ .../microdroid/test/MicrodroidTests.java | 38 +++++++++++++++++++ tests/testapk/src/native/testbinary.cpp | 23 +++++++++++ 4 files changed, 73 insertions(+) diff --git a/tests/aidl/com/android/microdroid/testservice/ITestService.aidl b/tests/aidl/com/android/microdroid/testservice/ITestService.aidl index c936e1b6..7ee1f01e 100644 --- a/tests/aidl/com/android/microdroid/testservice/ITestService.aidl +++ b/tests/aidl/com/android/microdroid/testservice/ITestService.aidl @@ -49,4 +49,10 @@ interface ITestService { /** Returns a mask of effective capabilities that the process running the payload binary has. */ String[] getEffectiveCapabilities(); + + /* write the content into the specified file. */ + void writeToFile(String content, String path); + + /* get the content of the specified file. */ + String readFromFile(String path); } diff --git a/tests/helper/src/java/com/android/microdroid/test/device/MicrodroidDeviceTestBase.java b/tests/helper/src/java/com/android/microdroid/test/device/MicrodroidDeviceTestBase.java index 9aed34d3..536f6630 100644 --- a/tests/helper/src/java/com/android/microdroid/test/device/MicrodroidDeviceTestBase.java +++ b/tests/helper/src/java/com/android/microdroid/test/device/MicrodroidDeviceTestBase.java @@ -126,6 +126,12 @@ public abstract class MicrodroidDeviceTestBase { } } + protected enum EncryptedStoreOperation { + NONE, + READ, + WRITE, + } + public abstract static class VmEventListener implements VirtualMachineCallback { private ExecutorService mExecutorService = Executors.newSingleThreadExecutor(); private OptionalLong mVcpuStartedNanoTime = OptionalLong.empty(); diff --git a/tests/testapk/src/java/com/android/microdroid/test/MicrodroidTests.java b/tests/testapk/src/java/com/android/microdroid/test/MicrodroidTests.java index 160b6797..897879bf 100644 --- a/tests/testapk/src/java/com/android/microdroid/test/MicrodroidTests.java +++ b/tests/testapk/src/java/com/android/microdroid/test/MicrodroidTests.java @@ -113,6 +113,7 @@ public class MicrodroidTests extends MicrodroidDeviceTestBase { private static final int MIN_MEM_ARM64 = 150; private static final int MIN_MEM_X86_64 = 196; + private static final String EXAMPLE_STRING = "Literally any string!! :)"; @Test @CddTest(requirements = {"9.17/C-1-1", "9.17/C-2-1"}) @@ -1142,6 +1143,29 @@ public class MicrodroidTests extends MicrodroidDeviceTestBase { assertThat(testResults.mEffectiveCapabilities).isEmpty(); } + @Test + @CddTest(requirements = {"9.17/C-1-1", "9.17/C-2-1"}) + public void encryptedStorageIsPersistent() throws Exception { + assumeSupportedKernel(); + + VirtualMachineConfig config = + newVmConfigBuilder() + .setPayloadBinaryPath("MicrodroidTestNativeLib.so") + .setMemoryMib(minMemoryRequired()) + .setEncryptedStorageKib(4096) + .setDebugLevel(DEBUG_LEVEL_FULL) + .build(); + VirtualMachine vm = forceCreateNewVirtualMachine("test_vm_a", config); + TestResults testResults = runVmTestService(vm, EncryptedStoreOperation.WRITE); + assertThat(testResults.mException).isNull(); + + // Re-run the same VM & verify the file persisted. Note, the previous `runVmTestService` + // stopped the VM + testResults = runVmTestService(vm, EncryptedStoreOperation.READ); + assertThat(testResults.mException).isNull(); + assertThat(testResults.mFileContent).isEqualTo(EXAMPLE_STRING); + } + private void assertFileContentsAreEqualInTwoVms(String fileName, String vmName1, String vmName2) throws IOException { File file1 = getVmFile(vmName1, fileName); @@ -1197,9 +1221,15 @@ public class MicrodroidTests extends MicrodroidDeviceTestBase { String mApkContentsPath; String mEncryptedStoragePath; String[] mEffectiveCapabilities; + String mFileContent; } private TestResults runVmTestService(VirtualMachine vm) throws Exception { + return runVmTestService(vm, EncryptedStoreOperation.NONE); + } + + private TestResults runVmTestService(VirtualMachine vm, EncryptedStoreOperation mode) + throws Exception { CompletableFuture payloadStarted = new CompletableFuture<>(); CompletableFuture payloadReady = new CompletableFuture<>(); TestResults testResults = new TestResults(); @@ -1222,6 +1252,14 @@ public class MicrodroidTests extends MicrodroidDeviceTestBase { testService.getEncryptedStoragePath(); testResults.mEffectiveCapabilities = testService.getEffectiveCapabilities(); + if (mode == EncryptedStoreOperation.WRITE) { + testService.writeToFile( + /*content*/ EXAMPLE_STRING, + /*path*/ "/mnt/encryptedstore/test_file"); + } else if (mode == EncryptedStoreOperation.READ) { + testResults.mFileContent = + testService.readFromFile("/mnt/encryptedstore/test_file"); + } } catch (Exception e) { testResults.mException = e; } diff --git a/tests/testapk/src/native/testbinary.cpp b/tests/testapk/src/native/testbinary.cpp index da408e42..4ba502a0 100644 --- a/tests/testapk/src/native/testbinary.cpp +++ b/tests/testapk/src/native/testbinary.cpp @@ -232,6 +232,29 @@ Result start_test_service() { return ScopedAStatus::fromServiceSpecificErrorWithMessage(-1, message.c_str()); } } + + ScopedAStatus writeToFile(const std::string& content, const std::string& path) override { + if (!android::base::WriteStringToFile(content, path)) { + std::string msg = "Failed to write " + content + " to file " + path + + ". Errono: " + std::to_string(errno); + return ScopedAStatus::fromExceptionCodeWithMessage(EX_SERVICE_SPECIFIC, + msg.c_str()); + } + // TODO(b/264520098): Remove sync() once TestService supports quit() method + // and Microdroid manager flushes filesystem caches on shutdown. + sync(); + return ScopedAStatus::ok(); + } + + ScopedAStatus readFromFile(const std::string& path, std::string* out) override { + if (!android::base::ReadFileToString(path, out)) { + std::string msg = + "Failed to read " + path + " to string. Errono: " + std::to_string(errno); + return ScopedAStatus::fromExceptionCodeWithMessage(EX_SERVICE_SPECIFIC, + msg.c_str()); + } + return ScopedAStatus::ok(); + } }; auto testService = ndk::SharedRefBase::make();