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
This commit is contained in:
Shikha Panwar 2022-12-15 12:24:11 +00:00
parent a30122fa78
commit dc11b7ea38
4 changed files with 73 additions and 0 deletions

View File

@ -49,4 +49,10 @@ interface ITestService {
/** Returns a mask of effective capabilities that the process running the payload binary has. */ /** Returns a mask of effective capabilities that the process running the payload binary has. */
String[] getEffectiveCapabilities(); 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);
} }

View File

@ -126,6 +126,12 @@ public abstract class MicrodroidDeviceTestBase {
} }
} }
protected enum EncryptedStoreOperation {
NONE,
READ,
WRITE,
}
public abstract static class VmEventListener implements VirtualMachineCallback { public abstract static class VmEventListener implements VirtualMachineCallback {
private ExecutorService mExecutorService = Executors.newSingleThreadExecutor(); private ExecutorService mExecutorService = Executors.newSingleThreadExecutor();
private OptionalLong mVcpuStartedNanoTime = OptionalLong.empty(); private OptionalLong mVcpuStartedNanoTime = OptionalLong.empty();

View File

@ -113,6 +113,7 @@ public class MicrodroidTests extends MicrodroidDeviceTestBase {
private static final int MIN_MEM_ARM64 = 150; private static final int MIN_MEM_ARM64 = 150;
private static final int MIN_MEM_X86_64 = 196; private static final int MIN_MEM_X86_64 = 196;
private static final String EXAMPLE_STRING = "Literally any string!! :)";
@Test @Test
@CddTest(requirements = {"9.17/C-1-1", "9.17/C-2-1"}) @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(); 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) private void assertFileContentsAreEqualInTwoVms(String fileName, String vmName1, String vmName2)
throws IOException { throws IOException {
File file1 = getVmFile(vmName1, fileName); File file1 = getVmFile(vmName1, fileName);
@ -1197,9 +1221,15 @@ public class MicrodroidTests extends MicrodroidDeviceTestBase {
String mApkContentsPath; String mApkContentsPath;
String mEncryptedStoragePath; String mEncryptedStoragePath;
String[] mEffectiveCapabilities; String[] mEffectiveCapabilities;
String mFileContent;
} }
private TestResults runVmTestService(VirtualMachine vm) throws Exception { private TestResults runVmTestService(VirtualMachine vm) throws Exception {
return runVmTestService(vm, EncryptedStoreOperation.NONE);
}
private TestResults runVmTestService(VirtualMachine vm, EncryptedStoreOperation mode)
throws Exception {
CompletableFuture<Boolean> payloadStarted = new CompletableFuture<>(); CompletableFuture<Boolean> payloadStarted = new CompletableFuture<>();
CompletableFuture<Boolean> payloadReady = new CompletableFuture<>(); CompletableFuture<Boolean> payloadReady = new CompletableFuture<>();
TestResults testResults = new TestResults(); TestResults testResults = new TestResults();
@ -1222,6 +1252,14 @@ public class MicrodroidTests extends MicrodroidDeviceTestBase {
testService.getEncryptedStoragePath(); testService.getEncryptedStoragePath();
testResults.mEffectiveCapabilities = testResults.mEffectiveCapabilities =
testService.getEffectiveCapabilities(); 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) { } catch (Exception e) {
testResults.mException = e; testResults.mException = e;
} }

View File

@ -232,6 +232,29 @@ Result<void> start_test_service() {
return ScopedAStatus::fromServiceSpecificErrorWithMessage(-1, message.c_str()); 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<TestService>(); auto testService = ndk::SharedRefBase::make<TestService>();