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::binder::Stability;
18 use crate::error::StatusCode;
19 use crate::parcel::{
20     BorrowedParcel, Deserialize, Parcel, Parcelable, Serialize, NON_NULL_PARCELABLE_FLAG,
21     NULL_PARCELABLE_FLAG,
22 };
23 
24 use downcast_rs::{impl_downcast, DowncastSync};
25 use std::any::Any;
26 use std::sync::{Arc, Mutex};
27 
28 /// Metadata that `ParcelableHolder` needs for all parcelables.
29 ///
30 /// The compiler auto-generates implementations of this trait
31 /// for AIDL parcelables.
32 pub trait ParcelableMetadata {
33     /// The Binder parcelable descriptor string.
34     ///
35     /// This string is a unique identifier for a Binder parcelable.
get_descriptor() -> &'static str36     fn get_descriptor() -> &'static str;
37 
38     /// The Binder parcelable stability.
get_stability(&self) -> Stability39     fn get_stability(&self) -> Stability {
40         Stability::Local
41     }
42 }
43 
44 trait AnyParcelable: DowncastSync + Parcelable + std::fmt::Debug {}
45 impl_downcast!(sync AnyParcelable);
46 impl<T> AnyParcelable for T where T: DowncastSync + Parcelable + std::fmt::Debug {}
47 
48 #[derive(Debug, Clone)]
49 enum ParcelableHolderData {
50     Empty,
51     Parcelable { parcelable: Arc<dyn AnyParcelable>, name: String },
52     Parcel(Parcel),
53 }
54 
55 /// A container that can hold any arbitrary `Parcelable`.
56 ///
57 /// This type is currently used for AIDL parcelable fields.
58 ///
59 /// `ParcelableHolder` is currently not thread-safe (neither
60 /// `Send` nor `Sync`), mainly because it internally contains
61 /// a `Parcel` which in turn is not thread-safe.
62 #[derive(Debug)]
63 pub struct ParcelableHolder {
64     // This is a `Mutex` because of `get_parcelable`
65     // which takes `&self` for consistency with C++.
66     // We could make `get_parcelable` take a `&mut self`
67     // and get rid of the `Mutex` here for a performance
68     // improvement, but then callers would require a mutable
69     // `ParcelableHolder` even for that getter method.
70     data: Mutex<ParcelableHolderData>,
71     stability: Stability,
72 }
73 
74 impl ParcelableHolder {
75     /// Construct a new `ParcelableHolder` with the given stability.
new(stability: Stability) -> Self76     pub fn new(stability: Stability) -> Self {
77         Self { data: Mutex::new(ParcelableHolderData::Empty), stability }
78     }
79 
80     /// Reset the contents of this `ParcelableHolder`.
81     ///
82     /// Note that this method does not reset the stability,
83     /// only the contents.
reset(&mut self)84     pub fn reset(&mut self) {
85         *self.data.get_mut().unwrap() = ParcelableHolderData::Empty;
86         // We could also clear stability here, but C++ doesn't
87     }
88 
89     /// Set the parcelable contained in this `ParcelableHolder`.
set_parcelable<T>(&mut self, p: Arc<T>) -> Result<(), StatusCode> where T: Any + Parcelable + ParcelableMetadata + std::fmt::Debug + Send + Sync,90     pub fn set_parcelable<T>(&mut self, p: Arc<T>) -> Result<(), StatusCode>
91     where
92         T: Any + Parcelable + ParcelableMetadata + std::fmt::Debug + Send + Sync,
93     {
94         if self.stability > p.get_stability() {
95             return Err(StatusCode::BAD_VALUE);
96         }
97 
98         *self.data.get_mut().unwrap() =
99             ParcelableHolderData::Parcelable { parcelable: p, name: T::get_descriptor().into() };
100 
101         Ok(())
102     }
103 
104     /// Retrieve the parcelable stored in this `ParcelableHolder`.
105     ///
106     /// This method attempts to retrieve the parcelable inside
107     /// the current object as a parcelable of type `T`.
108     /// The object is validated against `T` by checking that
109     /// its parcelable descriptor matches the one returned
110     /// by `T::get_descriptor()`.
111     ///
112     /// Returns one of the following:
113     /// * `Err(_)` in case of error
114     /// * `Ok(None)` if the holder is empty or the descriptor does not match
115     /// * `Ok(Some(_))` if the object holds a parcelable of type `T`
116     ///   with the correct descriptor
get_parcelable<T>(&self) -> Result<Option<Arc<T>>, StatusCode> where T: Any + Parcelable + ParcelableMetadata + Default + std::fmt::Debug + Send + Sync,117     pub fn get_parcelable<T>(&self) -> Result<Option<Arc<T>>, StatusCode>
118     where
119         T: Any + Parcelable + ParcelableMetadata + Default + std::fmt::Debug + Send + Sync,
120     {
121         let parcelable_desc = T::get_descriptor();
122         let mut data = self.data.lock().unwrap();
123         match *data {
124             ParcelableHolderData::Empty => Ok(None),
125             ParcelableHolderData::Parcelable { ref parcelable, ref name } => {
126                 if name != parcelable_desc {
127                     return Err(StatusCode::BAD_VALUE);
128                 }
129 
130                 match Arc::clone(parcelable).downcast_arc::<T>() {
131                     Err(_) => Err(StatusCode::BAD_VALUE),
132                     Ok(x) => Ok(Some(x)),
133                 }
134             }
135             ParcelableHolderData::Parcel(ref mut parcel) => {
136                 // Safety: 0 should always be a valid position.
137                 unsafe {
138                     parcel.set_data_position(0)?;
139                 }
140 
141                 let name: String = parcel.read()?;
142                 if name != parcelable_desc {
143                     return Ok(None);
144                 }
145 
146                 let mut parcelable = T::default();
147                 parcelable.read_from_parcel(parcel.borrowed_ref())?;
148 
149                 let parcelable = Arc::new(parcelable);
150                 let result = Arc::clone(&parcelable);
151                 *data = ParcelableHolderData::Parcelable { parcelable, name };
152 
153                 Ok(Some(result))
154             }
155         }
156     }
157 
158     /// Return the stability value of this object.
get_stability(&self) -> Stability159     pub fn get_stability(&self) -> Stability {
160         self.stability
161     }
162 }
163 
164 impl Clone for ParcelableHolder {
clone(&self) -> ParcelableHolder165     fn clone(&self) -> ParcelableHolder {
166         ParcelableHolder {
167             data: Mutex::new(self.data.lock().unwrap().clone()),
168             stability: self.stability,
169         }
170     }
171 }
172 
173 impl Serialize for ParcelableHolder {
serialize(&self, parcel: &mut BorrowedParcel<'_>) -> Result<(), StatusCode>174     fn serialize(&self, parcel: &mut BorrowedParcel<'_>) -> Result<(), StatusCode> {
175         parcel.write(&NON_NULL_PARCELABLE_FLAG)?;
176         self.write_to_parcel(parcel)
177     }
178 }
179 
180 impl Deserialize for ParcelableHolder {
181     type UninitType = Self;
uninit() -> Self::UninitType182     fn uninit() -> Self::UninitType {
183         Self::new(Default::default())
184     }
from_init(value: Self) -> Self::UninitType185     fn from_init(value: Self) -> Self::UninitType {
186         value
187     }
188 
deserialize(parcel: &BorrowedParcel<'_>) -> Result<Self, StatusCode>189     fn deserialize(parcel: &BorrowedParcel<'_>) -> Result<Self, StatusCode> {
190         let status: i32 = parcel.read()?;
191         if status == NULL_PARCELABLE_FLAG {
192             Err(StatusCode::UNEXPECTED_NULL)
193         } else {
194             let mut parcelable = ParcelableHolder::new(Default::default());
195             parcelable.read_from_parcel(parcel)?;
196             Ok(parcelable)
197         }
198     }
199 }
200 
201 impl Parcelable for ParcelableHolder {
write_to_parcel(&self, parcel: &mut BorrowedParcel<'_>) -> Result<(), StatusCode>202     fn write_to_parcel(&self, parcel: &mut BorrowedParcel<'_>) -> Result<(), StatusCode> {
203         parcel.write(&self.stability)?;
204 
205         let mut data = self.data.lock().unwrap();
206         match *data {
207             ParcelableHolderData::Empty => parcel.write(&0i32),
208             ParcelableHolderData::Parcelable { ref parcelable, ref name } => {
209                 let length_start = parcel.get_data_position();
210                 parcel.write(&0i32)?;
211 
212                 let data_start = parcel.get_data_position();
213                 parcel.write(name)?;
214                 parcelable.write_to_parcel(parcel)?;
215 
216                 let end = parcel.get_data_position();
217                 // Safety: we got the position from `get_data_position`.
218                 unsafe {
219                     parcel.set_data_position(length_start)?;
220                 }
221 
222                 assert!(end >= data_start);
223                 parcel.write(&(end - data_start))?;
224                 // Safety: we got the position from `get_data_position`.
225                 unsafe {
226                     parcel.set_data_position(end)?;
227                 }
228 
229                 Ok(())
230             }
231             ParcelableHolderData::Parcel(ref mut p) => {
232                 parcel.write(&p.get_data_size())?;
233                 parcel.append_all_from(&*p)
234             }
235         }
236     }
237 
read_from_parcel(&mut self, parcel: &BorrowedParcel<'_>) -> Result<(), StatusCode>238     fn read_from_parcel(&mut self, parcel: &BorrowedParcel<'_>) -> Result<(), StatusCode> {
239         if self.stability != parcel.read()? {
240             return Err(StatusCode::BAD_VALUE);
241         }
242 
243         let data_size: i32 = parcel.read()?;
244         if data_size < 0 {
245             // C++ returns BAD_VALUE here,
246             // while Java returns ILLEGAL_ARGUMENT
247             return Err(StatusCode::BAD_VALUE);
248         }
249         if data_size == 0 {
250             *self.data.get_mut().unwrap() = ParcelableHolderData::Empty;
251             return Ok(());
252         }
253 
254         // TODO: C++ ParcelableHolder accepts sizes up to SIZE_MAX here, but we
255         // only go up to i32::MAX because that's what our API uses everywhere
256         let data_start = parcel.get_data_position();
257         let data_end = data_start.checked_add(data_size).ok_or(StatusCode::BAD_VALUE)?;
258 
259         let mut new_parcel = Parcel::new();
260         new_parcel.append_from(parcel, data_start, data_size)?;
261         *self.data.get_mut().unwrap() = ParcelableHolderData::Parcel(new_parcel);
262 
263         // Safety: `append_from` checks if `data_size` overflows
264         // `parcel` and returns `BAD_VALUE` if that happens. We also
265         // explicitly check for negative and zero `data_size` above,
266         // so `data_end` is guaranteed to be greater than `data_start`.
267         unsafe {
268             parcel.set_data_position(data_end)?;
269         }
270 
271         Ok(())
272     }
273 }
274