Add a method for libbinder to wrap an accessor in a delegator

Libbinder is the only place with the IAccessorDelegator class so it must
be responsible for wrapping the IAccesses with an IAccessorDelegator.

This is used when the process with the permissions to connect to the
server over binder RPC is in a seperate process from the process that
wants to serve the IAccessor binder.

Test: atest vm_accessor_test binderRpcTest
Bug: 358427181

Change-Id: I0839f7d1b466ba9bfb13031596523314718d3677
diff --git a/libs/binder/Android.bp b/libs/binder/Android.bp
index 379b609..6903cb5 100644
--- a/libs/binder/Android.bp
+++ b/libs/binder/Android.bp
@@ -489,6 +489,7 @@
         "ProcessState.cpp",
         "Static.cpp",
         ":libbinder_aidl",
+        ":libbinder_accessor_aidl",
         ":libbinder_device_interface_sources",
     ],
     target: {
@@ -801,7 +802,6 @@
         "aidl/android/os/IServiceManager.aidl",
         "aidl/android/os/Service.aidl",
         "aidl/android/os/ServiceDebugInfo.aidl",
-        ":libbinder_accessor_aidl",
     ],
     path: "aidl",
 }
@@ -812,26 +812,7 @@
         "aidl/android/os/IAccessor.aidl",
     ],
     path: "aidl",
-}
-
-// TODO(b/353492849): Make this interface private to libbinder.
-aidl_interface {
-    name: "android.os.accessor",
-    srcs: [":libbinder_accessor_aidl"],
-    unstable: true,
-    backend: {
-        rust: {
-            enabled: true,
-            apex_available: [
-                "com.android.virt",
-            ],
-        },
-    },
-    visibility: [
-        ":__subpackages__",
-        "//system/tools/aidl:__subpackages__",
-        "//packages/modules/Virtualization:__subpackages__",
-    ],
+    visibility: [":__subpackages__"],
 }
 
 aidl_interface {
diff --git a/libs/binder/IServiceManager.cpp b/libs/binder/IServiceManager.cpp
index 77b80ef..32388db 100644
--- a/libs/binder/IServiceManager.cpp
+++ b/libs/binder/IServiceManager.cpp
@@ -386,7 +386,7 @@
         ALOGE("Binder is null");
         return BAD_VALUE;
     }
-    sp<IAccessor> accessor = interface_cast<IAccessor>(binder);
+    sp<IAccessor> accessor = checked_interface_cast<IAccessor>(binder);
     if (accessor == nullptr) {
         ALOGE("This binder for %s is not an IAccessor binder", String8(instance).c_str());
         return BAD_TYPE;
@@ -420,6 +420,28 @@
     return binder;
 }
 
+status_t delegateAccessor(const String16& name, const sp<IBinder>& accessor,
+                          sp<IBinder>* delegator) {
+    LOG_ALWAYS_FATAL_IF(delegator == nullptr, "delegateAccessor called with a null out param");
+    if (accessor == nullptr) {
+        ALOGW("Accessor argument to delegateAccessor is null.");
+        *delegator = nullptr;
+        return OK;
+    }
+    status_t status = validateAccessor(name, accessor);
+    if (status != OK) {
+        ALOGE("The provided accessor binder is not an IAccessor for instance %s. Status: "
+              "%s",
+              String8(name).c_str(), statusToString(status).c_str());
+        return status;
+    }
+    // validateAccessor already called checked_interface_cast and made sure this
+    // is a valid accessor object.
+    *delegator = sp<android::os::IAccessorDelegator>::make(interface_cast<IAccessor>(accessor));
+
+    return OK;
+}
+
 #if !defined(__ANDROID_VNDK__)
 // IPermissionController is not accessible to vendors
 
diff --git a/libs/binder/include/binder/IServiceManager.h b/libs/binder/include/binder/IServiceManager.h
index 2b23276..81f7cdb 100644
--- a/libs/binder/include/binder/IServiceManager.h
+++ b/libs/binder/include/binder/IServiceManager.h
@@ -291,6 +291,28 @@
  * \return OK if the binder is an IAccessor for `instance`
  */
 LIBBINDER_EXPORTED status_t validateAccessor(const String16& instance, const sp<IBinder>& binder);
+
+/**
+ * Have libbinder wrap this IAccessor binder in an IAccessorDelegator and return
+ * it.
+ *
+ * This is required only in very specific situations when the process that has
+ * permissions to connect the to RPC service's socket and create the FD for it
+ * is in a separate process from this process that wants to service the Accessor
+ * binder and the communication between these two processes is binder RPC. This
+ * is needed because the binder passed over the binder RPC connection can not be
+ * used as a kernel binder, and needs to be wrapped by a kernel binder that can
+ * then be registered with service manager.
+ *
+ * \param instance name of the Accessor.
+ * \param binder to wrap in a Delegator and register with service manager.
+ * \param outDelegator the wrapped kernel binder for IAccessorDelegator
+ *
+ * \return OK if the binder is an IAccessor for `instance` and the delegator was
+ * successfully created.
+ */
+LIBBINDER_EXPORTED status_t delegateAccessor(const String16& name, const sp<IBinder>& accessor,
+                                             sp<IBinder>* delegator);
 #endif // __TRUSTY__
 
 #ifndef __ANDROID__
diff --git a/libs/binder/ndk/binder_rpc.cpp b/libs/binder/ndk/binder_rpc.cpp
index 3c32a39..07b8c40 100644
--- a/libs/binder/ndk/binder_rpc.cpp
+++ b/libs/binder/ndk/binder_rpc.cpp
@@ -302,6 +302,28 @@
     }
 }
 
+binder_status_t ABinderRpc_Accessor_delegateAccessor(const char* instance, AIBinder* accessor,
+                                                     AIBinder** outDelegator) {
+    LOG_ALWAYS_FATAL_IF(outDelegator == nullptr, "The outDelegator argument is null");
+    if (instance == nullptr || accessor == nullptr) {
+        ALOGW("instance or accessor arguments to ABinderRpc_Accessor_delegateBinder are null");
+        *outDelegator = nullptr;
+        return STATUS_UNEXPECTED_NULL;
+    }
+    sp<IBinder> accessorBinder = accessor->getBinder();
+
+    sp<IBinder> delegator;
+    status_t status = android::delegateAccessor(String16(instance), accessorBinder, &delegator);
+    if (status != OK) {
+        return PruneStatusT(status);
+    }
+    sp<AIBinder> binder = ABpBinder::lookupOrCreateFromBinder(delegator);
+    // This AIBinder needs a strong ref to pass ownership to the caller
+    binder->incStrong(nullptr);
+    *outDelegator = binder.get();
+    return OK;
+}
+
 ABinderRpc_ConnectionInfo* ABinderRpc_ConnectionInfo_new(const sockaddr* addr, socklen_t len) {
     if (addr == nullptr || len < 0 || static_cast<size_t>(len) < sizeof(sa_family_t)) {
         ALOGE("Invalid arguments in ABinderRpc_Connection_new");
diff --git a/libs/binder/ndk/include_platform/android/binder_rpc.h b/libs/binder/ndk/include_platform/android/binder_rpc.h
index 7132554..9fe5d78 100644
--- a/libs/binder/ndk/include_platform/android/binder_rpc.h
+++ b/libs/binder/ndk/include_platform/android/binder_rpc.h
@@ -265,6 +265,35 @@
         __INTRODUCED_IN(36);
 
 /**
+ * Wrap an ABinderRpc_Accessor proxy binder with a delegator binder.
+ *
+ * The IAccessorDelegator binder delegates all calls to the proxy binder.
+ *
+ * This is required only in very specific situations when the process that has
+ * permissions to connect the to RPC service's socket and create the FD for it
+ * is in a separate process from this process that wants to serve the Accessor
+ * binder and the communication between these two processes is binder RPC. This
+ * is needed because the binder passed over the binder RPC connection can not be
+ * used as a kernel binder, and needs to be wrapped by a kernel binder that can
+ * then be registered with service manager.
+ *
+ * \param instance name of the service associated with the Accessor
+ * \param binder the AIBinder* from the ABinderRpc_Accessor from the
+ *        ABinderRpc_Accessor_asBinder. The other process across the binder RPC
+ *        connection will have called this and passed the AIBinder* across a
+ *        binder interface to the process calling this function.
+ * \param outDelegator the AIBinder* for the kernel binder that wraps the
+ *        'binder' argument and delegates all calls to it. The caller now owns
+ *        this object with one strong ref count and is responsible for removing
+ *        that ref count with with AIBinder_decStrong when the caller wishes to
+ *        drop the reference.
+ */
+binder_status_t ABinderRpc_Accessor_delegateAccessor(const char* _Nonnull instance,
+                                                     AIBinder* _Nonnull binder,
+                                                     AIBinder* _Nullable* _Nonnull outDelegator)
+        __INTRODUCED_IN(36);
+
+/**
  * Create a new ABinderRpc_ConnectionInfo with sockaddr. This can be supported socket
  * types like sockaddr_vm (vsock) and sockaddr_un (Unix Domain Sockets).
  *
diff --git a/libs/binder/ndk/libbinder_ndk.map.txt b/libs/binder/ndk/libbinder_ndk.map.txt
index c885816..4d691f8 100644
--- a/libs/binder/ndk/libbinder_ndk.map.txt
+++ b/libs/binder/ndk/libbinder_ndk.map.txt
@@ -257,6 +257,7 @@
     ABinderRpc_registerAccessorProvider; # systemapi
     ABinderRpc_unregisterAccessorProvider; # systemapi
     ABinderRpc_Accessor_new; # systemapi
+    ABinderRpc_Accessor_delegateAccessor; #systemapi
     ABinderRpc_Accessor_delete; # systemapi
     ABinderRpc_Accessor_asBinder; # systemapi
     ABinderRpc_Accessor_fromBinder; # systemapi
diff --git a/libs/binder/rust/src/lib.rs b/libs/binder/rust/src/lib.rs
index 0e8e388..f7f3f35 100644
--- a/libs/binder/rust/src/lib.rs
+++ b/libs/binder/rust/src/lib.rs
@@ -123,7 +123,7 @@
 #[cfg(not(trusty))]
 pub use state::{ProcessState, ThreadState};
 #[cfg(not(any(android_vendor, android_vndk)))]
-pub use system_only::{Accessor, ConnectionInfo};
+pub use system_only::{delegate_accessor, Accessor, ConnectionInfo};
 
 /// Binder result containing a [`Status`] on error.
 pub type Result<T> = std::result::Result<T, Status>;
diff --git a/libs/binder/rust/src/system_only.rs b/libs/binder/rust/src/system_only.rs
index a91d84d..08582ab 100644
--- a/libs/binder/rust/src/system_only.rs
+++ b/libs/binder/rust/src/system_only.rs
@@ -14,6 +14,8 @@
  * limitations under the License.
  */
 
+use crate::binder::AsNative;
+use crate::error::{status_result, Result};
 use crate::proxy::SpIBinder;
 use crate::sys;
 
@@ -185,3 +187,27 @@
         }
     }
 }
+
+/// Register a new service with the default service manager.
+///
+/// Registers the given binder object with the given identifier. If successful,
+/// this service can then be retrieved using that identifier.
+///
+/// This function will panic if the identifier contains a 0 byte (NUL).
+pub fn delegate_accessor(name: &str, mut binder: SpIBinder) -> Result<SpIBinder> {
+    let instance = CString::new(name).unwrap();
+    let mut delegator = ptr::null_mut();
+    let status =
+    // Safety: `AServiceManager_addService` expects valid `AIBinder` and C
+    // string pointers. Caller retains ownership of both pointers.
+    // `AServiceManager_addService` creates a new strong reference and copies
+    // the string, so both pointers need only be valid until the call returns.
+        unsafe { sys::ABinderRpc_Accessor_delegateAccessor(instance.as_ptr(),
+            binder.as_native_mut(), &mut delegator) };
+
+    status_result(status)?;
+
+    // Safety: `delegator` is either null or a valid, owned pointer at this
+    // point, so can be safely passed to `SpIBinder::from_raw`.
+    Ok(unsafe { SpIBinder::from_raw(delegator).expect("Expected valid binder at this point") })
+}
diff --git a/libs/binder/rust/tests/integration.rs b/libs/binder/rust/tests/integration.rs
index bdb7e4a..489fa0a 100644
--- a/libs/binder/rust/tests/integration.rs
+++ b/libs/binder/rust/tests/integration.rs
@@ -945,6 +945,43 @@
         assert!(deleted.load(Ordering::Relaxed));
     }
 
+    #[test]
+    fn test_accessor_delegator_new_each_time() {
+        let get_connection_info = move |_instance: &str| None;
+        let accessor = Accessor::new("foo.service", get_connection_info);
+        let delegator_binder =
+            binder::delegate_accessor("foo.service", accessor.as_binder().unwrap());
+        let delegator_binder2 =
+            binder::delegate_accessor("foo.service", accessor.as_binder().unwrap());
+
+        // The delegate_accessor creates new delegators each time
+        assert!(delegator_binder != delegator_binder2);
+    }
+
+    #[test]
+    fn test_accessor_delegate_the_delegator() {
+        let get_connection_info = move |_instance: &str| None;
+        let accessor = Accessor::new("foo.service", get_connection_info);
+        let delegator_binder =
+            binder::delegate_accessor("foo.service", accessor.as_binder().unwrap());
+        let delegator_binder2 =
+            binder::delegate_accessor("foo.service", delegator_binder.clone().unwrap());
+
+        assert!(delegator_binder.clone() == delegator_binder);
+        // The delegate_accessor creates new delegators each time. Even when they are delegators
+        // of delegators.
+        assert!(delegator_binder != delegator_binder2);
+    }
+
+    #[test]
+    fn test_accessor_delegator_wrong_name() {
+        let get_connection_info = move |_instance: &str| None;
+        let accessor = Accessor::new("foo.service", get_connection_info);
+        let delegator_binder =
+            binder::delegate_accessor("NOT.foo.service", accessor.as_binder().unwrap());
+        assert_eq!(delegator_binder, Err(StatusCode::NAME_NOT_FOUND));
+    }
+
     #[tokio::test]
     async fn reassociate_rust_binder_async() {
         let service_name = "testing_service";
diff --git a/libs/binder/tests/binderRpcTest.cpp b/libs/binder/tests/binderRpcTest.cpp
index 077a33a..506fc71 100644
--- a/libs/binder/tests/binderRpcTest.cpp
+++ b/libs/binder/tests/binderRpcTest.cpp
@@ -75,6 +75,8 @@
 constexpr char kTrustyIpcDevice[] = "/dev/trusty-ipc-dev0";
 #endif
 
+constexpr char kKnownAidlService[] = "activity";
+
 static std::string WaitStatusToString(int wstatus) {
     if (WIFEXITED(wstatus)) {
         return "exit status " + std::to_string(WEXITSTATUS(wstatus));
@@ -1549,22 +1551,47 @@
     EXPECT_EQ(nullptr, ABinderRpc_ConnectionInfo_new(reinterpret_cast<const sockaddr*>(&addr), 0));
 }
 
-TEST_P(BinderRpcAccessor, ARpcGetService) {
+TEST_F(BinderARpcNdk, ARpcDelegateAccessorWrongInstance) {
+    AccessorProviderData* data = new AccessorProviderData();
+    ABinderRpc_Accessor* accessor = getAccessor(kARpcInstance, data);
+    ASSERT_NE(accessor, nullptr);
+    AIBinder* localAccessorBinder = ABinderRpc_Accessor_asBinder(accessor);
+    EXPECT_NE(localAccessorBinder, nullptr);
+
+    AIBinder* delegatorBinder = nullptr;
+    binder_status_t status =
+            ABinderRpc_Accessor_delegateAccessor("bar", localAccessorBinder, &delegatorBinder);
+    EXPECT_EQ(status, NAME_NOT_FOUND);
+
+    AIBinder_decStrong(localAccessorBinder);
+    ABinderRpc_Accessor_delete(accessor);
+    delete data;
+}
+
+TEST_F(BinderARpcNdk, ARpcDelegateNonAccessor) {
+    auto service = defaultServiceManager()->checkService(String16(kKnownAidlService));
+    ASSERT_NE(nullptr, service);
+    ndk::SpAIBinder binder = ndk::SpAIBinder(AIBinder_fromPlatformBinder(service));
+
+    AIBinder* delegatorBinder = nullptr;
+    binder_status_t status =
+            ABinderRpc_Accessor_delegateAccessor("bar", binder.get(), &delegatorBinder);
+
+    EXPECT_EQ(status, BAD_TYPE);
+}
+
+inline void getServiceTest(BinderRpcTestProcessSession& proc,
+                           ABinderRpc_AccessorProvider_getAccessorCallback getAccessor) {
     constexpr size_t kNumThreads = 10;
     bool isDeleted = false;
 
-    auto proc = createRpcTestSocketServerProcess({.numThreads = kNumThreads});
-    EXPECT_EQ(OK, proc.rootBinder->pingBinder());
-
     AccessorProviderData* data =
             new AccessorProviderData{proc.proc->sessions[0].addr, proc.proc->sessions[0].addrLen,
                                      &isDeleted};
-
     ABinderRpc_AccessorProvider* provider =
             ABinderRpc_registerAccessorProvider(getAccessor, kARpcSupportedServices,
                                                 kARpcNumSupportedServices, data,
                                                 accessorProviderDataOnDelete);
-
     EXPECT_NE(provider, nullptr);
     EXPECT_FALSE(isDeleted);
 
@@ -1580,6 +1607,45 @@
     waitForExtraSessionCleanup(proc);
 }
 
+TEST_P(BinderRpcAccessor, ARpcGetService) {
+    constexpr size_t kNumThreads = 10;
+    auto proc = createRpcTestSocketServerProcess({.numThreads = kNumThreads});
+    EXPECT_EQ(OK, proc.rootBinder->pingBinder());
+
+    getServiceTest(proc, getAccessor);
+}
+
+// Create accessors and wrap each of the accessors in a delegator
+ABinderRpc_Accessor* getDelegatedAccessor(const char* instance, void* cookie) {
+    ABinderRpc_Accessor* accessor = getAccessor(instance, cookie);
+    AIBinder* accessorBinder = ABinderRpc_Accessor_asBinder(accessor);
+    // Once we have a handle to the AIBinder which holds a reference to the
+    // underlying accessor IBinder, we can get rid of the ABinderRpc_Accessor
+    ABinderRpc_Accessor_delete(accessor);
+
+    AIBinder* delegatorBinder = nullptr;
+    binder_status_t status =
+            ABinderRpc_Accessor_delegateAccessor(instance, accessorBinder, &delegatorBinder);
+    // No longer need this AIBinder. The delegator has a reference to the
+    // underlying IBinder on success, and on failure we are done here.
+    AIBinder_decStrong(accessorBinder);
+    if (status != OK || delegatorBinder == nullptr) {
+        ALOGE("Unexpected behavior. Status: %s, delegator ptr: %p", statusToString(status).c_str(),
+              delegatorBinder);
+        return nullptr;
+    }
+
+    return ABinderRpc_Accessor_fromBinder(instance, delegatorBinder);
+}
+
+TEST_P(BinderRpcAccessor, ARpcGetServiceWithDelegator) {
+    constexpr size_t kNumThreads = 10;
+    auto proc = createRpcTestSocketServerProcess({.numThreads = kNumThreads});
+    EXPECT_EQ(OK, proc.rootBinder->pingBinder());
+
+    getServiceTest(proc, getDelegatedAccessor);
+}
+
 #endif // BINDER_WITH_KERNEL_IPC
 
 #ifdef BINDER_RPC_TO_TRUSTY_TEST
@@ -1845,7 +1911,7 @@
     ASSERT_NE(nullptr, sm);
     // Any Java service with non-empty getInterfaceDescriptor() would do.
     // Let's pick activity.
-    auto binder = sm->checkService(String16("activity"));
+    auto binder = sm->checkService(String16(kKnownAidlService));
     ASSERT_NE(nullptr, binder);
     auto descriptor = binder->getInterfaceDescriptor();
     ASSERT_GE(descriptor.size(), 0u);