Merge "Add README at top of repository with links to others."
diff --git a/TEST_MAPPING b/TEST_MAPPING
index 13c68d7..69d4568 100644
--- a/TEST_MAPPING
+++ b/TEST_MAPPING
@@ -1,8 +1,13 @@
{
- "postsubmit": [
+ "presubmit": [
{
"name": "MicrodroidHostTestCases"
- },
+ }
+ ],
+ "postsubmit": [
+ // TODO(jiyong): promote this to presubmit. That currently doesn't work because
+ // this test is skipped for cf_x86_64_phone (not aosp_cf_x86_64_phone), but tradefed
+ // somehow thinks that the test wasn't executed at all and reports it as a failure.
{
"name": "VirtualizationTestCases"
}
diff --git a/apex/Android.bp b/apex/Android.bp
index 2194c67..bbd4aa5 100644
--- a/apex/Android.bp
+++ b/apex/Android.bp
@@ -7,6 +7,7 @@
// TODO(jiyong): make it updatable
updatable: false,
+ platform_apis: true,
manifest: "manifest.json",
@@ -48,10 +49,6 @@
"fd_server",
"vm",
"compos_key_cmd",
-
- // tools to create composite images
- "mk_cdisk",
- "mk_payload",
],
prebuilts: [
"com.android.virt.init.rc",
diff --git a/apkdmverity/TEST_MAPPING b/apkdmverity/TEST_MAPPING
index 997b3f9..1bbec76 100644
--- a/apkdmverity/TEST_MAPPING
+++ b/apkdmverity/TEST_MAPPING
@@ -1,5 +1,5 @@
{
- "postsubmit" : [
+ "presubmit" : [
{
"name" : "apkdmverity.test"
}
diff --git a/authfs/TEST_MAPPING b/authfs/TEST_MAPPING
index cabd5df..d0c0b09 100644
--- a/authfs/TEST_MAPPING
+++ b/authfs/TEST_MAPPING
@@ -3,10 +3,5 @@
{
"name": "authfs_device_test_src_lib"
}
- ],
- "postsubmit": [
- {
- "name": "MicrodroidHostTestCases"
- }
]
}
diff --git a/authfs/src/file/remote_file.rs b/authfs/src/file/remote_file.rs
index 0b6c007..037b8ec 100644
--- a/authfs/src/file/remote_file.rs
+++ b/authfs/src/file/remote_file.rs
@@ -17,13 +17,12 @@
use std::cmp::min;
use std::convert::TryFrom;
use std::io;
-use std::sync::{Arc, Mutex};
use super::{ChunkBuffer, RandomWrite, ReadByChunk, VirtFdService};
use crate::common::CHUNK_SIZE;
fn remote_read_chunk(
- service: &Arc<Mutex<VirtFdService>>,
+ service: &VirtFdService,
remote_fd: i32,
chunk_index: u64,
buf: &mut ChunkBuffer,
@@ -32,8 +31,6 @@
.map_err(|_| io::Error::from_raw_os_error(libc::EOVERFLOW))?;
let chunk = service
- .lock()
- .unwrap()
.readFile(remote_fd, offset, buf.len() as i32)
.map_err(|e| io::Error::new(io::ErrorKind::Other, e.get_description()))?;
let size = min(buf.len(), chunk.len());
@@ -43,12 +40,12 @@
pub struct RemoteFileReader {
// This needs to have Sync trait to be used in fuse::worker::start_message_loop.
- service: Arc<Mutex<VirtFdService>>,
+ service: VirtFdService,
file_fd: i32,
}
impl RemoteFileReader {
- pub fn new(service: Arc<Mutex<VirtFdService>>, file_fd: i32) -> Self {
+ pub fn new(service: VirtFdService, file_fd: i32) -> Self {
RemoteFileReader { service, file_fd }
}
}
@@ -61,13 +58,12 @@
pub struct RemoteMerkleTreeReader {
// This needs to be a Sync to be used in fuse::worker::start_message_loop.
- // TODO(victorhsieh): change to Strong<> once binder supports it.
- service: Arc<Mutex<VirtFdService>>,
+ service: VirtFdService,
file_fd: i32,
}
impl RemoteMerkleTreeReader {
- pub fn new(service: Arc<Mutex<VirtFdService>>, file_fd: i32) -> Self {
+ pub fn new(service: VirtFdService, file_fd: i32) -> Self {
RemoteMerkleTreeReader { service, file_fd }
}
}
@@ -79,8 +75,6 @@
let chunk = self
.service
- .lock()
- .unwrap()
.readFsverityMerkleTree(self.file_fd, offset, buf.len() as i32)
.map_err(|e| io::Error::new(io::ErrorKind::Other, e.get_description()))?;
let size = min(buf.len(), chunk.len());
@@ -91,12 +85,12 @@
pub struct RemoteFileEditor {
// This needs to have Sync trait to be used in fuse::worker::start_message_loop.
- service: Arc<Mutex<VirtFdService>>,
+ service: VirtFdService,
file_fd: i32,
}
impl RemoteFileEditor {
- pub fn new(service: Arc<Mutex<VirtFdService>>, file_fd: i32) -> Self {
+ pub fn new(service: VirtFdService, file_fd: i32) -> Self {
RemoteFileEditor { service, file_fd }
}
}
@@ -107,8 +101,6 @@
i64::try_from(offset).map_err(|_| io::Error::from_raw_os_error(libc::EOVERFLOW))?;
let size = self
.service
- .lock()
- .unwrap()
.writeFile(self.file_fd, &buf, offset)
.map_err(|e| io::Error::new(io::ErrorKind::Other, e.get_description()))?;
Ok(size as usize) // within range because size is supposed to <= buf.len(), which is a usize
@@ -118,8 +110,6 @@
let size =
i64::try_from(size).map_err(|_| io::Error::from_raw_os_error(libc::EOVERFLOW))?;
self.service
- .lock()
- .unwrap()
.resize(self.file_fd, size)
.map_err(|e| io::Error::new(io::ErrorKind::Other, e.get_description()))?;
Ok(())
diff --git a/authfs/src/main.rs b/authfs/src/main.rs
index 593fa74..9d36c3f 100644
--- a/authfs/src/main.rs
+++ b/authfs/src/main.rs
@@ -32,7 +32,6 @@
use std::fs::File;
use std::io::Read;
use std::path::{Path, PathBuf};
-use std::sync::{Arc, Mutex};
use structopt::StructOpt;
mod auth;
@@ -92,6 +91,14 @@
debug: bool,
}
+impl Args {
+ fn has_remote_files(&self) -> bool {
+ !self.remote_ro_file.is_empty()
+ || !self.remote_ro_file_unverified.is_empty()
+ || !self.remote_new_rw_file.is_empty()
+ }
+}
+
struct OptionRemoteRoFile {
ino: Inode,
@@ -216,15 +223,14 @@
) -> Result<FileConfig> {
let signature = service.readFsveritySignature(remote_id).context("Failed to read signature")?;
- let service = Arc::new(Mutex::new(service));
let authenticator = FakeAuthenticator::always_succeed();
Ok(FileConfig::RemoteVerifiedReadonlyFile {
reader: VerifiedFileReader::new(
&authenticator,
- RemoteFileReader::new(Arc::clone(&service), remote_id),
+ RemoteFileReader::new(service.clone(), remote_id),
file_size,
signature,
- RemoteMerkleTreeReader::new(Arc::clone(&service), remote_id),
+ RemoteMerkleTreeReader::new(service.clone(), remote_id),
)?,
file_size,
})
@@ -235,7 +241,7 @@
remote_id: i32,
file_size: u64,
) -> Result<FileConfig> {
- let reader = RemoteFileReader::new(Arc::new(Mutex::new(service)), remote_id);
+ let reader = RemoteFileReader::new(service, remote_id);
Ok(FileConfig::RemoteUnverifiedReadonlyFile { reader, file_size })
}
@@ -266,34 +272,44 @@
service: file::VirtFdService,
remote_id: i32,
) -> Result<FileConfig> {
- let remote_file = RemoteFileEditor::new(Arc::new(Mutex::new(service)), remote_id);
+ let remote_file = RemoteFileEditor::new(service, remote_id);
Ok(FileConfig::RemoteVerifiedNewFile { editor: VerifiedFileEditor::new(remote_file) })
}
fn prepare_file_pool(args: &Args) -> Result<BTreeMap<Inode, FileConfig>> {
let mut file_pool = BTreeMap::new();
- let service = file::get_binder_service(args.cid)?;
+ if args.has_remote_files() {
+ let service = file::get_binder_service(args.cid)?;
- for config in &args.remote_ro_file {
- file_pool.insert(
- config.ino,
- new_config_remote_verified_file(service.clone(), config.remote_id, config.file_size)?,
- );
- }
+ for config in &args.remote_ro_file {
+ file_pool.insert(
+ config.ino,
+ new_config_remote_verified_file(
+ service.clone(),
+ config.remote_id,
+ config.file_size,
+ )?,
+ );
+ }
- for config in &args.remote_ro_file_unverified {
- file_pool.insert(
- config.ino,
- new_config_remote_unverified_file(service.clone(), config.remote_id, config.file_size)?,
- );
- }
+ for config in &args.remote_ro_file_unverified {
+ file_pool.insert(
+ config.ino,
+ new_config_remote_unverified_file(
+ service.clone(),
+ config.remote_id,
+ config.file_size,
+ )?,
+ );
+ }
- for config in &args.remote_new_rw_file {
- file_pool.insert(
- config.ino,
- new_config_remote_new_verified_file(service.clone(), config.remote_id)?,
- );
+ for config in &args.remote_new_rw_file {
+ file_pool.insert(
+ config.ino,
+ new_config_remote_new_verified_file(service.clone(), config.remote_id)?,
+ );
+ }
}
for config in &args.local_ro_file {
diff --git a/compos/Android.bp b/compos/Android.bp
index 0cb6894..1eb6716 100644
--- a/compos/Android.bp
+++ b/compos/Android.bp
@@ -83,10 +83,3 @@
prefer_rlib: true,
apex_available: ["com.android.compos"],
}
-
-// TODO(b/190503456) Remove this when vm/virtualizationservice generates payload.img from vm_config
-prebuilt_etc {
- name: "compos_payload_config",
- src: "payload_config.json",
- filename: "payload_config.json",
-}
diff --git a/compos/apex/Android.bp b/compos/apex/Android.bp
index 95463d0..1fffa2e 100644
--- a/compos/apex/Android.bp
+++ b/compos/apex/Android.bp
@@ -34,6 +34,7 @@
// TODO(victorhsieh): make it updatable
updatable: false,
+ platform_apis: true,
binaries: [
"compos_key_service",
@@ -47,6 +48,6 @@
],
prebuilts: [
- "compos_payload_config",
+ "CompOSPayloadApp.apk.idsig",
],
}
diff --git a/compos/apk/Android.bp b/compos/apk/Android.bp
index c6192b9..c5d0c31 100644
--- a/compos/apk/Android.bp
+++ b/compos/apk/Android.bp
@@ -3,7 +3,42 @@
}
android_app {
- name: "CompOSPayloadApp",
+ name: "CompOSPayloadApp.unsigned",
sdk_version: "current",
apex_available: ["com.android.compos"],
}
+
+// TODO(b/190409306) this is temporal until we have a solid way to pass merkle tree
+java_genrule {
+ name: "CompOSPayloadApp.signing",
+ out: [
+ "CompOSPayloadApp.apk",
+ "CompOSPayloadApp.apk.idsig",
+ ],
+ srcs: [":CompOSPayloadApp.unsigned"],
+ tools: ["apksigner"],
+ tool_files: ["test.keystore"],
+ cmd: "$(location apksigner) sign " +
+ "--ks $(location test.keystore) " +
+ "--ks-pass=pass:testkey --key-pass=pass:testkey " +
+ "--in $(in) " +
+ "--out $(genDir)/CompOSPayloadApp.apk",
+ // $(genDir)/MicrodroidTestApp.apk.idsig is generated implicitly
+}
+
+android_app_import {
+ name: "CompOSPayloadApp",
+ // Make sure the build system doesn't try to resign the APK
+ dex_preopt: {
+ enabled: false,
+ },
+ apk: ":CompOSPayloadApp.signing{CompOSPayloadApp.apk}",
+ presigned: true,
+ filename: "CompOSPayloadApp.apk",
+ apex_available: ["com.android.compos"],
+}
+
+prebuilt_etc {
+ name: "CompOSPayloadApp.apk.idsig",
+ src: ":CompOSPayloadApp.signing{CompOSPayloadApp.apk.idsig}",
+}
diff --git a/compos/apk/assets/vm_config.json b/compos/apk/assets/vm_config.json
index a8dca71..f9f1f90 100644
--- a/compos/apk/assets/vm_config.json
+++ b/compos/apk/assets/vm_config.json
@@ -13,22 +13,10 @@
},
"apexes": [
{
- "name": "com.android.adbd"
- },
- {
"name": "com.android.art"
},
{
"name": "com.android.compos"
- },
- {
- "name": "com.android.i18n"
- },
- {
- "name": "com.android.os.statsd"
- },
- {
- "name": "com.android.sdkext"
}
]
}
\ No newline at end of file
diff --git a/compos/apk/test.keystore b/compos/apk/test.keystore
new file mode 100644
index 0000000..2f024d8
--- /dev/null
+++ b/compos/apk/test.keystore
Binary files differ
diff --git a/compos/payload_config.json b/compos/payload_config.json
deleted file mode 100644
index 588ccca..0000000
--- a/compos/payload_config.json
+++ /dev/null
@@ -1,15 +0,0 @@
-{
- "apk": {
- "path": "/apex/com.android.compos/app/CompOSPayloadApp/CompOSPayloadApp.apk",
- "name": "com.android.compos.payload"
- },
- "system_apexes": [
- "com.android.adbd",
- "com.android.art",
- "com.android.compos",
- "com.android.i18n",
- "com.android.os.statsd",
- "com.android.sdkext"
- ],
- "payload_config_path": "/mnt/apk/assets/vm_config.json"
-}
\ No newline at end of file
diff --git a/compos/src/compos_key_service.rs b/compos/src/compos_key_service.rs
index 97fd855..0cbe8de 100644
--- a/compos/src/compos_key_service.rs
+++ b/compos/src/compos_key_service.rs
@@ -39,7 +39,6 @@
use ring::signature;
use scopeguard::ScopeGuard;
use std::ffi::CString;
-use std::sync::Mutex;
const LOG_TAG: &str = "CompOsKeyService";
const OUR_SERVICE_NAME: &str = "android.system.composkeyservice";
@@ -68,10 +67,6 @@
struct CompOsKeyService {
random: SystemRandom,
- state: Mutex<State>,
-}
-
-struct State {
security_level: Strong<dyn IKeystoreSecurityLevel>,
}
@@ -102,20 +97,12 @@
fn new(keystore_service: &Strong<dyn IKeystoreService>) -> Self {
Self {
random: SystemRandom::new(),
- state: Mutex::new(State {
- security_level: keystore_service
- .getSecurityLevel(SecurityLevel::TRUSTED_ENVIRONMENT)
- .unwrap(),
- }),
+ security_level: keystore_service
+ .getSecurityLevel(SecurityLevel::TRUSTED_ENVIRONMENT)
+ .unwrap(),
}
}
- fn security_level(&self) -> Strong<dyn IKeystoreSecurityLevel> {
- // We need the Mutex because Strong<_> isn't sync. But we don't need to keep it locked
- // to make the call, once we've cloned the pointer.
- self.state.lock().unwrap().security_level.clone()
- }
-
fn do_generate(&self) -> Result<CompOsKeyData> {
let key_parameters =
[PURPOSE_SIGN, ALGORITHM, PADDING, DIGEST, KEY_SIZE, EXPONENT, NO_AUTH_REQUIRED];
@@ -124,7 +111,7 @@
let entropy = [];
let key_metadata = self
- .security_level()
+ .security_level
.generateKey(&KEY_DESCRIPTOR, attestation_key, &key_parameters, flags, &entropy)
.context("Generating key failed")?;
@@ -154,7 +141,7 @@
let forced = false;
let response = self
- .security_level()
+ .security_level
.createOperation(&key_descriptor, &operation_parameters, forced)
.context("Creating key failed")?;
let operation = scopeguard::guard(
diff --git a/compositediskconfig/src/lib.rs b/compositediskconfig/src/lib.rs
deleted file mode 100644
index 3546dd3..0000000
--- a/compositediskconfig/src/lib.rs
+++ /dev/null
@@ -1,45 +0,0 @@
-// Copyright 2021, 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.
-
-//! JSON configuration for composite disks, as used for running `mk_cdisk` and by the `vm` tool.
-
-use serde::{Deserialize, Serialize};
-use std::io::Write;
-use std::path::PathBuf;
-
-/// Configuration for running `mk_cdisk`.
-#[derive(Clone, Debug, Default, Deserialize, Eq, PartialEq, Serialize)]
-pub struct Config {
- /// The set of partitions to be assembled into a composite image.
- pub partitions: Vec<Partition>,
-}
-
-/// A partition to be assembled into a composite image.
-#[derive(Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
-pub struct Partition {
- /// A label for the partition.
- pub label: String,
- /// The filename of the partition image.
- pub path: PathBuf,
- /// Whether the partition should be writable.
- #[serde(default)]
- pub writable: bool,
-}
-
-impl Config {
- /// Write the configuration as JSON, in the format used by `mk_cdisk`.
- pub fn write_json(&self, writer: impl Write) -> serde_json::Result<()> {
- serde_json::to_writer(writer, self)
- }
-}
diff --git a/microdroid/README.md b/microdroid/README.md
index 802e847..f48a35c 100644
--- a/microdroid/README.md
+++ b/microdroid/README.md
@@ -74,20 +74,13 @@
"type": "microdroid_launcher",
"command": "MyMicrodroidApp.so"
},
- "apexes": [
- {"name": "com.android.adbd"},
- {"name": "com.android.i18n"},
- {"name": "com.android.os.statsd"},
- {"name": "com.android.sdkext"}
- ]
+ "apexes" : [ ... ]
}
```
The value of `task.command` should match with the name of the shared library
defined above. The `apexes` array is the APEXes that will be imported to
-microdroid. The above four APEXes are essential ones and therefore shouldn't be
-omitted. In the future, you wouldn't need to add the default ones manually. If
-more APEXes are required for you app, add their names too.
+microdroid.
Embed the shared library and the VM configuration file in an APK:
@@ -130,77 +123,39 @@
adb install out/dist/MyApp.apk
```
-### Creating `payload.img` manually (temporary step)
-
-This is a step that needs to be done manually for now. Eventually, this will be
-automatically done by a service named `virtualizationservice` which is part of
-the `com.android.virt` APEX.
-
-Create `payload.json` file:
-
-```json
-{
- "payload_config_path": "/mnt/apk/assets/VM_CONFIG_NAME,
- "system_apexes": [
- "com.android.adbd",
- "com.android.i18n",
- "com.android.os.statsd",
- "com.android.sdkext"
- ],
- "apk": {
- "name": "PACKAGE_NAME_OF_YOUR_APP",
- "path": "PATH_TO_YOUR_APP",
- "idsig_path": "PATH_TO_APK_IDSIG"
- }
-}
-```
-
-`ALL_CAP`s in the above are placeholders. They need to be replaced with correct
+`ALL_CAP`s below are placeholders. They need to be replaced with correct
values:
-
* `VM_CONFIG_FILE`: the name of the VM config file that you embedded in the APK.
-* `PACKAGE_NAME_OF_YOUR_APP`: package name of your app(e.g. `com.acme.app`).
+ (e.g. `vm_config.json`)
+* `PACKAGE_NAME_OF_YOUR_APP`: package name of your app (e.g. `com.acme.app`).
* `PATH_TO_YOUR_APP`: path to the installed APK on the device. Can be obtained
via the following command.
+ ```sh
+ adb shell pm path PACKAGE_NAME_OF_YOUR_APP
+ ```
+ It shall report a cryptic path similar to `/data/app/~~OgZq==/com.acme.app-HudMahQ==/base.apk`.
-```sh
-adb shell pm path PACKAGE_NAME_OF_YOUR_APP
-```
-
-It shall report a cryptic path similar to
-`/data/app/~~OgZq==/com.acme.app-HudMahQ==/base.apk`.
-
-* `PATH_TO_APK_IDSIG`: path to the pushed APK idsig on the device. See below
- `adb push` command: it will be `/data/local/tmp/virt/MyApp.apk.idsig` in this
- example.
-
-Once the file is done, execute the following command to push it to the device
-and run `mk_payload` to create `payload.img`:
+Push idsig of the APK to the device.
```sh
TEST_ROOT=/data/local/tmp/virt
-adb push out/dist/MyApp.apk.idsig $TEST_ROOT/MyApp.apk.idsig
-adb push path_to_payload.json $TEST_ROOT/payload.json
-adb shell /apex/com.android.virt/bin/my_payload $TEST_ROOT/payload.json $TEST_ROOT/payload.img
-adb shell chmod go+r $TEST_ROOT/payload*
+adb push out/dist/MyApp.apk.idsig $TEST_ROOT
```
-### Running the VM
-
Execute the following commands to launch a VM. The VM will boot to microdroid
and then automatically execute your app (the shared library
`MyMicrodroidApp.so`).
```sh
TEST_ROOT=/data/local/tmp/virt
-adb push packages/modules/Virtualization/microdroid/microdroid.json $TEST_ROOT/microdroid.json
adb root
adb shell setenforce 0
adb shell start virtualizationservice
-adb shell /apex/com.android.virt/bin/vm run $TEST_ROOT/microdroid.json
+adb shell /apex/com.android.virt/bin/vm run-app --daemonize --log $TEST_ROOT/log.txt PATH_TO_YOUR_APP $TEST_ROOT/MyApp.apk.idsig assets/VM_CONFIG_FILE
```
-The last command lets you know the CID assigned to the VM.
+The last command lets you know the CID assigned to the VM. The console output
+from the VM is stored to `$TEST_ROOT/log.txt` file for debugging purpose.
Note: the disabling of SELinux is a temporary step. The restriction will
eventually be removed.
@@ -211,7 +166,8 @@
adb shell /apex/com.android.virt/bin/vm stop CID
```
-, where `CID` is the reported CID value.
+, where `CID` is the reported CID value. This works only when the `vm` was
+invoked with the `--daemonize` flag.
## ADB
diff --git a/microdroid/microdroid.json b/microdroid/microdroid.json
index 7dc4b6a..b1ef86a 100644
--- a/microdroid/microdroid.json
+++ b/microdroid/microdroid.json
@@ -5,23 +5,23 @@
"partitions": [
{
"label": "boot_a",
- "path": "/apex/com.android.virt/etc/fs/microdroid_boot-5.10.img"
+ "paths": ["/apex/com.android.virt/etc/fs/microdroid_boot-5.10.img"]
},
{
"label": "vendor_boot_a",
- "path": "/apex/com.android.virt/etc/fs/microdroid_vendor_boot-5.10.img"
+ "paths": ["/apex/com.android.virt/etc/fs/microdroid_vendor_boot-5.10.img"]
},
{
"label": "vbmeta_a",
- "path": "/apex/com.android.virt/etc/fs/microdroid_vbmeta.img"
+ "paths": ["/apex/com.android.virt/etc/fs/microdroid_vbmeta.img"]
},
{
"label": "vbmeta_system_a",
- "path": "/apex/com.android.virt/etc/fs/microdroid_vbmeta_system.img"
+ "paths": ["/apex/com.android.virt/etc/fs/microdroid_vbmeta_system.img"]
},
{
"label": "super",
- "path": "/apex/com.android.virt/etc/fs/microdroid_super.img"
+ "paths": ["/apex/com.android.virt/etc/fs/microdroid_super.img"]
}
],
"writable": false
@@ -30,14 +30,10 @@
"partitions": [
{
"label": "uboot_env",
- "path": "/apex/com.android.virt/etc/uboot_env.img"
+ "paths": ["/apex/com.android.virt/etc/uboot_env.img"]
}
],
"writable": false
- },
- {
- "image": "/data/local/tmp/virt/payload.img",
- "writable": false
}
]
}
diff --git a/microdroid/payload/Android.bp b/microdroid/payload/Android.bp
index 5ea6c10..c7bc415 100644
--- a/microdroid/payload/Android.bp
+++ b/microdroid/payload/Android.bp
@@ -44,6 +44,9 @@
protos: ["metadata.proto"],
source_stem: "microdroid_metadata",
host_supported: true,
+ apex_available: [
+ "com.android.virt",
+ ],
}
cc_binary {
diff --git a/microdroid/payload/config/Android.bp b/microdroid/payload/config/Android.bp
index da58bdf..827f6e3 100644
--- a/microdroid/payload/config/Android.bp
+++ b/microdroid/payload/config/Android.bp
@@ -13,4 +13,7 @@
"libserde_json",
"libserde",
],
+ apex_available: [
+ "com.android.virt",
+ ],
}
diff --git a/microdroid/payload/metadata/Android.bp b/microdroid/payload/metadata/Android.bp
new file mode 100644
index 0000000..d3ec625
--- /dev/null
+++ b/microdroid/payload/metadata/Android.bp
@@ -0,0 +1,19 @@
+package {
+ default_applicable_licenses: ["Android-Apache-2.0"],
+}
+
+rust_library {
+ name: "libmicrodroid_metadata",
+ host_supported: true,
+ crate_name: "microdroid_metadata",
+ srcs: ["src/lib.rs"],
+ prefer_rlib: true,
+ edition: "2018",
+ rustlibs: [
+ "libmicrodroid_metadata_proto_rust",
+ "libprotobuf",
+ ],
+ apex_available: [
+ "com.android.virt",
+ ],
+}
diff --git a/microdroid/payload/metadata/src/lib.rs b/microdroid/payload/metadata/src/lib.rs
new file mode 100644
index 0000000..9c97411
--- /dev/null
+++ b/microdroid/payload/metadata/src/lib.rs
@@ -0,0 +1,42 @@
+// Copyright 2021, 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.
+
+//! Read/write metadata blob for VM payload image. The blob is supposed to be used as a metadata
+//! partition in the VM payload image.
+//! The layout of metadata blob is like:
+//! 4 bytes : size(N) in big endian
+//! N bytes : protobuf message for Metadata
+
+use protobuf::Message;
+use std::io;
+use std::io::Read;
+use std::io::Write;
+
+pub use microdroid_metadata::metadata::{ApexPayload, ApkPayload, Metadata};
+
+/// Reads a metadata from a reader
+pub fn read_metadata<T: Read>(mut r: T) -> io::Result<Metadata> {
+ let mut buf = [0u8; 4];
+ r.read_exact(&mut buf)?;
+ let size = i32::from_be_bytes(buf);
+ Ok(Metadata::parse_from_reader(&mut r.take(size as u64))?)
+}
+
+/// Writes a metadata to a writer
+pub fn write_metadata<T: Write>(metadata: &Metadata, mut w: T) -> io::Result<()> {
+ let mut buf = Vec::new();
+ metadata.write_to_writer(&mut buf)?;
+ w.write_all(&(buf.len() as i32).to_be_bytes())?;
+ w.write_all(&buf)
+}
diff --git a/microdroid/sepolicy/system/private/hwservice_contexts b/microdroid/sepolicy/system/private/hwservice_contexts
index 5b6e79d..f4583e2 100644
--- a/microdroid/sepolicy/system/private/hwservice_contexts
+++ b/microdroid/sepolicy/system/private/hwservice_contexts
@@ -1,85 +1,6 @@
-android.frameworks.automotive.display::IAutomotiveDisplayProxyService u:object_r:fwk_automotive_display_hwservice:s0
-android.frameworks.bufferhub::IBufferHub u:object_r:fwk_bufferhub_hwservice:s0
-android.frameworks.cameraservice.service::ICameraService u:object_r:fwk_camera_hwservice:s0
-android.frameworks.displayservice::IDisplayService u:object_r:fwk_display_hwservice:s0
-android.frameworks.schedulerservice::ISchedulingPolicyService u:object_r:fwk_scheduler_hwservice:s0
-android.frameworks.sensorservice::ISensorManager u:object_r:fwk_sensor_hwservice:s0
-android.frameworks.stats::IStats u:object_r:fwk_stats_hwservice:s0
-android.hardware.atrace::IAtraceDevice u:object_r:hal_atrace_hwservice:s0
-android.hardware.audio.effect::IEffectsFactory u:object_r:hal_audio_hwservice:s0
-android.hardware.audio::IDevicesFactory u:object_r:hal_audio_hwservice:s0
-android.hardware.authsecret::IAuthSecret u:object_r:hal_authsecret_hwservice:s0
-android.hardware.automotive.audiocontrol::IAudioControl u:object_r:hal_audiocontrol_hwservice:s0
-android.hardware.automotive.can::ICanController u:object_r:hal_can_controller_hwservice:s0
-android.hardware.automotive.can::ICanBus u:object_r:hal_can_bus_hwservice:s0
-android.hardware.automotive.evs::IEvsEnumerator u:object_r:hal_evs_hwservice:s0
-android.hardware.automotive.vehicle::IVehicle u:object_r:hal_vehicle_hwservice:s0
-android.hardware.biometrics.face::IBiometricsFace u:object_r:hal_face_hwservice:s0
-android.hardware.biometrics.fingerprint::IBiometricsFingerprint u:object_r:hal_fingerprint_hwservice:s0
-android.hardware.bluetooth::IBluetoothHci u:object_r:hal_bluetooth_hwservice:s0
-android.hardware.bluetooth.a2dp::IBluetoothAudioOffload u:object_r:hal_audio_hwservice:s0
-android.hardware.bluetooth.audio::IBluetoothAudioProvidersFactory u:object_r:hal_audio_hwservice:s0
-android.hardware.boot::IBootControl u:object_r:hal_bootctl_hwservice:s0
-android.hardware.broadcastradio::IBroadcastRadio u:object_r:hal_broadcastradio_hwservice:s0
-android.hardware.broadcastradio::IBroadcastRadioFactory u:object_r:hal_broadcastradio_hwservice:s0
-android.hardware.camera.provider::ICameraProvider u:object_r:hal_camera_hwservice:s0
-android.hardware.configstore::ISurfaceFlingerConfigs u:object_r:hal_configstore_ISurfaceFlingerConfigs:s0
-android.hardware.confirmationui::IConfirmationUI u:object_r:hal_confirmationui_hwservice:s0
-android.hardware.contexthub::IContexthub u:object_r:hal_contexthub_hwservice:s0
-android.hardware.cas::IMediaCasService u:object_r:hal_cas_hwservice:s0
-android.hardware.drm::ICryptoFactory u:object_r:hal_drm_hwservice:s0
-android.hardware.drm::IDrmFactory u:object_r:hal_drm_hwservice:s0
-android.hardware.dumpstate::IDumpstateDevice u:object_r:hal_dumpstate_hwservice:s0
-android.hardware.gatekeeper::IGatekeeper u:object_r:hal_gatekeeper_hwservice:s0
-android.hardware.gnss::IGnss u:object_r:hal_gnss_hwservice:s0
-android.hardware.graphics.allocator::IAllocator u:object_r:hal_graphics_allocator_hwservice:s0
-android.hardware.graphics.composer::IComposer u:object_r:hal_graphics_composer_hwservice:s0
-android.hardware.graphics.mapper::IMapper u:object_r:hal_graphics_mapper_hwservice:s0
-android.hardware.health::IHealth u:object_r:hal_health_hwservice:s0
-android.hardware.health.storage::IStorage u:object_r:hal_health_storage_hwservice:s0
-android.hardware.input.classifier::IInputClassifier u:object_r:hal_input_classifier_hwservice:s0
-android.hardware.ir::IConsumerIr u:object_r:hal_ir_hwservice:s0
-android.hardware.keymaster::IKeymasterDevice u:object_r:hal_keymaster_hwservice:s0
-android.hardware.tests.lazy::ILazy u:object_r:hal_lazy_test_hwservice:s0
-android.hardware.light::ILight u:object_r:hal_light_hwservice:s0
-android.hardware.lowpan::ILowpanDevice u:object_r:hal_lowpan_hwservice:s0
-android.hardware.media.omx::IOmx u:object_r:hal_omx_hwservice:s0
-android.hardware.media.omx::IOmxStore u:object_r:hal_omx_hwservice:s0
-android.hardware.media.c2::IComponentStore u:object_r:hal_codec2_hwservice:s0
-android.hardware.memtrack::IMemtrack u:object_r:hal_memtrack_hwservice:s0
-android.hardware.neuralnetworks::IDevice u:object_r:hal_neuralnetworks_hwservice:s0
-android.hardware.nfc::INfc u:object_r:hal_nfc_hwservice:s0
-android.hardware.oemlock::IOemLock u:object_r:hal_oemlock_hwservice:s0
-android.hardware.power::IPower u:object_r:hal_power_hwservice:s0
-android.hardware.power.stats::IPowerStats u:object_r:hal_power_stats_hwservice:s0
-android.hardware.radio.config::IRadioConfig u:object_r:hal_telephony_hwservice:s0
-android.hardware.radio.deprecated::IOemHook u:object_r:hal_telephony_hwservice:s0
-android.hardware.radio::IRadio u:object_r:hal_telephony_hwservice:s0
-android.hardware.radio::ISap u:object_r:hal_telephony_hwservice:s0
-android.hardware.renderscript::IDevice u:object_r:hal_renderscript_hwservice:s0
-android.hardware.secure_element::ISecureElement u:object_r:hal_secure_element_hwservice:s0
-android.hardware.sensors::ISensors u:object_r:hal_sensors_hwservice:s0
-android.hardware.soundtrigger::ISoundTriggerHw u:object_r:hal_audio_hwservice:s0
-android.hardware.tetheroffload.config::IOffloadConfig u:object_r:hal_tetheroffload_hwservice:s0
-android.hardware.tetheroffload.control::IOffloadControl u:object_r:hal_tetheroffload_hwservice:s0
-android.hardware.thermal::IThermal u:object_r:hal_thermal_hwservice:s0
-android.hardware.tv.cec::IHdmiCec u:object_r:hal_tv_cec_hwservice:s0
-android.hardware.tv.input::ITvInput u:object_r:hal_tv_input_hwservice:s0
-android.hardware.tv.tuner::ITuner u:object_r:hal_tv_tuner_hwservice:s0
-android.hardware.usb::IUsb u:object_r:hal_usb_hwservice:s0
-android.hardware.usb.gadget::IUsbGadget u:object_r:hal_usb_gadget_hwservice:s0
-android.hardware.vibrator::IVibrator u:object_r:hal_vibrator_hwservice:s0
-android.hardware.vr::IVr u:object_r:hal_vr_hwservice:s0
-android.hardware.weaver::IWeaver u:object_r:hal_weaver_hwservice:s0
-android.hardware.wifi::IWifi u:object_r:hal_wifi_hwservice:s0
-android.hardware.wifi.hostapd::IHostapd u:object_r:hal_wifi_hostapd_hwservice:s0
-android.hardware.wifi.supplicant::ISupplicant u:object_r:hal_wifi_supplicant_hwservice:s0
android.hidl.allocator::IAllocator u:object_r:hidl_allocator_hwservice:s0
android.hidl.base::IBase u:object_r:hidl_base_hwservice:s0
android.hidl.manager::IServiceManager u:object_r:hidl_manager_hwservice:s0
android.hidl.memory::IMapper u:object_r:hidl_memory_hwservice:s0
android.hidl.token::ITokenManager u:object_r:hidl_token_hwservice:s0
-android.system.net.netd::INetd u:object_r:system_net_netd_hwservice:s0
-android.system.suspend::ISystemSuspend u:object_r:system_suspend_hwservice:s0
-android.system.wifi.keystore::IKeystore u:object_r:system_wifi_keystore_hwservice:s0
* u:object_r:default_android_hwservice:s0
diff --git a/microdroid/sepolicy/system/private/keystore2_key_contexts b/microdroid/sepolicy/system/private/keystore2_key_contexts
index 4e7c260..02cdd5e 100644
--- a/microdroid/sepolicy/system/private/keystore2_key_contexts
+++ b/microdroid/sepolicy/system/private/keystore2_key_contexts
@@ -4,27 +4,6 @@
# <namespace> <label>
#
# <namespace> must be an integer in the interval [0 ... 2^31)
-# su_key is a keystore_key namespace for the su domain intended for native tests.
-0 u:object_r:su_key:s0
-
-# shell_key is a keystore_key namespace for the shell domain intended for native tests.
-1 u:object_r:shell_key:s0
-
-# vold_key is a keystore2_key namespace for vold. It allows using raw Keymint blobs.
-100 u:object_r:vold_key:s0
-
-# odsign_key is a keystore2_key namespace for the on-device signing daemon.
-101 u:object_r:odsign_key:s0
-
-# wifi_key is a keystore2_key namespace for the WI-FI subsystem. It replaces the WIFI_UID
-# namespace in keystore.
-102 u:object_r:wifi_key:s0
-
-# locksettings_key is a keystore2_key namespace for the LockSettingsService.
-103 u:object_r:locksettings_key:s0
-
-# resume_on_reboot_key is a keystore2_key namespace intended for resume on reboot.
-120 u:object_r:resume_on_reboot_key:s0
# vm_payload_key is a keystore2_key namespace intended for microdroid VM payloads.
# TODO(b/191843770): sort out a longer term policy
diff --git a/microdroid/sepolicy/system/private/microdroid_manager.te b/microdroid/sepolicy/system/private/microdroid_manager.te
index fba3e71..81a6839 100644
--- a/microdroid/sepolicy/system/private/microdroid_manager.te
+++ b/microdroid/sepolicy/system/private/microdroid_manager.te
@@ -22,10 +22,7 @@
allow microdroid_manager {shell_exec toolbox_exec}:file rx_file_perms;
# Let microdroid_manager kernel-log.
-# TODO(b/189805435) when ready this should be kmsg_device rather than kmsg_debug_device
-userdebug_or_eng(`
- allow microdroid_manager kmsg_debug_device:chr_file write;
-')
+allow microdroid_manager kmsg_device:chr_file w_file_perms;
# Let microdroid_manager read a config file from /mnt/apk (fusefs)
# TODO(b/188400186) remove the below two rules
diff --git a/microdroid/sepolicy/system/private/port_contexts b/microdroid/sepolicy/system/private/port_contexts
index b473c0c..2f40b38 100644
--- a/microdroid/sepolicy/system/private/port_contexts
+++ b/microdroid/sepolicy/system/private/port_contexts
@@ -1,3 +1 @@
-# portcon statements go here, e.g.
-# portcon tcp 80 u:object_r:http_port:s0
-
+# This file can't be empty, but is unused on microdroid
diff --git a/microdroid/sepolicy/system/private/property_contexts b/microdroid/sepolicy/system/private/property_contexts
index 1483f6f..c2a3a62 100644
--- a/microdroid/sepolicy/system/private/property_contexts
+++ b/microdroid/sepolicy/system/private/property_contexts
@@ -25,9 +25,6 @@
ctl.console u:object_r:ctl_console_prop:s0
ctl. u:object_r:ctl_default_prop:s0
-dev.mnt.blk.root u:object_r:system_prop:s0 exact string
-dev.mnt.blk.vendor u:object_r:system_prop:s0 exact string
-
sys.init.perf_lsm_hooks u:object_r:init_perf_lsm_hooks_prop:s0 exact bool
service.adb.root u:object_r:shell_prop:s0 exact bool
diff --git a/microdroid/sepolicy/system/private/seapp_contexts b/microdroid/sepolicy/system/private/seapp_contexts
index b8e42ea..2f40b38 100644
--- a/microdroid/sepolicy/system/private/seapp_contexts
+++ b/microdroid/sepolicy/system/private/seapp_contexts
@@ -1,178 +1 @@
-# The entries in this file define how security contexts for apps are determined.
-# Each entry lists input selectors, used to match the app, and outputs which are
-# used to determine the security contexts for matching apps.
-#
-# Input selectors:
-# isSystemServer (boolean)
-# isEphemeralApp (boolean)
-# isOwner (boolean)
-# user (string)
-# seinfo (string)
-# name (string)
-# path (string)
-# isPrivApp (boolean)
-# minTargetSdkVersion (unsigned integer)
-# fromRunAs (boolean)
-#
-# All specified input selectors in an entry must match (i.e. logical AND).
-# An unspecified string or boolean selector with no default will match any
-# value.
-# A user, name, or path string selector that ends in * will perform a prefix
-# match.
-# String matching is case-insensitive.
-# See external/selinux/libselinux/src/android/android_platform.c,
-# seapp_context_lookup().
-#
-# isSystemServer=true only matches the system server.
-# An unspecified isSystemServer defaults to false.
-# isEphemeralApp=true will match apps marked by PackageManager as Ephemeral
-# isOwner=true will only match for the owner/primary user.
-# user=_app will match any regular app process.
-# user=_isolated will match any isolated service process.
-# Other values of user are matched against the name associated with the process
-# UID.
-# seinfo= matches aginst the seinfo tag for the app, determined from
-# mac_permissions.xml files.
-# The ':' character is reserved and may not be used in seinfo.
-# name= matches against the package name of the app.
-# path= matches against the directory path when labeling app directories.
-# isPrivApp=true will only match for applications preinstalled in
-# /system/priv-app.
-# minTargetSdkVersion will match applications with a targetSdkVersion
-# greater than or equal to the specified value. If unspecified,
-# it has a default value of 0.
-# fromRunAs=true means the process being labeled is started by run-as. Default
-# is false.
-#
-# Precedence: entries are compared using the following rules, in the order shown
-# (see external/selinux/libselinux/src/android/android_platform.c,
-# seapp_context_cmp()).
-# (1) isSystemServer=true before isSystemServer=false.
-# (2) Specified isEphemeralApp= before unspecified isEphemeralApp=
-# boolean.
-# (3) Specified isOwner= before unspecified isOwner= boolean.
-# (4) Specified user= string before unspecified user= string;
-# more specific user= string before less specific user= string.
-# (5) Specified seinfo= string before unspecified seinfo= string.
-# (6) Specified name= string before unspecified name= string;
-# more specific name= string before less specific name= string.
-# (7) Specified path= string before unspecified path= string.
-# more specific name= string before less specific name= string.
-# (8) Specified isPrivApp= before unspecified isPrivApp= boolean.
-# (9) Higher value of minTargetSdkVersion= before lower value of
-# minTargetSdkVersion= integer. Note that minTargetSdkVersion=
-# defaults to 0 if unspecified.
-# (10) fromRunAs=true before fromRunAs=false.
-# (A fixed selector is more specific than a prefix, i.e. ending in *, and a
-# longer prefix is more specific than a shorter prefix.)
-# Apps are checked against entries in precedence order until the first match,
-# regardless of their order in this file.
-#
-# Duplicate entries, i.e. with identical input selectors, are not allowed.
-#
-# Outputs:
-# domain (string)
-# type (string)
-# levelFrom (string; one of none, all, app, or user)
-# level (string)
-#
-# domain= determines the label to be used for the app process; entries
-# without domain= are ignored for this purpose.
-# type= specifies the label to be used for the app data directory; entries
-# without type= are ignored for this purpose. The label specified must
-# have the app_data_file_type attribute.
-# levelFrom and level are used to determine the level (sensitivity + categories)
-# for MLS/MCS.
-# levelFrom=none omits the level.
-# levelFrom=app determines the level from the process UID.
-# levelFrom=user determines the level from the user ID.
-# levelFrom=all determines the level from both UID and user ID.
-#
-# levelFrom=user is only supported for _app or _isolated UIDs.
-# levelFrom=app or levelFrom=all is only supported for _app UIDs.
-# level may be used to specify a fixed level for any UID.
-#
-# For backwards compatibility levelFromUid=true is equivalent to levelFrom=app
-# and levelFromUid=false is equivalent to levelFrom=none.
-#
-#
-# Neverallow Assertions
-# Additional compile time assertion checks for the rules in this file can be
-# added as well. The assertion
-# rules are lines beginning with the keyword neverallow. Full support for PCRE
-# regular expressions exists on all input and output selectors. Neverallow
-# rules are never output to the built seapp_contexts file. Like all keywords,
-# neverallows are case-insensitive. A neverallow is asserted when all key value
-# inputs are matched on a key value rule line.
-#
-
-# only the system server can be in system_server domain
-neverallow isSystemServer=false domain=system_server
-neverallow isSystemServer="" domain=system_server
-
-# system domains should never be assigned outside of system uid
-neverallow user=((?!system).)* domain=system_app
-neverallow user=((?!system).)* type=system_app_data_file
-
-# any non priv-app with a non-known uid with a specified name should have a specified
-# seinfo
-neverallow user=_app isPrivApp=false name=.* seinfo=""
-neverallow user=_app isPrivApp=false name=.* seinfo=default
-
-# neverallow shared relro to any other domain
-# and neverallow any other uid into shared_relro
-neverallow user=shared_relro domain=((?!shared_relro).)*
-neverallow user=((?!shared_relro).)* domain=shared_relro
-
-# neverallow non-isolated uids into isolated_app domain
-# and vice versa
-neverallow user=_isolated domain=((?!isolated_app).)*
-neverallow user=((?!_isolated).)* domain=isolated_app
-
-# uid shell should always be in shell domain, however non-shell
-# uid's can be in shell domain
-neverallow user=shell domain=((?!shell).)*
-
-# only the package named com.android.shell can run in the shell domain
-neverallow domain=shell name=((?!com\.android\.shell).)*
-neverallow user=shell name=((?!com\.android\.shell).)*
-
-# Ephemeral Apps must run in the ephemeral_app domain
-neverallow isEphemeralApp=true domain=((?!ephemeral_app).)*
-
-isSystemServer=true domain=system_server_startup
-
-user=_app isPrivApp=true name=com.android.traceur domain=traceur_app type=app_data_file levelFrom=all
-user=_app isPrivApp=true name=com.android.remoteprovisioner domain=remote_prov_app type=app_data_file levelFrom=all
-user=system seinfo=platform domain=system_app type=system_app_data_file
-user=bluetooth seinfo=platform domain=bluetooth type=bluetooth_data_file
-user=network_stack seinfo=network_stack domain=network_stack type=radio_data_file
-user=nfc seinfo=platform domain=nfc type=nfc_data_file
-user=secure_element seinfo=platform domain=secure_element levelFrom=all
-user=radio seinfo=platform domain=radio type=radio_data_file
-user=shared_relro domain=shared_relro levelFrom=all
-user=shell seinfo=platform domain=shell name=com.android.shell type=shell_data_file
-user=webview_zygote seinfo=webview_zygote domain=webview_zygote
-user=_isolated domain=isolated_app levelFrom=user
-user=_app seinfo=app_zygote domain=app_zygote levelFrom=user
-user=_app seinfo=media domain=mediaprovider type=app_data_file levelFrom=user
-user=_app seinfo=platform domain=platform_app type=app_data_file levelFrom=user
-user=_app isEphemeralApp=true domain=ephemeral_app type=app_data_file levelFrom=all
-user=_app minTargetSdkVersion=31 isPrivApp=true domain=priv_app type=privapp_data_file levelFrom=all
-user=_app isPrivApp=true domain=priv_app type=privapp_data_file levelFrom=user
-user=_app isPrivApp=true name=com.google.android.permissioncontroller domain=permissioncontroller_app type=privapp_data_file levelFrom=all
-user=_app seinfo=media isPrivApp=true name=com.android.providers.media.module domain=mediaprovider_app type=privapp_data_file levelFrom=all
-user=_app isPrivApp=true name=com.google.android.providers.media.module domain=mediaprovider_app type=privapp_data_file levelFrom=all
-user=_app seinfo=platform isPrivApp=true name=com.android.permissioncontroller domain=permissioncontroller_app type=privapp_data_file levelFrom=all
-user=_app isPrivApp=true name=com.android.vzwomatrigger domain=vzwomatrigger_app type=privapp_data_file levelFrom=all
-user=_app isPrivApp=true name=com.google.android.gms domain=gmscore_app type=privapp_data_file levelFrom=user
-user=_app isPrivApp=true name=com.google.android.gms.* domain=gmscore_app type=privapp_data_file levelFrom=user
-user=_app isPrivApp=true name=com.google.android.gms:* domain=gmscore_app type=privapp_data_file levelFrom=user
-user=_app isPrivApp=true name=com.google.android.gsf domain=gmscore_app type=privapp_data_file levelFrom=user
-user=_app minTargetSdkVersion=30 domain=untrusted_app type=app_data_file levelFrom=all
-user=_app minTargetSdkVersion=29 domain=untrusted_app_29 type=app_data_file levelFrom=all
-user=_app minTargetSdkVersion=28 domain=untrusted_app_27 type=app_data_file levelFrom=all
-user=_app minTargetSdkVersion=26 domain=untrusted_app_27 type=app_data_file levelFrom=user
-user=_app domain=untrusted_app_25 type=app_data_file levelFrom=user
-user=_app minTargetSdkVersion=28 fromRunAs=true domain=runas_app levelFrom=all
-user=_app fromRunAs=true domain=runas_app levelFrom=user
+# This file can't be empty, but is unused on microdroid
diff --git a/microdroid/sepolicy/system/private/service_contexts b/microdroid/sepolicy/system/private/service_contexts
index b410b18..965b688 100644
--- a/microdroid/sepolicy/system/private/service_contexts
+++ b/microdroid/sepolicy/system/private/service_contexts
@@ -1,37 +1,10 @@
-android.hardware.authsecret.IAuthSecret/default u:object_r:hal_authsecret_service:s0
-android.hardware.automotive.audiocontrol.IAudioControl/default u:object_r:hal_audiocontrol_service:s0
-android.hardware.biometrics.face.IFace/default u:object_r:hal_face_service:s0
-android.hardware.biometrics.fingerprint.IFingerprint/default u:object_r:hal_fingerprint_service:s0
-android.hardware.gnss.IGnss/default u:object_r:hal_gnss_service:s0
-android.hardware.health.storage.IStorage/default u:object_r:hal_health_storage_service:s0
-android.hardware.identity.IIdentityCredentialStore/default u:object_r:hal_identity_service:s0
-android.hardware.light.ILights/default u:object_r:hal_light_service:s0
-android.hardware.memtrack.IMemtrack/default u:object_r:hal_memtrack_service:s0
-android.hardware.oemlock.IOemLock/default u:object_r:hal_oemlock_service:s0
-android.hardware.power.IPower/default u:object_r:hal_power_service:s0
-android.hardware.power.stats.IPowerStats/default u:object_r:hal_power_stats_service:s0
-android.hardware.rebootescrow.IRebootEscrow/default u:object_r:hal_rebootescrow_service:s0
android.hardware.security.keymint.IKeyMintDevice/default u:object_r:hal_keymint_service:s0
android.hardware.security.keymint.IRemotelyProvisionedComponent/default u:object_r:hal_remotelyprovisionedcomponent_service:s0
android.hardware.security.secureclock.ISecureClock/default u:object_r:hal_secureclock_service:s0
android.hardware.security.sharedsecret.ISharedSecret/default u:object_r:hal_sharedsecret_service:s0
-android.hardware.soundtrigger3.ISoundTriggerHw/default u:object_r:hal_audio_service:s0
-android.hardware.vibrator.IVibrator/default u:object_r:hal_vibrator_service:s0
-android.hardware.vibrator.IVibratorManager/default u:object_r:hal_vibrator_service:s0
-android.hardware.weaver.IWeaver/default u:object_r:hal_weaver_service:s0
-android.frameworks.stats.IStats/default u:object_r:fwk_stats_service:s0
android.system.keystore2.IKeystoreService/default u:object_r:keystore_service:s0
-accessibility u:object_r:accessibility_service:s0
-account u:object_r:account_service:s0
-activity u:object_r:activity_service:s0
-activity_task u:object_r:activity_task_service:s0
adb u:object_r:adb_service:s0
-aidl_lazy_test_1 u:object_r:aidl_lazy_test_service:s0
-aidl_lazy_test_2 u:object_r:aidl_lazy_test_service:s0
-alarm u:object_r:alarm_service:s0
-android.os.UpdateEngineService u:object_r:update_engine_service:s0
-android.os.UpdateEngineStableService u:object_r:update_engine_stable_service:s0
android.security.apc u:object_r:apc_service:s0
android.security.authorization u:object_r:authorization_service:s0
android.security.compat u:object_r:keystore_compat_hal_service:s0
@@ -40,270 +13,5 @@
android.security.maintenance u:object_r:keystore_maintenance_service:s0
android.security.remoteprovisioning u:object_r:remoteprovisioning_service:s0
android.security.vpnprofilestore u:object_r:vpnprofilestore_service:s0
-android.service.gatekeeper.IGateKeeperService u:object_r:gatekeeper_service:s0
-app_binding u:object_r:app_binding_service:s0
-app_hibernation u:object_r:app_hibernation_service:s0
-app_integrity u:object_r:app_integrity_service:s0
-app_prediction u:object_r:app_prediction_service:s0
-app_search u:object_r:app_search_service:s0
apexservice u:object_r:apex_service:s0
-blob_store u:object_r:blob_store_service:s0
-gsiservice u:object_r:gsi_service:s0
-appops u:object_r:appops_service:s0
-appwidget u:object_r:appwidget_service:s0
-artd u:object_r:artd_service:s0
-assetatlas u:object_r:assetatlas_service:s0
-attention u:object_r:attention_service:s0
-audio u:object_r:audio_service:s0
-auth u:object_r:auth_service:s0
-autofill u:object_r:autofill_service:s0
-backup u:object_r:backup_service:s0
-batteryproperties u:object_r:batteryproperties_service:s0
-batterystats u:object_r:batterystats_service:s0
-battery u:object_r:battery_service:s0
-binder_calls_stats u:object_r:binder_calls_stats_service:s0
-biometric u:object_r:biometric_service:s0
-bluetooth_manager u:object_r:bluetooth_manager_service:s0
-bluetooth u:object_r:bluetooth_service:s0
-broadcastradio u:object_r:broadcastradio_service:s0
-bugreport u:object_r:bugreport_service:s0
-cacheinfo u:object_r:cacheinfo_service:s0
-carrier_config u:object_r:radio_service:s0
-clipboard u:object_r:clipboard_service:s0
-com.android.net.IProxyService u:object_r:IProxyService_service:s0
-android.system.virtualizationservice u:object_r:virtualization_service:s0
-companiondevice u:object_r:companion_device_service:s0
-platform_compat u:object_r:platform_compat_service:s0
-platform_compat_native u:object_r:platform_compat_service:s0
-connectivity u:object_r:connectivity_service:s0
-connmetrics u:object_r:connmetrics_service:s0
-consumer_ir u:object_r:consumer_ir_service:s0
-content u:object_r:content_service:s0
-content_capture u:object_r:content_capture_service:s0
-content_suggestions u:object_r:content_suggestions_service:s0
-contexthub u:object_r:contexthub_service:s0
-country_detector u:object_r:country_detector_service:s0
-coverage u:object_r:coverage_service:s0
-cpuinfo u:object_r:cpuinfo_service:s0
-crossprofileapps u:object_r:crossprofileapps_service:s0
-dataloader_manager u:object_r:dataloader_manager_service:s0
-dbinfo u:object_r:dbinfo_service:s0
-device_config u:object_r:device_config_service:s0
-device_policy u:object_r:device_policy_service:s0
-device_identifiers u:object_r:device_identifiers_service:s0
-deviceidle u:object_r:deviceidle_service:s0
-device_state u:object_r:device_state_service:s0
-devicestoragemonitor u:object_r:devicestoragemonitor_service:s0
-diskstats u:object_r:diskstats_service:s0
-display u:object_r:display_service:s0
-dnsresolver u:object_r:dnsresolver_service:s0
-domain_verification u:object_r:domain_verification_service:s0
-color_display u:object_r:color_display_service:s0
-netd_listener u:object_r:netd_listener_service:s0
-network_watchlist u:object_r:network_watchlist_service:s0
-DockObserver u:object_r:DockObserver_service:s0
-dreams u:object_r:dreams_service:s0
-drm.drmManager u:object_r:drmserver_service:s0
-dropbox u:object_r:dropbox_service:s0
-dumpstate u:object_r:dumpstate_service:s0
-dynamic_system u:object_r:dynamic_system_service:s0
-econtroller u:object_r:radio_service:s0
-emergency_affordance u:object_r:emergency_affordance_service:s0
-euicc_card_controller u:object_r:radio_service:s0
-external_vibrator_service u:object_r:external_vibrator_service:s0
-lowpan u:object_r:lowpan_service:s0
-ethernet u:object_r:ethernet_service:s0
-face u:object_r:face_service:s0
-file_integrity u:object_r:file_integrity_service:s0
-fingerprint u:object_r:fingerprint_service:s0
-font u:object_r:font_service:s0
-android.hardware.fingerprint.IFingerprintDaemon u:object_r:fingerprintd_service:s0
-game u:object_r:game_service:s0
-gfxinfo u:object_r:gfxinfo_service:s0
-graphicsstats u:object_r:graphicsstats_service:s0
-gpu u:object_r:gpu_service:s0
-hardware u:object_r:hardware_service:s0
-hardware_properties u:object_r:hardware_properties_service:s0
-hdmi_control u:object_r:hdmi_control_service:s0
-ions u:object_r:radio_service:s0
-idmap u:object_r:idmap_service:s0
-incident u:object_r:incident_service:s0
-incidentcompanion u:object_r:incidentcompanion_service:s0
-inputflinger u:object_r:inputflinger_service:s0
-input_method u:object_r:input_method_service:s0
-input u:object_r:input_service:s0
-installd u:object_r:installd_service:s0
-iorapd u:object_r:iorapd_service:s0
-iphonesubinfo_msim u:object_r:radio_service:s0
-iphonesubinfo2 u:object_r:radio_service:s0
-iphonesubinfo u:object_r:radio_service:s0
-ims u:object_r:radio_service:s0
-imms u:object_r:imms_service:s0
-incremental u:object_r:incremental_service:s0
-ipsec u:object_r:ipsec_service:s0
-ircsmessage u:object_r:radio_service:s0
-iris u:object_r:iris_service:s0
-isms_msim u:object_r:radio_service:s0
-isms2 u:object_r:radio_service:s0
-isms u:object_r:radio_service:s0
-isub u:object_r:radio_service:s0
-jobscheduler u:object_r:jobscheduler_service:s0
-launcherapps u:object_r:launcherapps_service:s0
-legacy_permission u:object_r:legacy_permission_service:s0
-lights u:object_r:light_service:s0
-location u:object_r:location_service:s0
-location_time_zone_manager u:object_r:location_time_zone_manager_service:s0
-lock_settings u:object_r:lock_settings_service:s0
-looper_stats u:object_r:looper_stats_service:s0
-lpdump_service u:object_r:lpdump_service:s0
-media.aaudio u:object_r:audioserver_service:s0
-media.audio_flinger u:object_r:audioserver_service:s0
-media.audio_policy u:object_r:audioserver_service:s0
-media.camera u:object_r:cameraserver_service:s0
-media.camera.proxy u:object_r:cameraproxy_service:s0
-media.log u:object_r:audioserver_service:s0
-media.player u:object_r:mediaserver_service:s0
-media.metrics u:object_r:mediametrics_service:s0
-media.extractor u:object_r:mediaextractor_service:s0
-media.transcoding u:object_r:mediatranscoding_service:s0
-media.resource_manager u:object_r:mediaserver_service:s0
-media.resource_observer u:object_r:mediaserver_service:s0
-media.sound_trigger_hw u:object_r:audioserver_service:s0
-media.drm u:object_r:mediadrmserver_service:s0
-media.tuner u:object_r:mediatuner_service:s0
-media_communication u:object_r:media_communication_service:s0
-media_metrics u:object_r:media_metrics_service:s0
-media_projection u:object_r:media_projection_service:s0
-media_resource_monitor u:object_r:media_session_service:s0
-media_router u:object_r:media_router_service:s0
-media_session u:object_r:media_session_service:s0
-meminfo u:object_r:meminfo_service:s0
-memtrack.proxy u:object_r:memtrackproxy_service:s0
-midi u:object_r:midi_service:s0
-mount u:object_r:mount_service:s0
-music_recognition u:object_r:music_recognition_service:s0
-netd u:object_r:netd_service:s0
-netpolicy u:object_r:netpolicy_service:s0
-netstats u:object_r:netstats_service:s0
-network_stack u:object_r:network_stack_service:s0
-network_management u:object_r:network_management_service:s0
-network_score u:object_r:network_score_service:s0
-network_time_update_service u:object_r:network_time_update_service:s0
-nfc u:object_r:nfc_service:s0
-notification u:object_r:notification_service:s0
-oem_lock u:object_r:oem_lock_service:s0
-otadexopt u:object_r:otadexopt_service:s0
-overlay u:object_r:overlay_service:s0
-pac_proxy u:object_r:pac_proxy_service:s0
-package u:object_r:package_service:s0
-package_native u:object_r:package_native_service:s0
-people u:object_r:people_service:s0
-performance_hint u:object_r:hint_service:s0
-permission u:object_r:permission_service:s0
-permissionmgr u:object_r:permissionmgr_service:s0
-permission_checker u:object_r:permission_checker_service:s0
-persistent_data_block u:object_r:persistent_data_block_service:s0
-phone_msim u:object_r:radio_service:s0
-phone1 u:object_r:radio_service:s0
-phone2 u:object_r:radio_service:s0
-phone u:object_r:radio_service:s0
-pinner u:object_r:pinner_service:s0
-power_stats u:object_r:power_stats_service:s0
-power u:object_r:power_service:s0
-print u:object_r:print_service:s0
-processinfo u:object_r:processinfo_service:s0
-procstats u:object_r:procstats_service:s0
-profcollectd u:object_r:profcollectd_service:s0
-radio.phonesubinfo u:object_r:radio_service:s0
-radio.phone u:object_r:radio_service:s0
-radio.sms u:object_r:radio_service:s0
-rcs u:object_r:radio_service:s0
-reboot_readiness u:object_r:reboot_readiness_service:s0
-recovery u:object_r:recovery_service:s0
-resolver u:object_r:resolver_service:s0
-restrictions u:object_r:restrictions_service:s0
-role u:object_r:role_service:s0
-rollback u:object_r:rollback_service:s0
-rttmanager u:object_r:rttmanager_service:s0
-runtime u:object_r:runtime_service:s0
-samplingprofiler u:object_r:samplingprofiler_service:s0
-scheduling_policy u:object_r:scheduling_policy_service:s0
-search u:object_r:search_service:s0
-search_ui u:object_r:search_ui_service:s0
-secure_element u:object_r:secure_element_service:s0
-sec_key_att_app_id_provider u:object_r:sec_key_att_app_id_provider_service:s0
-sensorservice u:object_r:sensorservice_service:s0
-sensor_privacy u:object_r:sensor_privacy_service:s0
-serial u:object_r:serial_service:s0
-servicediscovery u:object_r:servicediscovery_service:s0
-manager u:object_r:service_manager_service:s0
-settings u:object_r:settings_service:s0
-shortcut u:object_r:shortcut_service:s0
-simphonebook_msim u:object_r:radio_service:s0
-simphonebook2 u:object_r:radio_service:s0
-simphonebook u:object_r:radio_service:s0
-sip u:object_r:radio_service:s0
-slice u:object_r:slice_service:s0
-smartspace u:object_r:smartspace_service:s0
-speech_recognition u:object_r:speech_recognition_service:s0
-stats u:object_r:stats_service:s0
-statscompanion u:object_r:statscompanion_service:s0
-statsmanager u:object_r:statsmanager_service:s0
-soundtrigger u:object_r:voiceinteraction_service:s0
-soundtrigger_middleware u:object_r:soundtrigger_middleware_service:s0
-statusbar u:object_r:statusbar_service:s0
-storaged u:object_r:storaged_service:s0
-storaged_pri u:object_r:storaged_service:s0
-storagestats u:object_r:storagestats_service:s0
-SurfaceFlinger u:object_r:surfaceflinger_service:s0
-suspend_control u:object_r:system_suspend_control_service:s0
-suspend_control_internal u:object_r:system_suspend_control_internal_service:s0
-system_config u:object_r:system_config_service:s0
-system_server_dumper u:object_r:system_server_dumper_service:s0
-system_update u:object_r:system_update_service:s0
-task u:object_r:task_service:s0
-telecom u:object_r:telecom_service:s0
-telephony.registry u:object_r:registry_service:s0
-telephony_ims u:object_r:radio_service:s0
-testharness u:object_r:testharness_service:s0
-tethering u:object_r:tethering_service:s0
-textclassification u:object_r:textclassification_service:s0
-textservices u:object_r:textservices_service:s0
-texttospeech u:object_r:texttospeech_service:s0
-time_detector u:object_r:timedetector_service:s0
-time_zone_detector u:object_r:timezonedetector_service:s0
-timezone u:object_r:timezone_service:s0
-thermalservice u:object_r:thermal_service:s0
-tracing.proxy u:object_r:tracingproxy_service:s0
-transformer u:object_r:transformer_service:s0
-trust u:object_r:trust_service:s0
-tv_input u:object_r:tv_input_service:s0
-tv_tuner_resource_mgr u:object_r:tv_tuner_resource_mgr_service:s0
-uce u:object_r:uce_service:s0
-uimode u:object_r:uimode_service:s0
-updatelock u:object_r:updatelock_service:s0
-uri_grants u:object_r:uri_grants_service:s0
-usagestats u:object_r:usagestats_service:s0
-usb u:object_r:usb_service:s0
-user u:object_r:user_service:s0
-uwb u:object_r:uwb_service:s0
-vcn_management u:object_r:vcn_management_service:s0
-vibrator u:object_r:vibrator_service:s0
-vibrator_manager u:object_r:vibrator_manager_service:s0
-virtual_touchpad u:object_r:virtual_touchpad_service:s0
-voiceinteraction u:object_r:voiceinteraction_service:s0
-vold u:object_r:vold_service:s0
-vpn_management u:object_r:vpn_management_service:s0
-vr_hwc u:object_r:vr_hwc_service:s0
-vrflinger_vsync u:object_r:vrflinger_vsync_service:s0
-vrmanager u:object_r:vr_manager_service:s0
-wallpaper u:object_r:wallpaper_service:s0
-webviewupdate u:object_r:webviewupdate_service:s0
-wifip2p u:object_r:wifip2p_service:s0
-wifiscanner u:object_r:wifiscanner_service:s0
-wifi u:object_r:wifi_service:s0
-wifinl80211 u:object_r:wifinl80211_service:s0
-wifiaware u:object_r:wifiaware_service:s0
-wifirtt u:object_r:rttmanager_service:s0
-window u:object_r:window_service:s0
* u:object_r:default_android_service:s0
diff --git a/microdroid/sepolicy/system/private/virtualizationservice.te b/microdroid/sepolicy/system/private/virtualizationservice.te
index 4c6f1f9..097f0a0 100644
--- a/microdroid/sepolicy/system/private/virtualizationservice.te
+++ b/microdroid/sepolicy/system/private/virtualizationservice.te
@@ -14,9 +14,6 @@
# When virtualizationservice execs a file with the crosvm_exec label, run it in the crosvm domain.
domain_auto_trans(virtualizationservice, crosvm_exec, crosvm)
-# Let virtualizationservice exec other files (e.g. mk_cdisk) in the same domain.
-allow virtualizationservice system_file:file execute_no_trans;
-
# Let virtualizationservice kill crosvm.
allow virtualizationservice crosvm:process sigkill;
diff --git a/microdroid_manager/Android.bp b/microdroid_manager/Android.bp
index 30f8481..267147f 100644
--- a/microdroid_manager/Android.bp
+++ b/microdroid_manager/Android.bp
@@ -9,15 +9,15 @@
edition: "2018",
prefer_rlib: true,
rustlibs: [
- "libenv_logger",
"libanyhow",
+ "libkernlog",
"libkeystore2_system_property-rust",
"liblog_rust",
- "libmicrodroid_metadata_proto_rust",
+ "libmicrodroid_metadata",
"libmicrodroid_payload_config",
"libprotobuf",
- "libserde_json",
"libserde",
+ "libserde_json",
],
init_rc: ["microdroid_manager.rc"],
}
diff --git a/microdroid_manager/microdroid_manager.rc b/microdroid_manager/microdroid_manager.rc
index 4f194a3..60d8ab7 100644
--- a/microdroid_manager/microdroid_manager.rc
+++ b/microdroid_manager/microdroid_manager.rc
@@ -1,7 +1,6 @@
service microdroid_manager /system/bin/microdroid_manager
disabled
- # TODO(b/189805435) for now redirect stdio to kmsg
- stdio_to_kmsg
+ file /dev/kmsg w
setenv RUST_LOG info
# TODO(jooyung) remove this when microdroid_manager becomes a daemon
- oneshot
\ No newline at end of file
+ oneshot
diff --git a/microdroid_manager/src/main.rs b/microdroid_manager/src/main.rs
index 10731c5..9bcfa67 100644
--- a/microdroid_manager/src/main.rs
+++ b/microdroid_manager/src/main.rs
@@ -29,9 +29,7 @@
const WAIT_TIMEOUT: Duration = Duration::from_secs(10);
fn main() -> Result<()> {
- // TODO(b/189805435) use kernlog
- env_logger::init();
-
+ kernlog::init()?;
info!("started.");
let metadata = metadata::load()?;
diff --git a/microdroid_manager/src/metadata.rs b/microdroid_manager/src/metadata.rs
index 4f7d7af..81d9cc4 100644
--- a/microdroid_manager/src/metadata.rs
+++ b/microdroid_manager/src/metadata.rs
@@ -15,25 +15,14 @@
//! Payload metadata from /dev/block/by-name/metadata
use log::info;
-use microdroid_metadata::metadata::Metadata;
-use protobuf::Message;
+use microdroid_metadata::{read_metadata, Metadata};
use std::fs::File;
use std::io;
-use std::io::Read;
const METADATA_PATH: &str = "/dev/block/by-name/metadata";
/// loads payload metadata from /dev/block/by-name/metadata
pub fn load() -> io::Result<Metadata> {
info!("loading payload metadata...");
-
- let mut f = File::open(METADATA_PATH)?;
- // metadata partition is
- // 4 bytes : size(N) in big endian
- // N bytes : message for Metadata
- let mut buf = [0u8; 4];
- f.read_exact(&mut buf)?;
- let size = i32::from_be_bytes(buf);
-
- Ok(Metadata::parse_from_reader(&mut f.take(size as u64))?)
+ read_metadata(File::open(METADATA_PATH)?)
}
diff --git a/tests/hostside/java/android/virt/test/MicrodroidTestCase.java b/tests/hostside/java/android/virt/test/MicrodroidTestCase.java
index 2457797..a3288a1 100644
--- a/tests/hostside/java/android/virt/test/MicrodroidTestCase.java
+++ b/tests/hostside/java/android/virt/test/MicrodroidTestCase.java
@@ -18,7 +18,6 @@
import static org.hamcrest.CoreMatchers.containsString;
import static org.hamcrest.CoreMatchers.is;
-import static org.hamcrest.CoreMatchers.not;
import static org.junit.Assert.assertThat;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
@@ -31,25 +30,17 @@
import com.android.tradefed.util.CommandStatus;
import com.android.tradefed.util.RunUtil;
-import org.json.JSONArray;
-import org.json.JSONObject;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
-import java.io.BufferedReader;
import java.io.File;
-import java.io.FileWriter;
-import java.io.InputStream;
-import java.io.InputStreamReader;
-import java.util.ArrayList;
import java.util.Arrays;
-import java.util.List;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
-import java.util.stream.Collectors;
-import java.util.zip.ZipFile;
@RunWith(DeviceJUnit4ClassRunner.class)
public class MicrodroidTestCase extends BaseHostJUnit4Test {
@@ -132,7 +123,7 @@
return result.getStdout().trim();
}
- // Run a shell command on Android
+ // Run a shell command on Android. the default timeout is 2 min by tradefed
private String runOnAndroid(String... cmd) throws Exception {
CommandResult result = getDevice().executeShellV2Command(join(cmd));
if (result.getStatus() != CommandStatus.SUCCESS) {
@@ -141,12 +132,25 @@
return result.getStdout().trim();
}
- // Same as runOnAndroid, but failutre is not an error
+ // Same as runOnAndroid, but failure is not an error
private String tryRunOnAndroid(String... cmd) throws Exception {
CommandResult result = getDevice().executeShellV2Command(join(cmd));
return result.getStdout().trim();
}
+ private String runOnAndroidWithTimeout(long timeoutMillis, String... cmd) throws Exception {
+ CommandResult result =
+ getDevice()
+ .executeShellV2Command(
+ join(cmd),
+ timeoutMillis,
+ java.util.concurrent.TimeUnit.MILLISECONDS);
+ if (result.getStatus() != CommandStatus.SUCCESS) {
+ fail(join(cmd) + " has failed: " + result);
+ }
+ return result.getStdout().trim();
+ }
+
// Run a shell command on Microdroid
private String runOnMicrodroid(String... cmd) {
final long timeout = 30000; // 30 sec. Microdroid is extremely slow on GCE-on-CF.
@@ -163,26 +167,16 @@
return String.join(" ", Arrays.asList(strs));
}
- private String createPayloadImage(String apkName, String packageName, String configPath)
+ private File findTestFile(String name) throws Exception {
+ return (new CompatibilityBuildHelper(getBuild())).getTestFile(name);
+ }
+
+ private String startMicrodroid(String apkName, String packageName, String configPath)
throws Exception {
+ // Install APK
File apkFile = findTestFile(apkName);
getDevice().installPackage(apkFile, /* reinstall */ true);
- // Read the config file from the apk and parse it to know the list of APEXes needed
- ZipFile apkAsZip = new ZipFile(apkFile);
- InputStream is = apkAsZip.getInputStream(apkAsZip.getEntry(configPath));
- String configString =
- new BufferedReader(new InputStreamReader(is))
- .lines()
- .collect(Collectors.joining("\n"));
- JSONObject configObject = new JSONObject(configString);
- JSONArray apexes = configObject.getJSONArray("apexes");
- List<String> apexNames = new ArrayList<>();
- for (int i = 0; i < apexes.length(); i++) {
- JSONObject anApex = apexes.getJSONObject(i);
- apexNames.add(anApex.getString("name"));
- }
-
// Get the path to the installed apk. Note that
// getDevice().getAppPackageInfo(...).getCodePath() doesn't work due to the incorrect
// parsing of the "=" character. (b/190975227). So we use the `pm path` command directly.
@@ -195,53 +189,37 @@
final String apkIdsigPath = TEST_ROOT + apkName + ".idsig";
getDevice().pushFile(idsigOnHost, apkIdsigPath);
- // Create payload.json from the gathered data
- JSONObject payloadObject = new JSONObject();
- payloadObject.put("system_apexes", new JSONArray(apexNames));
- payloadObject.put("payload_config_path", "/mnt/apk/" + configPath);
- JSONObject apkObject = new JSONObject();
- apkObject.put("name", packageName);
- apkObject.put("path", apkPath);
- apkObject.put("idsig_path", apkIdsigPath);
- payloadObject.put("apk", apkObject);
-
- // Copy the json file to Android
- File payloadJsonOnHost = File.createTempFile("payload", "json");
- FileWriter writer = new FileWriter(payloadJsonOnHost);
- writer.write(payloadObject.toString());
- writer.close();
- final String payloadJson = TEST_ROOT + "payload.json";
- getDevice().pushFile(payloadJsonOnHost, payloadJson);
-
- // Finally run mk_payload to create payload.img
- final String mkPayload = VIRT_APEX + "bin/mk_payload";
- final String payloadImg = TEST_ROOT + "payload.img";
- runOnAndroid(mkPayload, payloadJson, payloadImg);
- assertThat(runOnAndroid("du", "-b", payloadImg), is(not("")));
-
- // The generated files are owned by root. Allow the virtualizationservice to read them.
- runOnAndroid("chmod", "go+r", TEST_ROOT + "payload*");
-
- return payloadImg;
- }
-
- private File findTestFile(String name) throws Exception {
- return (new CompatibilityBuildHelper(getBuild())).getTestFile(name);
- }
-
- private String startMicrodroid(String apkName, String packageName, String configPath)
- throws Exception {
- // Create payload.img
- createPayloadImage(apkName, packageName, configPath);
+ final String logPath = TEST_ROOT + "log.txt";
// Run the VM
runOnAndroid("start", "virtualizationservice");
String ret =
runOnAndroid(
VIRT_APEX + "bin/vm",
- "run",
+ "run-app",
"--daemonize",
- VIRT_APEX + "etc/microdroid.json");
+ "--log " + logPath,
+ apkPath,
+ apkIdsigPath,
+ configPath);
+
+ // Redirect log.txt to logd using logwrapper
+ ExecutorService executor = Executors.newFixedThreadPool(1);
+ executor.execute(
+ () -> {
+ try {
+ // Keep redirecting sufficiently long enough
+ runOnAndroidWithTimeout(
+ MICRODROID_BOOT_TIMEOUT_MINUTES * 60 * 1000,
+ "logwrapper",
+ "tail",
+ "-f",
+ "-n +0",
+ logPath);
+ } catch (Exception e) {
+ // Consume
+ }
+ });
// Retrieve the CID from the vm tool output
Pattern pattern = Pattern.compile("with CID (\\d+)");
diff --git a/tests/testapk/assets/vm_config.json b/tests/testapk/assets/vm_config.json
index 8312f4d..b814394 100644
--- a/tests/testapk/assets/vm_config.json
+++ b/tests/testapk/assets/vm_config.json
@@ -9,19 +9,5 @@
"hello",
"microdroid"
]
- },
- "apexes": [
- {
- "name": "com.android.adbd"
- },
- {
- "name": "com.android.i18n"
- },
- {
- "name": "com.android.os.statsd"
- },
- {
- "name": "com.android.sdkext"
- }
- ]
+ }
}
diff --git a/tests/vsock_test.cc b/tests/vsock_test.cc
index 233c6dd..d9b8f21 100644
--- a/tests/vsock_test.cc
+++ b/tests/vsock_test.cc
@@ -32,6 +32,7 @@
#include "android-base/parseint.h"
#include "android-base/unique_fd.h"
#include "android/system/virtualizationservice/VirtualMachineConfig.h"
+#include "android/system/virtualizationservice/VirtualMachineRawConfig.h"
#include "virt/VirtualizationTest.h"
#define KVM_CAP_ARM_PROTECTED_VM 0xffbadab1
@@ -83,12 +84,13 @@
ret = TEMP_FAILURE_RETRY(listen(server_fd, 1));
ASSERT_EQ(ret, 0) << strerror(errno);
- VirtualMachineConfig config;
- config.kernel = ParcelFileDescriptor(unique_fd(open(kVmKernelPath, O_RDONLY | O_CLOEXEC)));
- config.initrd = ParcelFileDescriptor(unique_fd(open(kVmInitrdPath, O_RDONLY | O_CLOEXEC)));
- config.params = String16(kVmParams);
- config.protected_vm = protected_vm;
+ VirtualMachineRawConfig raw_config;
+ raw_config.kernel = ParcelFileDescriptor(unique_fd(open(kVmKernelPath, O_RDONLY | O_CLOEXEC)));
+ raw_config.initrd = ParcelFileDescriptor(unique_fd(open(kVmInitrdPath, O_RDONLY | O_CLOEXEC)));
+ raw_config.params = kVmParams;
+ raw_config.protected_vm = protected_vm;
+ VirtualMachineConfig config(std::move(raw_config));
sp<IVirtualMachine> vm;
status = virtualization_service->startVm(config, std::nullopt, &vm);
ASSERT_TRUE(status.isOk()) << "Error starting VM: " << status;
diff --git a/virtualizationservice/Android.bp b/virtualizationservice/Android.bp
index 700d0fc..a941742 100644
--- a/virtualizationservice/Android.bp
+++ b/virtualizationservice/Android.bp
@@ -27,12 +27,16 @@
"libcrc32fast",
"libdisk",
"liblog_rust",
+ "libmicrodroid_metadata",
+ "libmicrodroid_payload_config",
"libprotobuf",
"libprotos",
"libserde_json",
"libserde",
"libshared_child",
"libuuid",
+ "libvmconfig",
+ "libzip",
],
}
diff --git a/virtualizationservice/aidl/android/system/virtualizationservice/Partition.aidl b/virtualizationservice/aidl/android/system/virtualizationservice/Partition.aidl
index 782c239..9b8658b 100644
--- a/virtualizationservice/aidl/android/system/virtualizationservice/Partition.aidl
+++ b/virtualizationservice/aidl/android/system/virtualizationservice/Partition.aidl
@@ -18,10 +18,10 @@
/** A partition to be assembled into a composite image. */
parcelable Partition {
/** A label for the partition. */
- String label;
+ @utf8InCpp String label;
- /** The backing file descriptor of the partition image. */
- ParcelFileDescriptor image;
+ /** The backing file descriptors of the partition images. */
+ ParcelFileDescriptor[] images;
/** Whether the partition should be writable by the VM. */
boolean writable;
diff --git a/virtualizationservice/aidl/android/system/virtualizationservice/VirtualMachineAppConfig.aidl b/virtualizationservice/aidl/android/system/virtualizationservice/VirtualMachineAppConfig.aidl
new file mode 100644
index 0000000..5b270a3
--- /dev/null
+++ b/virtualizationservice/aidl/android/system/virtualizationservice/VirtualMachineAppConfig.aidl
@@ -0,0 +1,28 @@
+/*
+ * Copyright 2021 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 android.system.virtualizationservice;
+
+/** Configuration for running an App in a VM */
+parcelable VirtualMachineAppConfig {
+ /** Main APK */
+ ParcelFileDescriptor apk;
+
+ /** idsig for an APK */
+ ParcelFileDescriptor idsig;
+
+ /** Path to a configuration in an APK. This is the actual configuration for a VM. */
+ @utf8InCpp String configPath;
+}
diff --git a/virtualizationservice/aidl/android/system/virtualizationservice/VirtualMachineConfig.aidl b/virtualizationservice/aidl/android/system/virtualizationservice/VirtualMachineConfig.aidl
index cb28856..00a7937 100644
--- a/virtualizationservice/aidl/android/system/virtualizationservice/VirtualMachineConfig.aidl
+++ b/virtualizationservice/aidl/android/system/virtualizationservice/VirtualMachineConfig.aidl
@@ -15,31 +15,14 @@
*/
package android.system.virtualizationservice;
-import android.system.virtualizationservice.DiskImage;
+import android.system.virtualizationservice.VirtualMachineAppConfig;
+import android.system.virtualizationservice.VirtualMachineRawConfig;
-/** Configuration for running a VM. */
-parcelable VirtualMachineConfig {
- /** The kernel image, if any. */
- @nullable ParcelFileDescriptor kernel;
+/** Configuration for running a VM */
+union VirtualMachineConfig {
+ /** Configuration for a VM to run an APP */
+ VirtualMachineAppConfig appConfig;
- /** The initial ramdisk for the kernel, if any. */
- @nullable ParcelFileDescriptor initrd;
-
- /**
- * Parameters to pass to the kernel. As far as the VMM and boot protocol are concerned this is
- * just a string, but typically it will contain multiple parameters separated by spaces.
- */
- @nullable String params;
-
- /**
- * The bootloader to use. If this is supplied then the kernel and initrd must not be supplied;
- * the bootloader is instead responsibly for loading the kernel from one of the disks.
- */
- @nullable ParcelFileDescriptor bootloader;
-
- /** Disk images to be made available to the VM. */
- DiskImage[] disks;
-
- /** Whether the VM should be a protected VM. */
- boolean protected_vm;
+ /** Configuration for a VM with low-level configuration */
+ VirtualMachineRawConfig rawConfig;
}
diff --git a/virtualizationservice/aidl/android/system/virtualizationservice/VirtualMachineDebugInfo.aidl b/virtualizationservice/aidl/android/system/virtualizationservice/VirtualMachineDebugInfo.aidl
index 18b01ce..d081b8d 100644
--- a/virtualizationservice/aidl/android/system/virtualizationservice/VirtualMachineDebugInfo.aidl
+++ b/virtualizationservice/aidl/android/system/virtualizationservice/VirtualMachineDebugInfo.aidl
@@ -21,13 +21,13 @@
int cid;
/** Directory of temporary files used by the VM while it is running. */
- String temporaryDirectory;
+ @utf8InCpp String temporaryDirectory;
/** The UID of the process which requested the VM. */
int requesterUid;
/** The SID of the process which requested the VM. */
- String requesterSid;
+ @utf8InCpp String requesterSid;
/**
* The PID of the process which requested the VM. Note that this process may no longer exist and
diff --git a/virtualizationservice/aidl/android/system/virtualizationservice/VirtualMachineRawConfig.aidl b/virtualizationservice/aidl/android/system/virtualizationservice/VirtualMachineRawConfig.aidl
new file mode 100644
index 0000000..7848ed5
--- /dev/null
+++ b/virtualizationservice/aidl/android/system/virtualizationservice/VirtualMachineRawConfig.aidl
@@ -0,0 +1,45 @@
+/*
+ * Copyright 2021 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 android.system.virtualizationservice;
+
+import android.system.virtualizationservice.DiskImage;
+
+/** Raw Configuration for running a VM. */
+parcelable VirtualMachineRawConfig {
+ /** The kernel image, if any. */
+ @nullable ParcelFileDescriptor kernel;
+
+ /** The initial ramdisk for the kernel, if any. */
+ @nullable ParcelFileDescriptor initrd;
+
+ /**
+ * Parameters to pass to the kernel. As far as the VMM and boot protocol are concerned this is
+ * just a string, but typically it will contain multiple parameters separated by spaces.
+ */
+ @nullable @utf8InCpp String params;
+
+ /**
+ * The bootloader to use. If this is supplied then the kernel and initrd must not be supplied;
+ * the bootloader is instead responsibly for loading the kernel from one of the disks.
+ */
+ @nullable ParcelFileDescriptor bootloader;
+
+ /** Disk images to be made available to the VM. */
+ DiskImage[] disks;
+
+ /** Whether the VM should be a protected VM. */
+ boolean protected_vm;
+}
diff --git a/virtualizationservice/src/aidl.rs b/virtualizationservice/src/aidl.rs
index b1b0b38..a0b5217 100644
--- a/virtualizationservice/src/aidl.rs
+++ b/virtualizationservice/src/aidl.rs
@@ -16,27 +16,35 @@
use crate::composite::make_composite_image;
use crate::crosvm::{CrosvmConfig, DiskFile, VmInstance};
+use crate::payload;
use crate::{Cid, FIRST_GUEST_CID};
+
use android_system_virtualizationservice::aidl::android::system::virtualizationservice::IVirtualizationService::IVirtualizationService;
use android_system_virtualizationservice::aidl::android::system::virtualizationservice::DiskImage::DiskImage;
use android_system_virtualizationservice::aidl::android::system::virtualizationservice::IVirtualMachine::{
BnVirtualMachine, IVirtualMachine,
};
use android_system_virtualizationservice::aidl::android::system::virtualizationservice::IVirtualMachineCallback::IVirtualMachineCallback;
-use android_system_virtualizationservice::aidl::android::system::virtualizationservice::VirtualMachineConfig::VirtualMachineConfig;
+use android_system_virtualizationservice::aidl::android::system::virtualizationservice::{
+ VirtualMachineAppConfig::VirtualMachineAppConfig,
+ VirtualMachineConfig::VirtualMachineConfig,
+ VirtualMachineRawConfig::VirtualMachineRawConfig,
+};
use android_system_virtualizationservice::aidl::android::system::virtualizationservice::VirtualMachineDebugInfo::VirtualMachineDebugInfo;
use android_system_virtualizationservice::binder::{
self, BinderFeatures, ExceptionCode, Interface, ParcelFileDescriptor, Status, Strong, ThreadState,
};
-use command_fds::FdMapping;
+use anyhow::Result;
use disk::QcowFile;
use log::{debug, error, warn};
+use microdroid_payload_config::{ApexConfig, VmPayloadConfig};
use std::convert::TryInto;
use std::ffi::CString;
use std::fs::{File, create_dir};
use std::os::unix::io::AsRawFd;
use std::path::{Path, PathBuf};
use std::sync::{Arc, Mutex, Weak};
+use vmconfig::VmConfig;
pub const BINDER_SERVICE_IDENTIFIER: &str = "android.system.virtualizationservice";
@@ -93,6 +101,22 @@
)
})?;
+ let mut opt_raw_config = None;
+ let config = match config {
+ VirtualMachineConfig::AppConfig(config) => {
+ let raw_config = load_app_config(config, &temporary_directory).map_err(|e| {
+ error!("Failed to load app config from {}: {}", &config.configPath, e);
+ new_binder_exception(
+ ExceptionCode::SERVICE_SPECIFIC,
+ format!("Failed to load app config from {}: {}", &config.configPath, e),
+ )
+ })?;
+ opt_raw_config.replace(raw_config);
+ opt_raw_config.as_ref().unwrap()
+ }
+ VirtualMachineConfig::RawConfig(config) => config,
+ };
+
// Assemble disk images if needed.
let disks = config
.disks
@@ -117,17 +141,12 @@
params: config.params.to_owned(),
protected: config.protected_vm,
};
- let composite_disk_mappings: Vec<_> = indirect_files
- .iter()
- .map(|file| {
- let fd = file.as_raw_fd();
- FdMapping { parent_fd: fd, child_fd: fd }
- })
- .collect();
+ let composite_disk_fds: Vec<_> =
+ indirect_files.iter().map(|file| file.as_raw_fd()).collect();
let instance = VmInstance::start(
&crosvm_config,
log_fd,
- &composite_disk_mappings,
+ &composite_disk_fds,
temporary_directory,
requester_uid,
requester_sid,
@@ -262,6 +281,46 @@
Ok(DiskFile { image, writable: disk.writable })
}
+fn load_app_config(
+ config: &VirtualMachineAppConfig,
+ temporary_directory: &Path,
+) -> Result<VirtualMachineRawConfig> {
+ let apk_file = config.apk.as_ref().unwrap().as_ref();
+ let idsig_file = config.idsig.as_ref().unwrap().as_ref();
+ let config_path = &config.configPath;
+
+ let mut apk_zip = zip::ZipArchive::new(apk_file)?;
+ let config_file = apk_zip.by_name(config_path)?;
+ let vm_payload_config: VmPayloadConfig = serde_json::from_reader(config_file)?;
+
+ let os_name = &vm_payload_config.os.name;
+ let vm_config_path = PathBuf::from(format!("/apex/com.android.virt/etc/{}.json", os_name));
+ let vm_config_file = File::open(vm_config_path)?;
+ let mut vm_config = VmConfig::load(&vm_config_file)?;
+
+ // Microdroid requires additional payload disk image
+ if os_name == "microdroid" {
+ // TODO (b/192200378) move this to microdroid.json?
+ let mut apexes = vm_payload_config.apexes.clone();
+ apexes.extend(
+ ["com.android.adbd", "com.android.i18n", "com.android.os.statsd", "com.android.sdkext"]
+ .iter()
+ .map(|name| ApexConfig { name: name.to_string() }),
+ );
+ apexes.dedup_by(|a, b| a.name == b.name);
+
+ vm_config.disks.push(payload::make_disk_image(
+ format!("/proc/self/fd/{}", apk_file.as_raw_fd()).into(),
+ format!("/proc/self/fd/{}", idsig_file.as_raw_fd()).into(),
+ config_path,
+ &apexes,
+ temporary_directory,
+ )?);
+ }
+
+ vm_config.to_parcelable()
+}
+
/// Generates a unique filename to use for a composite disk image.
fn make_composite_image_filenames(
temporary_directory: &Path,
diff --git a/virtualizationservice/src/composite.rs b/virtualizationservice/src/composite.rs
index 5f792fd..1af0eed 100644
--- a/virtualizationservice/src/composite.rs
+++ b/virtualizationservice/src/composite.rs
@@ -72,6 +72,11 @@
((val + (align - 1)) / align) * align
}
+/// Round `val` to partition size(4K)
+pub fn align_to_partition_size(val: u64) -> u64 {
+ align_to_power_of_2(val, PARTITION_SIZE_SHIFT)
+}
+
impl PartitionInfo {
fn aligned_size(&self) -> u64 {
align_to_power_of_2(self.files.iter().map(|file| file.size).sum(), PARTITION_SIZE_SHIFT)
@@ -336,9 +341,9 @@
Ok((composite_image, files))
}
-/// Given the AIDL config containing a list of partitions, with a [`ParcelFileDescriptor`] for each
-/// partition, return the list of file descriptors which must be passed to the mk_cdisk child
-/// process and the composite disk image partition configuration for it.
+/// Given the AIDL config containing a list of partitions, with [`ParcelFileDescriptor`]s for each
+/// partition, return the list of file descriptors which must be passed to the composite disk image
+/// partition configuration for it.
fn convert_partitions(partitions: &[Partition]) -> Result<(Vec<PartitionInfo>, Vec<File>), Error> {
// File descriptors to pass to child process.
let mut files = vec![];
@@ -346,24 +351,27 @@
let partitions = partitions
.iter()
.map(|partition| {
- // TODO(b/187187765): This shouldn't be an Option.
- let file = partition
- .image
- .as_ref()
- .context("Invalid partition image file descriptor")?
- .as_ref()
- .try_clone()
- .context("Failed to clone partition image file descriptor")?;
- let size = get_partition_size(&file)?;
- let fd = file.as_raw_fd();
- files.push(file);
+ let image_files = partition
+ .images
+ .iter()
+ .map(|image| {
+ let file = image
+ .as_ref()
+ .try_clone()
+ .context("Failed to clone partition image file descriptor")?;
+
+ let size = get_partition_size(&file)?;
+ let fd = file.as_raw_fd();
+ let partition_info_file =
+ PartitionFileInfo { path: format!("/proc/self/fd/{}", fd).into(), size };
+ files.push(file);
+ Ok(partition_info_file)
+ })
+ .collect::<Result<Vec<_>, Error>>()?;
Ok(PartitionInfo {
label: partition.label.to_owned(),
- files: vec![PartitionFileInfo {
- path: format!("/proc/self/fd/{}", fd).into(),
- size,
- }],
+ files: image_files,
partition_type: ImagePartitionType::LinuxFilesystem,
writable: partition.writable,
})
diff --git a/virtualizationservice/src/crosvm.rs b/virtualizationservice/src/crosvm.rs
index 669c631..ae8388a 100644
--- a/virtualizationservice/src/crosvm.rs
+++ b/virtualizationservice/src/crosvm.rs
@@ -17,11 +17,11 @@
use crate::aidl::VirtualMachineCallbacks;
use crate::Cid;
use anyhow::{bail, Error};
-use command_fds::{CommandFdExt, FdMapping};
+use command_fds::CommandFdExt;
use log::{debug, error, info};
use shared_child::SharedChild;
use std::fs::{remove_dir_all, File};
-use std::os::unix::io::AsRawFd;
+use std::os::unix::io::{AsRawFd, RawFd};
use std::path::PathBuf;
use std::process::Command;
use std::sync::atomic::{AtomicBool, Ordering};
@@ -102,13 +102,13 @@
pub fn start(
config: &CrosvmConfig,
log_fd: Option<File>,
- composite_disk_mappings: &[FdMapping],
+ composite_disk_fds: &[RawFd],
temporary_directory: PathBuf,
requester_uid: u32,
requester_sid: String,
requester_debug_pid: i32,
) -> Result<Arc<VmInstance>, Error> {
- let child = run_vm(config, log_fd, composite_disk_mappings)?;
+ let child = run_vm(config, log_fd, composite_disk_fds)?;
let instance = Arc::new(VmInstance::new(
child,
config.cid,
@@ -161,7 +161,7 @@
fn run_vm(
config: &CrosvmConfig,
log_fd: Option<File>,
- composite_disk_mappings: &[FdMapping],
+ composite_disk_fds: &[RawFd],
) -> Result<SharedChild, Error> {
validate_config(config)?;
@@ -181,14 +181,14 @@
}
// Keep track of what file descriptors should be mapped to the crosvm process.
- let mut fd_mappings = composite_disk_mappings.to_vec();
+ let mut preserved_fds = composite_disk_fds.to_vec();
if let Some(bootloader) = &config.bootloader {
- command.arg("--bios").arg(add_fd_mapping(&mut fd_mappings, bootloader));
+ command.arg("--bios").arg(add_preserved_fd(&mut preserved_fds, bootloader));
}
if let Some(initrd) = &config.initrd {
- command.arg("--initrd").arg(add_fd_mapping(&mut fd_mappings, initrd));
+ command.arg("--initrd").arg(add_preserved_fd(&mut preserved_fds, initrd));
}
if let Some(params) = &config.params {
@@ -198,15 +198,15 @@
for disk in &config.disks {
command
.arg(if disk.writable { "--rwdisk" } else { "--disk" })
- .arg(add_fd_mapping(&mut fd_mappings, &disk.image));
+ .arg(add_preserved_fd(&mut preserved_fds, &disk.image));
}
if let Some(kernel) = &config.kernel {
- command.arg(add_fd_mapping(&mut fd_mappings, kernel));
+ command.arg(add_preserved_fd(&mut preserved_fds, kernel));
}
- debug!("Setting mappings {:?}", fd_mappings);
- command.fd_mappings(fd_mappings)?;
+ debug!("Preserving FDs {:?}", preserved_fds);
+ command.preserved_fds(preserved_fds);
info!("Running {:?}", command);
let result = SharedChild::spawn(&mut command)?;
@@ -224,10 +224,10 @@
Ok(())
}
-/// Adds a mapping for `file` to `fd_mappings`, and returns a string of the form "/proc/self/fd/N"
-/// where N is the file descriptor for the child process.
-fn add_fd_mapping(fd_mappings: &mut Vec<FdMapping>, file: &File) -> String {
+/// Adds the file descriptor for `file` to `preserved_fds`, and returns a string of the form
+/// "/proc/self/fd/N" where N is the file descriptor.
+fn add_preserved_fd(preserved_fds: &mut Vec<RawFd>, file: &File) -> String {
let fd = file.as_raw_fd();
- fd_mappings.push(FdMapping { parent_fd: fd, child_fd: fd });
+ preserved_fds.push(fd);
format!("/proc/self/fd/{}", fd)
}
diff --git a/virtualizationservice/src/main.rs b/virtualizationservice/src/main.rs
index 43b5fe4..658203b 100644
--- a/virtualizationservice/src/main.rs
+++ b/virtualizationservice/src/main.rs
@@ -18,6 +18,7 @@
mod composite;
mod crosvm;
mod gpt;
+mod payload;
use crate::aidl::{VirtualizationService, BINDER_SERVICE_IDENTIFIER};
use android_system_virtualizationservice::aidl::android::system::virtualizationservice::IVirtualizationService::BnVirtualizationService;
diff --git a/virtualizationservice/src/payload.rs b/virtualizationservice/src/payload.rs
new file mode 100644
index 0000000..aaf43e4
--- /dev/null
+++ b/virtualizationservice/src/payload.rs
@@ -0,0 +1,139 @@
+// Copyright 2021, 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.
+
+//! Payload disk image
+
+use crate::composite::align_to_partition_size;
+
+use anyhow::{Error, Result};
+use microdroid_metadata::{ApexPayload, ApkPayload, Metadata};
+use microdroid_payload_config::ApexConfig;
+use std::fs;
+use std::fs::OpenOptions;
+use std::io::{Seek, SeekFrom, Write};
+use std::path::{Path, PathBuf};
+use std::process::Command;
+use vmconfig::{DiskImage, Partition};
+
+// TODO(b/191601801): look up /apex/apex-info-list.xml
+fn get_path(package_name: &str) -> Result<PathBuf> {
+ let output = Command::new("pm").arg("path").arg(package_name).output()?;
+ let output = String::from_utf8(output.stdout)?;
+ Ok(PathBuf::from(output.strip_prefix("package:").unwrap().trim()))
+}
+
+/// When passing a host APEX file as a block device in a payload disk image,
+/// the size of the original file needs to be stored in the last 4 bytes so that
+/// other programs (e.g. apexd) can read it as a zip.
+fn make_size_filler(size: u64, filler_path: &Path) -> Result<bool> {
+ let partition_size = align_to_partition_size(size + 4);
+ let mut file = OpenOptions::new().create_new(true).write(true).open(filler_path)?;
+ file.set_len(partition_size - size)?;
+ file.seek(SeekFrom::End(-4))?;
+ file.write_all(&(size as i32).to_be_bytes())?;
+ Ok(true)
+}
+
+/// When passing a host APK file as a block device in a payload disk image and it is
+/// mounted via dm-verity, we need to make the device zero-padded up to 4K boundary.
+/// Otherwise, intergrity checks via hashtree will fail.
+fn make_zero_filler(size: u64, filler_path: &Path) -> Result<bool> {
+ let partition_size = align_to_partition_size(size);
+ if partition_size <= size {
+ return Ok(false);
+ }
+ let file = OpenOptions::new().create_new(true).write(true).open(filler_path)?;
+ file.set_len(partition_size - size)?;
+ Ok(true)
+}
+
+/// When passing a host idsig file as a block device, we don't need any filler because it is read
+/// in length-prefixed way.
+fn make_no_filler(_size: u64, _filler_path: &Path) -> Result<bool> {
+ Ok(false)
+}
+
+/// Creates a DiskImage with partitions:
+/// metadata: metadata
+/// microdroid-apex-0: [apex 0, size filler]
+/// microdroid-apex-1: [apex 1, size filler]
+/// ..
+/// microdroid-apk: [apk, zero filler]
+/// microdroid-apk-idsig: idsig
+pub fn make_disk_image(
+ apk_file: PathBuf,
+ idsig_file: PathBuf,
+ config_path: &str,
+ apexes: &[ApexConfig],
+ temporary_directory: &Path,
+) -> Result<DiskImage> {
+ let metadata_path = temporary_directory.join("metadata");
+ let metadata = Metadata {
+ version: 1u32,
+ apexes: apexes
+ .iter()
+ .map(|apex| ApexPayload { name: String::from(&apex.name), ..Default::default() })
+ .collect(),
+ apk: Some(ApkPayload {
+ name: String::from("apk"),
+ payload_partition_name: String::from("microdroid-apk"),
+ idsig_partition_name: String::from("microdroid-apk-idsig"),
+ ..Default::default()
+ })
+ .into(),
+ 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)?;
+ microdroid_metadata::write_metadata(&metadata, &mut metadata_file)?;
+
+ // put metadata at the first partition
+ let mut partitions = vec![Partition {
+ label: String::from("metadata"),
+ paths: vec![metadata_path],
+ writable: false,
+ }];
+
+ let mut filler_count = 0;
+ let mut make_partition = |label: String,
+ path: PathBuf,
+ make_filler: &dyn Fn(u64, &Path) -> Result<bool, Error>|
+ -> Result<Partition> {
+ let filler_path = temporary_directory.join(format!("filler-{}", filler_count));
+ let size = fs::metadata(&path)?.len();
+
+ if make_filler(size, &filler_path)? {
+ filler_count += 1;
+ Ok(Partition { label, paths: vec![path, filler_path], writable: false })
+ } else {
+ Ok(Partition { label, paths: vec![path], writable: false })
+ }
+ };
+ for (i, apex) in apexes.iter().enumerate() {
+ partitions.push(make_partition(
+ format!("microdroid-apex-{}", i),
+ get_path(&apex.name)?,
+ &make_size_filler,
+ )?);
+ }
+ partitions.push(make_partition(String::from("microdroid-apk"), apk_file, &make_zero_filler)?);
+ partitions.push(make_partition(
+ String::from("microdroid-apk-idsig"),
+ idsig_file,
+ &make_no_filler,
+ )?);
+
+ Ok(DiskImage { image: None, partitions, writable: false })
+}
diff --git a/vm/Android.bp b/vm/Android.bp
index c07beb2..734f2d3 100644
--- a/vm/Android.bp
+++ b/vm/Android.bp
@@ -10,13 +10,13 @@
rustlibs: [
"android.system.virtualizationservice-rust",
"libanyhow",
- "libcompositediskconfig",
"libenv_logger",
"liblibc",
"liblog_rust",
"libserde_json",
"libserde",
"libstructopt",
+ "libvmconfig",
],
apex_available: [
"com.android.virt",
diff --git a/vm/src/main.rs b/vm/src/main.rs
index 2c93ec4..d7bae30 100644
--- a/vm/src/main.rs
+++ b/vm/src/main.rs
@@ -14,14 +14,13 @@
//! Android VM control tool.
-mod config;
mod run;
mod sync;
use android_system_virtualizationservice::aidl::android::system::virtualizationservice::IVirtualizationService::IVirtualizationService;
use android_system_virtualizationservice::binder::{wait_for_interface, ProcessState, Strong, ParcelFileDescriptor};
use anyhow::{Context, Error};
-use run::command_run;
+use run::{command_run, command_run_app};
use std::convert::TryInto;
use std::fs::OpenOptions;
use std::path::{PathBuf, Path};
@@ -34,6 +33,27 @@
#[derive(StructOpt)]
#[structopt(no_version, global_settings = &[AppSettings::DisableVersion])]
enum Opt {
+ /// Run a virtual machine with a config in APK
+ RunApp {
+ /// Path to VM Payload APK
+ #[structopt(parse(from_os_str))]
+ apk: PathBuf,
+
+ /// Path to idsig of the APK
+ #[structopt(parse(from_os_str))]
+ idsig: PathBuf,
+
+ /// Path to VM config JSON within APK (e.g. assets/vm_config.json)
+ config_path: String,
+
+ /// Detach VM from the terminal and run in the background
+ #[structopt(short, long)]
+ daemonize: bool,
+
+ /// Path to file for VM log output.
+ #[structopt(short, long)]
+ log: Option<PathBuf>,
+ },
/// Run a virtual machine
Run {
/// Path to VM config JSON
@@ -43,6 +63,10 @@
/// Detach VM from the terminal and run in the background
#[structopt(short, long)]
daemonize: bool,
+
+ /// Path to file for VM log output.
+ #[structopt(short, long)]
+ log: Option<PathBuf>,
},
/// Stop a virtual machine running in the background
Stop {
@@ -73,7 +97,12 @@
.context("Failed to find VirtualizationService")?;
match opt {
- Opt::Run { config, daemonize } => command_run(service, &config, daemonize),
+ Opt::RunApp { apk, idsig, config_path, daemonize, log } => {
+ command_run_app(service, &apk, &idsig, &config_path, daemonize, log.as_deref())
+ }
+ Opt::Run { config, daemonize, log } => {
+ command_run(service, &config, daemonize, log.as_deref())
+ }
Opt::Stop { cid } => command_stop(service, cid),
Opt::List => command_list(service),
Opt::CreatePartition { path, size } => command_create_partition(service, &path, size),
diff --git a/vm/src/run.rs b/vm/src/run.rs
index ab4222f..1ae94ea 100644
--- a/vm/src/run.rs
+++ b/vm/src/run.rs
@@ -14,13 +14,16 @@
//! Command to run a VM.
-use crate::config::VmConfig;
use crate::sync::AtomicFlag;
use android_system_virtualizationservice::aidl::android::system::virtualizationservice::IVirtualizationService::IVirtualizationService;
use android_system_virtualizationservice::aidl::android::system::virtualizationservice::IVirtualMachine::IVirtualMachine;
use android_system_virtualizationservice::aidl::android::system::virtualizationservice::IVirtualMachineCallback::{
BnVirtualMachineCallback, IVirtualMachineCallback,
};
+use android_system_virtualizationservice::aidl::android::system::virtualizationservice::{
+ VirtualMachineAppConfig::VirtualMachineAppConfig,
+ VirtualMachineConfig::VirtualMachineConfig,
+};
use android_system_virtualizationservice::binder::{
BinderFeatures, DeathRecipient, IBinder, ParcelFileDescriptor, Strong,
};
@@ -30,19 +33,64 @@
use std::io;
use std::os::unix::io::{AsRawFd, FromRawFd};
use std::path::Path;
+use vmconfig::VmConfig;
+
+/// Run a VM from the given APK, idsig, and config.
+pub fn command_run_app(
+ service: Strong<dyn IVirtualizationService>,
+ apk: &Path,
+ idsig: &Path,
+ config_path: &str,
+ daemonize: bool,
+ log_path: Option<&Path>,
+) -> Result<(), Error> {
+ let apk_file = File::open(apk).context("Failed to open APK file")?;
+ let idsig_file = File::open(idsig).context("Failed to open idsig file")?;
+ let config = VirtualMachineConfig::AppConfig(VirtualMachineAppConfig {
+ apk: ParcelFileDescriptor::new(apk_file).into(),
+ idsig: ParcelFileDescriptor::new(idsig_file).into(),
+ configPath: config_path.to_owned(),
+ });
+ run(service, &config, &format!("{:?}!{:?}", apk, config_path), daemonize, log_path)
+}
/// Run a VM from the given configuration file.
pub fn command_run(
service: Strong<dyn IVirtualizationService>,
config_path: &Path,
daemonize: bool,
+ log_path: Option<&Path>,
) -> Result<(), Error> {
let config_file = File::open(config_path).context("Failed to open config file")?;
let config =
VmConfig::load(&config_file).context("Failed to parse config file")?.to_parcelable()?;
- let stdout =
- if daemonize { None } else { Some(ParcelFileDescriptor::new(duplicate_stdout()?)) };
- let vm = service.startVm(&config, stdout.as_ref()).context("Failed to start VM")?;
+ run(
+ service,
+ &VirtualMachineConfig::RawConfig(config),
+ &format!("{:?}", config_path),
+ daemonize,
+ log_path,
+ )
+}
+
+fn run(
+ service: Strong<dyn IVirtualizationService>,
+ config: &VirtualMachineConfig,
+ config_path: &str,
+ daemonize: bool,
+ log_path: Option<&Path>,
+) -> Result<(), Error> {
+ let stdout = if let Some(log_path) = log_path {
+ Some(ParcelFileDescriptor::new(
+ File::create(log_path)
+ .with_context(|| format!("Failed to open log file {:?}", log_path))?,
+ ))
+ } else if daemonize {
+ None
+ } else {
+ Some(ParcelFileDescriptor::new(duplicate_stdout()?))
+ };
+ let vm = service.startVm(config, stdout.as_ref()).context("Failed to start VM")?;
let cid = vm.getCid().context("Failed to get CID")?;
println!("Started VM from {:?} with CID {}.", config_path, cid);
diff --git a/compositediskconfig/Android.bp b/vmconfig/Android.bp
similarity index 66%
rename from compositediskconfig/Android.bp
rename to vmconfig/Android.bp
index 4608323..321eba0 100644
--- a/compositediskconfig/Android.bp
+++ b/vmconfig/Android.bp
@@ -3,12 +3,13 @@
}
rust_library {
- name: "libcompositediskconfig",
- host_supported: true,
- crate_name: "compositediskconfig",
+ name: "libvmconfig",
+ crate_name: "vmconfig",
srcs: ["src/lib.rs"],
edition: "2018",
rustlibs: [
+ "android.system.virtualizationservice-rust",
+ "libanyhow",
"libserde_json",
"libserde",
],
diff --git a/vm/src/config.rs b/vmconfig/src/lib.rs
similarity index 79%
rename from vm/src/config.rs
rename to vmconfig/src/lib.rs
index 8ea0d8f..7b0d2a5 100644
--- a/vm/src/config.rs
+++ b/vmconfig/src/lib.rs
@@ -12,16 +12,16 @@
// See the License for the specific language governing permissions and
// limitations under the License.
-//! Struct for VM configuration.
+//! Struct for VM configuration with JSON (de)serialization and AIDL parcelables
use android_system_virtualizationservice::{
aidl::android::system::virtualizationservice::DiskImage::DiskImage as AidlDiskImage,
aidl::android::system::virtualizationservice::Partition::Partition as AidlPartition,
- aidl::android::system::virtualizationservice::VirtualMachineConfig::VirtualMachineConfig,
+ aidl::android::system::virtualizationservice::VirtualMachineRawConfig::VirtualMachineRawConfig,
binder::ParcelFileDescriptor,
};
-use anyhow::{bail, Context, Error};
-use compositediskconfig::Partition;
+
+use anyhow::{bail, Context, Error, Result};
use serde::{Deserialize, Serialize};
use std::fs::{File, OpenOptions};
use std::io::BufReader;
@@ -76,8 +76,8 @@
/// Convert the `VmConfig` to a [`VirtualMachineConfig`] which can be passed to the Virt
/// Manager.
- pub fn to_parcelable(&self) -> Result<VirtualMachineConfig, Error> {
- Ok(VirtualMachineConfig {
+ pub fn to_parcelable(&self) -> Result<VirtualMachineRawConfig, Error> {
+ Ok(VirtualMachineRawConfig {
kernel: maybe_open_parcel_file(&self.kernel, false)?,
initrd: maybe_open_parcel_file(&self.initrd, false)?,
params: self.params.clone(),
@@ -105,7 +105,7 @@
impl DiskImage {
fn to_parcelable(&self) -> Result<AidlDiskImage, Error> {
let partitions =
- self.partitions.iter().map(partition_to_parcelable).collect::<Result<_, Error>>()?;
+ self.partitions.iter().map(Partition::to_parcelable).collect::<Result<_>>()?;
Ok(AidlDiskImage {
image: maybe_open_parcel_file(&self.image, self.writable)?,
writable: self.writable,
@@ -114,16 +114,35 @@
}
}
-fn partition_to_parcelable(partition: &Partition) -> Result<AidlPartition, Error> {
- Ok(AidlPartition {
- image: Some(open_parcel_file(&partition.path, partition.writable)?),
- writable: partition.writable,
- label: partition.label.to_owned(),
- })
+/// A partition to be assembled into a composite image.
+#[derive(Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
+pub struct Partition {
+ /// A label for the partition.
+ pub label: String,
+ /// The filename of the partition image.
+ #[serde(default)]
+ pub paths: Vec<PathBuf>,
+ /// Whether the partition should be writable.
+ #[serde(default)]
+ pub writable: bool,
+}
+
+impl Partition {
+ fn to_parcelable(&self) -> Result<AidlPartition> {
+ if self.paths.is_empty() {
+ bail!("Partition {} contains no paths", &self.label);
+ }
+ let images = self
+ .paths
+ .iter()
+ .map(|path| open_parcel_file(&path, self.writable))
+ .collect::<Result<Vec<_>, _>>()?;
+ Ok(AidlPartition { images, writable: self.writable, label: self.label.to_owned() })
+ }
}
/// Try to open the given file and wrap it in a [`ParcelFileDescriptor`].
-fn open_parcel_file(filename: &Path, writable: bool) -> Result<ParcelFileDescriptor, Error> {
+fn open_parcel_file(filename: &Path, writable: bool) -> Result<ParcelFileDescriptor> {
Ok(ParcelFileDescriptor::new(
OpenOptions::new()
.read(true)
@@ -137,6 +156,6 @@
fn maybe_open_parcel_file(
filename: &Option<PathBuf>,
writable: bool,
-) -> Result<Option<ParcelFileDescriptor>, Error> {
+) -> Result<Option<ParcelFileDescriptor>> {
filename.as_deref().map(|filename| open_parcel_file(filename, writable)).transpose()
}
diff --git a/zipfuse/TEST_MAPPING b/zipfuse/TEST_MAPPING
index 5b313c1..81a8aeb 100644
--- a/zipfuse/TEST_MAPPING
+++ b/zipfuse/TEST_MAPPING
@@ -1,5 +1,5 @@
{
- "postsubmit" : [
+ "presubmit" : [
{
"name" : "ZipFuseTest"
}