Revert "[vs] Extract writable partition initialization into a ne..."

Revert submission 2541653-libvsutil

Reason for revert: This code will stay deprivileged in
virtualizationmanager. No need to also link it into
virtualizationservice.

Reverted changes: /q/submissionid:2541653-libvsutil

Change-Id: I5075ff0a65f9a8af31263116fbce05a6a9cf0b7f
This commit is contained in:
David Brazdil 2023-04-19 14:22:42 +00:00 committed by Gerrit Code Review
parent 0547e864fc
commit f50c7a6627
7 changed files with 83 additions and 175 deletions

View File

@ -1,26 +0,0 @@
package {
default_applicable_licenses: ["Android-Apache-2.0"],
}
rust_library {
name: "libvsutil",
crate_name: "vsutil",
srcs: ["src/lib.rs"],
// Only build on targets which crosvm builds on.
enabled: false,
target: {
android64: {
compile_multilib: "64",
enabled: true,
},
linux_bionic_arm64: {
enabled: true,
},
},
rustlibs: [
"android.system.virtualizationservice-rust",
"libbinder_rs",
"libdisk",
],
apex_available: ["com.android.virt"],
}

View File

@ -1,28 +0,0 @@
// Copyright 2023, The Android Open Source Project
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//! Functions to process files.
use binder::{self, ExceptionCode, ParcelFileDescriptor, Status};
use std::fs::File;
/// Converts a `&ParcelFileDescriptor` to a `File` by cloning the file.
pub fn clone_file(fd: &ParcelFileDescriptor) -> binder::Result<File> {
fd.as_ref().try_clone().map_err(|e| {
Status::new_exception_str(
ExceptionCode::BAD_PARCELABLE,
Some(format!("Failed to clone File from ParcelFileDescriptor: {:?}", e)),
)
})
}

View File

@ -1,22 +0,0 @@
// Copyright 2023, The Android Open Source Project
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//! This library provides utility functions used by both various
//! Virtualization services.
mod file;
mod partition;
pub use file::clone_file;
pub use partition::init_writable_partition;

View File

@ -1,93 +0,0 @@
// Copyright 2023, The Android Open Source Project
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//! Functions to process partitions.
use crate::file::clone_file;
use android_system_virtualizationservice::aidl::android::system::virtualizationservice::{
PartitionType::PartitionType,
};
use binder::{self, ExceptionCode, ParcelFileDescriptor, Status};
use disk::QcowFile;
use std::io::{Error, ErrorKind, Write};
/// crosvm requires all partitions to be a multiple of 4KiB.
const PARTITION_GRANULE_BYTES: u64 = 4096;
/// Initialize an empty partition image of the given size to be used as a writable partition.
pub fn init_writable_partition(
image_fd: &ParcelFileDescriptor,
size_bytes: i64,
partition_type: PartitionType,
) -> binder::Result<()> {
let size_bytes = size_bytes.try_into().map_err(|e| {
Status::new_exception_str(
ExceptionCode::ILLEGAL_ARGUMENT,
Some(format!("Invalid size {}: {:?}", size_bytes, e)),
)
})?;
let size_bytes = round_up(size_bytes, PARTITION_GRANULE_BYTES);
let image = clone_file(image_fd)?;
// initialize the file. Any data in the file will be erased.
image.set_len(0).map_err(|e| {
Status::new_service_specific_error_str(-1, Some(format!("Failed to reset a file: {:?}", e)))
})?;
let mut part = QcowFile::new(image, size_bytes).map_err(|e| {
Status::new_service_specific_error_str(
-1,
Some(format!("Failed to create QCOW2 image: {:?}", e)),
)
})?;
match partition_type {
PartitionType::RAW => Ok(()),
PartitionType::ANDROID_VM_INSTANCE => format_as_android_vm_instance(&mut part),
PartitionType::ENCRYPTEDSTORE => format_as_encryptedstore(&mut part),
_ => Err(Error::new(
ErrorKind::Unsupported,
format!("Unsupported partition type {:?}", partition_type),
)),
}
.map_err(|e| {
Status::new_service_specific_error_str(
-1,
Some(format!("Failed to initialize partition as {:?}: {:?}", partition_type, e)),
)
})
}
fn round_up(input: u64, granule: u64) -> u64 {
if granule == 0 {
return input;
}
// If the input is absurdly large we round down instead of up; it's going to fail anyway.
let result = input.checked_add(granule - 1).unwrap_or(input);
(result / granule) * granule
}
fn format_as_android_vm_instance(part: &mut dyn Write) -> std::io::Result<()> {
const ANDROID_VM_INSTANCE_MAGIC: &str = "Android-VM-instance";
const ANDROID_VM_INSTANCE_VERSION: u16 = 1;
part.write_all(ANDROID_VM_INSTANCE_MAGIC.as_bytes())?;
part.write_all(&ANDROID_VM_INSTANCE_VERSION.to_le_bytes())?;
part.flush()
}
fn format_as_encryptedstore(part: &mut dyn Write) -> std::io::Result<()> {
const UNFORMATTED_STORAGE_MAGIC: &str = "UNFORMATTED-STORAGE";
part.write_all(UNFORMATTED_STORAGE_MAGIC.as_bytes())?;
part.flush()
}

View File

@ -54,7 +54,6 @@ rust_defaults {
"libtombstoned_client_rust",
"libvm_control",
"libvmconfig",
"libvsutil",
"libzip",
"libvsock",
"liblibfdt",

View File

@ -53,6 +53,7 @@ use binder::{
self, wait_for_interface, BinderFeatures, ExceptionCode, Interface, ParcelFileDescriptor,
Status, StatusCode, Strong,
};
use disk::QcowFile;
use lazy_static::lazy_static;
use log::{debug, error, info, warn};
use microdroid_payload_config::{OsConfig, Task, TaskType, VmPayloadConfig};
@ -63,7 +64,7 @@ use semver::VersionReq;
use std::convert::TryInto;
use std::ffi::CStr;
use std::fs::{read_dir, remove_file, File, OpenOptions};
use std::io::{BufRead, BufReader, Write};
use std::io::{BufRead, BufReader, Error, ErrorKind, Write};
use std::num::{NonZeroU16, NonZeroU32};
use std::os::unix::io::{FromRawFd, IntoRawFd};
use std::os::unix::raw::pid_t;
@ -71,7 +72,6 @@ use std::path::{Path, PathBuf};
use std::sync::{Arc, Mutex, Weak};
use vmconfig::VmConfig;
use vsock::VsockStream;
use vsutil::{clone_file, init_writable_partition};
use zip::ZipArchive;
/// The unique ID of a VM used (together with a port number) for vsock communication.
@ -83,8 +83,19 @@ pub const BINDER_SERVICE_IDENTIFIER: &str = "android.system.virtualizationservic
/// Gaps in composite disk images are filled with a shared zero.img.
const ZERO_FILLER_SIZE: u64 = 4096;
/// Magic string for the instance image
const ANDROID_VM_INSTANCE_MAGIC: &str = "Android-VM-instance";
/// Version of the instance image format
const ANDROID_VM_INSTANCE_VERSION: u16 = 1;
const MICRODROID_OS_NAME: &str = "microdroid";
const UNFORMATTED_STORAGE_MAGIC: &str = "UNFORMATTED-STORAGE";
/// crosvm requires all partitions to be a multiple of 4KiB.
const PARTITION_GRANULARITY_BYTES: u64 = 4096;
lazy_static! {
pub static ref GLOBAL_SERVICE: Strong<dyn IVirtualizationServiceInternal> =
wait_for_interface(BINDER_SERVICE_IDENTIFIER)
@ -178,7 +189,45 @@ impl IVirtualizationService for VirtualizationService {
partition_type: PartitionType,
) -> binder::Result<()> {
check_manage_access()?;
init_writable_partition(image_fd, size_bytes, partition_type)
let size_bytes = size_bytes.try_into().map_err(|e| {
Status::new_exception_str(
ExceptionCode::ILLEGAL_ARGUMENT,
Some(format!("Invalid size {}: {:?}", size_bytes, e)),
)
})?;
let size_bytes = round_up(size_bytes, PARTITION_GRANULARITY_BYTES);
let image = clone_file(image_fd)?;
// initialize the file. Any data in the file will be erased.
image.set_len(0).map_err(|e| {
Status::new_service_specific_error_str(
-1,
Some(format!("Failed to reset a file: {:?}", e)),
)
})?;
let mut part = QcowFile::new(image, size_bytes).map_err(|e| {
Status::new_service_specific_error_str(
-1,
Some(format!("Failed to create QCOW2 image: {:?}", e)),
)
})?;
match partition_type {
PartitionType::RAW => Ok(()),
PartitionType::ANDROID_VM_INSTANCE => format_as_android_vm_instance(&mut part),
PartitionType::ENCRYPTEDSTORE => format_as_encryptedstore(&mut part),
_ => Err(Error::new(
ErrorKind::Unsupported,
format!("Unsupported partition type {:?}", partition_type),
)),
}
.map_err(|e| {
Status::new_service_specific_error_str(
-1,
Some(format!("Failed to initialize partition as {:?}: {:?}", partition_type, e)),
)
})?;
Ok(())
}
/// Creates or update the idsig file by digesting the input APK file.
@ -435,6 +484,26 @@ fn write_zero_filler(zero_filler_path: &Path) -> Result<()> {
Ok(())
}
fn format_as_android_vm_instance(part: &mut dyn Write) -> std::io::Result<()> {
part.write_all(ANDROID_VM_INSTANCE_MAGIC.as_bytes())?;
part.write_all(&ANDROID_VM_INSTANCE_VERSION.to_le_bytes())?;
part.flush()
}
fn format_as_encryptedstore(part: &mut dyn Write) -> std::io::Result<()> {
part.write_all(UNFORMATTED_STORAGE_MAGIC.as_bytes())?;
part.flush()
}
fn round_up(input: u64, granularity: u64) -> u64 {
if granularity == 0 {
return input;
}
// If the input is absurdly large we round down instead of up; it's going to fail anyway.
let result = input.checked_add(granularity - 1).unwrap_or(input);
(result / granularity) * granularity
}
/// Given the configuration for a disk image, assembles the `DiskFile` to pass to crosvm.
///
/// This may involve assembling a composite disk from a set of partition images.
@ -886,6 +955,16 @@ fn get_state(instance: &VmInstance) -> VirtualMachineState {
}
}
/// Converts a `&ParcelFileDescriptor` to a `File` by cloning the file.
pub fn clone_file(file: &ParcelFileDescriptor) -> Result<File, Status> {
file.as_ref().try_clone().map_err(|e| {
Status::new_exception_str(
ExceptionCode::BAD_PARCELABLE,
Some(format!("Failed to clone File from ParcelFileDescriptor: {:?}", e)),
)
})
}
/// Converts an `&Option<ParcelFileDescriptor>` to an `Option<File>` by cloning the file.
fn maybe_clone_file(file: &Option<ParcelFileDescriptor>) -> Result<Option<File>, Status> {
file.as_ref().map(clone_file).transpose()

View File

@ -14,7 +14,7 @@
//! Functions for creating and collecting atoms.
use crate::aidl::GLOBAL_SERVICE;
use crate::aidl::{clone_file, GLOBAL_SERVICE};
use crate::crosvm::VmMetric;
use crate::get_calling_uid;
use android_system_virtualizationcommon::aidl::android::system::virtualizationcommon::DeathReason::DeathReason;
@ -37,7 +37,6 @@ use microdroid_payload_config::VmPayloadConfig;
use statslog_virtualization_rust::vm_creation_requested;
use std::thread;
use std::time::{Duration, SystemTime};
use vsutil::clone_file;
use zip::ZipArchive;
const INVALID_NUM_CPUS: i32 = -1;