Merge changes from topic "fmayle-flock-test" into main am: d093f03589
Original change: https://android-review.googlesource.com/c/platform/packages/modules/Virtualization/+/3255192
Change-Id: I73e7b60d3821407ad549203237e3d267626d181b
Signed-off-by: Automerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com>
diff --git a/android/virtmgr/Android.bp b/android/virtmgr/Android.bp
index f0b6881..0148ff6 100644
--- a/android/virtmgr/Android.bp
+++ b/android/virtmgr/Android.bp
@@ -70,6 +70,7 @@
"liblibfdt",
"libfsfdt",
"libhypervisor_props",
+ "libzerocopy",
"libuuid",
// TODO(b/202115393) stabilize the interface
"packagemanager_aidl-rust",
diff --git a/android/virtmgr/src/composite.rs b/android/virtmgr/src/composite.rs
index 681ec59..1219150 100644
--- a/android/virtmgr/src/composite.rs
+++ b/android/virtmgr/src/composite.rs
@@ -15,13 +15,16 @@
//! Functions for creating a composite disk image.
use android_system_virtualizationservice::aidl::android::system::virtualizationservice::Partition::Partition;
-use anyhow::{anyhow, Context, Error};
-use disk::{
- create_composite_disk, create_disk_file, ImagePartitionType, PartitionInfo, MAX_NESTING_DEPTH,
-};
+use anyhow::{bail, Context, Error};
+use disk::{create_composite_disk, ImagePartitionType, PartitionInfo};
use std::fs::{File, OpenOptions};
+use std::io::ErrorKind;
+use std::os::unix::fs::FileExt;
use std::os::unix::io::AsRawFd;
use std::path::{Path, PathBuf};
+use zerocopy::AsBytes;
+use zerocopy::FromBytes;
+use zerocopy::FromZeroes;
use uuid::Uuid;
@@ -98,7 +101,7 @@
.context("Failed to clone partition image file descriptor")?
.into();
let path = fd_path_for_file(&file);
- let size = get_partition_size(&file, &path)?;
+ let size = get_partition_size(&file)?;
files.push(file);
Ok(PartitionInfo {
@@ -122,16 +125,74 @@
/// Find the size of the partition image in the given file by parsing the header.
///
-/// This will work for raw, QCOW2, composite and Android sparse images.
-fn get_partition_size(partition: &File, path: &Path) -> Result<u64, Error> {
- // TODO: Use `context` once disk::Error implements std::error::Error.
- // TODO: Add check for is_sparse_file
- Ok(create_disk_file(
- partition.try_clone()?,
- /* is_sparse_file */ false,
- MAX_NESTING_DEPTH,
- path,
- )
- .map_err(|e| anyhow!("Failed to open partition image: {}", e))?
- .get_len()?)
+/// This will work for raw and Android sparse images. QCOW2 and composite images aren't supported.
+fn get_partition_size(file: &File) -> Result<u64, Error> {
+ match detect_image_type(file).context("failed to detect partition image type")? {
+ ImageType::Raw => Ok(file.metadata().context("failed to get metadata")?.len()),
+ ImageType::AndroidSparse => {
+ // Source: system/core/libsparse/sparse_format.h
+ #[repr(C)]
+ #[derive(Clone, Copy, Debug, AsBytes, FromZeroes, FromBytes)]
+ struct SparseHeader {
+ magic: u32,
+ major_version: u16,
+ minor_version: u16,
+ file_hdr_sz: u16,
+ chunk_hdr_size: u16,
+ blk_sz: u32,
+ total_blks: u32,
+ total_chunks: u32,
+ image_checksum: u32,
+ }
+ let mut header = SparseHeader::new_zeroed();
+ file.read_exact_at(header.as_bytes_mut(), 0)
+ .context("failed to read android sparse header")?;
+ let len = u64::from(header.total_blks)
+ .checked_mul(header.blk_sz.into())
+ .context("android sparse image len too big")?;
+ Ok(len)
+ }
+ t => bail!("unsupported partition image type: {t:?}"),
+ }
+}
+
+/// Image file types we can detect.
+#[derive(Debug, PartialEq, Eq)]
+enum ImageType {
+ Raw,
+ Qcow2,
+ CompositeDisk,
+ AndroidSparse,
+}
+
+/// Detect image type by looking for magic bytes.
+fn detect_image_type(file: &File) -> std::io::Result<ImageType> {
+ const CDISK_MAGIC: &str = "composite_disk\x1d";
+ const QCOW_MAGIC: u32 = 0x5146_49fb;
+ const SPARSE_HEADER_MAGIC: u32 = 0xed26ff3a;
+
+ let mut magic4 = [0u8; 4];
+ match file.read_exact_at(&mut magic4[..], 0) {
+ Ok(()) => {}
+ Err(e) if e.kind() == ErrorKind::UnexpectedEof => return Ok(ImageType::Raw),
+ Err(e) => return Err(e),
+ }
+ if magic4 == QCOW_MAGIC.to_be_bytes() {
+ return Ok(ImageType::Qcow2);
+ }
+ if magic4 == SPARSE_HEADER_MAGIC.to_le_bytes() {
+ return Ok(ImageType::AndroidSparse);
+ }
+
+ let mut buf = [0u8; CDISK_MAGIC.len()];
+ match file.read_exact_at(buf.as_bytes_mut(), 0) {
+ Ok(()) => {}
+ Err(e) if e.kind() == ErrorKind::UnexpectedEof => return Ok(ImageType::Raw),
+ Err(e) => return Err(e),
+ }
+ if buf == CDISK_MAGIC.as_bytes() {
+ return Ok(ImageType::CompositeDisk);
+ }
+
+ Ok(ImageType::Raw)
}
diff --git a/android/virtmgr/src/crosvm.rs b/android/virtmgr/src/crosvm.rs
index 5886535..0f41932 100644
--- a/android/virtmgr/src/crosvm.rs
+++ b/android/virtmgr/src/crosvm.rs
@@ -1045,8 +1045,9 @@
}
for disk in config.disks {
+ // Disk file locking is disabled because of missing SELinux policies.
command.arg("--block").arg(format!(
- "path={},ro={}",
+ "path={},ro={},lock=false",
add_preserved_fd(&mut preserved_fds, disk.image),
!disk.writable,
));
diff --git a/android/virtualizationservice/aidl/android/system/virtualizationservice/Partition.aidl b/android/virtualizationservice/aidl/android/system/virtualizationservice/Partition.aidl
index 11a2115..99dc648 100644
--- a/android/virtualizationservice/aidl/android/system/virtualizationservice/Partition.aidl
+++ b/android/virtualizationservice/aidl/android/system/virtualizationservice/Partition.aidl
@@ -20,7 +20,12 @@
/** A label for the partition. */
@utf8InCpp String label;
- /** The backing file descriptor of the partition image. */
+ /**
+ * The backing file descriptor of the partition image.
+ *
+ * The image file must either be a raw binary file, or an android-sparse
+ * formatted file.
+ */
ParcelFileDescriptor image;
/** Whether the partition should be writable by the VM. */