Merge "Don't wait for onDied"
diff --git a/authfs/aidl/com/android/virt/fs/IVirtFdService.aidl b/authfs/aidl/com/android/virt/fs/IVirtFdService.aidl
index a565a6f..d8f481a 100644
--- a/authfs/aidl/com/android/virt/fs/IVirtFdService.aidl
+++ b/authfs/aidl/com/android/virt/fs/IVirtFdService.aidl
@@ -16,21 +16,16 @@
package com.android.virt.fs;
-/** {@hide} */
+/**
+ * A service that works like a file server, where the files and directories are identified by "FD"
+ * as the unique identifier.
+ *
+ * When a binder error is returned and it is a service specific error, the error code is an errno
+ * value which is an int.
+ *
+ * {@hide}
+ */
interface IVirtFdService {
- /** Error when the requesting FD is unknown. */
- const int ERROR_UNKNOWN_FD = 1;
-
- /**
- * Error when I/O fails. This can happen when actual I/O error happens to the backing file,
- * when the given offset or size are invalid, or any problems that can fail a read/write
- * request.
- */
- const int ERROR_IO = 2;
-
- /** Error when the file is too large to handle correctly. */
- const int ERROR_FILE_TOO_LARGE = 3;
-
/** Maximum content size that the service allows the client to request. */
const int MAX_REQUESTING_DATA = 16384;
diff --git a/authfs/fd_server/src/aidl.rs b/authfs/fd_server/src/aidl.rs
index b235025..48547e7 100644
--- a/authfs/fd_server/src/aidl.rs
+++ b/authfs/fd_server/src/aidl.rs
@@ -16,6 +16,7 @@
use anyhow::Result;
use log::error;
+use nix::errno::Errno;
use std::cmp::min;
use std::collections::BTreeMap;
use std::convert::TryInto;
@@ -26,30 +27,22 @@
use crate::fsverity;
use authfs_aidl_interface::aidl::com::android::virt::fs::IVirtFdService::{
- BnVirtFdService, IVirtFdService, ERROR_FILE_TOO_LARGE, ERROR_IO, ERROR_UNKNOWN_FD,
- MAX_REQUESTING_DATA,
+ BnVirtFdService, IVirtFdService, MAX_REQUESTING_DATA,
};
use authfs_aidl_interface::binder::{
- BinderFeatures, ExceptionCode, Interface, Result as BinderResult, Status, StatusCode, Strong,
+ BinderFeatures, Interface, Result as BinderResult, Status, StatusCode, Strong,
};
-use binder_common::new_binder_exception;
+use binder_common::new_binder_service_specific_error;
fn validate_and_cast_offset(offset: i64) -> Result<u64, Status> {
- offset.try_into().map_err(|_| {
- new_binder_exception(ExceptionCode::ILLEGAL_ARGUMENT, format!("Invalid offset: {}", offset))
- })
+ offset.try_into().map_err(|_| new_errno_error(Errno::EINVAL))
}
fn validate_and_cast_size(size: i32) -> Result<usize, Status> {
if size > MAX_REQUESTING_DATA {
- Err(new_binder_exception(
- ExceptionCode::ILLEGAL_ARGUMENT,
- format!("Unexpectedly large size: {}", size),
- ))
+ Err(new_errno_error(Errno::EFBIG))
} else {
- size.try_into().map_err(|_| {
- new_binder_exception(ExceptionCode::ILLEGAL_ARGUMENT, format!("Invalid size: {}", size))
- })
+ size.try_into().map_err(|_| new_errno_error(Errno::EINVAL))
}
}
@@ -89,7 +82,7 @@
where
F: FnOnce(&FdConfig) -> BinderResult<R>,
{
- let fd_config = self.fd_pool.get(&id).ok_or_else(|| Status::from(ERROR_UNKNOWN_FD))?;
+ let fd_config = self.fd_pool.get(&id).ok_or_else(|| new_errno_error(Errno::EBADF))?;
handler(fd_config)
}
}
@@ -105,7 +98,7 @@
FdConfig::Readonly { file, .. } | FdConfig::ReadWrite(file) => {
read_into_buf(file, size, offset).map_err(|e| {
error!("readFile: read error: {}", e);
- Status::from(ERROR_IO)
+ new_errno_error(Errno::EIO)
})
}
})
@@ -120,14 +113,14 @@
if let Some(tree_file) = &alt_merkle_tree {
read_into_buf(tree_file, size, offset).map_err(|e| {
error!("readFsverityMerkleTree: read error: {}", e);
- Status::from(ERROR_IO)
+ new_errno_error(Errno::EIO)
})
} else {
let mut buf = vec![0; size];
let s = fsverity::read_merkle_tree(file.as_raw_fd(), offset, &mut buf)
.map_err(|e| {
error!("readFsverityMerkleTree: failed to retrieve merkle tree: {}", e);
- Status::from(e.raw_os_error().unwrap_or(ERROR_IO))
+ new_errno_error(Errno::EIO)
})?;
debug_assert!(s <= buf.len(), "Shouldn't return more bytes than asked");
buf.truncate(s);
@@ -138,7 +131,7 @@
// For a writable file, Merkle tree is not expected to be served since Auth FS
// doesn't trust it anyway. Auth FS may keep the Merkle tree privately for its own
// use.
- Err(new_binder_exception(ExceptionCode::UNSUPPORTED_OPERATION, "Unsupported"))
+ Err(new_errno_error(Errno::ENOSYS))
}
})
}
@@ -152,13 +145,13 @@
let offset = 0;
read_into_buf(sig_file, size, offset).map_err(|e| {
error!("readFsveritySignature: read error: {}", e);
- Status::from(ERROR_IO)
+ new_errno_error(Errno::EIO)
})
} else {
let mut buf = vec![0; MAX_REQUESTING_DATA as usize];
let s = fsverity::read_signature(file.as_raw_fd(), &mut buf).map_err(|e| {
error!("readFsverityMerkleTree: failed to retrieve merkle tree: {}", e);
- Status::from(e.raw_os_error().unwrap_or(ERROR_IO))
+ new_errno_error(Errno::EIO)
})?;
debug_assert!(s <= buf.len(), "Shouldn't return more bytes than asked");
buf.truncate(s);
@@ -167,7 +160,7 @@
}
FdConfig::ReadWrite(_file) => {
// There is no signature for a writable file.
- Err(new_binder_exception(ExceptionCode::UNSUPPORTED_OPERATION, "Unsupported"))
+ Err(new_errno_error(Errno::ENOSYS))
}
})
}
@@ -176,19 +169,14 @@
self.handle_fd(id, |config| match config {
FdConfig::Readonly { .. } => Err(StatusCode::INVALID_OPERATION.into()),
FdConfig::ReadWrite(file) => {
- let offset: u64 = offset.try_into().map_err(|_| {
- new_binder_exception(ExceptionCode::ILLEGAL_ARGUMENT, "Invalid offset")
- })?;
+ let offset: u64 = offset.try_into().map_err(|_| new_errno_error(Errno::EINVAL))?;
// Check buffer size just to make `as i32` safe below.
if buf.len() > i32::MAX as usize {
- return Err(new_binder_exception(
- ExceptionCode::ILLEGAL_ARGUMENT,
- "Buffer size is too big",
- ));
+ return Err(new_errno_error(Errno::EOVERFLOW));
}
Ok(file.write_at(buf, offset).map_err(|e| {
error!("writeFile: write error: {}", e);
- Status::from(ERROR_IO)
+ new_errno_error(Errno::EIO)
})? as i32)
}
})
@@ -199,14 +187,11 @@
FdConfig::Readonly { .. } => Err(StatusCode::INVALID_OPERATION.into()),
FdConfig::ReadWrite(file) => {
if size < 0 {
- return Err(new_binder_exception(
- ExceptionCode::ILLEGAL_ARGUMENT,
- "Invalid size to resize to",
- ));
+ return Err(new_errno_error(Errno::EINVAL));
}
file.set_len(size as u64).map_err(|e| {
error!("resize: set_len error: {}", e);
- Status::from(ERROR_IO)
+ new_errno_error(Errno::EIO)
})
}
})
@@ -219,19 +204,19 @@
.metadata()
.map_err(|e| {
error!("getFileSize error: {}", e);
- Status::from(ERROR_IO)
+ new_errno_error(Errno::EIO)
})?
.len();
Ok(size.try_into().map_err(|e| {
error!("getFileSize: File too large: {}", e);
- Status::from(ERROR_FILE_TOO_LARGE)
+ new_errno_error(Errno::EFBIG)
})?)
}
FdConfig::ReadWrite(_file) => {
// Content and metadata of a writable file needs to be tracked by authfs, since
// fd_server isn't considered trusted. So there is no point to support getFileSize
// for a writable file.
- Err(new_binder_exception(ExceptionCode::UNSUPPORTED_OPERATION, "Unsupported"))
+ Err(new_errno_error(Errno::ENOSYS))
}
})
}
@@ -244,3 +229,7 @@
file.read_exact_at(&mut buf, offset)?;
Ok(buf)
}
+
+fn new_errno_error(errno: Errno) -> Status {
+ new_binder_service_specific_error(errno as i32, errno.desc())
+}
diff --git a/authfs/tests/Android.bp b/authfs/tests/Android.bp
index 88c1ba6..92fa428 100644
--- a/authfs/tests/Android.bp
+++ b/authfs/tests/Android.bp
@@ -14,7 +14,7 @@
"VirtualizationTestHelper",
],
test_suites: ["general-tests"],
- target_required: ["open_then_run"],
+ target_required: ["open_then_run_module"],
data: [
":authfs_test_files",
":MicrodroidTestApp.signed",
@@ -22,7 +22,16 @@
}
rust_test {
- name: "open_then_run",
+ // PushFilePreparer can sometimes push the directory (if named "open_then_run", which contains
+ // the actual executable in a per-architecture sub-directory) instead of the executable. This
+ // makes it harder to use because the host Java test have to detect the executable path
+ // dynamically, e.g. if it's a directory, append the device's architecture to build the actual
+ // executable path. By simply renaming the module (thus the host directory), this forces
+ // PushFilePreparer to always push the executable to the destination, so that the Java test can
+ // easily locate the executable with a constant path.
+ name: "open_then_run_module",
+ stem: "open_then_run",
+
crate_name: "open_then_run",
srcs: ["open_then_run.rs"],
edition: "2018",
diff --git a/authfs/tests/java/src/com/android/fs/AuthFsHostTest.java b/authfs/tests/java/src/com/android/fs/AuthFsHostTest.java
index 7229dde..3ed8748 100644
--- a/authfs/tests/java/src/com/android/fs/AuthFsHostTest.java
+++ b/authfs/tests/java/src/com/android/fs/AuthFsHostTest.java
@@ -57,6 +57,9 @@
/** Mount point of authfs on Microdroid during the test */
private static final String MOUNT_DIR = "/data/local/tmp";
+ /** Path to open_then_run on Android */
+ private static final String OPEN_THEN_RUN_BIN = TEST_DIR + "/open_then_run";
+
/** Path to fd_server on Android */
private static final String FD_SERVER_BIN = "/apex/com.android.virt/bin/fd_server";
@@ -374,18 +377,13 @@
}
}
- private String getOpenThenRunPath() {
- // Construct path to match PushFilePreparer's upload path.
- return TEST_DIR + "/open_then_run/" + mArch + "/open_then_run";
- }
-
private void runFdServerOnAndroid(String helperFlags, String fdServerFlags)
throws DeviceNotAvailableException {
String cmd =
"cd "
+ TEST_DIR
+ " && "
- + getOpenThenRunPath()
+ + OPEN_THEN_RUN_BIN
+ " "
+ helperFlags
+ " -- "
diff --git a/microdroid/bootconfig.x86_64 b/microdroid/bootconfig.x86_64
index 2977ee3..6076889 100644
--- a/microdroid/bootconfig.x86_64
+++ b/microdroid/bootconfig.x86_64
@@ -1 +1 @@
-androidboot.boot_devices = pci0000:00/0000:00:03.0,pci0000:00/0000:00:04.0,pci0000:00/0000:00:05.0
+androidboot.boot_devices = pci0000:00/0000:00:04.0,pci0000:00/0000:00:05.0,pci0000:00/0000:00:06.0
diff --git a/microdroid/init.rc b/microdroid/init.rc
index ad551cc..664402f 100644
--- a/microdroid/init.rc
+++ b/microdroid/init.rc
@@ -195,7 +195,7 @@
seclabel u:r:shell:s0
setenv HOSTNAME console
-service seriallogging /system/bin/logcat -b all -v threadtime -f /dev/hvc1 *:V
+service seriallogging /system/bin/logcat -b all -v threadtime -f /dev/hvc2 *:V
disabled
user logd
group root logd
diff --git a/microdroid/ueventd.rc b/microdroid/ueventd.rc
index 85f2f9d..037b8fc 100644
--- a/microdroid/ueventd.rc
+++ b/microdroid/ueventd.rc
@@ -26,4 +26,4 @@
/dev/tty0 0660 root system
# Virtual console for logcat
-/dev/hvc1 0660 logd logd
+/dev/hvc2 0660 logd logd
diff --git a/virtualizationservice/src/crosvm.rs b/virtualizationservice/src/crosvm.rs
index 08be052..bf1ff0c 100644
--- a/virtualizationservice/src/crosvm.rs
+++ b/virtualizationservice/src/crosvm.rs
@@ -251,8 +251,9 @@
// Setup the serial devices.
// 1. uart device: used as the output device by bootloaders and as early console by linux
- // 2. virtio-console device: used as the console device
- // 3. virtio-console device: used as the logcat output
+ // 2. virtio-console device: used as the console device where kmsg is redirected to
+ // 3. virtio-console device: used as the androidboot.console device (not used currently)
+ // 4. virtio-console device: used as the logcat output
//
// When [console|log]_fd is not specified, the devices are attached to sink, which means what's
// written there is discarded.
@@ -273,8 +274,10 @@
command.arg(format!("--serial={},hardware=serial", &console_arg));
// /dev/hvc0
command.arg(format!("--serial={},hardware=virtio-console,num=1", &console_arg));
- // /dev/hvc1
- command.arg(format!("--serial={},hardware=virtio-console,num=2", &log_arg));
+ // /dev/hvc1 (not used currently)
+ command.arg("--serial=type=sink,hardware=virtio-console,num=2");
+ // /dev/hvc2
+ command.arg(format!("--serial={},hardware=virtio-console,num=3", &log_arg));
if let Some(bootloader) = &config.bootloader {
command.arg("--bios").arg(add_preserved_fd(&mut preserved_fds, bootloader));