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