Take ownership of inherited FDs using the rustutils crate

Ignore-AOSP-First: the topic includes git_main-only change. Will
cherry-pick the rest.

Bug: 3259955
Test: watch TH
Flag: EXEMPT refactor
Change-Id: I316a56142401b5f9bcb8ed350280019d7ddab123
diff --git a/android/fd_server/src/main.rs b/android/fd_server/src/main.rs
index 26315bf..de7ca1d 100644
--- a/android/fd_server/src/main.rs
+++ b/android/fd_server/src/main.rs
@@ -29,9 +29,10 @@
 use log::debug;
 use nix::sys::stat::{umask, Mode};
 use rpcbinder::RpcServer;
+use rustutils::inherited_fd::take_fd_ownership;
 use std::collections::BTreeMap;
 use std::fs::File;
-use std::os::unix::io::{FromRawFd, OwnedFd};
+use std::os::unix::io::OwnedFd;
 
 use aidl::{FdConfig, FdService};
 use authfs_fsverity_metadata::parse_fsverity_metadata;
@@ -39,20 +40,6 @@
 // TODO(b/259920193): support dynamic port for multiple fd_server instances
 const RPC_SERVICE_PORT: u32 = 3264;
 
-fn is_fd_valid(fd: i32) -> bool {
-    // SAFETY: a query-only syscall
-    let retval = unsafe { libc::fcntl(fd, libc::F_GETFD) };
-    retval >= 0
-}
-
-fn fd_to_owned<T: FromRawFd>(fd: i32) -> Result<T> {
-    if !is_fd_valid(fd) {
-        bail!("Bad FD: {}", fd);
-    }
-    // SAFETY: The caller is supposed to provide valid FDs to this process.
-    Ok(unsafe { T::from_raw_fd(fd) })
-}
-
 fn parse_arg_ro_fds(arg: &str) -> Result<(i32, FdConfig)> {
     let result: Result<Vec<i32>, _> = arg.split(':').map(|x| x.parse::<i32>()).collect();
     let fds = result?;
@@ -62,13 +49,13 @@
     Ok((
         fds[0],
         FdConfig::Readonly {
-            file: fd_to_owned(fds[0])?,
+            file: take_fd_ownership(fds[0])?.into(),
             // Alternative metadata source, if provided
             alt_metadata: fds
                 .get(1)
-                .map(|fd| fd_to_owned(*fd))
+                .map(|fd| take_fd_ownership(*fd))
                 .transpose()?
-                .and_then(|f| parse_fsverity_metadata(f).ok()),
+                .and_then(|f| parse_fsverity_metadata(f.into()).ok()),
         },
     ))
 }
@@ -105,23 +92,27 @@
         fd_pool.insert(fd, config);
     }
     for fd in args.rw_fds {
-        let file = fd_to_owned::<File>(fd)?;
+        let file: File = take_fd_ownership(fd)?.into();
         if file.metadata()?.len() > 0 {
             bail!("File is expected to be empty");
         }
         fd_pool.insert(fd, FdConfig::ReadWrite(file));
     }
     for fd in args.ro_dirs {
-        fd_pool.insert(fd, FdConfig::InputDir(fd_to_owned(fd)?));
+        fd_pool.insert(fd, FdConfig::InputDir(take_fd_ownership(fd)?));
     }
     for fd in args.rw_dirs {
-        fd_pool.insert(fd, FdConfig::OutputDir(fd_to_owned(fd)?));
+        fd_pool.insert(fd, FdConfig::OutputDir(take_fd_ownership(fd)?));
     }
-    let ready_fd = args.ready_fd.map(fd_to_owned).transpose()?;
+    let ready_fd = args.ready_fd.map(take_fd_ownership).transpose()?;
     Ok((fd_pool, ready_fd))
 }
 
 fn main() -> Result<()> {
+    // SAFETY: This is very early in the process. Nobody has taken ownership of the inherited FDs
+    // yet.
+    unsafe { rustutils::inherited_fd::init_once()? };
+
     android_logger::init_once(
         android_logger::Config::default()
             .with_tag("fd_server")