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