• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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::boxed::Box;
27 use 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)]
33 pub 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)]
39 pub 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
50 unsafe 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
55 unsafe impl Sync for Accessor {}
56 
57 impl 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.
new<F>(instance: &str, callback: F) -> Accessor where F: Fn(&str) -> Option<ConnectionInfo> + Send + Sync + 'static,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
from_binder(instance: &str, binder: SpIBinder) -> Option<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.
as_binder(&self) -> Option<SpIBinder>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.
release(mut self) -> *mut sys::ABinderRpc_Accessor133     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.
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,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.
cookie_decr_refcount<F>(cookie: *mut c_void) where F: Fn(&str) -> Option<ConnectionInfo> + Send + Sync + 'static,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 
226 impl Drop for Accessor {
drop(&mut self)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).
delegate_accessor(name: &str, mut binder: SpIBinder) -> Result<SpIBinder>248 pub 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)]
270 pub 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
278 unsafe 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
283 unsafe impl Sync for AccessorProvider {}
284 
285 impl 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.
new<F>(instances: &[String], provider: F) -> Option<AccessorProvider> where F: Fn(&str) -> Option<Accessor> + Send + Sync + 'static,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.
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,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.
accessor_cookie_decr_refcount<F>(cookie: *mut c_void) where F: Fn(&str) -> Option<Accessor> + Send + Sync + 'static,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 
391 impl Drop for AccessorProvider {
drop(&mut self)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 }
402