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