Pass payload disk images as file descriptors rather than paths.
Converting to "/proc/self/fd/N" and then opening it again is not allowed
by SELinux policy.
Bug: 193402941
Test: atest VirtualizationTestCases MicrodroidHostTestCases
Change-Id: Ic0a96e2f5977972d21d2ead47f1fbf4dd079eafa
diff --git a/virtualizationservice/src/payload.rs b/virtualizationservice/src/payload.rs
index 9c6deae..28ef502 100644
--- a/virtualizationservice/src/payload.rs
+++ b/virtualizationservice/src/payload.rs
@@ -14,6 +14,11 @@
//! Payload disk image
+use android_system_virtualizationservice::aidl::android::system::virtualizationservice::{
+ DiskImage::DiskImage, Partition::Partition, VirtualMachineAppConfig::VirtualMachineAppConfig,
+ VirtualMachineRawConfig::VirtualMachineRawConfig,
+};
+use android_system_virtualizationservice::binder::ParcelFileDescriptor;
use anyhow::{anyhow, Context, Result};
use microdroid_metadata::{ApexPayload, ApkPayload, Metadata};
use microdroid_payload_config::ApexConfig;
@@ -22,7 +27,12 @@
use serde_xml_rs::from_reader;
use std::fs::{File, OpenOptions};
use std::path::{Path, PathBuf};
-use vmconfig::{DiskImage, Partition};
+use vmconfig::open_parcel_file;
+
+/// The list of APEXes which microdroid requires.
+// TODO(b/192200378) move this to microdroid.json?
+const MICRODROID_REQUIRED_APEXES: [&str; 3] =
+ ["com.android.adbd", "com.android.i18n", "com.android.os.statsd"];
const APEX_INFO_LIST_PATH: &str = "/apex/apex-info-list.xml";
@@ -65,23 +75,14 @@
}
}
-/// Creates a DiskImage with partitions:
-/// metadata: metadata
-/// microdroid-apex-0: apex 0
-/// microdroid-apex-1: apex 1
-/// ..
-/// microdroid-apk: apk
-/// microdroid-apk-idsig: idsig
-pub fn make_payload_disk(
- apk_file: PathBuf,
- idsig_file: PathBuf,
+fn make_metadata_file(
config_path: &str,
apexes: &[ApexConfig],
temporary_directory: &Path,
-) -> Result<DiskImage> {
+) -> Result<ParcelFileDescriptor> {
let metadata_path = temporary_directory.join("metadata");
let metadata = Metadata {
- version: 1u32,
+ version: 1,
apexes: apexes
.iter()
.map(|apex| ApexPayload { name: apex.name.clone(), ..Default::default() })
@@ -96,35 +97,97 @@
payload_config_path: format!("/mnt/apk/{}", config_path),
..Default::default()
};
- let mut metadata_file =
- OpenOptions::new().create_new(true).read(true).write(true).open(&metadata_path)?;
+
+ // Write metadata to file.
+ let mut metadata_file = OpenOptions::new()
+ .create_new(true)
+ .read(true)
+ .write(true)
+ .open(&metadata_path)
+ .with_context(|| format!("Failed to open metadata file {:?}", metadata_path))?;
microdroid_metadata::write_metadata(&metadata, &mut metadata_file)?;
+ // Re-open the metadata file as read-only.
+ open_parcel_file(&metadata_path, false)
+}
+
+/// Creates a DiskImage with partitions:
+/// metadata: metadata
+/// microdroid-apex-0: apex 0
+/// microdroid-apex-1: apex 1
+/// ..
+/// microdroid-apk: apk
+/// microdroid-apk-idsig: idsig
+fn make_payload_disk(
+ apk_file: File,
+ idsig_file: File,
+ config_path: &str,
+ apexes: &[ApexConfig],
+ temporary_directory: &Path,
+) -> Result<DiskImage> {
+ let metadata_file = make_metadata_file(config_path, apexes, temporary_directory)?;
// put metadata at the first partition
let mut partitions = vec![Partition {
label: "payload-metadata".to_owned(),
- paths: vec![metadata_path],
+ images: vec![metadata_file],
writable: false,
}];
let apex_info_list = ApexInfoList::load()?;
for (i, apex) in apexes.iter().enumerate() {
+ let apex_path = apex_info_list.get_path_for(&apex.name)?;
+ let apex_file = open_parcel_file(&apex_path, false)?;
partitions.push(Partition {
label: format!("microdroid-apex-{}", i),
- paths: vec![apex_info_list.get_path_for(&apex.name)?],
+ images: vec![apex_file],
writable: false,
});
}
partitions.push(Partition {
label: "microdroid-apk".to_owned(),
- paths: vec![apk_file],
+ images: vec![ParcelFileDescriptor::new(apk_file)],
writable: false,
});
partitions.push(Partition {
label: "microdroid-apk-idsig".to_owned(),
- paths: vec![idsig_file],
+ images: vec![ParcelFileDescriptor::new(idsig_file)],
writable: false,
});
Ok(DiskImage { image: None, partitions, writable: false })
}
+
+pub fn add_microdroid_images(
+ config: &VirtualMachineAppConfig,
+ temporary_directory: &Path,
+ apk_file: File,
+ idsig_file: File,
+ mut apexes: Vec<ApexConfig>,
+ vm_config: &mut VirtualMachineRawConfig,
+) -> Result<()> {
+ apexes.extend(
+ MICRODROID_REQUIRED_APEXES.iter().map(|name| ApexConfig { name: name.to_string() }),
+ );
+ apexes.dedup_by(|a, b| a.name == b.name);
+
+ vm_config.disks.push(make_payload_disk(
+ apk_file,
+ idsig_file,
+ &config.configPath,
+ &apexes,
+ temporary_directory,
+ )?);
+
+ if config.debug {
+ vm_config.disks[1].partitions.push(Partition {
+ label: "bootconfig".to_owned(),
+ images: vec![open_parcel_file(
+ Path::new("/apex/com.android.virt/etc/microdroid_bootconfig.debug"),
+ false,
+ )?],
+ writable: false,
+ });
+ }
+
+ Ok(())
+}