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