Merge "Refactor Dice policy test" into main
diff --git a/Android.bp b/Android.bp
index 64d193a..550a6be 100644
--- a/Android.bp
+++ b/Android.bp
@@ -14,18 +14,7 @@
// limitations under the License.
package {
- default_applicable_licenses: ["packages_modules_Virtualization_license"],
-}
-
-// Added automatically by a large-scale-change
-// See: http://go/android-license-faq
-license {
- name: "packages_modules_Virtualization_license",
- visibility: [":__subpackages__"],
- license_kinds: [
- "legacy_unencumbered",
- ],
- // large-scale-change unable to identify any license_text files
+ default_applicable_licenses: ["Android-Apache-2.0"],
}
soong_config_module_type {
diff --git a/apex/Android.bp b/apex/Android.bp
index ccbdb3b..a05f7b0 100644
--- a/apex/Android.bp
+++ b/apex/Android.bp
@@ -13,7 +13,6 @@
config_namespace: "ANDROID",
bool_variables: [
"avf_enabled",
- "avf_kernel_modules_enabled",
],
properties: [
"defaults",
@@ -30,9 +29,6 @@
defaults: ["com.android.virt_avf_disabled"],
},
},
- avf_kernel_modules_enabled: {
- prebuilts: ["microdroid_kernel_with_modules"],
- },
},
}
diff --git a/apkdmverity/Android.bp b/apkdmverity/Android.bp
index cc54d2e..c4c90cd 100644
--- a/apkdmverity/Android.bp
+++ b/apkdmverity/Android.bp
@@ -14,7 +14,6 @@
"libapkverify",
"libbitflags",
"libclap",
- "libdata_model",
"libdm_rust",
"libitertools",
"liblibc",
@@ -22,6 +21,7 @@
"libnum_traits",
"libscopeguard",
"libuuid",
+ "libzerocopy",
],
proc_macros: ["libnum_derive"],
multilib: {
diff --git a/javalib/src/android/system/virtualmachine/VirtualMachine.java b/javalib/src/android/system/virtualmachine/VirtualMachine.java
index 675a046..16f9631 100644
--- a/javalib/src/android/system/virtualmachine/VirtualMachine.java
+++ b/javalib/src/android/system/virtualmachine/VirtualMachine.java
@@ -1382,7 +1382,7 @@
return ERROR_PAYLOAD_VERIFICATION_FAILED;
case ErrorCode.PAYLOAD_CHANGED:
return ERROR_PAYLOAD_CHANGED;
- case ErrorCode.PAYLOAD_CONFIG_INVALID:
+ case ErrorCode.PAYLOAD_INVALID_CONFIG:
return ERROR_PAYLOAD_INVALID_CONFIG;
default:
return ERROR_UNKNOWN;
diff --git a/libs/cborutil/Android.bp b/libs/cborutil/Android.bp
new file mode 100644
index 0000000..4758c4b
--- /dev/null
+++ b/libs/cborutil/Android.bp
@@ -0,0 +1,42 @@
+package {
+ default_applicable_licenses: ["Android-Apache-2.0"],
+}
+
+rust_defaults {
+ name: "libcbor_util_defaults",
+ crate_name: "cbor_util",
+ srcs: ["src/lib.rs"],
+ defaults: ["avf_build_flags_rust"],
+ prefer_rlib: true,
+ apex_available: [
+ "com.android.virt",
+ ],
+}
+
+rust_library_rlib {
+ name: "libcbor_util_nostd",
+ defaults: ["libcbor_util_defaults"],
+ no_stdlibs: true,
+ stdlibs: [
+ "libcompiler_builtins.rust_sysroot",
+ "libcore.rust_sysroot",
+ ],
+ rustlibs: [
+ "libciborium_nostd",
+ "libcoset_nostd",
+ "libserde_nostd",
+ ],
+}
+
+rust_library {
+ name: "libcbor_util",
+ defaults: ["libcbor_util_defaults"],
+ features: [
+ "std",
+ ],
+ rustlibs: [
+ "libciborium",
+ "libcoset",
+ "libserde",
+ ],
+}
diff --git a/service_vm/requests/src/cbor.rs b/libs/cborutil/src/lib.rs
similarity index 84%
rename from service_vm/requests/src/cbor.rs
rename to libs/cborutil/src/lib.rs
index 36492e5..2ec5af4 100644
--- a/service_vm/requests/src/cbor.rs
+++ b/libs/cborutil/src/lib.rs
@@ -14,12 +14,16 @@
//! Utility functions for CBOR serialization/deserialization.
+#![cfg_attr(not(feature = "std"), no_std)]
+
+extern crate alloc;
+
use alloc::vec::Vec;
use coset::{CoseError, Result};
use serde::{de::DeserializeOwned, Serialize};
/// Serializes the given data to a CBOR-encoded byte vector.
-pub(crate) fn serialize<T: ?Sized + Serialize>(v: &T) -> Result<Vec<u8>> {
+pub fn serialize<T: ?Sized + Serialize>(v: &T) -> Result<Vec<u8>> {
let mut data = Vec::new();
ciborium::into_writer(v, &mut data)?;
Ok(data)
@@ -27,7 +31,7 @@
/// Deserializes the given type from a CBOR-encoded byte slice, failing if any extra
/// data remains after the type has been read.
-pub(crate) fn deserialize<T: DeserializeOwned>(mut data: &[u8]) -> Result<T> {
+pub fn deserialize<T: DeserializeOwned>(mut data: &[u8]) -> Result<T> {
let res = ciborium::from_reader(&mut data)?;
if data.is_empty() {
Ok(res)
diff --git a/libs/devicemapper/Android.bp b/libs/devicemapper/Android.bp
index 8f9c25c..5332469 100644
--- a/libs/devicemapper/Android.bp
+++ b/libs/devicemapper/Android.bp
@@ -13,10 +13,10 @@
"libanyhow",
"libbitflags",
"liblibc",
- "libdata_model",
"libhex",
"libnix",
"libuuid",
+ "libzerocopy",
],
multilib: {
lib32: {
diff --git a/libs/devicemapper/src/crypt.rs b/libs/devicemapper/src/crypt.rs
index 8281b34..36c45c7 100644
--- a/libs/devicemapper/src/crypt.rs
+++ b/libs/devicemapper/src/crypt.rs
@@ -20,10 +20,10 @@
use crate::DmTargetSpec;
use anyhow::{ensure, Context, Result};
-use data_model::DataInit;
use std::io::Write;
use std::mem::size_of;
use std::path::Path;
+use zerocopy::AsBytes;
const SECTOR_SIZE: u64 = 512;
@@ -174,7 +174,7 @@
header.next = aligned_size as u32;
let mut buf = Vec::with_capacity(aligned_size);
- buf.write_all(header.as_slice())?;
+ buf.write_all(header.as_bytes())?;
buf.write_all(body.as_bytes())?;
buf.write_all(vec![0; padding].as_slice())?;
diff --git a/libs/devicemapper/src/lib.rs b/libs/devicemapper/src/lib.rs
index 868ac5a..8d004f9 100644
--- a/libs/devicemapper/src/lib.rs
+++ b/libs/devicemapper/src/lib.rs
@@ -32,12 +32,13 @@
#![cfg_attr(test, allow(unused))]
use anyhow::{Context, Result};
-use data_model::DataInit;
use std::fs::{File, OpenOptions};
use std::io::Write;
use std::mem::size_of;
use std::os::unix::io::AsRawFd;
use std::path::{Path, PathBuf};
+use zerocopy::AsBytes;
+use zerocopy::FromZeroes;
/// Exposes DmCryptTarget & related builder
pub mod crypt;
@@ -87,7 +88,7 @@
// `DmTargetSpec` is the header of the data structure for a device-mapper target. When doing the
// ioctl, one of more `DmTargetSpec` (and its body) are appened to the `DmIoctl` struct.
#[repr(C)]
-#[derive(Copy, Clone)]
+#[derive(Copy, Clone, AsBytes, FromZeroes)]
struct DmTargetSpec {
sector_start: u64,
length: u64, // number of 512 sectors
@@ -96,13 +97,9 @@
target_type: [u8; DM_MAX_TYPE_NAME],
}
-// SAFETY: C struct is safe to be initialized from raw data
-unsafe impl DataInit for DmTargetSpec {}
-
impl DmTargetSpec {
fn new(target_type: &str) -> Result<Self> {
- // safe because the size of the array is the same as the size of the struct
- let mut spec: Self = *DataInit::from_mut_slice(&mut [0; size_of::<Self>()]).unwrap();
+ let mut spec = Self::new_zeroed();
spec.target_type.as_mut().write_all(target_type.as_bytes())?;
Ok(spec)
}
@@ -110,8 +107,7 @@
impl DmIoctl {
fn new(name: &str) -> Result<DmIoctl> {
- // safe because the size of the array is the same as the size of the struct
- let mut data: Self = *DataInit::from_mut_slice(&mut [0; size_of::<Self>()]).unwrap();
+ let mut data: Self = Self::new_zeroed();
data.version[0] = DM_VERSION_MAJOR;
data.version[1] = DM_VERSION_MINOR;
data.version[2] = DM_VERSION_PATCHLEVEL;
@@ -202,7 +198,7 @@
}
let mut payload = Vec::with_capacity(payload_size);
- payload.extend_from_slice(data.as_slice());
+ payload.extend_from_slice(data.as_bytes());
payload.extend_from_slice(target);
dm_table_load(self, payload.as_mut_ptr() as *mut DmIoctl)
.context("failed to load table")?;
diff --git a/libs/devicemapper/src/loopdevice.rs b/libs/devicemapper/src/loopdevice.rs
index 16b5b65..9dc722b 100644
--- a/libs/devicemapper/src/loopdevice.rs
+++ b/libs/devicemapper/src/loopdevice.rs
@@ -25,15 +25,14 @@
use crate::util::*;
use anyhow::{Context, Result};
-use data_model::DataInit;
use libc::O_DIRECT;
use std::fs::{File, OpenOptions};
-use std::mem::size_of;
use std::os::unix::fs::OpenOptionsExt;
use std::os::unix::io::AsRawFd;
use std::path::{Path, PathBuf};
use std::thread;
use std::time::{Duration, Instant};
+use zerocopy::FromZeroes;
use crate::loopdevice::sys::*;
@@ -122,9 +121,7 @@
.custom_flags(if direct_io { O_DIRECT } else { 0 })
.open(&path)
.context(format!("failed to open {:?}", path.as_ref()))?;
- // safe because the size of the array is the same as the size of the struct
- let mut config: loop_config =
- *DataInit::from_mut_slice(&mut [0; size_of::<loop_config>()]).unwrap();
+ let mut config = loop_config::new_zeroed();
config.fd = backing_file.as_raw_fd() as u32;
config.block_size = 4096;
config.info.lo_offset = offset;
diff --git a/libs/devicemapper/src/loopdevice/sys.rs b/libs/devicemapper/src/loopdevice/sys.rs
index a35eaa9..ce4ef61 100644
--- a/libs/devicemapper/src/loopdevice/sys.rs
+++ b/libs/devicemapper/src/loopdevice/sys.rs
@@ -15,7 +15,7 @@
*/
use bitflags::bitflags;
-use data_model::DataInit;
+use zerocopy::FromZeroes;
// This UAPI is copied and converted from include/uapi/linux/loop.h Note that this module doesn't
// implement all the features introduced in loop(4). Only the features that are required to support
@@ -28,7 +28,7 @@
pub const LOOP_CLR_FD: libc::c_ulong = 0x4C01;
#[repr(C)]
-#[derive(Copy, Clone)]
+#[derive(Copy, Clone, FromZeroes)]
pub struct loop_config {
pub fd: u32,
pub block_size: u32,
@@ -36,11 +36,8 @@
pub reserved: [u64; 8],
}
-// SAFETY: C struct is safe to be initialized from raw data
-unsafe impl DataInit for loop_config {}
-
#[repr(C)]
-#[derive(Copy, Clone)]
+#[derive(Copy, Clone, FromZeroes)]
pub struct loop_info64 {
pub lo_device: u64,
pub lo_inode: u64,
@@ -57,13 +54,12 @@
pub lo_init: [u64; 2],
}
-// SAFETY: C struct is safe to be initialized from raw data
-unsafe impl DataInit for loop_info64 {}
+#[repr(transparent)]
+#[derive(Copy, Clone, Debug, Eq, Hash, Ord, PartialEq, PartialOrd, FromZeroes)]
+pub struct Flag(u32);
bitflags! {
- #[repr(transparent)]
- #[derive(Copy, Clone, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
- pub struct Flag: u32 {
+ impl Flag: u32 {
const LO_FLAGS_READ_ONLY = 1 << 0;
const LO_FLAGS_AUTOCLEAR = 1 << 2;
const LO_FLAGS_PARTSCAN = 1 << 3;
diff --git a/libs/devicemapper/src/sys.rs b/libs/devicemapper/src/sys.rs
index 3cecde3..bd1e165 100644
--- a/libs/devicemapper/src/sys.rs
+++ b/libs/devicemapper/src/sys.rs
@@ -15,7 +15,8 @@
*/
use bitflags::bitflags;
-use data_model::DataInit;
+use zerocopy::AsBytes;
+use zerocopy::FromZeroes;
// UAPI for device mapper can be found at include/uapi/linux/dm-ioctl.h
@@ -44,7 +45,7 @@
}
#[repr(C)]
-#[derive(Copy, Clone)]
+#[derive(Copy, Clone, AsBytes, FromZeroes)]
pub struct DmIoctl {
pub version: [u32; 3],
pub data_size: u32,
@@ -60,9 +61,6 @@
pub data: [u8; 7],
}
-// SAFETY: C struct is safe to be initialized from raw data
-unsafe impl DataInit for DmIoctl {}
-
pub const DM_VERSION_MAJOR: u32 = 4;
pub const DM_VERSION_MINOR: u32 = 0;
pub const DM_VERSION_PATCHLEVEL: u32 = 0;
@@ -71,10 +69,12 @@
pub const DM_UUID_LEN: usize = 129;
pub const DM_MAX_TYPE_NAME: usize = 16;
+#[repr(transparent)]
+#[derive(Copy, Clone, Debug, Eq, Hash, Ord, PartialEq, PartialOrd, AsBytes, FromZeroes)]
+pub struct Flag(u32);
+
bitflags! {
- #[repr(transparent)]
- #[derive(Copy, Clone, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
- pub struct Flag: u32 {
+ impl Flag: u32 {
const DM_READONLY_FLAG = 1 << 0;
const DM_SUSPEND_FLAG = 1 << 1;
const DM_PERSISTENT_DEV_FLAG = 1 << 3;
diff --git a/libs/devicemapper/src/verity.rs b/libs/devicemapper/src/verity.rs
index e0c5e52..24584f8 100644
--- a/libs/devicemapper/src/verity.rs
+++ b/libs/devicemapper/src/verity.rs
@@ -19,10 +19,10 @@
// which is then given to `DeviceMapper` to create a mapper device.
use anyhow::{bail, Context, Result};
-use data_model::DataInit;
use std::io::Write;
use std::mem::size_of;
use std::path::Path;
+use zerocopy::AsBytes;
use crate::util::*;
use crate::DmTargetSpec;
@@ -195,7 +195,7 @@
header.next = aligned_size as u32;
let mut buf = Vec::with_capacity(aligned_size);
- buf.write_all(header.as_slice())?;
+ buf.write_all(header.as_bytes())?;
buf.write_all(body.as_bytes())?;
buf.write_all(vec![0; padding].as_slice())?;
Ok(DmVerityTarget(buf.into_boxed_slice()))
diff --git a/libs/dice/open_dice/src/ops.rs b/libs/dice/open_dice/src/ops.rs
index 7174d3e..47b5244 100644
--- a/libs/dice/open_dice/src/ops.rs
+++ b/libs/dice/open_dice/src/ops.rs
@@ -95,6 +95,10 @@
///
/// The corresponding public key is included in the leaf certificate of the DICE chain
/// contained in `dice_artifacts`.
+///
+/// Refer to the following documentation for more information about CDI_Leaf_Priv:
+///
+/// security/rkp/aidl/android/hardware/security/keymint/IRemotelyProvisionedComponent.aidl
pub fn derive_cdi_leaf_priv(dice_artifacts: &dyn DiceArtifacts) -> Result<PrivateKey> {
let cdi_priv_key_seed = derive_cdi_private_key_seed(dice_artifacts.cdi_attest())?;
let (_, private_key) = keypair_from_seed(cdi_priv_key_seed.as_array())?;
diff --git a/microdroid/Android.bp b/microdroid/Android.bp
index b494cfa..42ff4b0 100644
--- a/microdroid/Android.bp
+++ b/microdroid/Android.bp
@@ -471,46 +471,3 @@
},
},
}
-
-flag_aware_avb_add_hash_footer {
- name: "microdroid_kernel_with_modules_signed",
- src: ":empty_file",
- filename: "microdroid_kernel_with_modules",
- partition_name: "boot",
- private_key: ":microdroid_sign_key",
- salt: bootloader_salt,
- enabled: false,
- arch: {
- arm64: {
- src: ":microdroid_kernel_with_modules_prebuilts-6.1-arm64",
- enabled: true,
- },
- },
- include_descriptors_from_images: [
- ":microdroid_initrd_normal_hashdesc",
- ":microdroid_initrd_debug_hashdesc",
- ],
- // Below are properties that are conditionally set depending on value of build flags.
- soong_config_variables: {
- release_avf_enable_llpvm_changes: {
- rollback_index: 1,
- props: [
- {
- name: "com.android.virt.cap",
- value: "secretkeeper_protection",
- },
- ],
- },
- },
-}
-
-prebuilt_etc {
- name: "microdroid_kernel_with_modules",
- src: ":empty_file",
- relative_install_path: "fs",
- arch: {
- arm64: {
- src: ":microdroid_kernel_with_modules_signed",
- },
- },
-}
diff --git a/microdroid/kernel/with-modules/Android.bp b/microdroid/kernel/with-modules/Android.bp
deleted file mode 100644
index f1ec06e..0000000
--- a/microdroid/kernel/with-modules/Android.bp
+++ /dev/null
@@ -1,32 +0,0 @@
-// Copyright (C) 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.
-
-package {
- default_applicable_licenses: ["microdroid_kernel_with_modules_prebuilts_6.1_arm64_license"],
-}
-
-// See: http://go/android-license-faq
-license {
- name: "microdroid_kernel_with_modules_prebuilts_6.1_arm64_license",
- visibility: [":__subpackages__"],
- license_kinds: [
- "SPDX-license-identifier-GPL-2.0-only",
- ],
- // large-scale-change unable to identify any license_text files
-}
-
-filegroup {
- name: "microdroid_kernel_with_modules_prebuilts-6.1-arm64",
- srcs: ["kernel_with_modules-6.1"],
-}
diff --git a/microdroid/kernel/with-modules/README.md b/microdroid/kernel/with-modules/README.md
deleted file mode 100644
index 46f6a59..0000000
--- a/microdroid/kernel/with-modules/README.md
+++ /dev/null
@@ -1,10 +0,0 @@
-# Microdroid kernel with modules
-
-This directory contains prebuilts of the Microdroid kernel with support for
-loading vendor modules. Only arm64 architecture is supported.
-
-NOTE: the prebuilt was generated on a local machine, and can only be used on
-development devices.
-
-NOTE: this feature is WIP and kernel is subject to change.
-
diff --git a/microdroid/kernel/with-modules/kernel_with_modules-6.1 b/microdroid/kernel/with-modules/kernel_with_modules-6.1
deleted file mode 100755
index b732ce3..0000000
--- a/microdroid/kernel/with-modules/kernel_with_modules-6.1
+++ /dev/null
Binary files differ
diff --git a/microdroid_manager/src/main.rs b/microdroid_manager/src/main.rs
index 8175753..7ba54f8 100644
--- a/microdroid_manager/src/main.rs
+++ b/microdroid_manager/src/main.rs
@@ -92,7 +92,7 @@
#[error("Payload verification has failed: {0}")]
PayloadVerificationFailed(String),
#[error("Payload config is invalid: {0}")]
- InvalidConfig(String),
+ PayloadInvalidConfig(String),
}
fn translate_error(err: &Error) -> (ErrorCode, String) {
@@ -102,8 +102,8 @@
MicrodroidError::PayloadVerificationFailed(msg) => {
(ErrorCode::PAYLOAD_VERIFICATION_FAILED, msg.to_string())
}
- MicrodroidError::InvalidConfig(msg) => {
- (ErrorCode::PAYLOAD_CONFIG_INVALID, msg.to_string())
+ MicrodroidError::PayloadInvalidConfig(msg) => {
+ (ErrorCode::PAYLOAD_INVALID_CONFIG, msg.to_string())
}
// Connection failure won't be reported to VS; return the default value
@@ -126,7 +126,7 @@
MicrodroidError::PayloadVerificationFailed(_) => {
"MICRODROID_PAYLOAD_VERIFICATION_FAILED"
}
- MicrodroidError::InvalidConfig(_) => "MICRODROID_INVALID_PAYLOAD_CONFIG",
+ MicrodroidError::PayloadInvalidConfig(_) => "MICRODROID_INVALID_PAYLOAD_CONFIG",
})
} else {
// Send context information back after a separator, to ease diagnosis.
@@ -326,12 +326,14 @@
if is_new_instance() {
ensure!(
saved_data.is_none(),
- MicrodroidError::InvalidConfig("Found instance data on first boot.".to_string())
+ MicrodroidError::PayloadInvalidConfig(
+ "Found instance data on first boot.".to_string()
+ )
);
} else {
ensure!(
saved_data.is_some(),
- MicrodroidError::InvalidConfig("Instance data not found.".to_string())
+ MicrodroidError::PayloadInvalidConfig("Instance data not found.".to_string())
);
};
}
@@ -367,7 +369,7 @@
};
let payload_metadata = metadata.payload.ok_or_else(|| {
- MicrodroidError::InvalidConfig("No payload config in metadata".to_string())
+ MicrodroidError::PayloadInvalidConfig("No payload config in metadata".to_string())
})?;
// To minimize the exposure to untrusted data, derive dice profile as soon as possible.
@@ -407,7 +409,7 @@
let task = config
.task
.as_ref()
- .ok_or_else(|| MicrodroidError::InvalidConfig("No task in VM config".to_string()))?;
+ .ok_or_else(|| MicrodroidError::PayloadInvalidConfig("No task in VM config".to_string()))?;
ensure!(
config.extra_apks.len() == verified_data.extra_apks_data.len(),
diff --git a/pvmfw/README.md b/pvmfw/README.md
index 698972a..124ef89 100644
--- a/pvmfw/README.md
+++ b/pvmfw/README.md
@@ -42,7 +42,7 @@
[AVF]: https://source.android.com/docs/core/virtualization
[why-avf]: https://source.android.com/docs/core/virtualization/whyavf
-[BCC]: https://pigweed.googlesource.com/open-dice/+/master/src/android/README.md
+[BCC]: https://pigweed.googlesource.com/open-dice/+/refs/heads/main/docs/android.md
[pKVM]: https://source.android.com/docs/core/virtualization/architecture#hypervisor
[open-dice]: https://pigweed.googlesource.com/open-dice/+/refs/heads/main/docs/specification.md
@@ -191,7 +191,7 @@
pvmfw will provision assigned devices with the VM DTBO.
[header]: src/config.rs
-[DTBO]: https://android.googlesource.com/platform/external/dtc/+/refs/heads/master/Documentation/dt-object-internal.txt
+[DTBO]: https://android.googlesource.com/platform/external/dtc/+/refs/heads/main/Documentation/dt-object-internal.txt
[debug_policy]: ../docs/debug/README.md#debug-policy
#### Virtual Platform Boot Certificate Chain Handover
@@ -416,20 +416,34 @@
`avb_add_hash_footer` Soong module (see [how we sign the Microdroid
kernel][soong-udroid]).
-[soong-udroid]: https://cs.android.com/android/platform/superproject/+/master:packages/modules/Virtualization/microdroid/Android.bp;l=427;drc=ca0049be4d84897b8c9956924cfae506773103eb
+[soong-udroid]: https://cs.android.com/android/platform/superproject/main/+/main:packages/modules/Virtualization/microdroid/Android.bp;l=425;drc=b94a5cf516307c4279f6c16a63803527a8affc6d
## Development
For faster iteration, you can build pvmfw, adb-push it to the device, and use
it directly for a new pVM, without having to flash it to the physical
-partition. To do that, set the system property `hypervisor.pvmfw.path` to point
-to the pvmfw image you pushed as shown below:
+partition. To do that, the binary image composition performed by ABL described
+above must be replicated to produce a single file containing the pvmfw binary
+and its configuration data.
+
+As a quick prototyping solution, a valid BCC (such as the [bcc.dat] test file)
+can be appended to the `pvmfw.bin` image with `pvmfw-tool`.
```shell
-m pvmfw_img
-adb push out/target/product/generic_arm64/system/etc/pvmfw.img /data/local/tmp/pvmfw.img
+m pvmfw-tool pvmfw_bin
+PVMFW_BIN=${ANDROID_PRODUCT_OUT}/system/etc/pvmfw.bin
+BCC_DAT=${ANDROID_BUILD_TOP}/packages/modules/Virtualization/tests/pvmfw/assets/bcc.dat
+
+pvmfw-tool custom_pvmfw ${PVMFW_BIN} ${BCC_DAT}
+```
+
+The result can then be pushed to the device. Pointing the system property
+`hypervisor.pvmfw.path` to it will cause AVF to use that image as pvmfw:
+
+```shell
+adb push custom_pvmfw /data/local/tmp/pvmfw
adb root
-adb shell setprop hypervisor.pvmfw.path /data/local/tmp/pvmfw.img
+adb shell setprop hypervisor.pvmfw.path /data/local/tmp/pvmfw
```
Then run a protected VM, for example:
@@ -439,3 +453,5 @@
```
Note: `adb root` is required to set the system property.
+
+[bcc.dat]: https://cs.android.com/android/platform/superproject/main/+/main:packages/modules/Virtualization/tests/pvmfw/assets/bcc.dat
diff --git a/pvmfw/src/config.rs b/pvmfw/src/config.rs
index 926f42b..78b6323 100644
--- a/pvmfw/src/config.rs
+++ b/pvmfw/src/config.rs
@@ -16,8 +16,10 @@
use core::fmt;
use core::mem;
+use core::num::NonZeroUsize;
use core::ops::Range;
use core::result;
+use core::slice;
use log::{info, warn};
use static_assertions::const_assert_eq;
use vmbase::util::RangeExt;
@@ -53,6 +55,8 @@
MissingEntry(Entry),
/// Range described by entry does not fit within config data.
EntryOutOfBounds(Entry, Range<usize>, Range<usize>),
+ /// Entries are in out of order
+ EntryOutOfOrder,
}
impl fmt::Display for Error {
@@ -70,6 +74,7 @@
"Entry {entry:?} out of bounds: {range:#x?} must be within range {limits:#x?}"
)
}
+ Self::EntryOutOfOrder => write!(f, "Entries are out of order"),
}
}
}
@@ -133,19 +138,6 @@
size: u32,
}
-impl HeaderEntry {
- pub fn as_range(&self) -> Option<Range<usize>> {
- let size = usize::try_from(self.size).unwrap();
- if size != 0 {
- let offset = self.offset.try_into().unwrap();
- // Allow overflows here for the Range to properly describe the entry (validated later).
- Some(offset..(offset + size))
- } else {
- None
- }
- }
-}
-
#[repr(C, packed)]
#[derive(Clone, Copy, Debug, Eq, FromZeroes, FromBytes, PartialEq)]
pub struct Version {
@@ -161,10 +153,38 @@
}
}
+/// Range with non-empty length.
+#[derive(Debug, Copy, Clone)]
+struct NonEmptyRange {
+ start: usize,
+ size: NonZeroUsize,
+}
+
+impl NonEmptyRange {
+ pub fn new(start: usize, size: usize) -> Option<Self> {
+ // Ensure end() is safe.
+ start.checked_add(size).unwrap();
+
+ Some(Self { start, size: NonZeroUsize::new(size)? })
+ }
+
+ fn end(&self) -> usize {
+ self.start + self.len()
+ }
+
+ fn len(&self) -> usize {
+ self.size.into()
+ }
+
+ fn as_range(&self) -> Range<usize> {
+ self.start..self.end()
+ }
+}
+
#[derive(Debug)]
pub struct Config<'a> {
body: &'a mut [u8],
- ranges: [Option<Range<usize>>; Entry::COUNT],
+ ranges: [Option<NonEmptyRange>; Entry::COUNT],
}
impl<'a> Config<'a> {
@@ -209,68 +229,64 @@
// Validate that we won't get an invalid alignment in the following due to padding to u64.
const_assert_eq!(mem::size_of::<HeaderEntry>() % mem::size_of::<u64>(), 0);
+ // Ensure entries are in the body.
let limits = header.body_lowest_bound()?..total_size;
- let ranges = [
- // TODO: Find a way to do this programmatically even if the trait
- // `core::marker::Copy` is not implemented for `core::ops::Range<usize>`.
- Self::validated_body_range(Entry::Bcc, &header_entries, &limits)?,
- Self::validated_body_range(Entry::DebugPolicy, &header_entries, &limits)?,
- Self::validated_body_range(Entry::VmDtbo, &header_entries, &limits)?,
- ];
+ let mut ranges: [Option<NonEmptyRange>; Entry::COUNT] = [None; Entry::COUNT];
+ let mut last_end = 0;
+ for entry in [Entry::Bcc, Entry::DebugPolicy, Entry::VmDtbo] {
+ let Some(header_entry) = header_entries.get(entry as usize) else { continue };
+ let entry_offset = header_entry.offset.try_into().unwrap();
+ let entry_size = header_entry.size.try_into().unwrap();
+ let Some(range) = NonEmptyRange::new(entry_offset, entry_size) else { continue };
+ let range = range.as_range();
+ if !range.is_within(&limits) {
+ return Err(Error::EntryOutOfBounds(entry, range, limits));
+ }
+
+ if last_end > range.start {
+ return Err(Error::EntryOutOfOrder);
+ }
+ last_end = range.end;
+
+ ranges[entry as usize] = NonEmptyRange::new(
+ entry_offset - limits.start, // is_within() validates safety of this.
+ entry_size,
+ );
+ }
+ // Ensures that BCC exists.
+ ranges[Entry::Bcc as usize].ok_or(Error::MissingEntry(Entry::Bcc))?;
Ok(Self { body, ranges })
}
/// Get slice containing the platform BCC.
- pub fn get_entries(&mut self) -> Result<(&mut [u8], Option<&mut [u8]>)> {
+ pub fn get_entries(&mut self) -> (&mut [u8], Option<&mut [u8]>) {
// This assumes that the blobs are in-order w.r.t. the entries.
- let bcc_range = self.get_entry_range(Entry::Bcc).ok_or(Error::MissingEntry(Entry::Bcc))?;
+ let bcc_range = self.get_entry_range(Entry::Bcc);
let dp_range = self.get_entry_range(Entry::DebugPolicy);
let vm_dtbo_range = self.get_entry_range(Entry::VmDtbo);
// TODO(b/291191157): Provision device assignment with this.
if let Some(vm_dtbo_range) = vm_dtbo_range {
info!("Found VM DTBO at {:?}", vm_dtbo_range);
}
- let bcc_start = bcc_range.start;
- let bcc_end = bcc_range.len();
- let (_, rest) = self.body.split_at_mut(bcc_start);
- let (bcc, rest) = rest.split_at_mut(bcc_end);
- let dp = if let Some(dp_range) = dp_range {
- let dp_start = dp_range.start.checked_sub(bcc_range.end).unwrap();
- let dp_end = dp_range.len();
- let (_, rest) = rest.split_at_mut(dp_start);
- let (dp, _) = rest.split_at_mut(dp_end);
- Some(dp)
- } else {
- None
- };
-
- Ok((bcc, dp))
- }
-
- pub fn get_entry_range(&self, entry: Entry) -> Option<Range<usize>> {
- self.ranges[entry as usize].clone()
- }
-
- fn validated_body_range(
- entry: Entry,
- header_entries: &[HeaderEntry],
- limits: &Range<usize>,
- ) -> Result<Option<Range<usize>>> {
- if let Some(header_entry) = header_entries.get(entry as usize) {
- if let Some(r) = header_entry.as_range() {
- return if r.start <= r.end && r.is_within(limits) {
- let start = r.start - limits.start;
- let end = r.end - limits.start;
-
- Ok(Some(start..end))
- } else {
- Err(Error::EntryOutOfBounds(entry, r, limits.clone()))
- };
- }
+ // SAFETY: When instantiate, ranges are validated to be in the body range without
+ // overlapping.
+ unsafe {
+ let ptr = self.body.as_mut_ptr() as usize;
+ (
+ Self::from_raw_range_mut(ptr, bcc_range.unwrap()),
+ dp_range.map(|dp_range| Self::from_raw_range_mut(ptr, dp_range)),
+ )
}
+ }
- Ok(None)
+ fn get_entry_range(&self, entry: Entry) -> Option<NonEmptyRange> {
+ self.ranges[entry as usize]
+ }
+
+ unsafe fn from_raw_range_mut(ptr: usize, range: NonEmptyRange) -> &'a mut [u8] {
+ // SAFETY: The caller must ensure that the range is valid from ptr.
+ unsafe { slice::from_raw_parts_mut((ptr + range.start) as *mut u8, range.end()) }
}
}
diff --git a/pvmfw/src/entry.rs b/pvmfw/src/entry.rs
index 3efa61e..9c929a9 100644
--- a/pvmfw/src/entry.rs
+++ b/pvmfw/src/entry.rs
@@ -207,10 +207,7 @@
RebootReason::InvalidConfig
})?;
- let (bcc_slice, debug_policy) = appended.get_entries().map_err(|e| {
- error!("Failed to obtained the config entries: {e}");
- RebootReason::InvalidConfig
- })?;
+ let (bcc_slice, debug_policy) = appended.get_entries();
// Up to this point, we were using the built-in static (from .rodata) page tables.
MEMORY.lock().replace(MemoryTracker::new(
@@ -430,10 +427,10 @@
}
}
- fn get_entries(&mut self) -> config::Result<(&mut [u8], Option<&mut [u8]>)> {
+ fn get_entries(&mut self) -> (&mut [u8], Option<&mut [u8]>) {
match self {
Self::Config(ref mut cfg) => cfg.get_entries(),
- Self::LegacyBcc(ref mut bcc) => Ok((bcc, None)),
+ Self::LegacyBcc(ref mut bcc) => (bcc, None),
}
}
}
diff --git a/service_vm/README.md b/service_vm/README.md
new file mode 100644
index 0000000..3d94f78
--- /dev/null
+++ b/service_vm/README.md
@@ -0,0 +1,45 @@
+# Service VM
+
+The Service VM is a lightweight, bare-metal virtual machine specifically
+designed to run various services for other virtual machines. It fulfills the
+following requirements:
+
+- Only one instance of the Service VM is allowed to run at any given time.
+- The *secret* contained within the instance image of the Service VM remains
+ unchanged during updates of both the client VMs and the Service VM.
+
+The secret is an encrypted random array that can only be decrypted by
+[pVM Firmware][pvmfw]. It is incorporated into the [CDI values][cdi] calculation
+of each VM loaded by pVM Firmware to ensure consistent CDI values for the VM
+across all reboots.
+
+[cdi]: https://android.googlesource.com/platform/external/open-dice/+/main/docs/specification.md#CDI-Values
+[pvmfw]: https://android.googlesource.com/platform/packages/modules/Virtualization/+/main/pvmfw/README.md
+
+## RKP VM (Remote Key Provisioning Virtual Machine)
+
+The RKP VM is a key dependency of the Service VM. It is a virtual machine that
+undergoes validation by the [RKP][rkp] Server and acts as a remotely provisioned
+component for verifying the integrity of other virtual machines.
+
+[rkp]: https://source.android.com/docs/core/ota/modular-system/remote-key-provisioning
+
+### RKP VM attestation
+
+The RKP VM is recognized and attested by the RKP server, which acts as a trusted
+entity responsible for verifying the DICE chain of the RKP VM. This verification
+ensures that the RKP VM is operating on a genuine device.
+Additionally, the RKP VM is validated by the pVM Firmware, as part of the
+verified boot process.
+
+### Client VM attestation
+
+Once the RKP VM is successfully attested, it assumes the role of a trusted
+platform to attest client VMs. It leverages its trusted status to validate the
+integrity of the [DICE chain][open-dice] associated with each client VM. This
+validation process verifies that the client VMs are running in the expected
+[Microdroid][microdroid] VM environment, and certifies the payload executed
+within the VM. Currently, only Microdroid VMs are supported.
+
+[open-dice]: https://android.googlesource.com/platform/external/open-dice/+/main/docs/android.md
+[microdroid]: https://android.googlesource.com/platform/packages/modules/Virtualization/+/main/microdroid/README.md
diff --git a/service_vm/requests/Android.bp b/service_vm/requests/Android.bp
index f85064a..ecede8b 100644
--- a/service_vm/requests/Android.bp
+++ b/service_vm/requests/Android.bp
@@ -18,6 +18,7 @@
rustlibs: [
"libbssl_avf_error_nostd",
"libbssl_avf_nostd",
+ "libcbor_util_nostd",
"libciborium_nostd",
"libcoset_nostd",
"libdiced_open_dice_nostd",
diff --git a/service_vm/requests/src/keyblob.rs b/service_vm/requests/src/keyblob.rs
index a714edd..456c879 100644
--- a/service_vm/requests/src/keyblob.rs
+++ b/service_vm/requests/src/keyblob.rs
@@ -14,7 +14,6 @@
//! Handles the encryption and decryption of the key blob.
-use crate::cbor;
use alloc::vec;
use alloc::vec::Vec;
use bssl_avf::{hkdf, rand_bytes, Aead, AeadContext, Digester, AES_GCM_NONCE_LENGTH};
@@ -70,16 +69,6 @@
Self::V1(blob) => blob.decrypt_private_key(kek_secret),
}
}
-
- // TODO(b/241428146): This function will be used once the retrieval mechanism is available.
- #[cfg(test)]
- pub(crate) fn from_cbor_slice(slice: &[u8]) -> coset::Result<Self> {
- cbor::deserialize(slice)
- }
-
- pub(crate) fn to_cbor_vec(&self) -> coset::Result<Vec<u8>> {
- cbor::serialize(&self)
- }
}
impl EncryptedKeyBlobV1 {
@@ -136,8 +125,9 @@
#[test]
fn decrypting_keyblob_succeeds_with_the_same_kek() -> Result<()> {
- let encrypted_key_blob = EncryptedKeyBlob::new(&TEST_KEY, &TEST_SECRET1)?.to_cbor_vec()?;
- let encrypted_key_blob = EncryptedKeyBlob::from_cbor_slice(&encrypted_key_blob)?;
+ let encrypted_key_blob =
+ cbor_util::serialize(&EncryptedKeyBlob::new(&TEST_KEY, &TEST_SECRET1)?)?;
+ let encrypted_key_blob: EncryptedKeyBlob = cbor_util::deserialize(&encrypted_key_blob)?;
let decrypted_key = encrypted_key_blob.decrypt_private_key(&TEST_SECRET1)?;
assert_eq!(TEST_KEY, decrypted_key.as_slice());
@@ -146,8 +136,9 @@
#[test]
fn decrypting_keyblob_fails_with_a_different_kek() -> Result<()> {
- let encrypted_key_blob = EncryptedKeyBlob::new(&TEST_KEY, &TEST_SECRET1)?.to_cbor_vec()?;
- let encrypted_key_blob = EncryptedKeyBlob::from_cbor_slice(&encrypted_key_blob)?;
+ let encrypted_key_blob =
+ cbor_util::serialize(&EncryptedKeyBlob::new(&TEST_KEY, &TEST_SECRET1)?)?;
+ let encrypted_key_blob: EncryptedKeyBlob = cbor_util::deserialize(&encrypted_key_blob)?;
let err = encrypted_key_blob.decrypt_private_key(&TEST_SECRET2).unwrap_err();
let expected_err: RequestProcessingError =
diff --git a/service_vm/requests/src/lib.rs b/service_vm/requests/src/lib.rs
index 6fa6e0b..e3c5794 100644
--- a/service_vm/requests/src/lib.rs
+++ b/service_vm/requests/src/lib.rs
@@ -19,7 +19,6 @@
extern crate alloc;
mod api;
-mod cbor;
mod keyblob;
mod pub_key;
mod rkp;
diff --git a/service_vm/requests/src/rkp.rs b/service_vm/requests/src/rkp.rs
index 933737c..8d7d771 100644
--- a/service_vm/requests/src/rkp.rs
+++ b/service_vm/requests/src/rkp.rs
@@ -15,7 +15,6 @@
//! This module contains functions related to the attestation of the
//! service VM via the RKP (Remote Key Provisioning) server.
-use crate::cbor;
use crate::keyblob::EncryptedKeyBlob;
use crate::pub_key::{build_maced_public_key, validate_public_key};
use alloc::string::String;
@@ -51,7 +50,8 @@
let key_blob =
EncryptedKeyBlob::new(ec_key.private_key()?.as_slice(), dice_artifacts.cdi_seal())?;
- let key_pair = EcdsaP256KeyPair { maced_public_key, key_blob: key_blob.to_cbor_vec()? };
+ let key_pair =
+ EcdsaP256KeyPair { maced_public_key, key_blob: cbor_util::serialize(&key_blob)? };
Ok(key_pair)
}
@@ -81,7 +81,7 @@
// TODO(b/299256925): Add device info in CBOR format here.
Value::Array(public_keys),
])?;
- let csr_payload = cbor::serialize(&csr_payload)?;
+ let csr_payload = cbor_util::serialize(&csr_payload)?;
// Builds `SignedData`.
let signed_data_payload =
@@ -93,14 +93,14 @@
// Check http://b/301574013#comment3 for more information.
let uds_certs = Value::Map(Vec::new());
let dice_cert_chain = dice_artifacts.bcc().ok_or(RequestProcessingError::MissingDiceChain)?;
- let dice_cert_chain: Value = cbor::deserialize(dice_cert_chain)?;
+ let dice_cert_chain: Value = cbor_util::deserialize(dice_cert_chain)?;
let auth_req = cbor!([
Value::Integer(AUTH_REQ_SCHEMA_V1.into()),
uds_certs,
dice_cert_chain,
signed_data,
])?;
- Ok(cbor::serialize(&auth_req)?)
+ Ok(cbor_util::serialize(&auth_req)?)
}
fn derive_hmac_key(dice_artifacts: &dyn DiceArtifacts) -> Result<Zeroizing<[u8; HMAC_KEY_LENGTH]>> {
@@ -122,7 +122,7 @@
let protected = HeaderBuilder::new().algorithm(signing_algorithm).build();
let signed_data = CoseSign1Builder::new()
.protected(protected)
- .payload(cbor::serialize(payload)?)
+ .payload(cbor_util::serialize(payload)?)
.try_create_signature(&[], |message| sign_message(message, &cdi_leaf_priv))?
.build();
Ok(signed_data)
diff --git a/tests/hostside/java/com/android/microdroid/test/MicrodroidHostTests.java b/tests/hostside/java/com/android/microdroid/test/MicrodroidHostTests.java
index 692b1b8..001dfeb 100644
--- a/tests/hostside/java/com/android/microdroid/test/MicrodroidHostTests.java
+++ b/tests/hostside/java/com/android/microdroid/test/MicrodroidHostTests.java
@@ -765,16 +765,22 @@
// Check if the native library in the APK is has correct filesystem info
final String[] abis = microdroid.run("getprop", "ro.product.cpu.abilist").split(",");
- assertThat(abis).hasLength(1);
+ assertWithMessage("Incorrect ABI list").that(abis).hasLength(1);
// Check that no denials have happened so far
- assertThat(android.tryRun("egrep", "'avc:[[:space:]]{1,2}denied'", LOG_PATH)).isNull();
- assertThat(android.tryRun("egrep", "'avc:[[:space:]]{1,2}denied'", CONSOLE_PATH)).isNull();
+ assertWithMessage("Unexpected denials during VM boot")
+ .that(android.tryRun("egrep", "'avc:[[:space:]]{1,2}denied'", LOG_PATH))
+ .isNull();
+ assertWithMessage("Unexpected denials during VM boot")
+ .that(android.tryRun("egrep", "'avc:[[:space:]]{1,2}denied'", CONSOLE_PATH))
+ .isNull();
assertThat(getDeviceNumCpus(microdroid)).isEqualTo(getDeviceNumCpus(android));
// Check that selinux is enabled
- assertThat(microdroid.run("getenforce")).isEqualTo("Enforcing");
+ assertWithMessage("SELinux should be in enforcing mode")
+ .that(microdroid.run("getenforce"))
+ .isEqualTo("Enforcing");
// TODO(b/176805428): adb is broken for nested VM
if (!isCuttlefish()) {
diff --git a/tests/pvmfw/tools/PvmfwTool.java b/tests/pvmfw/tools/PvmfwTool.java
index e4b6020..62c641b 100644
--- a/tests/pvmfw/tools/PvmfwTool.java
+++ b/tests/pvmfw/tools/PvmfwTool.java
@@ -25,13 +25,13 @@
public class PvmfwTool {
public static void printUsage() {
System.out.println("pvmfw-tool: Appends pvmfw.bin and config payloads.");
- System.out.println("Requires BCC and debug policy dtbo files");
+ System.out.println("Requires BCC and optional debug policy dtbo files");
System.out.println("");
- System.out.println("Usage: pvmfw-tool <pvmfw_with_config> <pvmfw_bin> <bcc.dat> <dp.dtbo>");
+ System.out.println("Usage: pvmfw-tool <out> <pvmfw.bin> <bcc.dat> [<dp.dtbo>]");
}
public static void main(String[] args) {
- if (args.length != 4) {
+ if (args.length != 4 && args.length != 3) {
printUsage();
System.exit(1);
}
@@ -39,11 +39,14 @@
File out = new File(args[0]);
File pvmfw_bin = new File(args[1]);
File bcc_dat = new File(args[2]);
- File dtbo = new File(args[3]);
try {
- Pvmfw pvmfw = new Pvmfw.Builder(pvmfw_bin, bcc_dat).setDebugPolicyOverlay(dtbo).build();
- pvmfw.serialize(out);
+ Pvmfw.Builder builder = new Pvmfw.Builder(pvmfw_bin, bcc_dat);
+ if (args.length == 4) {
+ File dtbo = new File(args[3]);
+ builder.setDebugPolicyOverlay(dtbo);
+ }
+ builder.build().serialize(out);
} catch (IOException e) {
e.printStackTrace();
printUsage();
diff --git a/tests/pvmfw/tools/pvmfw-tool-manifest.txt b/tests/pvmfw/tools/pvmfw-tool-manifest.txt
index dc71fd2..8b2535a 100644
--- a/tests/pvmfw/tools/pvmfw-tool-manifest.txt
+++ b/tests/pvmfw/tools/pvmfw-tool-manifest.txt
@@ -1,2 +1,2 @@
Manifest-Version: 1.0
-Main-Class: com.android.microdroid.PvmfwTool
+Main-Class: com.android.pvmfw.PvmfwTool
diff --git a/tests/vendor_images/Android.bp b/tests/vendor_images/Android.bp
index 09c657c..e5f863a 100644
--- a/tests/vendor_images/Android.bp
+++ b/tests/vendor_images/Android.bp
@@ -2,8 +2,16 @@
default_applicable_licenses: ["Android-Apache-2.0"],
}
+prebuilt_etc {
+ name: "vendor_sign_key",
+ src: ":avb_testkey_rsa4096",
+ installable: false,
+}
+
android_filesystem {
name: "test_microdroid_vendor_image",
type: "ext4",
file_contexts: ":microdroid_vendor_file_contexts.gen",
+ use_avb: true,
+ avb_private_key: ":vendor_sign_key",
}
diff --git a/virtualizationmanager/src/aidl.rs b/virtualizationmanager/src/aidl.rs
index 684aa64..5283ffe 100644
--- a/virtualizationmanager/src/aidl.rs
+++ b/virtualizationmanager/src/aidl.rs
@@ -474,7 +474,7 @@
.into_iter()
.map(|x| VfioDevice {
sysfs_path: PathBuf::from(&x.sysfsPath),
- dtbo_node: x.dtboNode,
+ dtbo_label: x.dtboLabel,
})
.collect::<Vec<_>>()
} else {
diff --git a/virtualizationmanager/src/crosvm.rs b/virtualizationmanager/src/crosvm.rs
index b053d99..bb6066f 100644
--- a/virtualizationmanager/src/crosvm.rs
+++ b/virtualizationmanager/src/crosvm.rs
@@ -128,7 +128,7 @@
#[derive(Clone, Debug)]
pub struct VfioDevice {
pub sysfs_path: PathBuf,
- pub dtbo_node: String,
+ pub dtbo_label: String,
}
/// The lifecycle state which the payload in the VM has reported itself to be in.
@@ -716,7 +716,7 @@
}
if let Some(p) = path.to_str() {
- Ok(format!("--vfio={p},iommu=viommu,dt-symbol={0}", device.dtbo_node))
+ Ok(format!("--vfio={p},iommu=viommu,dt-symbol={0}", device.dtbo_label))
} else {
bail!("invalid path {path:?}");
}
diff --git a/virtualizationservice/aidl/android/system/virtualizationcommon/ErrorCode.aidl b/virtualizationservice/aidl/android/system/virtualizationcommon/ErrorCode.aidl
index 04b9749..cf1e251 100644
--- a/virtualizationservice/aidl/android/system/virtualizationcommon/ErrorCode.aidl
+++ b/virtualizationservice/aidl/android/system/virtualizationcommon/ErrorCode.aidl
@@ -39,5 +39,5 @@
/**
* Error code indicating that the payload config is invalid.
*/
- PAYLOAD_CONFIG_INVALID = 3,
+ PAYLOAD_INVALID_CONFIG = 3,
}
diff --git a/virtualizationservice/aidl/android/system/virtualizationservice_internal/IVirtualizationServiceInternal.aidl b/virtualizationservice/aidl/android/system/virtualizationservice_internal/IVirtualizationServiceInternal.aidl
index f3a7617..172dc59 100644
--- a/virtualizationservice/aidl/android/system/virtualizationservice_internal/IVirtualizationServiceInternal.aidl
+++ b/virtualizationservice/aidl/android/system/virtualizationservice_internal/IVirtualizationServiceInternal.aidl
@@ -25,7 +25,7 @@
interface IVirtualizationServiceInternal {
parcelable BoundDevice {
String sysfsPath;
- String dtboNode;
+ String dtboLabel;
}
/**
* Removes the memlock rlimit of the calling process.
diff --git a/virtualizationservice/assignable_devices.xsd b/virtualizationservice/assignable_devices.xsd
index 8f43019..2fbc1c9 100644
--- a/virtualizationservice/assignable_devices.xsd
+++ b/virtualizationservice/assignable_devices.xsd
@@ -25,7 +25,7 @@
</xs:element>
<xs:complexType name="device">
<xs:attribute name="kind" type="xs:string"/>
- <xs:attribute name="dtbo_node" type="xs:string"/>
+ <xs:attribute name="dtbo_label" type="xs:string"/>
<xs:attribute name="sysfs_path" type="xs:string"/>
</xs:complexType>
</xs:schema>
diff --git a/virtualizationservice/schema/current.txt b/virtualizationservice/schema/current.txt
index ef99294..6e3fbb6 100644
--- a/virtualizationservice/schema/current.txt
+++ b/virtualizationservice/schema/current.txt
@@ -3,10 +3,10 @@
public class Device {
ctor public Device();
- method public String getDtbo_node();
+ method public String getDtbo_label();
method public String getKind();
method public String getSysfs_path();
- method public void setDtbo_node(String);
+ method public void setDtbo_label(String);
method public void setKind(String);
method public void setSysfs_path(String);
}
diff --git a/virtualizationservice/src/aidl.rs b/virtualizationservice/src/aidl.rs
index ed5c513..a19ecd2 100644
--- a/virtualizationservice/src/aidl.rs
+++ b/virtualizationservice/src/aidl.rs
@@ -209,7 +209,7 @@
.into_iter()
.filter_map(|x| {
if devices.contains(&x.sysfs_path) {
- Some(BoundDevice { sysfsPath: x.sysfs_path, dtboNode: x.dtbo_node })
+ Some(BoundDevice { sysfsPath: x.sysfs_path, dtboLabel: x.dtbo_label })
} else {
None
}
@@ -222,7 +222,7 @@
#[derive(Debug, Deserialize)]
struct Device {
kind: String,
- dtbo_node: String,
+ dtbo_label: String,
sysfs_path: String,
}
diff --git a/virtualizationservice/vfio_handler/src/aidl.rs b/virtualizationservice/vfio_handler/src/aidl.rs
index 618c165..2968ff9 100644
--- a/virtualizationservice/vfio_handler/src/aidl.rs
+++ b/virtualizationservice/vfio_handler/src/aidl.rs
@@ -239,7 +239,7 @@
if dt_table_header.magic.get() != DT_TABLE_MAGIC
|| dt_table_header.header_size.get() as usize != size_of::<DtTableHeader>()
{
- return Err(anyhow!("DtTableHeader is invalid")).or_service_specific_exception(-1)?;
+ return Err(anyhow!("DtTableHeader is invalid")).or_service_specific_exception(-1);
}
Ok(dt_table_header)
}
@@ -250,7 +250,7 @@
index: u32,
) -> binder::Result<DtTableEntry> {
if index >= header.dt_entry_count.get() {
- return Err(anyhow!("Invalid dtbo index {index}")).or_service_specific_exception(-1)?;
+ return Err(anyhow!("Invalid dtbo index {index}")).or_service_specific_exception(-1);
}
let Some(prev_dt_entry_total_size) = header.dt_entry_size.get().checked_mul(index) else {
return Err(anyhow!("Unexpected arithmetic result"))
diff --git a/vmbase/src/entry.rs b/vmbase/src/entry.rs
index 2ff66cc..b19efce 100644
--- a/vmbase/src/entry.rs
+++ b/vmbase/src/entry.rs
@@ -53,8 +53,14 @@
// We keep a null byte at the top of the stack guard to act as a string terminator.
let random_guard = &mut stack_guard[..(SIZE_OF_STACK_GUARD - 1)];
- rand::init().expect("Failed to initialize a source of entropy");
- rand::fill_with_entropy(random_guard).expect("Failed to get stack canary entropy");
+ if let Err(e) = rand::init() {
+ panic!("Failed to initialize a source of entropy: {e}");
+ }
+
+ if let Err(e) = rand::fill_with_entropy(random_guard) {
+ panic!("Failed to get stack canary entropy: {e}");
+ }
+
bionic::__get_tls().stack_guard = u64::from_ne_bytes(stack_guard);
// Note: If rust_entry ever returned (which it shouldn't by being -> !), the compiler-injected
diff --git a/vmbase/src/heap.rs b/vmbase/src/heap.rs
index c8b76ac..ec03d38 100644
--- a/vmbase/src/heap.rs
+++ b/vmbase/src/heap.rs
@@ -81,9 +81,7 @@
#[no_mangle]
unsafe extern "C" fn calloc(nmemb: usize, size: usize) -> *mut c_void {
- let Some(size) = nmemb.checked_mul(size) else {
- return ptr::null_mut()
- };
+ let Some(size) = nmemb.checked_mul(size) else { return ptr::null_mut() };
allocate(size, true).map_or(ptr::null_mut(), |p| p.cast::<c_void>().as_ptr())
}
diff --git a/vmclient/src/error_code.rs b/vmclient/src/error_code.rs
index 10e6d4d..59b25a0 100644
--- a/vmclient/src/error_code.rs
+++ b/vmclient/src/error_code.rs
@@ -28,7 +28,7 @@
PayloadChanged,
/// Error code indicating that the payload config is invalid.
- PayloadConfigInvalid,
+ PayloadInvalidConfig,
/// Payload sent a death reason which was not recognised by the client library.
Unrecognised(AidlErrorCode),
@@ -40,7 +40,7 @@
AidlErrorCode::UNKNOWN => Self::Unknown,
AidlErrorCode::PAYLOAD_VERIFICATION_FAILED => Self::PayloadVerificationFailed,
AidlErrorCode::PAYLOAD_CHANGED => Self::PayloadChanged,
- AidlErrorCode::PAYLOAD_CONFIG_INVALID => Self::PayloadConfigInvalid,
+ AidlErrorCode::PAYLOAD_INVALID_CONFIG => Self::PayloadInvalidConfig,
_ => Self::Unrecognised(error_code),
}
}