1 /* 2 * Copyright (c) 2023 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 "app_state_observer.h" 17 #include <unistd.h> 18 #include "account_adapt.h" 19 #include "bundle_manager_adapter.h" 20 #include "dlp_permission.h" 21 #include "dlp_permission_log.h" 22 #include "bundle_mgr_client.h" 23 #include "dlp_sandbox_change_callback_manager.h" 24 #include "open_dlp_file_callback_manager.h" 25 #include "iservice_registry.h" 26 #include "i_dlp_permission_service.h" 27 28 namespace OHOS { 29 namespace Security { 30 namespace DlpPermission { 31 using OHOS::AppExecFwk::AppProcessState; 32 namespace { 33 constexpr OHOS::HiviewDFX::HiLogLabel LABEL = {LOG_CORE, SECURITY_DOMAIN_DLP_PERMISSION, "AppStateObserver"}; 34 const std::string PERMISSION_ACCESS_DLP_FILE = "ohos.permission.ACCESS_DLP_FILE"; 35 const std::string DLP_MANAGER_BUNDLE_NAME = "com.ohos.dlpmanager"; 36 } AppStateObserver()37 AppStateObserver::AppStateObserver() 38 {} 39 ~AppStateObserver()40 AppStateObserver::~AppStateObserver() 41 { 42 UninstallAllDlpSandbox(); 43 } 44 UninstallDlpSandbox(DlpSandboxInfo & appInfo)45 void AppStateObserver::UninstallDlpSandbox(DlpSandboxInfo& appInfo) 46 { 47 if (appInfo.appIndex <= 0) { // never uninstall original hap 48 return; 49 } 50 DLP_LOG_INFO(LABEL, "uninstall dlp sandbox %{public}s%{public}d, uid: %{public}d", appInfo.bundleName.c_str(), 51 appInfo.appIndex, appInfo.uid); 52 AppExecFwk::BundleMgrClient bundleMgrClient; 53 bundleMgrClient.UninstallSandboxApp(appInfo.bundleName, appInfo.appIndex, appInfo.userId); 54 RetentionFileManager::GetInstance().DelSandboxInfo(appInfo.tokenId); 55 } 56 UninstallAllDlpSandboxForUser(int32_t userId)57 void AppStateObserver::UninstallAllDlpSandboxForUser(int32_t userId) 58 { 59 AppExecFwk::BundleMgrClient bundleMgrClient; 60 std::lock_guard<std::mutex> lock(sandboxInfoLock_); 61 for (auto iter = sandboxInfo_.begin(); iter != sandboxInfo_.end();) { 62 auto& appInfo = iter->second; 63 if (appInfo.userId != userId) { 64 ++iter; 65 continue; 66 } 67 if (RetentionFileManager::GetInstance().CanUninstall(appInfo.tokenId)) { 68 UninstallDlpSandbox(appInfo); 69 } 70 EraseUidTokenIdMap(appInfo.tokenId); 71 DLP_LOG_INFO(LABEL, "ExecuteCallbackAsync appInfo bundleName:%{public}s,appIndex:%{public}d,pid:%{public}d", 72 appInfo.bundleName.c_str(), appInfo.appIndex, appInfo.pid); 73 DlpSandboxChangeCallbackManager::GetInstance().ExecuteCallbackAsync(appInfo); 74 iter = sandboxInfo_.erase(iter); 75 } 76 } 77 UninstallAllDlpSandbox()78 void AppStateObserver::UninstallAllDlpSandbox() 79 { 80 DLP_LOG_INFO(LABEL, "service exit, uninstall all dlp sandbox"); 81 std::lock_guard<std::mutex> lock(userIdListLock_); 82 for (const auto& iter : userIdList_) { 83 UninstallAllDlpSandboxForUser(iter); 84 } 85 userIdList_.clear(); 86 } 87 ExitSaAfterAllDlpManagerDie()88 void AppStateObserver::ExitSaAfterAllDlpManagerDie() 89 { 90 std::lock_guard<std::mutex> lock(userIdListLock_); 91 DLP_LOG_DEBUG(LABEL, "userIdList_ size:%{public}zu", userIdList_.size()); 92 if (userIdList_.empty() && CallbackListenerEmpty()) { 93 DLP_LOG_INFO(LABEL, "all dlp manager app die, and callbacks are empty, start service exit"); 94 auto systemAbilityMgr = SystemAbilityManagerClient::GetInstance().GetSystemAbilityManager(); 95 if (systemAbilityMgr == nullptr) { 96 DLP_LOG_ERROR(LABEL, "Failed to get SystemAbilityManager."); 97 return; 98 } 99 int32_t ret = systemAbilityMgr->UnloadSystemAbility(SA_ID_DLP_PERMISSION_SERVICE); 100 if (ret != DLP_OK) { 101 DLP_LOG_ERROR(LABEL, "Failed to UnloadSystemAbility service! errcode=%{public}d", ret); 102 return; 103 } 104 DLP_LOG_INFO(LABEL, "UnloadSystemAbility successfully!"); 105 } 106 } 107 EraseUserId(int32_t userId)108 void AppStateObserver::EraseUserId(int32_t userId) 109 { 110 std::lock_guard<std::mutex> lock(userIdListLock_); 111 auto iter = userIdList_.find(userId); 112 if (iter != userIdList_.end()) { 113 DLP_LOG_INFO(LABEL, "erase userId %{public}d", userId); 114 userIdList_.erase(userId); 115 } 116 } 117 AddUserId(int32_t userId)118 void AppStateObserver::AddUserId(int32_t userId) 119 { 120 std::lock_guard<std::mutex> lock(userIdListLock_); 121 if (userIdList_.count(userId) <= 0) { 122 DLP_LOG_INFO(LABEL, "add userId %{public}d", userId); 123 userIdList_.emplace(userId); 124 } 125 return; 126 } 127 GetSandboxInfo(int32_t uid,DlpSandboxInfo & appInfo)128 bool AppStateObserver::GetSandboxInfo(int32_t uid, DlpSandboxInfo& appInfo) 129 { 130 std::lock_guard<std::mutex> lock(sandboxInfoLock_); 131 auto iter = sandboxInfo_.find(uid); 132 if (iter != sandboxInfo_.end()) { 133 appInfo = iter->second; 134 return true; 135 } 136 return false; 137 } 138 UpdatReadFlag(int32_t uid)139 void AppStateObserver::UpdatReadFlag(int32_t uid) 140 { 141 std::lock_guard<std::mutex> lock(sandboxInfoLock_); 142 auto iter = sandboxInfo_.find(uid); 143 if (iter != sandboxInfo_.end()) { 144 iter->second.hasRead = true; 145 } 146 } 147 CheckSandboxInfo(const std::string & bundleName,int32_t appIndex,int32_t userId)148 bool AppStateObserver::CheckSandboxInfo(const std::string& bundleName, int32_t appIndex, int32_t userId) 149 { 150 std::lock_guard<std::mutex> lock(sandboxInfoLock_); 151 for (const auto& iter : sandboxInfo_) { 152 if (iter.second.bundleName == bundleName && iter.second.appIndex == appIndex && iter.second.userId == userId) { 153 return true; 154 } 155 } 156 return false; 157 } 158 EraseSandboxInfo(int32_t uid)159 void AppStateObserver::EraseSandboxInfo(int32_t uid) 160 { 161 std::lock_guard<std::mutex> lock(sandboxInfoLock_); 162 auto iter = sandboxInfo_.find(uid); 163 if (iter != sandboxInfo_.end()) { 164 DLP_LOG_INFO(LABEL, "sandbox app %{public}s%{public}d info delete success, uid: %{public}d", 165 iter->second.bundleName.c_str(), iter->second.appIndex, iter->second.uid); 166 sandboxInfo_.erase(iter); 167 } 168 } 169 AddSandboxInfo(const DlpSandboxInfo & appInfo)170 void AppStateObserver::AddSandboxInfo(const DlpSandboxInfo& appInfo) 171 { 172 std::lock_guard<std::mutex> lock(sandboxInfoLock_); 173 if (sandboxInfo_.count(appInfo.uid) > 0) { 174 DLP_LOG_ERROR(LABEL, "sandbox app %{public}s%{public}d is already insert, ignore it", 175 appInfo.bundleName.c_str(), appInfo.appIndex); 176 } else { 177 sandboxInfo_[appInfo.uid] = appInfo; 178 DLP_LOG_INFO(LABEL, "sandbox app %{public}s%{public}d info insert success, uid: %{public}d", 179 appInfo.bundleName.c_str(), appInfo.appIndex, appInfo.uid); 180 } 181 return; 182 } 183 AddDlpSandboxInfo(const DlpSandboxInfo & appInfo)184 void AppStateObserver::AddDlpSandboxInfo(const DlpSandboxInfo& appInfo) 185 { 186 if (appInfo.bundleName.empty() || appInfo.tokenId <= 0 || appInfo.appIndex <= 0) { 187 DLP_LOG_ERROR(LABEL, "Param is error"); 188 return; 189 } 190 int32_t userId; 191 if (GetUserIdFromUid(appInfo.uid, &userId) != 0) { 192 DLP_LOG_WARN(LABEL, "has uid:%{public}d", appInfo.uid); 193 return; 194 } 195 AddUserId(userId); 196 AddSandboxInfo(appInfo); 197 AddUidWithTokenId(appInfo.tokenId, appInfo.uid); 198 RetentionInfo retentionInfo = { 199 .appIndex = appInfo.appIndex, 200 .tokenId = appInfo.tokenId, 201 .bundleName = appInfo.bundleName, 202 .dlpFileAccess = appInfo.dlpFileAccess, 203 .userId = appInfo.userId 204 }; 205 RetentionFileManager::GetInstance().AddSandboxInfo(retentionInfo); 206 OpenDlpFileCallbackManager::GetInstance().ExecuteCallbackAsync(appInfo); 207 return; 208 } 209 SetAppProxy(const sptr<AppExecFwk::AppMgrProxy> & appProxy)210 void AppStateObserver::SetAppProxy(const sptr<AppExecFwk::AppMgrProxy>& appProxy) 211 { 212 appProxy_ = appProxy; 213 } 214 GetRunningProcessesInfo(std::vector<RunningProcessInfo> & infoVec)215 bool AppStateObserver::GetRunningProcessesInfo(std::vector<RunningProcessInfo>& infoVec) 216 { 217 if (appProxy_ == nullptr) { 218 DLP_LOG_ERROR(LABEL, "AppProxy_ is nullptr"); 219 return false; 220 } 221 int32_t ret = appProxy_->GetAllRunningProcesses(infoVec); 222 if (ret != ERR_OK) { 223 DLP_LOG_ERROR(LABEL, "GetAllRunningProcesses failed, errorCode=%{public}d", ret); 224 return false; 225 } 226 return true; 227 } 228 GetOpeningSandboxInfo(const std::string & bundleName,const std::string & uri,int32_t userId,SandboxInfo & sandboxInfo)229 bool AppStateObserver::GetOpeningSandboxInfo(const std::string& bundleName, const std::string& uri, 230 int32_t userId, SandboxInfo& sandboxInfo) 231 { 232 std::lock_guard<std::mutex> lock(sandboxInfoLock_); 233 for (auto iter = sandboxInfo_.begin(); iter != sandboxInfo_.end(); iter++) { 234 DlpSandboxInfo appInfo = iter->second; 235 if (appInfo.userId != userId || appInfo.bundleName != bundleName || appInfo.uri != uri) { 236 continue; 237 } 238 std::vector<RunningProcessInfo> infoVec; 239 (void)GetRunningProcessesInfo(infoVec); 240 for (auto it = infoVec.begin(); it != infoVec.end(); it++) { 241 if (it->uid_ != appInfo.uid) { 242 continue; 243 } 244 if (it->state_ == AppProcessState::APP_STATE_END || it->state_ == AppProcessState::APP_STATE_TERMINATED) { 245 DLP_LOG_INFO(LABEL, "APP is dead, appName:%{public}s, state=%{public}d", it->processName_.c_str(), 246 it->state_); 247 return false; 248 } 249 DLP_LOG_INFO(LABEL, "APP is running, appName:%{public}s, state=%{public}d", it->processName_.c_str(), 250 it->state_); 251 sandboxInfo.appIndex = appInfo.appIndex; 252 sandboxInfo.tokenId = appInfo.tokenId; 253 return true; 254 } 255 break; 256 } 257 return false; 258 } 259 GetOpeningReadOnlySandbox(const std::string & bundleName,int32_t userId,int32_t & appIndex)260 void AppStateObserver::GetOpeningReadOnlySandbox(const std::string& bundleName, int32_t userId, int32_t& appIndex) 261 { 262 std::lock_guard<std::mutex> lock(sandboxInfoLock_); 263 for (auto iter = sandboxInfo_.begin(); iter != sandboxInfo_.end(); iter++) { 264 DlpSandboxInfo appInfo = iter->second; 265 if (appInfo.userId == userId && appInfo.bundleName == bundleName && 266 appInfo.dlpFileAccess == DLPFileAccess::READ_ONLY) { 267 appIndex = appInfo.appIndex; 268 return; 269 } 270 } 271 appIndex = -1; 272 return; 273 } 274 EraseDlpSandboxInfo(int uid)275 uint32_t AppStateObserver::EraseDlpSandboxInfo(int uid) 276 { 277 DlpSandboxInfo appInfo; 278 if (!GetSandboxInfo(uid, appInfo)) { 279 return 0; 280 } 281 282 EraseSandboxInfo(appInfo.uid); 283 EraseUidTokenIdMap(appInfo.tokenId); 284 return appInfo.tokenId; 285 } 286 OnProcessDied(const AppExecFwk::ProcessData & processData)287 void AppStateObserver::OnProcessDied(const AppExecFwk::ProcessData& processData) 288 { 289 DLP_LOG_INFO(LABEL, "%{public}s is died, uid: %{public}d", processData.bundleName.c_str(), processData.uid); 290 291 // current died process is dlpmanager 292 if (processData.bundleName == DLP_MANAGER_BUNDLE_NAME && 293 processData.processName == DLP_MANAGER_BUNDLE_NAME && 294 BundleManagerAdapter::GetInstance().CheckHapPermission(processData.bundleName, PERMISSION_ACCESS_DLP_FILE)) { 295 int32_t userId; 296 if (GetUserIdFromUid(processData.uid, &userId) != 0) { 297 return; 298 } 299 DLP_LOG_INFO(LABEL, "%{public}s in userId %{public}d is died", processData.bundleName.c_str(), userId); 300 UninstallAllDlpSandboxForUser(userId); 301 EraseUserId(userId); 302 ExitSaAfterAllDlpManagerDie(); 303 return; 304 } 305 // if current died process is a listener 306 if (RemoveCallbackListener(processData.pid)) { 307 ExitSaAfterAllDlpManagerDie(); 308 return; 309 } 310 if (processData.renderUid != -1) { 311 DLP_LOG_INFO(LABEL, "Ignore render process death, renderUid: %{public}d", processData.renderUid); 312 return; 313 } 314 // current died process is dlp sandbox app 315 DlpSandboxInfo appInfo; 316 if (!GetSandboxInfo(processData.uid, appInfo)) { 317 return; 318 } 319 if (RetentionFileManager::GetInstance().CanUninstall(appInfo.tokenId)) { 320 UninstallDlpSandbox(appInfo); 321 } 322 EraseDlpSandboxInfo(appInfo.uid); 323 DLP_LOG_INFO(LABEL, "ExecuteCallbackAsync appInfo bundleName:%{public}s,appIndex:%{public}d,pid:%{public}d", 324 appInfo.bundleName.c_str(), appInfo.appIndex, appInfo.pid); 325 DlpSandboxChangeCallbackManager::GetInstance().ExecuteCallbackAsync(appInfo); 326 } 327 EraseUidTokenIdMap(uint32_t tokenId)328 void AppStateObserver::EraseUidTokenIdMap(uint32_t tokenId) 329 { 330 std::lock_guard<std::mutex> lock(tokenIdToUidMapLock_); 331 auto iter = tokenIdToUidMap_.find(tokenId); 332 if (iter != tokenIdToUidMap_.end()) { 333 DLP_LOG_INFO(LABEL, "erase tokenId: %{public}d", tokenId); 334 tokenIdToUidMap_.erase(iter); 335 } 336 } 337 AddUidWithTokenId(uint32_t tokenId,int32_t uid)338 void AppStateObserver::AddUidWithTokenId(uint32_t tokenId, int32_t uid) 339 { 340 if (tokenId == 0) { 341 DLP_LOG_ERROR(LABEL, "tokenId is invalid"); 342 return; 343 } 344 std::lock_guard<std::mutex> lock(tokenIdToUidMapLock_); 345 if (tokenIdToUidMap_.count(tokenId) > 0) { 346 return; 347 } 348 DLP_LOG_INFO(LABEL, "add tokenId: %{public}d, uid: %{public}d", tokenId, uid); 349 tokenIdToUidMap_[tokenId] = uid; 350 } 351 GetUidByTokenId(uint32_t tokenId,int32_t & uid)352 bool AppStateObserver::GetUidByTokenId(uint32_t tokenId, int32_t& uid) 353 { 354 std::lock_guard<std::mutex> lock(tokenIdToUidMapLock_); 355 auto iter = tokenIdToUidMap_.find(tokenId); 356 if (iter != tokenIdToUidMap_.end()) { 357 uid = iter->second; 358 DLP_LOG_INFO(LABEL, "tokenId: %{public}d, uid: %{public}d", tokenId, uid); 359 return true; 360 } 361 return false; 362 } 363 CallbackListenerEmpty()364 bool AppStateObserver::CallbackListenerEmpty() 365 { 366 std::lock_guard<std::mutex> lock(callbackListLock_); 367 return callbackList_.empty(); 368 } 369 RemoveCallbackListener(int32_t pid)370 bool AppStateObserver::RemoveCallbackListener(int32_t pid) 371 { 372 std::lock_guard<std::mutex> lock(callbackListLock_); 373 auto iter = callbackList_.find(pid); 374 if (iter != callbackList_.end()) { 375 (*iter).second--; 376 if ((*iter).second <= 0) { 377 DLP_LOG_INFO(LABEL, "erase pid %{public}d", pid); 378 callbackList_.erase(pid); 379 return callbackList_.empty(); 380 } 381 } 382 return false; 383 } 384 AddCallbackListener(int32_t pid)385 void AppStateObserver::AddCallbackListener(int32_t pid) 386 { 387 std::lock_guard<std::mutex> lock(callbackListLock_); 388 DLP_LOG_INFO(LABEL, "add pid %{public}d", pid); 389 callbackList_[pid]++; 390 } 391 IsCopyable(DLPFileAccess dlpFileAccess)392 static bool IsCopyable(DLPFileAccess dlpFileAccess) 393 { 394 switch (dlpFileAccess) { 395 case READ_ONLY: 396 return false; 397 case CONTENT_EDIT: 398 return true; 399 case FULL_CONTROL: 400 return true; 401 default: 402 return false; 403 } 404 } 405 QueryDlpFileCopyableByTokenId(bool & copyable,uint32_t tokenId)406 int32_t AppStateObserver::QueryDlpFileCopyableByTokenId(bool& copyable, uint32_t tokenId) 407 { 408 int32_t uid; 409 copyable = false; 410 if (!GetUidByTokenId(tokenId, uid)) { 411 DLP_LOG_WARN(LABEL, "current tokenId %{public}d is not a sandbox app", tokenId); 412 copyable = false; 413 return DLP_SERVICE_ERROR_APPOBSERVER_ERROR; 414 } 415 DLPFileAccess dlpFileAccess = NO_PERMISSION; 416 int32_t res = QueryDlpFileAccessByUid(dlpFileAccess, uid); 417 if (res != DLP_OK) { 418 copyable = false; 419 } else { 420 copyable = IsCopyable(dlpFileAccess); 421 } 422 return res; 423 } 424 QueryDlpFileAccessByUid(DLPFileAccess & dlpFileAccess,int32_t uid)425 int32_t AppStateObserver::QueryDlpFileAccessByUid(DLPFileAccess& dlpFileAccess, int32_t uid) 426 { 427 DlpSandboxInfo appInfo; 428 if (!GetSandboxInfo(uid, appInfo) || appInfo.dlpFileAccess == NO_PERMISSION) { 429 DLP_LOG_ERROR(LABEL, "current uid %{public}d is not a sandbox app", uid); 430 dlpFileAccess = NO_PERMISSION; 431 return DLP_SERVICE_ERROR_APPOBSERVER_ERROR; 432 } 433 dlpFileAccess = appInfo.dlpFileAccess; 434 DLP_LOG_INFO(LABEL, "current dlp sandbox %{public}s%{public}d's perm type is %{public}d", 435 appInfo.bundleName.c_str(), appInfo.appIndex, dlpFileAccess); 436 return DLP_OK; 437 } 438 IsInDlpSandbox(bool & inSandbox,int32_t uid)439 int32_t AppStateObserver::IsInDlpSandbox(bool& inSandbox, int32_t uid) 440 { 441 inSandbox = false; 442 DlpSandboxInfo appInfo; 443 if (GetSandboxInfo(uid, appInfo)) { 444 inSandbox = appInfo.appIndex > 0 ? true : false; 445 } 446 DLP_LOG_INFO(LABEL, "uid: %{public}d, inSandbox: %{public}d", uid, inSandbox); 447 return DLP_OK; 448 } 449 DumpSandbox(int fd)450 void AppStateObserver::DumpSandbox(int fd) 451 { 452 std::lock_guard<std::mutex> lock(sandboxInfoLock_); 453 dprintf(fd, "DlpSandbox:\n"); 454 for (auto iter = sandboxInfo_.begin(); iter != sandboxInfo_.end(); iter++) { 455 DlpSandboxInfo& appInfo = iter->second; 456 dprintf(fd, " userId:%d;bundleName:%s;sandboxIndex:%d;dlpFileAccess:%s\n", 457 appInfo.userId, appInfo.bundleName.c_str(), appInfo.appIndex, 458 appInfo.dlpFileAccess == READ_ONLY ? "ReadOnly" : "FullControl"); 459 } 460 } 461 } // namespace DlpPermission 462 } // namespace Security 463 } // namespace OHOS 464