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