Flag guard the code related to the vendor modules feature
The feature is guarded by the RELEASE_AVF_ENABLE_VENDOR_MODULES flag. On
the virtmgr side the flag-guard check is done in the create_vm_internal
function. On the vm binary side the related flags (--vendor, --kernel)
are only enabled if the RELEASE_AVF_ENABLE_VENDOR_MODULES flag is
enabled.
Additionally the vendor modules related tests in MicrodroidTests now run
conditionally depending on the result of the
`isFeatureEnabled(FEATURE_VENDOR_MODULES)` call.
Bug: 298007909
Test: atest MicrodroidTests
Change-Id: I1467194c802720601a10d0a760a8f1d7ce134037
diff --git a/Android.bp b/Android.bp
index 1fae793..d1086ba 100644
--- a/Android.bp
+++ b/Android.bp
@@ -34,6 +34,7 @@
config_namespace: "ANDROID",
bool_variables: [
"release_avf_enable_multi_tenant_microdroid_vm",
+ "release_avf_enable_vendor_modules",
],
properties: [
"cfgs",
@@ -46,5 +47,8 @@
release_avf_enable_multi_tenant_microdroid_vm: {
cfgs: ["payload_not_root"],
},
+ release_avf_enable_vendor_modules: {
+ cfgs: ["vendor_modules"],
+ },
},
}
diff --git a/javalib/api/test-current.txt b/javalib/api/test-current.txt
index 51c2223..bedb267 100644
--- a/javalib/api/test-current.txt
+++ b/javalib/api/test-current.txt
@@ -13,13 +13,14 @@
public static final class VirtualMachineConfig.Builder {
method @NonNull @RequiresPermission(android.system.virtualmachine.VirtualMachine.USE_CUSTOM_VIRTUAL_MACHINE_PERMISSION) public android.system.virtualmachine.VirtualMachineConfig.Builder setPayloadConfigPath(@NonNull String);
- method @NonNull @RequiresPermission(android.system.virtualmachine.VirtualMachine.USE_CUSTOM_VIRTUAL_MACHINE_PERMISSION) public android.system.virtualmachine.VirtualMachineConfig.Builder setVendorDiskImage(@NonNull java.io.File);
+ method @FlaggedApi("RELEASE_AVF_ENABLE_VENDOR_MODULES") @NonNull @RequiresPermission(android.system.virtualmachine.VirtualMachine.USE_CUSTOM_VIRTUAL_MACHINE_PERMISSION) public android.system.virtualmachine.VirtualMachineConfig.Builder setVendorDiskImage(@NonNull java.io.File);
method @NonNull public android.system.virtualmachine.VirtualMachineConfig.Builder setVmConsoleInputSupported(boolean);
}
public class VirtualMachineManager {
method @RequiresPermission(android.system.virtualmachine.VirtualMachine.MANAGE_VIRTUAL_MACHINE_PERMISSION) public boolean isFeatureEnabled(String) throws android.system.virtualmachine.VirtualMachineException;
field public static final String FEATURE_PAYLOAD_NOT_ROOT = "com.android.kvm.PAYLOAD_NON_ROOT";
+ field public static final String FEATURE_VENDOR_MODULES = "com.android.kvm.VENDOR_MODULES";
}
}
diff --git a/javalib/src/android/system/virtualmachine/VirtualMachineConfig.java b/javalib/src/android/system/virtualmachine/VirtualMachineConfig.java
index b307854..cc8f65b 100644
--- a/javalib/src/android/system/virtualmachine/VirtualMachineConfig.java
+++ b/javalib/src/android/system/virtualmachine/VirtualMachineConfig.java
@@ -21,6 +21,7 @@
import static java.util.Objects.requireNonNull;
+import android.annotation.FlaggedApi;
import android.annotation.IntDef;
import android.annotation.IntRange;
import android.annotation.NonNull;
@@ -903,6 +904,7 @@
*/
@TestApi
@RequiresPermission(VirtualMachine.USE_CUSTOM_VIRTUAL_MACHINE_PERMISSION)
+ @FlaggedApi("RELEASE_AVF_ENABLE_VENDOR_MODULES")
@NonNull
public Builder setVendorDiskImage(@NonNull File vendorDiskImage) {
mVendorDiskImage = vendorDiskImage;
diff --git a/javalib/src/android/system/virtualmachine/VirtualMachineManager.java b/javalib/src/android/system/virtualmachine/VirtualMachineManager.java
index c4096da..0a79553 100644
--- a/javalib/src/android/system/virtualmachine/VirtualMachineManager.java
+++ b/javalib/src/android/system/virtualmachine/VirtualMachineManager.java
@@ -107,7 +107,7 @@
@Retention(RetentionPolicy.SOURCE)
@StringDef(
prefix = "FEATURE_",
- value = {FEATURE_PAYLOAD_NOT_ROOT})
+ value = {FEATURE_PAYLOAD_NOT_ROOT, FEATURE_VENDOR_MODULES})
public @interface Features {}
/**
@@ -120,6 +120,15 @@
IVirtualizationService.FEATURE_PAYLOAD_NON_ROOT;
/**
+ * Feature to run payload as non-root user.
+ *
+ * @hide
+ */
+ @TestApi
+ public static final String FEATURE_VENDOR_MODULES =
+ IVirtualizationService.FEATURE_VENDOR_MODULES;
+
+ /**
* Returns a set of flags indicating what this implementation of virtualization is capable of.
*
* @see #CAPABILITY_PROTECTED_VM
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 d6183cf..473a560 100644
--- a/tests/testapk/src/java/com/android/microdroid/test/MicrodroidTests.java
+++ b/tests/testapk/src/java/com/android/microdroid/test/MicrodroidTests.java
@@ -1537,11 +1537,7 @@
@CddTest(requirements = {"9.17/C-1-1"})
public void payloadIsNotRoot() throws Exception {
assumeSupportedDevice();
-
- VirtualMachineManager vmm = getVirtualMachineManager();
- assumeTrue(
- VirtualMachineManager.FEATURE_PAYLOAD_NOT_ROOT + " not enabled",
- vmm.isFeatureEnabled(VirtualMachineManager.FEATURE_PAYLOAD_NOT_ROOT));
+ assumeFeatureEnabled(VirtualMachineManager.FEATURE_PAYLOAD_NOT_ROOT);
VirtualMachineConfig config =
newVmConfigBuilder()
@@ -2098,6 +2094,7 @@
@Test
public void configuringVendorDiskImageRequiresCustomPermission() throws Exception {
assumeSupportedDevice();
+ assumeFeatureEnabled(VirtualMachineManager.FEATURE_VENDOR_MODULES);
File vendorDiskImage =
new File("/data/local/tmp/cts/microdroid/test_microdroid_vendor_image.img");
@@ -2122,6 +2119,7 @@
@Test
public void bootsWithVendorPartition() throws Exception {
assumeSupportedDevice();
+ assumeFeatureEnabled(VirtualMachineManager.FEATURE_VENDOR_MODULES);
grantPermission(VirtualMachine.USE_CUSTOM_VIRTUAL_MACHINE_PERMISSION);
@@ -2249,4 +2247,9 @@
.that(KERNEL_VERSION)
.isNotEqualTo("5.4");
}
+
+ private void assumeFeatureEnabled(String featureName) throws Exception {
+ VirtualMachineManager vmm = getVirtualMachineManager();
+ assumeTrue(featureName + " not enabled", vmm.isFeatureEnabled(featureName));
+ }
}
diff --git a/virtualizationmanager/src/aidl.rs b/virtualizationmanager/src/aidl.rs
index 1ddf129..62fa09d 100644
--- a/virtualizationmanager/src/aidl.rs
+++ b/virtualizationmanager/src/aidl.rs
@@ -35,6 +35,7 @@
IVirtualMachineCallback::IVirtualMachineCallback,
IVirtualizationService::IVirtualizationService,
IVirtualizationService::FEATURE_PAYLOAD_NON_ROOT,
+ IVirtualizationService::FEATURE_VENDOR_MODULES,
MemoryTrimLevel::MemoryTrimLevel,
Partition::Partition,
PartitionType::PartitionType,
@@ -274,6 +275,7 @@
// TODO(b/298012279): make this scalable.
match feature {
FEATURE_PAYLOAD_NON_ROOT => Ok(cfg!(payload_not_root)),
+ FEATURE_VENDOR_MODULES => Ok(cfg!(vendor_modules)),
_ => {
warn!("unknown feature {}", feature);
Ok(false)
@@ -326,6 +328,8 @@
let requester_uid = get_calling_uid();
let requester_debug_pid = get_calling_pid();
+ check_config_features(config)?;
+
// Allocating VM context checks the MANAGE_VIRTUAL_MACHINE permission.
let (vm_context, cid, temporary_directory) = self.create_vm_context(requester_debug_pid)?;
@@ -1100,6 +1104,24 @@
}
}
+fn check_no_vendor_modules(config: &VirtualMachineConfig) -> binder::Result<()> {
+ let VirtualMachineConfig::AppConfig(config) = config else { return Ok(()) };
+ if let Some(custom_config) = &config.customConfig {
+ if custom_config.vendorImage.is_some() || custom_config.customKernelImage.is_some() {
+ return Err(anyhow!("vendor modules feature is disabled"))
+ .or_binder_exception(ExceptionCode::UNSUPPORTED_OPERATION);
+ }
+ }
+ Ok(())
+}
+
+fn check_config_features(config: &VirtualMachineConfig) -> binder::Result<()> {
+ if !cfg!(vendor_modules) {
+ check_no_vendor_modules(config)?;
+ }
+ Ok(())
+}
+
fn clone_or_prepare_logger_fd(
debug_config: &DebugConfig,
fd: Option<&ParcelFileDescriptor>,
diff --git a/virtualizationservice/aidl/android/system/virtualizationservice/IVirtualizationService.aidl b/virtualizationservice/aidl/android/system/virtualizationservice/IVirtualizationService.aidl
index 0ee958d..fa50d54 100644
--- a/virtualizationservice/aidl/android/system/virtualizationservice/IVirtualizationService.aidl
+++ b/virtualizationservice/aidl/android/system/virtualizationservice/IVirtualizationService.aidl
@@ -23,6 +23,7 @@
interface IVirtualizationService {
const String FEATURE_PAYLOAD_NON_ROOT = "com.android.kvm.PAYLOAD_NON_ROOT";
+ const String FEATURE_VENDOR_MODULES = "com.android.kvm.VENDOR_MODULES";
/**
* Create the VM with the given config file, and return a handle to it ready to start it. If
diff --git a/vm/src/main.rs b/vm/src/main.rs
index 4c44496..e133b8b 100644
--- a/vm/src/main.rs
+++ b/vm/src/main.rs
@@ -98,10 +98,12 @@
storage_size: Option<u64>,
/// Path to custom kernel image to use when booting Microdroid.
+ #[cfg(vendor_modules)]
#[arg(long)]
kernel: Option<PathBuf>,
/// Path to disk image containing vendor-specific modules.
+ #[cfg(vendor_modules)]
#[arg(long)]
vendor: Option<PathBuf>,
@@ -110,6 +112,29 @@
devices: Vec<PathBuf>,
}
+impl MicrodroidConfig {
+ #[cfg(vendor_modules)]
+ fn kernel(&self) -> &Option<PathBuf> {
+ &self.kernel
+ }
+
+ #[cfg(not(vendor_modules))]
+ fn kernel(&self) -> Option<PathBuf> {
+ None
+ }
+
+ #[cfg(vendor_modules)]
+ fn vendor(&self) -> &Option<PathBuf> {
+ &self.vendor
+ }
+
+ #[cfg(not(vendor_modules))]
+ #[inline(always)]
+ fn vendor(&self) -> Option<PathBuf> {
+ None
+ }
+}
+
#[derive(Args)]
/// Flags for the run_app subcommand
pub struct RunAppConfig {
diff --git a/vm/src/run.rs b/vm/src/run.rs
index fc8d7e0..1ba9dec 100644
--- a/vm/src/run.rs
+++ b/vm/src/run.rs
@@ -84,25 +84,25 @@
)?;
}
- let storage = if let Some(path) = config.microdroid.storage {
+ let storage = if let Some(ref path) = config.microdroid.storage {
if !path.exists() {
command_create_partition(
service.as_ref(),
- &path,
+ path,
config.microdroid.storage_size.unwrap_or(10 * 1024 * 1024),
PartitionType::ENCRYPTEDSTORE,
)?;
}
- Some(open_parcel_file(&path, true)?)
+ Some(open_parcel_file(path, true)?)
} else {
None
};
let kernel =
- config.microdroid.kernel.as_ref().map(|p| open_parcel_file(p, false)).transpose()?;
+ config.microdroid.kernel().as_ref().map(|p| open_parcel_file(p, false)).transpose()?;
let vendor =
- config.microdroid.vendor.as_ref().map(|p| open_parcel_file(p, false)).transpose()?;
+ config.microdroid.vendor().as_ref().map(|p| open_parcel_file(p, false)).transpose()?;
let extra_idsig_files: Result<Vec<File>, _> =
config.extra_idsigs.iter().map(File::open).collect();