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