authfs: Support RPC binder
This change adds a new flag --rpc-binder to authfs, and --cid to
fd_server. The flag allows both to communicate through vsock. The
capability of local binder is kept for now (and still the default),
but can be removed later.
The change relies on the newly introduced libbinder_rpc_unstable.so
and the corresponding bindgen, in order to access the unstable API from
Rust.
Also, add authfs and libbinder_rpc_unstable to microdroid.
Bug: 190547489
Bug: 189947807
Test: [Android shell] sh -c 'exec 9<>/data/local/tmp/output \
/apex/com.android.virt/bin/fd_server --rw-fds 9 --rpc-binder'
[VM shell] /apex/com.android.virt/bin/authfs \
/data/local/tmp --cid 2 --remote-new-rw-file 9:9
[VM shell 2] ps -A > /data/local/tmp/9
[Android shell] cat /data/local/tmp/output # see correct data
Change-Id: I200f746aa4078508a0f0d2498a1525bb898a6e3b
diff --git a/authfs/fd_server/src/main.rs b/authfs/fd_server/src/main.rs
index 204d1b1..5137a2e 100644
--- a/authfs/fd_server/src/main.rs
+++ b/authfs/fd_server/src/main.rs
@@ -37,6 +37,7 @@
use std::os::unix::io::{AsRawFd, FromRawFd};
use anyhow::{bail, Context, Result};
+use binder::unstable_api::AsNative;
use log::{debug, error};
use authfs_aidl_interface::aidl::com::android::virt::fs::IVirtFdService::{
@@ -48,6 +49,7 @@
};
const SERVICE_NAME: &str = "authfs_fd_server";
+const RPC_SERVICE_PORT: u32 = 3264; // TODO: support dynamic port for multiple fd_server instances
fn new_binder_exception<T: AsRef<str>>(exception: ExceptionCode, message: T) -> Status {
Status::new_exception(exception, CString::new(message.as_ref()).as_deref().ok())
@@ -275,7 +277,7 @@
Ok((fd, FdConfig::ReadWrite(file)))
}
-fn parse_args() -> Result<BTreeMap<i32, FdConfig>> {
+fn parse_args() -> Result<(bool, BTreeMap<i32, FdConfig>)> {
#[rustfmt::skip]
let matches = clap::App::new("fd_server")
.arg(clap::Arg::with_name("ro-fds")
@@ -286,6 +288,8 @@
.long("rw-fds")
.multiple(true)
.number_of_values(1))
+ .arg(clap::Arg::with_name("rpc-binder")
+ .long("rpc-binder"))
.get_matches();
let mut fd_pool = BTreeMap::new();
@@ -301,7 +305,9 @@
fd_pool.insert(fd, config);
}
}
- Ok(fd_pool)
+
+ let rpc_binder = matches.is_present("rpc-binder");
+ Ok((rpc_binder, fd_pool))
}
fn main() -> Result<()> {
@@ -309,14 +315,32 @@
android_logger::Config::default().with_tag("fd_server").with_min_level(log::Level::Debug),
);
- let fd_pool = parse_args()?;
+ let (rpc_binder, fd_pool) = parse_args()?;
- ProcessState::start_thread_pool();
-
- add_service(SERVICE_NAME, FdService::new_binder(fd_pool).as_binder())
- .with_context(|| format!("Failed to register service {}", SERVICE_NAME))?;
- debug!("fd_server is running.");
-
- ProcessState::join_thread_pool();
- bail!("Unexpected exit after join_thread_pool")
+ if rpc_binder {
+ let mut service = FdService::new_binder(fd_pool).as_binder();
+ debug!("fd_server is starting as a rpc service.");
+ // SAFETY: Service ownership is transferring to the server and won't be valid afterward.
+ // Plus the binder objects are threadsafe.
+ let retval = unsafe {
+ binder_rpc_unstable_bindgen::RunRpcServer(
+ service.as_native_mut() as *mut binder_rpc_unstable_bindgen::AIBinder,
+ RPC_SERVICE_PORT,
+ )
+ };
+ if retval {
+ debug!("RPC server has shut down gracefully");
+ Ok(())
+ } else {
+ bail!("Premature termination of RPC server");
+ }
+ } else {
+ ProcessState::start_thread_pool();
+ let service = FdService::new_binder(fd_pool).as_binder();
+ add_service(SERVICE_NAME, service)
+ .with_context(|| format!("Failed to register service {}", SERVICE_NAME))?;
+ debug!("fd_server is running as a local service.");
+ ProcessState::join_thread_pool();
+ bail!("Unexpected exit after join_thread_pool")
+ }
}