Expose binder security context to rust binder services

This patch exposes AIBinder_setRequestingSid and AIBinder_getCallingSid
to binder services written in Rust. This is required by services to
effectively enforce SEPolicy because relying only on the caller's PID is
racy.

Bug: 165070170
Test: atest rustBinderTest
Change-Id: Iae25d4fedded7d133354ba4c82527f33e5d5e1ce
diff --git a/libs/binder/rust/src/binder.rs b/libs/binder/rust/src/binder.rs
index d55eafe..d8e0609 100644
--- a/libs/binder/rust/src/binder.rs
+++ b/libs/binder/rust/src/binder.rs
@@ -98,6 +98,9 @@
     /// Send a ping transaction to this object
     fn ping_binder(&mut self) -> Result<()>;
 
+    /// Indicate that the service intends to receive caller security contexts.
+    fn set_requesting_sid(&mut self, enable: bool);
+
     /// Dump this object to the given file handle
     fn dump<F: AsRawFd>(&mut self, fp: &F, args: &[&str]) -> Result<()>;
 
diff --git a/libs/binder/rust/src/proxy.rs b/libs/binder/rust/src/proxy.rs
index 13e5619..fde8b68 100644
--- a/libs/binder/rust/src/proxy.rs
+++ b/libs/binder/rust/src/proxy.rs
@@ -242,6 +242,12 @@
         status_result(status)
     }
 
+    fn set_requesting_sid(&mut self, enable: bool) {
+        unsafe {
+            sys::AIBinder_setRequestingSid(self.as_native_mut(), enable)
+        };
+    }
+
     fn dump<F: AsRawFd>(&mut self, fp: &F, args: &[&str]) -> Result<()> {
         let args: Vec<_> = args.iter().map(|a| CString::new(*a).unwrap()).collect();
         let mut arg_ptrs: Vec<_> = args.iter().map(|a| a.as_ptr()).collect();
diff --git a/libs/binder/rust/src/state.rs b/libs/binder/rust/src/state.rs
index 992f074..0e05f10 100644
--- a/libs/binder/rust/src/state.rs
+++ b/libs/binder/rust/src/state.rs
@@ -98,4 +98,36 @@
             sys::AIBinder_getCallingPid()
         }
     }
+
+    /// This function makes the client's security context available to the
+    /// service calling this function. This can be used for access control.
+    /// It does not suffer from the TOCTOU issues of get_calling_pid.
+    ///
+    /// Implementations of `check_permission` should use the given CStr
+    /// argument as context for selinux permission checks. If `None` is
+    /// given, the implementation should fall back to using the PID
+    /// instead.
+    ///
+    /// Note: `None` may be passed to the callback if the caller did not
+    /// `set_requesting_sid` on the serviced binder, or if the underlying
+    /// kernel is too old to support this feature.
+    pub fn with_calling_sid<T, F>(check_permission: F) -> T
+    where
+        for<'a> F: FnOnce(Option<&'a std::ffi::CStr>) -> T {
+        // Safety: AIBinder_getCallingSid returns a c-string pointer
+        // that is valid for a transaction. Also, the string returned
+        // is thread local. By restricting the lifetime of the CStr
+        // reference to the scope of the callback, we prevent it being
+        // used beyond the guaranteed lifetime.
+        check_permission(unsafe {
+            let sid = sys::AIBinder_getCallingSid();
+            // AIBinder_getCallingSid() returns a '\0' terminated string
+            // or NULL.
+            if sid.is_null() {
+                None
+            } else {
+                Some(std::ffi::CStr::from_ptr(sid))
+            }
+        })
+    }
 }