1 /* 2 * Copyright (C) 2022-2024 Huawei Device Co., Ltd. 3 * Licensed under the Apache License, Version 2.0 (the "License"); 4 * you may not use this file except in compliance with the License. 5 * You may obtain a copy of the License at 6 * 7 * http://www.apache.org/licenses/LICENSE-2.0 8 * 9 * Unless required by applicable law or agreed to in writing, software 10 * distributed under the License is distributed on an "AS IS" BASIS, 11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 * See the License for the specific language governing permissions and 13 * limitations under the License. 14 */ 15 16 #include "process_skeleton.h" 17 18 #include <cinttypes> 19 #include <unistd.h> 20 21 #include "binder_connector.h" 22 #include "check_instance_exit.h" 23 #include "ipc_debug.h" 24 #include "log_tags.h" 25 #include "securec.h" 26 #include "string_ex.h" 27 28 namespace OHOS { 29 static constexpr OHOS::HiviewDFX::HiLogLabel LOG_LABEL = { LOG_CORE, LOG_ID_IPC_COMMON, "ProcessSkeleton" }; 30 static constexpr int PRINT_ERR_CNT = 100; 31 32 #ifdef __aarch64__ 33 static constexpr uint32_t IPC_OBJECT_MASK = 0xffffffff; 34 #else 35 static constexpr uint32_t IPC_OBJECT_MASK = 0xffffff; 36 #endif 37 38 ProcessSkeleton* ProcessSkeleton::instance_ = nullptr; 39 std::mutex ProcessSkeleton::mutex_; 40 ProcessSkeleton::DestroyInstance ProcessSkeleton::destroyInstance_; 41 std::atomic<bool> ProcessSkeleton::exitFlag_ = false; 42 GetInstance()43 ProcessSkeleton* ProcessSkeleton::GetInstance() 44 { 45 if ((instance_ == nullptr) && !exitFlag_) { 46 std::lock_guard<std::mutex> lockGuard(mutex_); 47 if ((instance_ == nullptr) && !exitFlag_) { 48 instance_ = new (std::nothrow) ProcessSkeleton(); 49 if (instance_ == nullptr) { 50 ZLOGE(LOG_LABEL, "create ProcessSkeleton object failed"); 51 return nullptr; 52 } 53 } 54 } 55 return instance_; 56 } 57 ~ProcessSkeleton()58 ProcessSkeleton::~ProcessSkeleton() 59 { 60 ZLOGI(LOG_LABEL, "enter"); 61 std::lock_guard<std::mutex> lockGuard(mutex_); 62 exitFlag_ = true; 63 { 64 std::unique_lock<std::shared_mutex> objLock(objMutex_); 65 objects_.clear(); 66 isContainStub_.clear(); 67 } 68 { 69 std::unique_lock<std::shared_mutex> validObjLock(validObjectMutex_); 70 validObjectRecord_.clear(); 71 } 72 { 73 std::unique_lock<std::shared_mutex> invokerProcLock(invokerProcMutex_); 74 invokerProcInfo_.clear(); 75 } 76 } 77 GetRegistryObject()78 sptr<IRemoteObject> ProcessSkeleton::GetRegistryObject() 79 { 80 CHECK_INSTANCE_EXIT_WITH_RETVAL(exitFlag_, nullptr); 81 std::lock_guard<std::mutex> lockGuard(mutex_); 82 return registryObject_; 83 } 84 SetRegistryObject(sptr<IRemoteObject> & object)85 void ProcessSkeleton::SetRegistryObject(sptr<IRemoteObject> &object) 86 { 87 CHECK_INSTANCE_EXIT(exitFlag_); 88 std::lock_guard<std::mutex> lockGuard(mutex_); 89 registryObject_ = object; 90 } 91 SetSamgrFlag(bool flag)92 void ProcessSkeleton::SetSamgrFlag(bool flag) 93 { 94 isSamgr_ = flag; 95 } 96 GetSamgrFlag()97 bool ProcessSkeleton::GetSamgrFlag() 98 { 99 return isSamgr_; 100 } 101 IsContainsObject(IRemoteObject * object)102 bool ProcessSkeleton::IsContainsObject(IRemoteObject *object) 103 { 104 CHECK_INSTANCE_EXIT_WITH_RETVAL(exitFlag_, false); 105 if (object == nullptr) { 106 return false; 107 } 108 // check whether it is a valid IPCObjectStub object. 109 std::shared_lock<std::shared_mutex> lockGuard(objMutex_); 110 auto it = isContainStub_.find(object); 111 if (it != isContainStub_.end()) { 112 return it->second; 113 } 114 115 return false; 116 } 117 DetachObject(IRemoteObject * object,const std::u16string & descriptor)118 bool ProcessSkeleton::DetachObject(IRemoteObject *object, const std::u16string &descriptor) 119 { 120 CHECK_INSTANCE_EXIT_WITH_RETVAL(exitFlag_, false); 121 std::unique_lock<std::shared_mutex> lockGuard(objMutex_); 122 (void)isContainStub_.erase(object); 123 124 // This handle may have already been replaced with a new IPCObjectProxy, 125 // if someone failed the AttemptIncStrong. 126 auto iterator = objects_.find(descriptor); 127 if (iterator == objects_.end()) { 128 ZLOGD(LOG_LABEL, "not found, desc:%{public}s maybe has been updated", 129 ConvertToSecureDesc(Str16ToStr8(descriptor)).c_str()); 130 return false; 131 } 132 133 if (object->IsProxyObject()) { 134 proxyObjectCountNum_.fetch_sub(1, std::memory_order_relaxed); 135 } 136 137 if (iterator->second.GetRefPtr() != object) { 138 ZLOGI(LOG_LABEL, "can not erase it because addr if different, " 139 "desc:%{public}s, recorded object:%{public}u, detach object:%{public}u", 140 ConvertToSecureDesc(Str16ToStr8(descriptor)).c_str(), ConvertAddr(iterator->second.GetRefPtr()), 141 ConvertAddr(object)); 142 return true; 143 } 144 145 objects_.erase(iterator); 146 ZLOGD(LOG_LABEL, "erase desc:%{public}s", ConvertToSecureDesc(Str16ToStr8(descriptor)).c_str()); 147 return true; 148 } 149 AttachObject(IRemoteObject * object,const std::u16string & descriptor,bool lockFlag)150 bool ProcessSkeleton::AttachObject(IRemoteObject *object, const std::u16string &descriptor, bool lockFlag) 151 { 152 CHECK_INSTANCE_EXIT_WITH_RETVAL(exitFlag_, false); 153 std::unique_lock<std::shared_mutex> lockGuard(objMutex_, std::defer_lock); 154 if (lockFlag) { 155 lockGuard.lock(); 156 } 157 (void)isContainStub_.insert(std::pair<IRemoteObject *, bool>(object, true)); 158 159 if (descriptor.empty()) { 160 ZLOGE(LOG_LABEL, "descriptor is null %{public}u", ConvertAddr(object)); 161 return false; 162 } 163 // If attemptIncStrong failed, old proxy might still exist, replace it with the new proxy. 164 wptr<IRemoteObject> wp = object; 165 166 if (object->IsProxyObject()) { 167 uint64_t proxyObjectCountNum = proxyObjectCountNum_.fetch_add(1, std::memory_order_relaxed) + 1; 168 if (ipcProxyCallback_ != nullptr && ipcProxyLimitNum_ > 0 && proxyObjectCountNum > ipcProxyLimitNum_) { 169 ZLOGW(LOG_LABEL, "ipc proxy num:%{public}" PRIu64 " exceeds limit:%{public}" PRIu64, 170 proxyObjectCountNum, ipcProxyLimitNum_); 171 ipcProxyCallback_(proxyObjectCountNum); 172 } 173 } 174 auto result = objects_.insert_or_assign(descriptor, wp); 175 ZLOGD(LOG_LABEL, "attach %{public}u desc:%{public}s type:%{public}s", 176 ConvertAddr(object), ConvertToSecureDesc(Str16ToStr8(descriptor)).c_str(), result.second ? "insert" : "assign"); 177 return true; 178 } 179 QueryObject(const std::u16string & descriptor,bool lockFlag)180 sptr<IRemoteObject> ProcessSkeleton::QueryObject(const std::u16string &descriptor, bool lockFlag) 181 { 182 sptr<IRemoteObject> result = nullptr; 183 if (descriptor.empty()) { 184 ZLOGE(LOG_LABEL, "descriptor is null"); 185 return result; 186 } 187 IRemoteObject *remoteObject = nullptr; 188 CHECK_INSTANCE_EXIT_WITH_RETVAL(exitFlag_, nullptr); 189 { 190 std::shared_lock<std::shared_mutex> lockGuard(objMutex_, std::defer_lock); 191 ZLOGD(LOG_LABEL, "The value of lockflag is:%{public}d", lockFlag); 192 if (lockFlag) { 193 lockGuard.lock(); 194 } 195 auto it = objects_.find(descriptor); 196 if (it != objects_.end()) { 197 // Life-time of IPCObjectProxy is extended to WEAK 198 // now it's weak reference counted, so it's safe to get raw pointer 199 remoteObject = it->second.GetRefPtr(); 200 } 201 } 202 203 if (remoteObject == nullptr) { 204 ZLOGD(LOG_LABEL, "not found object, desc:%{public}s", ConvertToSecureDesc(Str16ToStr8(descriptor)).c_str()); 205 return result; 206 } 207 std::u16string desc; 208 if (!IsValidObject(remoteObject, desc)) { 209 ZLOGD(LOG_LABEL, "object %{public}u is inValid", ConvertAddr(remoteObject)); 210 return result; 211 } 212 213 if (!remoteObject->AttemptIncStrong(this)) { 214 ZLOGD(LOG_LABEL, "object %{public}u AttemptIncStrong failed", ConvertAddr(remoteObject)); 215 return result; 216 } 217 218 result = remoteObject; 219 result->CheckIsAttemptAcquireSet(this); 220 221 return result; 222 } 223 LockObjectMutex()224 bool ProcessSkeleton::LockObjectMutex() 225 { 226 CHECK_INSTANCE_EXIT_WITH_RETVAL(exitFlag_, false); 227 objMutex_.lock(); 228 return true; 229 } 230 UnlockObjectMutex()231 bool ProcessSkeleton::UnlockObjectMutex() 232 { 233 CHECK_INSTANCE_EXIT_WITH_RETVAL(exitFlag_, false); 234 objMutex_.unlock(); 235 return true; 236 } 237 AttachValidObject(IRemoteObject * object,const std::u16string & desc)238 bool ProcessSkeleton::AttachValidObject(IRemoteObject *object, const std::u16string &desc) 239 { 240 CHECK_INSTANCE_EXIT_WITH_RETVAL(exitFlag_, false); 241 std::unique_lock<std::shared_mutex> lockGuard(validObjectMutex_); 242 auto result = validObjectRecord_.insert_or_assign(object, desc); 243 ZLOGD(LOG_LABEL, "%{public}u descriptor:%{public}s", ConvertAddr(object), 244 ConvertToSecureDesc(Str16ToStr8(desc)).c_str()); 245 return result.second; 246 } 247 DetachValidObject(IRemoteObject * object)248 bool ProcessSkeleton::DetachValidObject(IRemoteObject *object) 249 { 250 bool ret = false; 251 CHECK_INSTANCE_EXIT_WITH_RETVAL(exitFlag_, false); 252 std::unique_lock<std::shared_mutex> lockGuard(validObjectMutex_); 253 auto it = validObjectRecord_.find(object); 254 if (it != validObjectRecord_.end()) { 255 ZLOGD(LOG_LABEL, "erase %{public}u ", ConvertAddr(object)); 256 validObjectRecord_.erase(it); 257 ret = true; 258 } 259 return ret; 260 } 261 IsValidObject(IRemoteObject * object,std::u16string & desc)262 bool ProcessSkeleton::IsValidObject(IRemoteObject *object, std::u16string &desc) 263 { 264 CHECK_INSTANCE_EXIT_WITH_RETVAL(exitFlag_, false); 265 if (object == nullptr) { 266 return false; 267 } 268 std::shared_lock<std::shared_mutex> lockGuard(validObjectMutex_); 269 auto it = validObjectRecord_.find(object); 270 if (it != validObjectRecord_.end()) { 271 desc = it->second; 272 ZLOGD(LOG_LABEL, "%{public}u descriptor:%{public}s", ConvertAddr(object), 273 ConvertToSecureDesc(Str16ToStr8(desc)).c_str()); 274 return true; 275 } 276 return false; 277 } 278 AttachInvokerProcInfo(bool isLocal,InvokerProcInfo & invokeInfo)279 bool ProcessSkeleton::AttachInvokerProcInfo(bool isLocal, InvokerProcInfo &invokeInfo) 280 { 281 CHECK_INSTANCE_EXIT_WITH_RETVAL(exitFlag_, false); 282 std::unique_lock<std::shared_mutex> lockGuard(invokerProcMutex_); 283 std::string key = std::to_string(gettid()) + "_" + std::to_string(isLocal); 284 auto result = invokerProcInfo_.insert_or_assign(key, invokeInfo); 285 auto &info = result.first->second; 286 ZLOGD(LOG_LABEL, "%{public}u, %{public}u %{public}u %{public}u %{public}" PRIu64 " %{public}" PRIu64, 287 info.invoker, info.pid, info.realPid, info.uid, info.tokenId, info.firstTokenId); 288 return result.second; 289 } 290 QueryInvokerProcInfo(bool isLocal,InvokerProcInfo & invokeInfo)291 bool ProcessSkeleton::QueryInvokerProcInfo(bool isLocal, InvokerProcInfo &invokeInfo) 292 { 293 CHECK_INSTANCE_EXIT_WITH_RETVAL(exitFlag_, false); 294 std::shared_lock<std::shared_mutex> lockGuard(invokerProcMutex_); 295 std::string key = std::to_string(gettid()) + "_" + std::to_string(isLocal); 296 auto it = invokerProcInfo_.find(key); 297 if (it == invokerProcInfo_.end()) { 298 return false; 299 } 300 invokeInfo = it->second; 301 ZLOGD(LOG_LABEL, "%{public}u, %{public}u %{public}u %{public}u %{public}" PRIu64 " %{public}" PRIu64, 302 invokeInfo.invoker, invokeInfo.pid, invokeInfo.realPid, invokeInfo.uid, invokeInfo.tokenId, 303 invokeInfo.firstTokenId); 304 return true; 305 } 306 DetachInvokerProcInfo(bool isLocal)307 bool ProcessSkeleton::DetachInvokerProcInfo(bool isLocal) 308 { 309 CHECK_INSTANCE_EXIT_WITH_RETVAL(exitFlag_, false); 310 std::unique_lock<std::shared_mutex> lockGuard(invokerProcMutex_); 311 std::string key = std::to_string(gettid()) + "_" + std::to_string(isLocal); 312 auto it = invokerProcInfo_.find(key); 313 if (it != invokerProcInfo_.end()) { 314 auto &invokeInfo = it->second; 315 ZLOGD(LOG_LABEL, "%{public}u, %{public}u %{public}u %{public}u %{public}" PRIu64 " %{public}" PRIu64, 316 invokeInfo.invoker, invokeInfo.pid, invokeInfo.realPid, invokeInfo.uid, invokeInfo.tokenId, 317 invokeInfo.firstTokenId); 318 invokerProcInfo_.erase(it); 319 return true; 320 } 321 return false; 322 } 323 IsPrint(int err,std::atomic<int> & lastErr,std::atomic<int> & lastErrCnt)324 bool ProcessSkeleton::IsPrint(int err, std::atomic<int> &lastErr, std::atomic<int> &lastErrCnt) 325 { 326 bool isPrint = false; 327 if (err == lastErr) { 328 if (lastErrCnt >= INT_MAX) { 329 lastErrCnt = 0; 330 } 331 if (++lastErrCnt % PRINT_ERR_CNT == 0) { 332 isPrint = true; 333 } 334 } else { 335 isPrint = true; 336 lastErrCnt = 0; 337 lastErr = err; 338 } 339 return isPrint; 340 } 341 ConvertToSecureDesc(const std::string & str)342 std::string ProcessSkeleton::ConvertToSecureDesc(const std::string &str) 343 { 344 auto pos = str.find_last_of("."); 345 if (pos != std::string::npos) { 346 return "*" + str.substr(pos); 347 } 348 return str; 349 } 350 SetIPCProxyLimit(uint64_t num,std::function<void (uint64_t num)> callback)351 bool ProcessSkeleton::SetIPCProxyLimit(uint64_t num, std::function<void (uint64_t num)> callback) 352 { 353 ipcProxyLimitNum_ = num; 354 ipcProxyCallback_ = callback; 355 return true; 356 } 357 ConvertAddr(const void * ptr)358 uint32_t ProcessSkeleton::ConvertAddr(const void *ptr) 359 { 360 if (ptr == nullptr) { 361 ZLOGE(LOG_LABEL, "ptr is null"); 362 return 0; 363 } 364 return static_cast<uint32_t>((reinterpret_cast<uintptr_t>(ptr)) & IPC_OBJECT_MASK); 365 } 366 FlattenDBinderData(Parcel & parcel,const dbinder_negotiation_data * & dbinderData)367 bool ProcessSkeleton::FlattenDBinderData(Parcel &parcel, const dbinder_negotiation_data *&dbinderData) 368 { 369 size_t start = parcel.GetWritePosition(); 370 binder_buffer_object obj; 371 obj.hdr.type = BINDER_TYPE_PTR; 372 obj.flags = BINDER_BUFFER_FLAG_HAS_DBINDER; 373 obj.buffer = reinterpret_cast<binder_uintptr_t>(dbinderData); 374 obj.length = sizeof(dbinder_negotiation_data); 375 if (!parcel.WriteBuffer(&obj, sizeof(binder_buffer_object))) { 376 ZLOGE(LOG_LABEL, "WriteBuffer fail"); 377 return false; 378 } 379 size_t stop = parcel.GetWritePosition(); 380 ZLOGD(LOG_LABEL, "serialization:%{public}zu sizeof:%{public}zu", stop - start, sizeof(binder_buffer_object)); 381 return true; 382 } 383 UnFlattenDBinderData(Parcel & parcel,dbinder_negotiation_data * & dbinderData)384 bool ProcessSkeleton::UnFlattenDBinderData(Parcel &parcel, dbinder_negotiation_data *&dbinderData) 385 { 386 auto *buf = parcel.ReadBuffer(sizeof(binder_buffer_object), false); 387 if (buf == nullptr) { 388 return false; 389 } 390 auto obj = reinterpret_cast<const binder_buffer_object *>(buf); 391 auto ret = memcpy_s(dbinderData, sizeof(dbinder_negotiation_data), 392 reinterpret_cast<const void *>(obj->buffer), obj->length); 393 return (ret == EOK); 394 } 395 GetSubStr(const std::string & str,std::string & substr,size_t offset,size_t length)396 bool ProcessSkeleton::GetSubStr(const std::string &str, std::string &substr, size_t offset, size_t length) 397 { 398 if (str.empty() || str.length() < offset + length) { 399 ZLOGE(LOG_LABEL, "strLen:%{public}zu, offset:%{public}zu, subLen:%{public}zu", str.length(), offset, length); 400 return false; 401 } 402 substr = str.substr(offset, length); 403 return true; 404 } 405 IsNumStr(const std::string & str)406 bool ProcessSkeleton::IsNumStr(const std::string &str) 407 { 408 if (str.empty()) { 409 return false; 410 } 411 return std::all_of(str.begin(), str.end(), ::isdigit); 412 } 413 GetThreadStopFlag()414 bool ProcessSkeleton::GetThreadStopFlag() 415 { 416 return stopThreadFlag_.load(); 417 } 418 IncreaseThreadCount()419 void ProcessSkeleton::IncreaseThreadCount() 420 { 421 std::unique_lock<std::mutex> lockGuard(threadCountMutex_); 422 runningChildThreadNum_.fetch_add(1); 423 } 424 DecreaseThreadCount()425 void ProcessSkeleton::DecreaseThreadCount() 426 { 427 std::unique_lock<std::mutex> lockGuard(threadCountMutex_); 428 if (runningChildThreadNum_.load() > 0) { 429 runningChildThreadNum_.fetch_sub(1); 430 431 if (runningChildThreadNum_.load() == 0) { 432 threadCountCon_.notify_one(); 433 } 434 } 435 } 436 NotifyChildThreadStop()437 void ProcessSkeleton::NotifyChildThreadStop() 438 { 439 // set child thread exit flag 440 stopThreadFlag_.store(true); 441 // after closeing fd, child threads will be not block in the 'WriteBinder' function 442 BinderConnector *connector = BinderConnector::GetInstance(); 443 if (connector != nullptr) { 444 connector->CloseDriverFd(); 445 } 446 ZLOGI(LOG_LABEL, "start waiting for child thread to exit, child thread num:%{public}zu", 447 runningChildThreadNum_.load()); 448 std::unique_lock<std::mutex> lockGuard(threadCountMutex_); 449 threadCountCon_.wait_for(lockGuard, 450 std::chrono::seconds(MAIN_THREAD_MAX_WAIT_TIME), 451 [&threadNum = this->runningChildThreadNum_] { return threadNum.load() == 0; }); 452 if (runningChildThreadNum_.load() != 0) { 453 ZLOGI(LOG_LABEL, "wait timeout, %{public}zu child threads not exiting", runningChildThreadNum_.load()); 454 return; 455 } 456 ZLOGI(LOG_LABEL, "wait finished, all child thread have exited"); 457 } 458 } // namespace OHOS