binder/
system_only.rs

1/*
2 * Copyright (C) 2024 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 *      http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17use crate::binder::AsNative;
18use crate::error::{status_result, Result};
19use crate::proxy::SpIBinder;
20use crate::sys;
21
22use std::ffi::{c_void, CStr, CString};
23use std::os::raw::c_char;
24
25use libc::{sockaddr, sockaddr_un, sockaddr_vm, socklen_t};
26use std::boxed::Box;
27use std::{mem, ptr};
28
29/// Rust wrapper around ABinderRpc_Accessor objects for RPC binder service management.
30///
31/// Dropping the `Accessor` will drop the underlying object and the binder it owns.
32#[derive(Debug)]
33pub struct Accessor {
34    accessor: *mut sys::ABinderRpc_Accessor,
35}
36
37/// Socket connection info required for libbinder to connect to a service.
38#[derive(Debug, Clone, Copy, PartialEq, Eq)]
39pub enum ConnectionInfo {
40    /// For vsock connection
41    Vsock(sockaddr_vm),
42    /// For unix domain socket connection
43    Unix(sockaddr_un),
44}
45
46/// Safety: A `Accessor` is a wrapper around `ABinderRpc_Accessor` which is
47/// `Sync` and `Send`. As
48/// `ABinderRpc_Accessor` is threadsafe, this structure is too.
49/// The Fn owned the Accessor has `Sync` and `Send` properties
50unsafe impl Send for Accessor {}
51
52/// Safety: A `Accessor` is a wrapper around `ABinderRpc_Accessor` which is
53/// `Sync` and `Send`. As `ABinderRpc_Accessor` is threadsafe, this structure is too.
54/// The Fn owned the Accessor has `Sync` and `Send` properties
55unsafe impl Sync for Accessor {}
56
57impl Accessor {
58    /// Create a new accessor that will call the given callback when its
59    /// connection info is required.
60    /// The callback object and all objects it captures are owned by the Accessor
61    /// and will be deleted some time after the Accessor is Dropped. If the callback
62    /// is being called when the Accessor is Dropped, the callback will not be deleted
63    /// immediately.
64    pub fn new<F>(instance: &str, callback: F) -> Accessor
65    where
66        F: Fn(&str) -> Option<ConnectionInfo> + Send + Sync + 'static,
67    {
68        let callback: *mut c_void = Box::into_raw(Box::new(callback)) as *mut c_void;
69        let inst = CString::new(instance).unwrap();
70
71        // Safety: The function pointer is a valid connection_info callback.
72        // This call returns an owned `ABinderRpc_Accessor` pointer which
73        // must be destroyed via `ABinderRpc_Accessor_delete` when no longer
74        // needed.
75        // When the underlying ABinderRpc_Accessor is deleted, it will call
76        // the cookie_decr_refcount callback to release its strong ref.
77        let accessor = unsafe {
78            sys::ABinderRpc_Accessor_new(
79                inst.as_ptr(),
80                Some(Self::connection_info::<F>),
81                callback,
82                Some(Self::cookie_decr_refcount::<F>),
83            )
84        };
85
86        Accessor { accessor }
87    }
88
89    /// Creates a new Accessor instance based on an existing Accessor's binder.
90    /// This is useful when the Accessor instance is hosted in another process
91    /// that has the permissions to create the socket connection FD.
92    ///
93    /// The `instance` argument must match the instance that the original Accessor
94    /// is responsible for.
95    /// `instance` must not contain null bytes and is used to create a CString to
96    /// pass through FFI.
97    /// The `binder` argument must be a valid binder from an Accessor
98    pub fn from_binder(instance: &str, binder: SpIBinder) -> Option<Accessor> {
99        let inst = CString::new(instance).unwrap();
100
101        // Safety: All `SpIBinder` objects (the `binder` argument) hold a valid pointer
102        // to an `AIBinder` that is guaranteed to remain valid for the lifetime of the
103        // SpIBinder. `ABinderRpc_Accessor_fromBinder` creates a new pointer to that binder
104        // that it is responsible for.
105        // The `inst` argument is a new CString that will copied by
106        // `ABinderRpc_Accessor_fromBinder` and not modified.
107        let accessor =
108            unsafe { sys::ABinderRpc_Accessor_fromBinder(inst.as_ptr(), binder.as_raw()) };
109        if accessor.is_null() {
110            return None;
111        }
112        Some(Accessor { accessor })
113    }
114
115    /// Get the underlying binder for this Accessor for when it needs to be either
116    /// registered with service manager or sent to another process.
117    pub fn as_binder(&self) -> Option<SpIBinder> {
118        // Safety: `ABinderRpc_Accessor_asBinder` returns either a null pointer or a
119        // valid pointer to an owned `AIBinder`. Either of these values is safe to
120        // pass to `SpIBinder::from_raw`.
121        unsafe { SpIBinder::from_raw(sys::ABinderRpc_Accessor_asBinder(self.accessor)) }
122    }
123
124    /// Release the underlying ABinderRpc_Accessor pointer for use with the ndk API
125    /// This gives up ownership of the ABinderRpc_Accessor and it is the responsibility of
126    /// the caller to delete it with ABinderRpc_Accessor_delete
127    ///
128    /// # Safety
129    ///
130    /// - The returned `ABinderRpc_Accessor` pointer is now owned by the caller, who must
131    ///   call `ABinderRpc_Accessor_delete` to delete the object.
132    /// - This `Accessor` object is now useless after `release` so it can be dropped.
133    unsafe fn release(mut self) -> *mut sys::ABinderRpc_Accessor {
134        if self.accessor.is_null() {
135            log::error!("Attempting to release an Accessor that was already released");
136            return ptr::null_mut();
137        }
138        let ptr = self.accessor;
139        self.accessor = ptr::null_mut();
140        ptr
141    }
142
143    /// Callback invoked from C++ when the connection info is needed.
144    ///
145    /// # Safety
146    ///
147    /// - The `instance` parameter must be a non-null pointer to a valid C string for
148    ///   CStr::from_ptr. The memory must contain a valid null terminator at the end of
149    ///   the string within isize::MAX from the pointer. The memory must not be mutated for
150    ///   the duration of this function  call and must be valid for reads from the pointer
151    ///   to the null terminator.
152    /// - The `cookie` parameter must be the cookie for a `Box<F>` and
153    ///   the caller must hold a ref-count to it.
154    unsafe extern "C" fn connection_info<F>(
155        instance: *const c_char,
156        cookie: *mut c_void,
157    ) -> *mut binder_ndk_sys::ABinderRpc_ConnectionInfo
158    where
159        F: Fn(&str) -> Option<ConnectionInfo> + Send + Sync + 'static,
160    {
161        if cookie.is_null() || instance.is_null() {
162            log::error!("Cookie({cookie:p}) or instance({instance:p}) is null!");
163            return ptr::null_mut();
164        }
165        // Safety: The caller promises that `cookie` is for a Box<F>.
166        let callback = unsafe { (cookie as *const F).as_ref().unwrap() };
167
168        // Safety: The caller in libbinder_ndk will have already verified this is a valid
169        // C string
170        let inst = unsafe {
171            match CStr::from_ptr(instance).to_str() {
172                Ok(s) => s,
173                Err(err) => {
174                    log::error!("Failed to get a valid C string! {err:?}");
175                    return ptr::null_mut();
176                }
177            }
178        };
179
180        let connection = match callback(inst) {
181            Some(con) => con,
182            None => {
183                return ptr::null_mut();
184            }
185        };
186
187        match connection {
188            ConnectionInfo::Vsock(addr) => {
189                // Safety: The sockaddr is being copied in the NDK API
190                unsafe {
191                    sys::ABinderRpc_ConnectionInfo_new(
192                        &addr as *const sockaddr_vm as *const sockaddr,
193                        mem::size_of::<sockaddr_vm>() as socklen_t,
194                    )
195                }
196            }
197            ConnectionInfo::Unix(addr) => {
198                // Safety: The sockaddr is being copied in the NDK API
199                // The cast is from sockaddr_un* to sockaddr*.
200                unsafe {
201                    sys::ABinderRpc_ConnectionInfo_new(
202                        &addr as *const sockaddr_un as *const sockaddr,
203                        mem::size_of::<sockaddr_un>() as socklen_t,
204                    )
205                }
206            }
207        }
208    }
209
210    /// Callback that drops the `Box<F>`.
211    /// This is invoked from C++ when a binder is unlinked.
212    ///
213    /// # Safety
214    ///
215    /// - The `cookie` parameter must be the cookie for a `Box<F>` and
216    ///   the owner must give up a ref-count to it.
217    unsafe extern "C" fn cookie_decr_refcount<F>(cookie: *mut c_void)
218    where
219        F: Fn(&str) -> Option<ConnectionInfo> + Send + Sync + 'static,
220    {
221        // Safety: The caller promises that `cookie` is for a Box<F>.
222        unsafe { std::mem::drop(Box::from_raw(cookie as *mut F)) };
223    }
224}
225
226impl Drop for Accessor {
227    fn drop(&mut self) {
228        if self.accessor.is_null() {
229            // This Accessor was already released.
230            return;
231        }
232        // Safety: `self.accessor` is always a valid, owned
233        // `ABinderRpc_Accessor` pointer returned by
234        // `ABinderRpc_Accessor_new` when `self` was created. This delete
235        // method can only be called once when `self` is dropped.
236        unsafe {
237            sys::ABinderRpc_Accessor_delete(self.accessor);
238        }
239    }
240}
241
242/// Register a new service with the default service manager.
243///
244/// Registers the given binder object with the given identifier. If successful,
245/// this service can then be retrieved using that identifier.
246///
247/// This function will panic if the identifier contains a 0 byte (NUL).
248pub fn delegate_accessor(name: &str, mut binder: SpIBinder) -> Result<SpIBinder> {
249    let instance = CString::new(name).unwrap();
250    let mut delegator = ptr::null_mut();
251    let status =
252    // Safety: `AServiceManager_addService` expects valid `AIBinder` and C
253    // string pointers. Caller retains ownership of both pointers.
254    // `AServiceManager_addService` creates a new strong reference and copies
255    // the string, so both pointers need only be valid until the call returns.
256        unsafe { sys::ABinderRpc_Accessor_delegateAccessor(instance.as_ptr(),
257            binder.as_native_mut(), &mut delegator) };
258
259    status_result(status)?;
260
261    // Safety: `delegator` is either null or a valid, owned pointer at this
262    // point, so can be safely passed to `SpIBinder::from_raw`.
263    Ok(unsafe { SpIBinder::from_raw(delegator).expect("Expected valid binder at this point") })
264}
265
266/// Rust wrapper around ABinderRpc_AccessorProvider objects for RPC binder service management.
267///
268/// Dropping the `AccessorProvider` will drop/unregister the underlying object.
269#[derive(Debug)]
270pub struct AccessorProvider {
271    accessor_provider: *mut sys::ABinderRpc_AccessorProvider,
272}
273
274/// Safety: A `AccessorProvider` is a wrapper around `ABinderRpc_AccessorProvider` which is
275/// `Sync` and `Send`. As
276/// `ABinderRpc_AccessorProvider` is threadsafe, this structure is too.
277/// The Fn owned the AccessorProvider has `Sync` and `Send` properties
278unsafe impl Send for AccessorProvider {}
279
280/// Safety: A `AccessorProvider` is a wrapper around `ABinderRpc_AccessorProvider` which is
281/// `Sync` and `Send`. As `ABinderRpc_AccessorProvider` is threadsafe, this structure is too.
282/// The Fn owned the AccessorProvider has `Sync` and `Send` properties
283unsafe impl Sync for AccessorProvider {}
284
285impl AccessorProvider {
286    /// Create a new `AccessorProvider` that will give libbinder `Accessors` in order to
287    /// connect to binder services over sockets.
288    ///
289    /// `instances` is a list of all instances that this `AccessorProvider` is responsible for.
290    /// It is declaring these instances as available to this process and will return
291    /// `Accessor` objects for them when libbinder calls the `provider` callback.
292    /// `provider` is the callback that libbinder will call when a service is being requested.
293    /// The callback takes a `&str` argument representing the service that is being requested.
294    /// See the `ABinderRpc_AccessorProvider_getAccessorCallback` for the C++ equivalent.
295    pub fn new<F>(instances: &[String], provider: F) -> Option<AccessorProvider>
296    where
297        F: Fn(&str) -> Option<Accessor> + Send + Sync + 'static,
298    {
299        let callback: *mut c_void = Box::into_raw(Box::new(provider)) as *mut c_void;
300        let c_str_instances: Vec<CString> =
301            instances.iter().map(|s| CString::new(s.as_bytes()).unwrap()).collect();
302        let mut c_instances: Vec<*const c_char> =
303            c_str_instances.iter().map(|s| s.as_ptr()).collect();
304        let num_instances: usize = c_instances.len();
305        // Safety:
306        // - The function pointer for the first argument is a valid `get_accessor` callback.
307        // - This call returns an owned `ABinderRpc_AccessorProvider` pointer which
308        //   must be destroyed via `ABinderRpc_unregisterAccessorProvider` when no longer
309        //   needed.
310        // - When the underlying ABinderRpc_AccessorProvider is deleted, it will call
311        //   the `cookie_decr_refcount` callback on the `callback` pointer to release its
312        //   strong ref.
313        // - The `c_instances` vector is not modified by the function
314        let accessor_provider = unsafe {
315            sys::ABinderRpc_registerAccessorProvider(
316                Some(Self::get_accessor::<F>),
317                c_instances.as_mut_ptr(),
318                num_instances,
319                callback,
320                Some(Self::accessor_cookie_decr_refcount::<F>),
321            )
322        };
323
324        if accessor_provider.is_null() {
325            return None;
326        }
327        Some(AccessorProvider { accessor_provider })
328    }
329
330    /// Callback invoked from C++ when an Accessor is needed.
331    ///
332    /// # Safety
333    ///
334    /// - libbinder guarantees the `instance` argument is a valid C string if it's not null.
335    /// - The `cookie` pointer is same pointer that we pass to ABinderRpc_registerAccessorProvider
336    ///   in AccessorProvider.new() which is the closure that we will delete with
337    ///   self.accessor_cookie_decr_refcount when unregistering the AccessorProvider.
338    unsafe extern "C" fn get_accessor<F>(
339        instance: *const c_char,
340        cookie: *mut c_void,
341    ) -> *mut binder_ndk_sys::ABinderRpc_Accessor
342    where
343        F: Fn(&str) -> Option<Accessor> + Send + Sync + 'static,
344    {
345        if cookie.is_null() || instance.is_null() {
346            log::error!("Cookie({cookie:p}) or instance({instance:p}) is null!");
347            return ptr::null_mut();
348        }
349        // Safety: The caller promises that `cookie` is for a Box<F>.
350        let callback = unsafe { (cookie as *const F).as_ref().unwrap() };
351
352        let inst = {
353            // Safety: The caller in libbinder_ndk will have already verified this is a valid
354            // C string
355            match unsafe { CStr::from_ptr(instance) }.to_str() {
356                Ok(s) => s,
357                Err(err) => {
358                    log::error!("Failed to get a valid C string! {err:?}");
359                    return ptr::null_mut();
360                }
361            }
362        };
363
364        match callback(inst) {
365            Some(a) => {
366                // Safety: This is giving up ownership of this ABinderRpc_Accessor
367                // to the caller of this function (libbinder) and it is responsible
368                // for deleting it.
369                unsafe { a.release() }
370            }
371            None => ptr::null_mut(),
372        }
373    }
374
375    /// Callback that decrements the ref-count.
376    /// This is invoked from C++ when the provider is unregistered.
377    ///
378    /// # Safety
379    ///
380    /// - The `cookie` parameter must be the cookie for a `Box<F>` and
381    ///   the owner must give up a ref-count to it.
382    unsafe extern "C" fn accessor_cookie_decr_refcount<F>(cookie: *mut c_void)
383    where
384        F: Fn(&str) -> Option<Accessor> + Send + Sync + 'static,
385    {
386        // Safety: The caller promises that `cookie` is for a Box<F>.
387        unsafe { std::mem::drop(Box::from_raw(cookie as *mut F)) };
388    }
389}
390
391impl Drop for AccessorProvider {
392    fn drop(&mut self) {
393        // Safety: `self.accessor_provider` is always a valid, owned
394        // `ABinderRpc_AccessorProvider` pointer returned by
395        // `ABinderRpc_registerAccessorProvider` when `self` was created. This delete
396        // method can only be called once when `self` is dropped.
397        unsafe {
398            sys::ABinderRpc_unregisterAccessorProvider(self.accessor_provider);
399        }
400    }
401}