Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit b4eafd35 authored by Devin Moore's avatar Devin Moore
Browse files

Add Accessor::from_binder

This allows other processes to host the Accessor object from libbinder.
This can be useful when another process has the sepolicy permissions to
create the connection.

Test: atest rustBinderTest
Bug: 358427181

Change-Id: Iedc51e2fa5b50e91438690d5d551156927a91807
parent 91088b92
Loading
Loading
Loading
Loading
+26 −0
Original line number Diff line number Diff line
@@ -91,6 +91,32 @@ impl Accessor {
        Accessor { accessor }
    }

    /// Creates a new Accessor instance based on an existing Accessor's binder.
    /// This is useful when the Accessor instance is hosted in another process
    /// that has the permissions to create the socket connection FD.
    ///
    /// The `instance` argument must match the instance that the original Accessor
    /// is responsible for.
    /// `instance` must not contain null bytes and is used to create a CString to
    /// pass through FFI.
    /// The `binder` argument must be a valid binder from an Accessor
    pub fn from_binder(instance: &str, binder: SpIBinder) -> Option<Accessor> {
        let inst = CString::new(instance).unwrap();

        // Safety: All `SpIBinder` objects (the `binder` argument) hold a valid pointer
        // to an `AIBinder` that is guaranteed to remain valid for the lifetime of the
        // SpIBinder. `ABinderRpc_Accessor_fromBinder` creates a new pointer to that binder
        // that it is responsible for.
        // The `inst` argument is a new CString that will copied by
        // `ABinderRpc_Accessor_fromBinder` and not modified.
        let accessor =
            unsafe { sys::ABinderRpc_Accessor_fromBinder(inst.as_ptr(), binder.as_raw()) };
        if accessor.is_null() {
            return None;
        }
        Some(Accessor { accessor })
    }

    /// Get the underlying binder for this Accessor for when it needs to be either
    /// registered with service manager or sent to another process.
    pub fn as_binder(&self) -> Option<SpIBinder> {
+28 −0
Original line number Diff line number Diff line
@@ -1038,6 +1038,34 @@ mod tests {
        assert!(deleted.load(Ordering::Relaxed));
    }

    #[test]
    fn test_accessor_from_accessor_binder() {
        let get_connection_info = move |_instance: &str| None;
        let accessor = Accessor::new("foo.service", get_connection_info);
        let accessor2 =
            Accessor::from_binder("foo.service", accessor.as_binder().unwrap()).unwrap();
        assert_eq!(accessor.as_binder(), accessor2.as_binder());
    }

    #[test]
    fn test_accessor_from_non_accessor_binder() {
        let service_name = "rust_test_ibinder";
        let _process = ScopedServiceProcess::new(service_name);
        let binder = binder::get_service(service_name).unwrap();
        assert!(binder.is_binder_alive());

        let accessor = Accessor::from_binder("rust_test_ibinder", binder);
        assert!(accessor.is_none());
    }

    #[test]
    fn test_accessor_from_wrong_accessor_binder() {
        let get_connection_info = move |_instance: &str| None;
        let accessor = Accessor::new("foo.service", get_connection_info);
        let accessor2 = Accessor::from_binder("NOT.foo.service", accessor.as_binder().unwrap());
        assert!(accessor2.is_none());
    }

    #[tokio::test]
    async fn reassociate_rust_binder_async() {
        let service_name = "testing_service";