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