1 /*
2  * Copyright (C) 2021 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::serialization::Serializer;
18 use crate::sys::*;
19 use crate::{Deserialize, Serialize, TipcError};
20 use core::convert::TryInto;
21 use core::ffi::CStr;
22 use core::mem::MaybeUninit;
23 use log::{error, warn};
24 use trusty_sys::{c_int, c_long};
25 
26 /// An open IPC connection or shared memory reference.
27 ///
28 /// A `Handle` can either represent an open IPC connection or a shared memory
29 /// reference. Which one a given handle represents generally must be determined
30 /// from context, i.e. the handle returned by [`Handle::connect`] will always
31 /// represent an IPC connection. A given incoming or outgoing message will
32 /// generally have specific semantics regarding what kind of handles are sent
33 /// along with it.
34 ///
35 /// # IPC Connections
36 ///
37 /// This handle knows how to send and receive messages which implement
38 /// [`Serialize`] and [`Deserialize`] respectively. Serialization and parsing
39 /// are handled by the message itself.
40 ///
41 /// The handle owns its connection, which is closed when this struct is dropped.
42 /// Do not rely on the connection being closed for protocol correctness, as the
43 /// drop method may not always be called.
44 ///
45 /// # Shared Memory References
46 ///
47 /// An incoming TIPC message may include one or more handles representing a
48 /// shared memory buffer. These can be mapped into process memory using
49 /// [`Handle::mmap`]. The returned [`UnsafeSharedBuf`] object provides access to
50 /// the shared memory buffer and will unmap the buffer automatically on drop.
51 #[repr(transparent)]
52 #[derive(Eq, PartialEq, Debug)]
53 pub struct Handle(handle_t);
54 
55 /// Maximum number of handles that can be transferred in an IPC message at once.
56 pub const MAX_MSG_HANDLES: usize = 8;
57 /// Maximum numbers of iovecs that can be sent or received over IPC at once.
58 pub const MAX_MSG_IOVECS: usize = 32;
59 /// Maximum number of segments that can be serialized by BorrowingSerializer.
60 pub const MAX_SERIALIZED_SEGMENTS: usize = 32;
61 
62 impl Handle {
63     /// Open a client connection to the given service.
64     ///
65     /// The service `port` can be either a Trusty TA or kernel port name. This
66     /// call is synchronous and will block until the specified port exists.
67     ///
68     /// # Examples
69     ///
70     /// Open a TIPC connection to `com.android.trusty.test_port`:
71     ///
72     /// ```
73     /// use core::ffi::CStr;
74     /// use tipc::Handle;
75     ///
76     /// let port = CStr::from_bytes_with_nul(b"com.android.trusty.test_port\0")
77     ///                  .unwrap();
78     ///
79     /// if let Ok(handle) = Handle::connect(port) {
80     ///     println!("Connection successful");
81     /// } else {
82     ///     println!("Connection attempt failed");
83     /// }
84     /// ```
connect(port: &CStr) -> crate::Result<Self>85     pub fn connect(port: &CStr) -> crate::Result<Self> {
86         // SAFETY: external syscall. port is guaranteed to be a well-formed,
87         // null-terminated C string.
88         let rc = unsafe { trusty_sys::connect(port.as_ptr(), IPC_CONNECT_WAIT_FOR_PORT as u32) };
89         if rc < 0 {
90             Err(TipcError::from_uapi(rc))
91         } else {
92             rc.try_into().map(Handle).or(Err(TipcError::InvalidHandle))
93         }
94     }
95 
try_clone(&self) -> crate::Result<Self>96     pub fn try_clone(&self) -> crate::Result<Self> {
97         // SAFETY: external syscall, handle descriptor is valid for the lifetime
98         // of self. Return value is either an error or a new valid handle
99         // descriptor that we can take ownership of.
100         let rc = unsafe { trusty_sys::dup(self.0) };
101         Self::from_raw(rc.try_into().or(Err(TipcError::InvalidHandle))?)
102     }
103 
104     /// Construct a Handle from a raw file descriptor
105     ///
106     /// Conditionally creates a Handle from the return value of a C FFI function.
107     /// If the integer value is < 0, then we will refuse to create the Handle.
from_raw(fd: i32) -> crate::Result<Self>108     pub fn from_raw(fd: i32) -> crate::Result<Self> {
109         if fd < 0 {
110             Err(TipcError::from_uapi(fd as c_long))
111         } else {
112             Ok(Self(fd))
113         }
114     }
115 
116     /// Send an IPC message.
117     ///
118     /// Serializes `msg` using its [`Serialize`] implementation and send it
119     /// across this IPC connection. Attempts to serialize the message in-place
120     /// without new allocations.
send<'s, T: Serialize<'s>>(&self, msg: &'s T) -> crate::Result<()>121     pub fn send<'s, T: Serialize<'s>>(&self, msg: &'s T) -> crate::Result<()> {
122         let mut serializer = BorrowingSerializer::default();
123         msg.serialize(&mut serializer)?;
124         self.send_vectored(&serializer.buffers[..], &serializer.handles[..])
125     }
126 
127     /// Receive an IPC message.
128     ///
129     /// Receives a message into the given temporary `buffer`, and deserializes
130     /// the received message into a `T` using `T::Deserialize`. If the received
131     /// message does not fit into `buffer` this method will return error value
132     /// [`TipcError::NotEnoughBuffer`]. In the case of insufficient buffer
133     /// space, the message data will be lost and must be resent to recover.
134     ///
135     /// TODO: Support a timeout for the wait.
recv<T: Deserialize>(&self, buffer: &mut [u8]) -> Result<T, T::Error>136     pub fn recv<T: Deserialize>(&self, buffer: &mut [u8]) -> Result<T, T::Error> {
137         let mut handles: [Option<Handle>; MAX_MSG_HANDLES] = Default::default();
138         let (byte_count, handle_count) = self.recv_vectored(&mut [buffer], &mut handles)?;
139 
140         T::deserialize(&buffer[..byte_count], &mut handles[..handle_count])
141     }
142 
143     /// Receive raw bytes and handles into slices of buffers and handles.
144     ///
145     /// Returns a tuple of the number of bytes written into the buffer and the
146     /// number of handles received. `handles` should have space for at least
147     /// [`MAX_MSG_HANDLES`].
recv_vectored( &self, buffers: &mut [&mut [u8]], handles: &mut [Option<Handle>], ) -> crate::Result<(usize, usize)>148     pub fn recv_vectored(
149         &self,
150         buffers: &mut [&mut [u8]],
151         handles: &mut [Option<Handle>],
152     ) -> crate::Result<(usize, usize)> {
153         let _ = self.wait(None)?;
154 
155         let mut raw_handles = [-1; MAX_MSG_HANDLES];
156 
157         let (buf_len, handles_len) = self.get_msg(|msg_info| {
158             if msg_info.len > buffers.iter().map(|b| b.len()).sum() {
159                 return Err(TipcError::NotEnoughBuffer);
160             }
161 
162             let mut iovs = arrayvec::ArrayVec::<_, MAX_MSG_IOVECS>::new();
163             assert!(buffers.len() <= MAX_MSG_IOVECS);
164             iovs.extend(buffers.iter_mut().map(|buf| trusty_sys::iovec {
165                 iov_base: buf.as_mut_ptr().cast(),
166                 iov_len: buf.len(),
167             }));
168 
169             let mut msg = trusty_sys::ipc_msg {
170                 num_iov: iovs.len().try_into()?,
171                 iov: iovs.as_mut_ptr(),
172 
173                 num_handles: raw_handles.len().try_into()?,
174                 handles: raw_handles.as_mut_ptr() as *mut i32,
175             };
176 
177             // SAFETY: syscall, pointer is initialized with valid data and
178             // mutably borrowed. The buffers that the msg refers to are valid
179             // and writable across this call. `Handle` is a transparent wrapper
180             // around `handle_t`, i.e. `i32` so we can safely cast the handles
181             // slice to an `i32` pointer. Although the syscall requires a
182             // mutable handle pointer, it does not mutate these handles, so we
183             // can safely cast the immutable slice to mutable pointer.
184             let rc = unsafe { trusty_sys::read_msg(self.as_raw_fd(), msg_info.id, 0, &mut msg) };
185 
186             if rc < 0 {
187                 Err(TipcError::from_uapi(rc))
188             } else {
189                 Ok((rc.try_into()?, msg_info.num_handles.try_into()?))
190             }
191         })?;
192 
193         // Convert the raw handles list into a list of `Option<Handle>`.
194         for (index, raw_handle) in raw_handles[..handles_len].into_iter().enumerate() {
195             handles[index] = Some(Handle(*raw_handle));
196         }
197 
198         Ok((buf_len, handles_len))
199     }
200 
201     /// Send a set of buffers and file/memref handles.
202     ///
203     /// Sends a set of buffers and set of handles at once. `buf` must fit in the
204     /// message queue and `handles` must contain no more than
205     /// [`MAX_MSG_HANDLES`].
206     ///
207     /// If the message fails to fit in the server's message queue, the send will
208     /// block and retry when the kernel indicates that the queue is unblocked.
send_vectored(&self, buffers: &[&[u8]], handles: &[Handle]) -> crate::Result<()>209     pub fn send_vectored(&self, buffers: &[&[u8]], handles: &[Handle]) -> crate::Result<()> {
210         let mut iovs = arrayvec::ArrayVec::<_, MAX_MSG_IOVECS>::new();
211         assert!(buffers.len() <= MAX_MSG_IOVECS);
212         iovs.extend(
213             buffers.iter().map(|buf| trusty_sys::iovec {
214                 iov_base: buf.as_ptr() as *mut _,
215                 iov_len: buf.len(),
216             }),
217         );
218         let total_num_bytes = buffers.iter().map(|b| b.len()).sum();
219 
220         let mut msg = trusty_sys::ipc_msg {
221             num_iov: iovs.len().try_into()?,
222             iov: iovs.as_mut_ptr(),
223 
224             num_handles: handles.len().try_into()?,
225             handles: handles.as_ptr() as *mut i32,
226         };
227         // SAFETY: syscall, pointer is initialized with valid data and mutably
228         // borrowed. The buffers that the msg refers to are valid and writable
229         // across this call. `Handle` is a transparent wrapper around
230         // `handle_t`, i.e. `i32` so we can safely cast the handles slice to an
231         // `i32` pointer. Although the syscall requires a mutable handle
232         // pointer, it does not mutate these handles, so we can safely cast the
233         // immutable slice to mutable pointer.
234         let mut rc = unsafe { trusty_sys::send_msg(self.as_raw_fd(), &mut msg) };
235 
236         // If there's not enough space in the buffer to send the message, wait until we
237         // get a `SEND_UNBLOCKED` event or another error occurs.
238         if rc == trusty_sys::Error::NotEnoughBuffer as c_long {
239             loop {
240                 let event = self.wait(None)?;
241                 if event.event & IPC_HANDLE_POLL_SEND_UNBLOCKED as u32 != 0 {
242                     break;
243                 } else if event.event & IPC_HANDLE_POLL_MSG as u32 != 0 {
244                     warn!("Received a message while waiting for send to be unblocked, abandoning send attempt");
245                     return Err(TipcError::Busy);
246                 } else if event.event & IPC_HANDLE_POLL_HUP as u32 != 0 {
247                     return Err(TipcError::ChannelClosed);
248                 } else {
249                     error!(
250                         "Unexpected event while waiting for send to be unblocked: {}",
251                         event.event,
252                     );
253                 }
254             }
255 
256             // Retry the send. It should go through this time because sending is now
257             // unblocked.
258             rc = unsafe { trusty_sys::send_msg(self.as_raw_fd(), &mut msg) };
259         }
260 
261         if rc < 0 {
262             Err(TipcError::from_uapi(rc))
263         } else if rc as usize != total_num_bytes {
264             Err(TipcError::IncompleteWrite { num_bytes_written: rc as usize })
265         } else {
266             Ok(())
267         }
268     }
269 
270     /// Get the raw file descriptor of this handle.
271     ///
272     /// Returns the raw integer OS file descriptor(fd) associated with this handle. This is
273     /// primarily useful for interacting with FFI interfaces. The programmer must ensure that any
274     /// interactions with the raw fd do not cause it to close or otherwise become invalid. This
275     /// handle must outlive all uses of the returned fd. Otherwise, the behavior is undefined.
as_raw_fd(&self) -> i32276     pub fn as_raw_fd(&self) -> i32 {
277         self.0
278     }
279 
280     /// Wait for an event on this handle for `timeout` milliseconds, or
281     /// indefinitely if `None`.
wait(&self, timeout: Option<u32>) -> crate::Result<trusty_sys::uevent>282     pub(crate) fn wait(&self, timeout: Option<u32>) -> crate::Result<trusty_sys::uevent> {
283         let timeout = timeout.unwrap_or(INFINITE_TIME);
284         let mut uevent = MaybeUninit::zeroed();
285         // SAFETY: syscall, uevent is borrowed mutably and outlives the call
286         let rc = unsafe { trusty_sys::wait(self.as_raw_fd(), uevent.as_mut_ptr(), timeout) };
287         if rc != 0 {
288             Err(TipcError::from_uapi(rc))
289         } else {
290             // SAFETY: If the wait call succeeded, the uevent structure has been
291             // fully initialized.
292             let uevent = unsafe { uevent.assume_init() };
293             Ok(uevent)
294         }
295     }
296 
297     /// Receive an IPC message.
298     ///
299     /// The `func` callback must call `trusty_sys::read_msg()` with the provided
300     /// message id from `ipc_msg_info` to read the message bytes. A message is
301     /// only valid for the lifetime of this callback and the message bytes
302     /// should be copied into the return value, if needed.
get_msg<F, R>(&self, mut func: F) -> crate::Result<R> where F: FnMut(&trusty_sys::ipc_msg_info) -> crate::Result<R>,303     fn get_msg<F, R>(&self, mut func: F) -> crate::Result<R>
304     where
305         F: FnMut(&trusty_sys::ipc_msg_info) -> crate::Result<R>,
306     {
307         let mut msg_info: MaybeUninit<trusty_sys::ipc_msg_info> = MaybeUninit::uninit();
308 
309         // SAFETY: syscall, msg_info pointer is mutably borrowed and will be
310         // correctly initialized if the syscall returns 0.
311         let msg_info = unsafe {
312             let rc = trusty_sys::get_msg(self.as_raw_fd(), msg_info.as_mut_ptr());
313             if rc != 0 {
314                 return Err(TipcError::from_uapi(rc));
315             }
316             msg_info.assume_init()
317         };
318 
319         let ret = func(&msg_info);
320 
321         // SAFETY: syscall with safe arguments
322         let put_msg_rc = unsafe { trusty_sys::put_msg(self.as_raw_fd(), msg_info.id) };
323 
324         // prefer returning the callback error to the put_msg error, if any
325         if put_msg_rc != 0 {
326             Err(ret.err().unwrap_or_else(|| TipcError::from_uapi(put_msg_rc)))
327         } else {
328             ret
329         }
330     }
331 
332     /// Maps the shared memory buffer represented by this handle.
333     ///
334     /// If `size` is not already a multiple of the page size it will be rounded up
335     /// to the nearest multiple of the page size. Use the
336     /// [`len`][UnsafeSharedBuf::len] method on the returned [`UnsafeSharedBuf`] to
337     /// determine the final size of the mapped buffer.
mmap(&self, size: usize, flags: MMapFlags) -> crate::Result<UnsafeSharedBuf>338     pub fn mmap(&self, size: usize, flags: MMapFlags) -> crate::Result<UnsafeSharedBuf> {
339         let prot = match flags {
340             MMapFlags::Read => trusty_sys::MMAP_FLAG_PROT_READ as c_int,
341             MMapFlags::Write => trusty_sys::MMAP_FLAG_PROT_WRITE as c_int,
342             MMapFlags::ReadWrite => {
343                 (trusty_sys::MMAP_FLAG_PROT_READ | trusty_sys::MMAP_FLAG_PROT_WRITE) as c_int
344             }
345         };
346 
347         // SAFETY: FFI call with all safe arguments.
348         let page_size = unsafe { libc::getauxval(libc::AT_PAGESZ) };
349 
350         // Round `size` up to the nearest multiple of the page size.
351         let page_size: usize = page_size.try_into().unwrap();
352         let size = (size + (page_size - 1)) & !(page_size - 1);
353 
354         // SAFETY: FFI call with all safe arguments.
355         let buf_ptr =
356             unsafe { libc::mmap(core::ptr::null_mut(), size, prot, 0, self.as_raw_fd(), 0) };
357 
358         if buf_ptr == libc::MAP_FAILED {
359             Err(TipcError::InvalidHandle)
360         } else {
361             Ok(UnsafeSharedBuf { buf: buf_ptr as *mut u8, len: size })
362         }
363     }
364 }
365 
366 impl Drop for Handle {
drop(&mut self)367     fn drop(&mut self) {
368         // SAFETY syscall with safe arguments
369         unsafe {
370             let _ = trusty_sys::close(self.as_raw_fd());
371         }
372     }
373 }
374 
375 /// A serializer that borrows its input bytes and does not allocate.
376 #[derive(Default)]
377 struct BorrowingSerializer<'a> {
378     buffers: arrayvec::ArrayVec<&'a [u8], MAX_SERIALIZED_SEGMENTS>,
379     handles: arrayvec::ArrayVec<Handle, MAX_MSG_HANDLES>,
380 }
381 
382 impl<'a> Serializer<'a> for BorrowingSerializer<'a> {
383     type Ok = ();
384     type Error = TipcError;
385 
serialize_bytes(&mut self, bytes: &'a [u8]) -> Result<Self::Ok, Self::Error>386     fn serialize_bytes(&mut self, bytes: &'a [u8]) -> Result<Self::Ok, Self::Error> {
387         self.buffers.try_push(bytes).or(Err(TipcError::AllocError))
388     }
389 
serialize_handle(&mut self, handle: &'a Handle) -> Result<Self::Ok, Self::Error>390     fn serialize_handle(&mut self, handle: &'a Handle) -> Result<Self::Ok, Self::Error> {
391         self.handles.try_push(Handle(handle.as_raw_fd())).or(Err(TipcError::AllocError))
392     }
393 }
394 
395 /// Memory protection flags for [`Handle::mmap`].
396 #[derive(Debug, Clone, Copy, PartialEq, Eq)]
397 pub enum MMapFlags {
398     /// The shared buffer can be read from.
399     Read,
400 
401     /// The shared buffer can be written to.
402     Write,
403 
404     /// The shared buffer can be read from and written to.
405     ReadWrite,
406 }
407 
408 /// A shared buffer that has been mapped into memory
409 ///
410 /// # Safety
411 ///
412 /// Note that all operations performed on the shared buffer must be performed
413 /// through a raw pointer, accessible via the [`ptr`][Self::ptr] method. Rust's
414 /// ownership semantics do not align with how shared buffers work, and so it
415 /// cannot be represented as a normal Rust slice or reference. Extra care must
416 /// be taken on the part of the user to ensure that all reads and writes
417 /// performed on the buffer are done safely.
418 ///
419 /// Most notably, it is **never** safe to take a reference to data in the shared
420 /// buffer. All read operations must copy data from the buffer via the raw
421 /// pointer APIs in order to safely read shared memory.
422 ///
423 /// # Unmapping
424 ///
425 /// Call [`unmap`][Self::unmap] once the shared memory is no longer needed to
426 /// unmap the buffer. Doing this invalidates any existing pointers to the
427 /// buffer, so care must be taken to ensure that any such pointers are not used
428 /// after unmapping.
429 ///
430 /// Note that the buffer is not automatically unmapped on drop. Failing to unmap
431 /// the buffer will leak memory until the process exits.
432 #[derive(Debug)]
433 pub struct UnsafeSharedBuf {
434     buf: *mut u8,
435     len: usize,
436 }
437 
438 impl UnsafeSharedBuf {
439     /// Gets the pointer to the start of the buffer.
440     ///
441     /// Any pointers returned by this method are invalidated once
442     /// [`unmap`][Self::unmap] is called.
ptr(&self) -> *mut u8443     pub fn ptr(&self) -> *mut u8 {
444         self.buf
445     }
446 
447     /// Gets the length of the buffer.
448     ///
449     /// Guaranteed to always be a multiple of the page size.
len(&self) -> usize450     pub fn len(&self) -> usize {
451         self.len
452     }
453 
454     /// Unmaps the shared memory buffer.
455     ///
456     /// Invalidates any pointers to the shared memory that were previously returned
457     /// by calls to [`ptr`][Self::ptr].
unmap(self)458     pub fn unmap(self) {
459         let rc = unsafe { libc::munmap(self.buf as *mut _, self.len) };
460         if rc != 0 {
461             panic!("Failed to unmap shared buf");
462         }
463     }
464 }
465 
466 #[cfg(test)]
467 pub(crate) mod test {
468     use super::Handle;
469     use crate::sys;
470     use crate::TipcError;
471     use std::sync::Once;
472     use test::expect_eq;
473     use trusty_sys::Error;
474 
475     // Expected limits: should be in sync with kernel settings
476 
477     /// First user handle ID
478     pub const USER_BASE_HANDLE: i32 = sys::USER_BASE_HANDLE as i32;
479 
480     /// Maximum number of user handles
481     pub const MAX_USER_HANDLES: i32 = sys::MAX_USER_HANDLES as i32;
482 
483     const INVALID_IPC_HANDLE: Handle = Handle(-1);
484 
485     static mut FIRST_FREE_HANDLE_INDEX: i32 = -1;
486     static FIRST_FREE_HANDLE_INDEX_INIT: Once = Once::new();
487 
488     // We don't know ahead of time what the first free handle will be, so we have to
489     // check and save the result the first time we need it.
first_free_handle_index() -> i32490     pub fn first_free_handle_index() -> i32 {
491         type Channel = crate::service::Channel<crate::service::SingleDispatcher<()>>;
492 
493         FIRST_FREE_HANDLE_INDEX_INIT.call_once(|| {
494             let chan = Channel::try_new_port(
495                 &crate::PortCfg::new("com.android.tipc.handle_probe").unwrap(),
496             )
497             .unwrap();
498 
499             // SAFETY: Write access is guarded by Once
500             unsafe {
501                 FIRST_FREE_HANDLE_INDEX = chan.handle().0 - USER_BASE_HANDLE;
502             }
503         });
504 
505         // SAFETY: Once call above gates write access, so we know that the
506         // static has been initialized at this point and will be read-only from
507         // now on. Read-only access to a static i32 is safe.
508         unsafe { FIRST_FREE_HANDLE_INDEX }
509     }
510 
511     #[test]
wait_negative()512     fn wait_negative() {
513         let timeout = Some(1000); // 1 sec
514 
515         expect_eq!(
516             INVALID_IPC_HANDLE.wait(timeout).err(),
517             Some(TipcError::InvalidHandle),
518             "wait on invalid handle"
519         );
520 
521         //   call wait on an invalid (out of range) handle
522         //
523         //   check handling of the following cases:
524         //     - handle is on the upper boundary of valid handle range
525         //     - handle is above of the upper boundary of valid handle range
526         //     - handle is below of valid handle range
527         //
528         //   in all cases, the expected result is ERR_BAD_HANDLE error.
529         expect_eq!(
530             Handle(USER_BASE_HANDLE + MAX_USER_HANDLES).wait(timeout).err(),
531             Some(TipcError::InvalidHandle),
532             "wait on invalid handle"
533         );
534 
535         expect_eq!(
536             Handle(USER_BASE_HANDLE + MAX_USER_HANDLES + 1).wait(timeout).err(),
537             Some(TipcError::InvalidHandle),
538             "wait on invalid handle"
539         );
540 
541         expect_eq!(
542             Handle(USER_BASE_HANDLE - 1).wait(timeout).err(),
543             Some(TipcError::InvalidHandle),
544             "wait on invalid handle"
545         );
546 
547         // wait on non-existent handle in valid range
548         for i in first_free_handle_index()..MAX_USER_HANDLES {
549             expect_eq!(
550                 Handle(USER_BASE_HANDLE + i).wait(timeout).err(),
551                 Some(TipcError::SystemError(Error::NotFound)),
552                 "wait on invalid handle"
553             );
554         }
555     }
556 }
557