Merge "Rewrite key management & signing"
diff --git a/.prebuilt_info/prebuilt_info_pvmfw_pvmfw_img.asciipb b/.prebuilt_info/prebuilt_info_pvmfw_pvmfw_img.asciipb
index 0f60384..445f731 100644
--- a/.prebuilt_info/prebuilt_info_pvmfw_pvmfw_img.asciipb
+++ b/.prebuilt_info/prebuilt_info_pvmfw_pvmfw_img.asciipb
@@ -1,6 +1,6 @@
drops {
android_build_drop {
- build_id: "8160972"
+ build_id: "8191635"
target: "u-boot_pvmfw"
source_file: "pvmfw.img"
}
diff --git a/javalib/src/android/system/virtualmachine/VirtualMachine.java b/javalib/src/android/system/virtualmachine/VirtualMachine.java
index c48c4fe..14ff111 100644
--- a/javalib/src/android/system/virtualmachine/VirtualMachine.java
+++ b/javalib/src/android/system/virtualmachine/VirtualMachine.java
@@ -223,7 +223,7 @@
}
/** Loads a virtual machine that is already created before. */
- /* package */ static @NonNull VirtualMachine load(
+ /* package */ static @Nullable VirtualMachine load(
@NonNull Context context, @NonNull String name) throws VirtualMachineException {
File configFilePath = getConfigFilePath(context, name);
VirtualMachineConfig config;
diff --git a/javalib/src/android/system/virtualmachine/VirtualMachineManager.java b/javalib/src/android/system/virtualmachine/VirtualMachineManager.java
index 3654886..51fa51f 100644
--- a/javalib/src/android/system/virtualmachine/VirtualMachineManager.java
+++ b/javalib/src/android/system/virtualmachine/VirtualMachineManager.java
@@ -17,6 +17,7 @@
package android.system.virtualmachine;
import android.annotation.NonNull;
+import android.annotation.Nullable;
import android.content.Context;
import java.lang.ref.WeakReference;
@@ -72,7 +73,7 @@
* Returns an existing {@link VirtualMachine} with the given name. Returns null if there is no
* such virtual machine.
*/
- public @NonNull VirtualMachine get(@NonNull String name) throws VirtualMachineException {
+ public @Nullable VirtualMachine get(@NonNull String name) throws VirtualMachineException {
return VirtualMachine.load(mContext, name);
}
diff --git a/pvmfw/pvmfw.img b/pvmfw/pvmfw.img
index 27c2d2b..5e99b5f 100644
--- a/pvmfw/pvmfw.img
+++ b/pvmfw/pvmfw.img
Binary files differ
diff --git a/tests/hostside/java/android/virt/test/MicrodroidTestCase.java b/tests/hostside/java/android/virt/test/MicrodroidTestCase.java
index 1e96246..10b90d3 100644
--- a/tests/hostside/java/android/virt/test/MicrodroidTestCase.java
+++ b/tests/hostside/java/android/virt/test/MicrodroidTestCase.java
@@ -86,7 +86,7 @@
// Run MicrodroidTests#connectToVmService test, which should fail
final DeviceTestRunOptions options = new DeviceTestRunOptions(PACKAGE_NAME)
.setTestClassName(PACKAGE_NAME + ".MicrodroidTests")
- .setTestMethodName("connectToVmService")
+ .setTestMethodName("connectToVmService[protectedVm=false]")
.setCheckResults(false);
assertFalse(runDeviceTests(options));
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 63fdca1..e76fbc9 100644
--- a/tests/testapk/src/java/com/android/microdroid/test/MicrodroidTests.java
+++ b/tests/testapk/src/java/com/android/microdroid/test/MicrodroidTests.java
@@ -18,19 +18,15 @@
import static com.google.common.truth.Truth.assertThat;
import static com.google.common.truth.TruthJUnit.assume;
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertFalse;
-import static org.junit.Assert.assertTrue;
-import static org.junit.Assert.fail;
import static org.junit.Assume.assumeNoException;
import static java.nio.file.StandardCopyOption.REPLACE_EXISTING;
import android.content.Context;
import android.os.Build;
-import android.os.IBinder;
import android.os.ParcelFileDescriptor;
import android.os.SystemProperties;
+import android.sysprop.HypervisorProperties;
import android.system.virtualmachine.VirtualMachine;
import android.system.virtualmachine.VirtualMachineCallback;
import android.system.virtualmachine.VirtualMachineConfig;
@@ -49,7 +45,7 @@
import org.junit.Test;
import org.junit.rules.Timeout;
import org.junit.runner.RunWith;
-import org.junit.runners.JUnit4;
+import org.junit.runners.Parameterized;
import java.io.File;
import java.io.IOException;
@@ -58,10 +54,9 @@
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
-import java.util.concurrent.Future;
import java.util.concurrent.TimeUnit;
-@RunWith(JUnit4.class)
+@RunWith(Parameterized.class)
public class MicrodroidTests {
@Rule public Timeout globalTimeout = Timeout.seconds(300);
@@ -73,6 +68,14 @@
public VirtualMachine mVm;
}
+ @Parameterized.Parameters(name = "protectedVm={0}")
+ public static Object[] protectedVmConfigs() {
+ return new Object[] { false, true };
+ }
+
+ @Parameterized.Parameter
+ public boolean mProtectedVm;
+
private boolean mPkvmSupported = false;
private Inner mInner;
@@ -88,6 +91,17 @@
assumeNoException(e);
return;
}
+ if (mProtectedVm) {
+ assume()
+ .withMessage("Skip where protected VMs aren't support")
+ .that(HypervisorProperties.hypervisor_protected_vm_supported().orElse(false))
+ .isTrue();
+ } else {
+ assume()
+ .withMessage("Skip where VMs aren't support")
+ .that(HypervisorProperties.hypervisor_vm_supported().orElse(false))
+ .isTrue();
+ }
mInner = new Inner();
mInner.mContext = ApplicationProvider.getApplicationContext();
mInner.mVmm = VirtualMachineManager.getInstance(mInner.mContext);
@@ -98,6 +112,9 @@
if (!mPkvmSupported) {
return;
}
+ if (mInner == null) {
+ return;
+ }
if (mInner.mVm == null) {
return;
}
@@ -142,7 +159,7 @@
}
}
- private static final int MIN_MEM_ARM64 = 135;
+ private static final int MIN_MEM_ARM64 = 145;
private static final int MIN_MEM_X86_64 = 196;
@Test
@@ -153,8 +170,8 @@
.isNotEqualTo("5.4");
VirtualMachineConfig.Builder builder =
- new VirtualMachineConfig.Builder(mInner.mContext,
- "assets/vm_config_extra_apk.json");
+ new VirtualMachineConfig.Builder(mInner.mContext, "assets/vm_config_extra_apk.json")
+ .protectedVm(mProtectedVm);
if (Build.SUPPORTED_ABIS.length > 0) {
String primaryAbi = Build.SUPPORTED_ABIS[0];
switch(primaryAbi) {
@@ -169,58 +186,55 @@
VirtualMachineConfig config = builder.build();
mInner.mVm = mInner.mVmm.getOrCreate("test_vm_extra_apk", config);
+
+ class TestResults {
+ Exception mException;
+ Integer mAddInteger;
+ String mAppRunProp;
+ String mSublibRunProp;
+ String mExtraApkTestProp;
+ }
+ final CompletableFuture<Boolean> payloadStarted = new CompletableFuture<>();
+ final CompletableFuture<Boolean> payloadReady = new CompletableFuture<>();
+ final TestResults testResults = new TestResults();
VmEventListener listener =
new VmEventListener() {
- private boolean mPayloadReadyCalled = false;
- private boolean mPayloadStartedCalled = false;
-
- private void testVMService(Future<IBinder> service) {
+ private void testVMService(VirtualMachine vm) {
try {
- IBinder binder = service.get();
-
- ITestService testService = ITestService.Stub.asInterface(binder);
- assertEquals(
- testService.addInteger(123, 456),
- 123 + 456);
- assertEquals(
- testService.readProperty("debug.microdroid.app.run"),
- "true");
- assertEquals(
- testService.readProperty("debug.microdroid.app.sublib.run"),
- "true");
- assertEquals(
- testService.readProperty("debug.microdroid.test.extra_apk"),
- "PASS");
+ ITestService testService = ITestService.Stub.asInterface(
+ vm.connectToVsockServer(ITestService.SERVICE_PORT).get());
+ testResults.mAddInteger = testService.addInteger(123, 456);
+ testResults.mAppRunProp =
+ testService.readProperty("debug.microdroid.app.run");
+ testResults.mSublibRunProp =
+ testService.readProperty("debug.microdroid.app.sublib.run");
+ testResults.mExtraApkTestProp =
+ testService.readProperty("debug.microdroid.test.extra_apk");
} catch (Exception e) {
- fail("Exception while testing service: " + e.toString());
+ testResults.mException = e;
}
}
@Override
public void onPayloadReady(VirtualMachine vm) {
- mPayloadReadyCalled = true;
- try {
- testVMService(vm.connectToVsockServer(ITestService.SERVICE_PORT));
- } catch (Exception e) {
- fail("Exception while connecting to service: " + e.toString());
- }
-
+ payloadReady.complete(true);
+ testVMService(vm);
forceStop(vm);
}
@Override
public void onPayloadStarted(VirtualMachine vm, ParcelFileDescriptor stream) {
- mPayloadStartedCalled = true;
- }
-
- @Override
- public void onDied(VirtualMachine vm, @DeathReason int reason) {
- assertTrue(mPayloadReadyCalled);
- assertTrue(mPayloadStartedCalled);
- super.onDied(vm, reason);
+ payloadStarted.complete(true);
}
};
listener.runToFinish(mInner.mVm);
+ assertThat(payloadStarted.getNow(false)).isTrue();
+ assertThat(payloadReady.getNow(false)).isTrue();
+ assertThat(testResults.mException).isNull();
+ assertThat(testResults.mAddInteger).isEqualTo(123 + 456);
+ assertThat(testResults.mAppRunProp).isEqualTo("true");
+ assertThat(testResults.mSublibRunProp).isEqualTo("true");
+ assertThat(testResults.mExtraApkTestProp).isEqualTo("PASS");
}
@Test
@@ -237,7 +251,8 @@
.isNotEqualTo("5.4");
VirtualMachineConfig.Builder builder =
- new VirtualMachineConfig.Builder(mInner.mContext, "assets/vm_config.json");
+ new VirtualMachineConfig.Builder(mInner.mContext, "assets/vm_config.json")
+ .protectedVm(mProtectedVm);
VirtualMachineConfig normalConfig = builder.debugLevel(DebugLevel.NONE).build();
mInner.mVm = mInner.mVmm.getOrCreate("test_vm", normalConfig);
VmEventListener listener =
@@ -260,40 +275,28 @@
Files.copy(newVmConfig.toPath(), oldVmConfig.toPath(), REPLACE_EXISTING);
newVm.delete();
mInner.mVm = mInner.mVmm.get("test_vm"); // re-load with the copied-in config file.
+ final CompletableFuture<Boolean> payloadStarted = new CompletableFuture<>();
listener =
new VmEventListener() {
- private boolean mPayloadStarted = false;
- private boolean mErrorOccurred = false;
-
@Override
public void onPayloadStarted(VirtualMachine vm, ParcelFileDescriptor stream) {
- mPayloadStarted = true;
+ payloadStarted.complete(true);
forceStop(vm);
}
-
- @Override
- public void onError(VirtualMachine vm, int errorCode, String message) {
- mErrorOccurred = true;
- forceStop(vm);
- }
-
- @Override
- public void onDied(VirtualMachine vm, @DeathReason int reason) {
- assertFalse(mPayloadStarted);
- assertTrue(mErrorOccurred);
- super.onDied(vm, reason);
- }
};
listener.runToFinish(mInner.mVm);
+ assertThat(payloadStarted.getNow(false)).isFalse();
}
private byte[] launchVmAndGetSecret(String instanceName)
throws VirtualMachineException, InterruptedException {
VirtualMachineConfig.Builder builder =
- new VirtualMachineConfig.Builder(mInner.mContext, "assets/vm_config.json");
+ new VirtualMachineConfig.Builder(mInner.mContext, "assets/vm_config.json")
+ .protectedVm(mProtectedVm);
VirtualMachineConfig normalConfig = builder.debugLevel(DebugLevel.NONE).build();
mInner.mVm = mInner.mVmm.getOrCreate(instanceName, normalConfig);
final CompletableFuture<byte[]> secret = new CompletableFuture<>();
+ final CompletableFuture<Exception> exception = new CompletableFuture<>();
VmEventListener listener =
new VmEventListener() {
@Override
@@ -302,13 +305,14 @@
ITestService testService = ITestService.Stub.asInterface(
vm.connectToVsockServer(ITestService.SERVICE_PORT).get());
secret.complete(testService.insecurelyExposeSecret());
+ forceStop(vm);
} catch (Exception e) {
- fail("Exception while connecting to service: " + e.toString());
+ exception.complete(e);
}
- forceStop(vm);
}
};
listener.runToFinish(mInner.mVm);
+ assertThat(exception.getNow(null)).isNull();
return secret.getNow(null);
}
@@ -361,6 +365,7 @@
VirtualMachineConfig config =
new VirtualMachineConfig.Builder(mInner.mContext, "assets/vm_config.json")
+ .protectedVm(mProtectedVm)
.debugLevel(DebugLevel.NONE)
.build();
@@ -370,23 +375,17 @@
mInner.mVm = mInner.mVmm.getOrCreate("test_vm_integrity", config);
+ final CompletableFuture<Boolean> payloadReady = new CompletableFuture<>();
VmEventListener listener =
new VmEventListener() {
- private boolean mPayloadReadyCalled = false;
-
@Override
public void onPayloadReady(VirtualMachine vm) {
- mPayloadReadyCalled = true;
+ payloadReady.complete(true);
forceStop(vm);
}
-
- @Override
- public void onDied(VirtualMachine vm, @DeathReason int reason) {
- assertTrue(mPayloadReadyCalled);
- super.onDied(vm, reason);
- }
};
listener.runToFinish(mInner.mVm);
+ assertThat(payloadReady.getNow(false)).isTrue();
// Launch the same VM after flipping a bit of the instance image.
// Flip actual data, as flipping trivial bits like the magic string isn't interesting.
@@ -405,30 +404,16 @@
instanceFile.close();
mInner.mVm = mInner.mVmm.get("test_vm_integrity"); // re-load the vm with new instance disk
+ final CompletableFuture<Boolean> payloadStarted = new CompletableFuture<>();
listener =
new VmEventListener() {
- private boolean mPayloadStarted = false;
- private boolean mErrorOccurred = false;
-
@Override
public void onPayloadStarted(VirtualMachine vm, ParcelFileDescriptor stream) {
- mPayloadStarted = true;
+ payloadStarted.complete(true);
forceStop(vm);
}
-
- @Override
- public void onError(VirtualMachine vm, int errorCode, String message) {
- mErrorOccurred = true;
- forceStop(vm);
- }
-
- @Override
- public void onDied(VirtualMachine vm, @DeathReason int reason) {
- assertFalse(mPayloadStarted);
- assertTrue(mErrorOccurred);
- super.onDied(vm, reason);
- }
};
listener.runToFinish(mInner.mVm);
+ assertThat(payloadStarted.getNow(false)).isFalse();
}
}