[rpc_binder] Create RpcServer with new_bound_socket
This cl is part of the change to replace the init-dependent binder
API ARpcServer_newInitUnixDomain with a more generic version
ARpcServer_newBoundSocket.
Test: atest microdroid_manager_test
Test: m authfs_service
Bug: 275729094
Change-Id: I6e54166f919f0033bf5357cd0e1ece4e9d54f763
diff --git a/authfs/service/Android.bp b/authfs/service/Android.bp
index de6326d..2101a36 100644
--- a/authfs/service/Android.bp
+++ b/authfs/service/Android.bp
@@ -17,6 +17,7 @@
"liblog_rust",
"libnix",
"librpcbinder_rs",
+ "librustutils",
"libshared_child",
],
prefer_rlib: true,
diff --git a/authfs/service/src/main.rs b/authfs/service/src/main.rs
index e710f07..78de07a 100644
--- a/authfs/service/src/main.rs
+++ b/authfs/service/src/main.rs
@@ -25,8 +25,10 @@
use anyhow::{bail, Result};
use log::*;
use rpcbinder::RpcServer;
+use rustutils::sockets::android_get_control_socket;
use std::ffi::OsString;
use std::fs::{create_dir, read_dir, remove_dir_all, remove_file};
+use std::os::unix::io::{FromRawFd, OwnedFd};
use std::sync::atomic::{AtomicUsize, Ordering};
use authfs_aidl_interface::aidl::com::android::virt::fs::AuthFsConfig::AuthFsConfig;
@@ -106,6 +108,25 @@
Ok(())
}
+/// Prepares a socket file descriptor for the authfs service.
+///
+/// # Safety requirement
+///
+/// The caller must ensure that this function is the only place that claims ownership
+/// of the file descriptor and it is called only once.
+unsafe fn prepare_authfs_service_socket() -> Result<OwnedFd> {
+ let raw_fd = android_get_control_socket(AUTHFS_SERVICE_SOCKET_NAME)?;
+
+ // Creating OwnedFd for stdio FDs is not safe.
+ if [libc::STDIN_FILENO, libc::STDOUT_FILENO, libc::STDERR_FILENO].contains(&raw_fd) {
+ bail!("File descriptor {raw_fd} is standard I/O descriptor");
+ }
+ // SAFETY: Initializing OwnedFd for a RawFd created by the init.
+ // We checked that the integer value corresponds to a valid FD and that the caller
+ // ensures that this is the only place to claim its ownership.
+ Ok(unsafe { OwnedFd::from_raw_fd(raw_fd) })
+}
+
fn try_main() -> Result<()> {
let debuggable = env!("TARGET_BUILD_VARIANT") != "user";
let log_level = if debuggable { log::Level::Trace } else { log::Level::Info };
@@ -115,9 +136,11 @@
clean_up_working_directory()?;
+ // SAFETY: This is the only place we take the ownership of the fd of the authfs service.
+ let socket_fd = unsafe { prepare_authfs_service_socket()? };
let service = AuthFsService::new_binder(debuggable).as_binder();
debug!("{} is starting as a rpc service.", AUTHFS_SERVICE_SOCKET_NAME);
- let server = RpcServer::new_init_unix_domain(service, AUTHFS_SERVICE_SOCKET_NAME)?;
+ let server = RpcServer::new_bound_socket(service, socket_fd)?;
info!("The RPC server '{}' is running.", AUTHFS_SERVICE_SOCKET_NAME);
server.join();
info!("The RPC server at '{}' has shut down gracefully.", AUTHFS_SERVICE_SOCKET_NAME);