[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/microdroid_manager/src/main.rs b/microdroid_manager/src/main.rs
index be86247..8fa2807 100644
--- a/microdroid_manager/src/main.rs
+++ b/microdroid_manager/src/main.rs
@@ -58,6 +58,7 @@
 use std::io::{Read, Write};
 use std::os::unix::process::CommandExt;
 use std::os::unix::process::ExitStatusExt;
+use std::os::unix::io::{FromRawFd, OwnedFd};
 use std::path::Path;
 use std::process::{Child, Command, Stdio};
 use std::str;
@@ -190,23 +191,36 @@
     })
 }
 
-fn prepare_vm_payload_service_socket() -> Result<()> {
-    android_get_control_socket(VM_PAYLOAD_SERVICE_SOCKET_NAME)?;
+/// Prepares a socket file descriptor for the vm payload 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_vm_payload_service_socket() -> Result<OwnedFd> {
+    let raw_fd = android_get_control_socket(VM_PAYLOAD_SERVICE_SOCKET_NAME)?;
 
-    // TODO(b/275729094): Convert the obtained file descriptor to `OwnedFd`
-    //  and use it to set the `RpcServer`.
-    Ok(())
+    // 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 _ignored = kernlog::init();
     info!("started.");
 
+    // SAFETY: This is the only place we take the ownership of the fd of the vm payload service.
+    //
     // To ensure that the CLOEXEC flag is set on the file descriptor as early as possible,
     // it is necessary to fetch the socket corresponding to vm_payload_service at the
     // very beginning, as android_get_control_socket() sets the CLOEXEC flag on the file
     // descriptor.
-    prepare_vm_payload_service_socket()?;
+    let vm_payload_service_fd = unsafe { prepare_vm_payload_service_socket()? };
 
     load_crashkernel_if_supported().context("Failed to load crashkernel")?;
 
@@ -217,7 +231,7 @@
         .context("cannot connect to VirtualMachineService")
         .map_err(|e| MicrodroidError::FailedToConnectToVirtualizationService(e.to_string()))?;
 
-    match try_run_payload(&service) {
+    match try_run_payload(&service, vm_payload_service_fd) {
         Ok(code) => {
             if code == 0 {
                 info!("task successfully finished");
@@ -331,7 +345,10 @@
     Ok(Some(u32::from_be_bytes(log) == 1))
 }
 
-fn try_run_payload(service: &Strong<dyn IVirtualMachineService>) -> Result<i32> {
+fn try_run_payload(
+    service: &Strong<dyn IVirtualMachineService>,
+    vm_payload_service_fd: OwnedFd,
+) -> Result<i32> {
     let metadata = load_metadata().context("Failed to load payload metadata")?;
     let dice = DiceDriver::new(Path::new("/dev/open-dice0")).context("Failed to load DICE")?;
 
@@ -448,7 +465,12 @@
     // Wait until zipfuse has mounted the APKs so we can access the payload
     zipfuse.wait_until_done()?;
 
-    register_vm_payload_service(allow_restricted_apis, service.clone(), dice_artifacts)?;
+    register_vm_payload_service(
+        allow_restricted_apis,
+        service.clone(),
+        dice_artifacts,
+        vm_payload_service_fd,
+    )?;
 
     // Wait for encryptedstore to finish mounting the storage (if enabled) before setting
     // microdroid_manager.init_done. Reason is init stops uneventd after that.