• 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 "user_unlocked_event_subscriber.h"
17 
18 #include <sys/stat.h>
19 
20 #include "account_helper.h"
21 #include "bundle_mgr_service.h"
22 #if defined (BUNDLE_FRAMEWORK_SANDBOX_APP) && defined (DLP_PERMISSION_ENABLE)
23 #include "dlp_permission_kit.h"
24 #endif
25 #include "installd_client.h"
26 
27 namespace OHOS {
28 namespace AppExecFwk {
29 namespace {
30 static constexpr int16_t MODE_BASE = 07777;
31 static constexpr int16_t DATA_GROUP_DIR_MODE = 02770;
32 constexpr const char* BUNDLE_BACKUP_HOME_PATH_EL1_NEW = "/data/app/el1/%/base/";
33 constexpr const char* BUNDLE_BACKUP_HOME_PATH_EL2_NEW = "/data/app/el2/%/base/";
34 constexpr const char* BUNDLE_BACKUP_INNER_DIR = "/.backup";
35 static std::mutex TASK_MUTEX;
36 static std::atomic<uint32_t> CURRENT_TASK_NUM = 0;
37 
38 template<typename Func, typename...Args>
ReturnIfNewTask(Func func,uint32_t tempTask,Args &&...args)39 inline void ReturnIfNewTask(Func func, uint32_t tempTask, Args&&... args)
40 {
41     if (CURRENT_TASK_NUM != tempTask) {
42         APP_LOGI("need stop current task, new first");
43         return;
44     }
45     func(std::forward<Args>(args)...);
46 }
47 }
UserUnlockedEventSubscriber(const EventFwk::CommonEventSubscribeInfo & subscribeInfo)48 UserUnlockedEventSubscriber::UserUnlockedEventSubscriber(
49     const EventFwk::CommonEventSubscribeInfo &subscribeInfo) : EventFwk::CommonEventSubscriber(subscribeInfo)
50 {}
51 
~UserUnlockedEventSubscriber()52 UserUnlockedEventSubscriber::~UserUnlockedEventSubscriber()
53 {}
54 
OnReceiveEvent(const EventFwk::CommonEventData & data)55 void UserUnlockedEventSubscriber::OnReceiveEvent(const EventFwk::CommonEventData &data)
56 {
57     std::string action = data.GetWant().GetAction();
58     if (action == EventFwk::CommonEventSupport::COMMON_EVENT_USER_UNLOCKED) {
59         int32_t userId = data.GetCode();
60         APP_LOGI_NOFUNC("UserUnlockedEventSubscriber -u %{public}d unlocked", userId);
61         std::lock_guard<std::mutex> lock(mutex_);
62         if ((userId_ != userId)) {
63             userId_ = userId;
64             std::thread updateDataDirThread(UpdateAppDataMgr::UpdateAppDataDirSelinuxLabel, userId);
65             updateDataDirThread.detach();
66 #ifdef BUNDLE_FRAMEWORK_APP_CONTROL
67             DelayedSingleton<AppControlManager>::GetInstance()->SetAppInstallControlStatus();
68 #endif
69         }
70     }
71     if (action == EventFwk::CommonEventSupport::COMMON_EVENT_USER_SWITCHED) {
72         int32_t userId = data.GetCode();
73         APP_LOGI_NOFUNC("UserUnlockedEventSubscriber -u %{public}d switched", userId);
74         std::lock_guard<std::mutex> lock(mutex_);
75         if (AccountHelper::IsOsAccountVerified(userId) && (userId_ != userId)) {
76             APP_LOGI_NOFUNC("UserUnlockedEventSubscriber -u %{public}d unlocked", userId);
77             userId_ = userId;
78             std::thread updateDataDirThread(UpdateAppDataMgr::UpdateAppDataDirSelinuxLabel, userId);
79             updateDataDirThread.detach();
80         }
81 #if defined (BUNDLE_FRAMEWORK_SANDBOX_APP) && defined (DLP_PERMISSION_ENABLE)
82         APP_LOGI("RemoveUnreservedSandbox call ClearUnreservedSandbox");
83         Security::DlpPermission::DlpPermissionKit::ClearUnreservedSandbox();
84 #endif
85 #ifdef BUNDLE_FRAMEWORK_APP_CONTROL
86         DelayedSingleton<AppControlManager>::GetInstance()->SetAppInstallControlStatus();
87 #endif
88     }
89 }
90 
CheckPathAttribute(const std::string & path,const BundleInfo & bundleInfo,bool & isExist)91 void UpdateAppDataMgr::CheckPathAttribute(const std::string &path, const BundleInfo &bundleInfo, bool &isExist)
92 {
93     if (!isExist) {
94         return;
95     }
96     FileStat fileStat;
97     if (InstalldClient::GetInstance()->GetFileStat(path, fileStat) != ERR_OK) {
98         APP_LOGE("GetFileStat path(%{public}s) failed", path.c_str());
99         return;
100     }
101     if (fileStat.uid != bundleInfo.uid) {
102         APP_LOGW("path: %{public}s uid is not same, fileStat.uid:%{public}d, bundleInfo.uid:%{public}d",
103             path.c_str(), static_cast<int32_t>(fileStat.uid), bundleInfo.uid);
104         isExist = false;
105     }
106     if (fileStat.gid != ServiceConstants::DATABASE_DIR_GID) {
107         APP_LOGW("path: %{public}s gid is not same, fileStat.gid:%{public}d, gid:%{public}d",
108             path.c_str(), static_cast<int32_t>(fileStat.gid), ServiceConstants::DATABASE_DIR_GID);
109         isExist = false;
110     }
111     uint32_t fileMode = static_cast<uint32_t>(fileStat.mode);
112     if ((fileMode & MODE_BASE) != (S_IRWXU | S_IRWXG | S_ISGID)) {
113         APP_LOGW("path: %{public}s mode is not same, fileStat.mode:%{public}d, mode:%{public}d",
114             path.c_str(), static_cast<int32_t>(fileStat.mode), static_cast<int32_t>((S_IRWXU | S_IRWXG | S_ISGID)));
115     }
116 }
117 
CreateBundleDataDir(const BundleInfo & bundleInfo,int32_t userId,const std::string & elDir)118 bool UpdateAppDataMgr::CreateBundleDataDir(
119     const BundleInfo &bundleInfo, int32_t userId, const std::string &elDir)
120 {
121     std::string baseBundleDataDir = ServiceConstants::BUNDLE_APP_DATA_BASE_DIR + elDir +
122         ServiceConstants::PATH_SEPARATOR + std::to_string(userId) + ServiceConstants::DATABASE + bundleInfo.name;
123     bool isExist = false;
124     if (InstalldClient::GetInstance()->IsExistDir(baseBundleDataDir, isExist) != ERR_OK) {
125         APP_LOGE("path: %{public}s IsExistDir failed", baseBundleDataDir.c_str());
126         return false;
127     }
128     CheckPathAttribute(baseBundleDataDir, bundleInfo, isExist);
129     if (!isExist) {
130         APP_LOGI_NOFUNC("path: %{public}s need CreateBundleDataDir", baseBundleDataDir.c_str());
131         CreateDirParam createDirParam;
132         createDirParam.userId = userId;
133         createDirParam.bundleName = bundleInfo.name;
134         createDirParam.uid = bundleInfo.uid;
135         createDirParam.gid = bundleInfo.gid;
136         createDirParam.apl = bundleInfo.applicationInfo.appPrivilegeLevel;
137         createDirParam.isPreInstallApp = bundleInfo.isPreInstallApp;
138         createDirParam.debug = bundleInfo.applicationInfo.appProvisionType == Constants::APP_PROVISION_TYPE_DEBUG;
139         if (elDir != ServiceConstants::BUNDLE_EL[0]) {
140             createDirParam.createDirFlag = CreateDirFlag::CREATE_DIR_UNLOCKED;
141         }
142         ProcessExtensionDir(bundleInfo, createDirParam.extensionDirs);
143         if (InstalldClient::GetInstance()->CreateBundleDataDir(createDirParam) != ERR_OK) {
144             APP_LOGW("failed to CreateBundleDataDir");
145         }
146     }
147     CreateDataGroupDir(bundleInfo, userId);
148     return true;
149 }
150 
CreateDataGroupDir(const BundleInfo & bundleInfo,int32_t userId)151 void UpdateAppDataMgr::CreateDataGroupDir(const BundleInfo &bundleInfo, int32_t userId)
152 {
153     auto dataMgr = DelayedSingleton<BundleMgrService>::GetInstance()->GetDataMgr();
154     if (dataMgr == nullptr) {
155         APP_LOGE("CreateDataGroupDir failed for DataMgr is nullptr");
156         return;
157     }
158     std::vector<DataGroupInfo> dataGroupInfos;
159     if (!dataMgr->QueryDataGroupInfos(bundleInfo.name, userId, dataGroupInfos)) {
160         APP_LOGW("QueryDataGroupInfo for bundle %{public}s userId %{public}d failed", bundleInfo.name.c_str(), userId);
161         return;
162     }
163     if (dataGroupInfos.empty()) {
164         return;
165     }
166 
167     std::string parentDir = std::string(ServiceConstants::REAL_DATA_PATH) + ServiceConstants::PATH_SEPARATOR
168         + std::to_string(userId);
169     if (!BundleUtil::IsExistDir(parentDir)) {
170         APP_LOGE("parent dir(%{public}s) missing: group", parentDir.c_str());
171         return;
172     }
173     for (const DataGroupInfo &dataGroupInfo : dataGroupInfos) {
174         std::string dir = parentDir + ServiceConstants::DATA_GROUP_PATH + dataGroupInfo.uuid;
175         APP_LOGD("create group dir: %{public}s", dir.c_str());
176         auto result = InstalldClient::GetInstance()->Mkdir(dir,
177             DATA_GROUP_DIR_MODE, dataGroupInfo.uid, dataGroupInfo.gid);
178         if (result != ERR_OK) {
179             APP_LOGW("create data group dir %{public}s userId %{public}d failed", dataGroupInfo.uuid.c_str(), userId);
180         }
181     }
182 }
183 
UpdateAppDataDirSelinuxLabel(int32_t userId)184 void UpdateAppDataMgr::UpdateAppDataDirSelinuxLabel(int32_t userId)
185 {
186     uint32_t tempTaskNum = CURRENT_TASK_NUM.fetch_add(1) + 1;
187     std::lock_guard<std::mutex> guard(TASK_MUTEX);
188     APP_LOGI("UpdateAppDataDirSelinuxLabel hold TASK_MUTEX");
189     if (tempTaskNum != CURRENT_TASK_NUM) {
190         APP_LOGI("need stop current task, new first, -u %{public}d", userId);
191         return;
192     }
193     APP_LOGI("UpdateAppDataDirSelinuxLabel userId:%{public}d start", userId);
194     auto dataMgr = DelayedSingleton<BundleMgrService>::GetInstance()->GetDataMgr();
195     if (dataMgr == nullptr) {
196         APP_LOGE("UpdateAppDataDirSelinuxLabel DataMgr is nullptr");
197         return;
198     }
199     std::vector<BundleInfo> bundleInfos;
200     if (!dataMgr->GetBundleInfos(BundleFlag::GET_BUNDLE_WITH_EXTENSION_INFO, bundleInfos, userId)) {
201         APP_LOGE("UpdateAppDataDirSelinuxLabel GetAllBundleInfos failed");
202         return;
203     }
204 
205     ReturnIfNewTask(ProcessUpdateAppDataDir, tempTaskNum, userId, bundleInfos, ServiceConstants::BUNDLE_EL[1]);
206 #ifdef CHECK_ELDIR_ENABLED
207     ReturnIfNewTask(ProcessUpdateAppDataDir, tempTaskNum, userId, bundleInfos, ServiceConstants::DIR_EL3);
208     ReturnIfNewTask(ProcessUpdateAppDataDir, tempTaskNum, userId, bundleInfos, ServiceConstants::DIR_EL4);
209 #endif
210     ReturnIfNewTask(ProcessUpdateAppLogDir, tempTaskNum, bundleInfos, userId);
211     ReturnIfNewTask(ProcessFileManagerDir, tempTaskNum, bundleInfos, userId);
212     ReturnIfNewTask(ProcessNewBackupDir, tempTaskNum, bundleInfos, userId);
213     APP_LOGI("UpdateAppDataDirSelinuxLabel userId:%{public}d end", userId);
214 }
215 
ProcessUpdateAppDataDir(int32_t userId,const std::vector<BundleInfo> & bundleInfos,const std::string & elDir)216 void UpdateAppDataMgr::ProcessUpdateAppDataDir(
217     int32_t userId, const std::vector<BundleInfo> &bundleInfos, const std::string &elDir)
218 {
219     std::string baseBundleDataDir = ServiceConstants::BUNDLE_APP_DATA_BASE_DIR + elDir +
220         ServiceConstants::PATH_SEPARATOR + std::to_string(userId);
221     for (const auto &bundleInfo : bundleInfos) {
222         if (bundleInfo.appIndex > 0) {
223             APP_LOGI("bundleName:%{public}s appIndex:%{public}d clone app no need to change",
224                 bundleInfo.name.c_str(), bundleInfo.appIndex);
225             continue;
226         }
227         if ((userId != Constants::DEFAULT_USERID && bundleInfo.singleton) ||
228             !CreateBundleDataDir(bundleInfo, userId, elDir)) {
229             continue;
230         }
231         std::string baseDir = baseBundleDataDir + ServiceConstants::BASE + bundleInfo.name;
232         if (InstalldClient::GetInstance()->SetDirApl(baseDir, bundleInfo.name,
233             bundleInfo.applicationInfo.appPrivilegeLevel, bundleInfo.isPreInstallApp,
234             bundleInfo.applicationInfo.appProvisionType == Constants::APP_PROVISION_TYPE_DEBUG) != ERR_OK) {
235             APP_LOGW_NOFUNC("failed to SetDirApl baseDir dir");
236             continue;
237         }
238         std::string baseDataDir = baseBundleDataDir + ServiceConstants::DATABASE + bundleInfo.name;
239         if (InstalldClient::GetInstance()->SetDirApl(baseDataDir, bundleInfo.name,
240             bundleInfo.applicationInfo.appPrivilegeLevel, bundleInfo.isPreInstallApp,
241             bundleInfo.applicationInfo.appProvisionType == Constants::APP_PROVISION_TYPE_DEBUG) != ERR_OK) {
242             APP_LOGW_NOFUNC("failed to SetDirApl baseDataDir dir");
243         }
244     }
245 }
246 
ProcessExtensionDir(const BundleInfo & bundleInfo,std::vector<std::string> & dirs)247 void UpdateAppDataMgr::ProcessExtensionDir(const BundleInfo &bundleInfo, std::vector<std::string> &dirs)
248 {
249     for (const ExtensionAbilityInfo &info : bundleInfo.extensionInfos) {
250         if (!info.needCreateSandbox) {
251             continue;
252         }
253         std::string extensionDir = ServiceConstants::EXTENSION_DIR + info.moduleName +
254             ServiceConstants::FILE_SEPARATOR_LINE + info.name +
255             ServiceConstants::FILE_SEPARATOR_PLUS + info.bundleName;
256         dirs.emplace_back(extensionDir);
257     }
258 }
259 
ProcessUpdateAppLogDir(const std::vector<BundleInfo> & bundleInfos,int32_t userId)260 void UpdateAppDataMgr::ProcessUpdateAppLogDir(const std::vector<BundleInfo> &bundleInfos, int32_t userId)
261 {
262     for (const auto &bundleInfo : bundleInfos) {
263         if (userId != Constants::DEFAULT_USERID && bundleInfo.singleton) {
264             continue;
265         }
266         if (!CreateBundleLogDir(bundleInfo, userId)) {
267             APP_LOGD("log dir create failed or already exists");
268         }
269     }
270 }
271 
ProcessNewBackupDir(const std::vector<BundleInfo> & bundleInfos,int32_t userId)272 void UpdateAppDataMgr::ProcessNewBackupDir(const std::vector<BundleInfo> &bundleInfos, int32_t userId)
273 {
274     APP_LOGI_NOFUNC("process new back up dir, start");
275     for (const auto &bundleInfo : bundleInfos) {
276         if (bundleInfo.appIndex > 0) {
277             APP_LOGI("bundleName:%{public}s appIndex %{public}d clone app no need to create",
278                 bundleInfo.name.c_str(), bundleInfo.appIndex);
279             continue;
280         }
281         if (bundleInfo.singleton) {
282             CreateNewBackupDir(bundleInfo, Constants::DEFAULT_USERID);
283             continue;
284         }
285         if (userId != Constants::DEFAULT_USERID) {
286             CreateNewBackupDir(bundleInfo, userId);
287         }
288     }
289     APP_LOGI_NOFUNC("process new back up dir, end");
290 }
291 
CreateNewBackupDir(const BundleInfo & bundleInfo,int32_t userId)292 void UpdateAppDataMgr::CreateNewBackupDir(const BundleInfo &bundleInfo, int32_t userId)
293 {
294     std::string parentEl1Dir = BUNDLE_BACKUP_HOME_PATH_EL1_NEW;
295     parentEl1Dir = parentEl1Dir.replace(parentEl1Dir.find("%"), 1, std::to_string(userId));
296     std::string parentEl2Dir = BUNDLE_BACKUP_HOME_PATH_EL2_NEW;
297     parentEl2Dir = parentEl2Dir.replace(parentEl2Dir.find("%"), 1, std::to_string(userId));
298     if (!BundleUtil::IsExistDir(parentEl1Dir) || !BundleUtil::IsExistDir(parentEl2Dir)) {
299         APP_LOGE("parent dir(%{public}s or %{public}s) missing: backup", parentEl1Dir.c_str(), parentEl2Dir.c_str());
300         return;
301     }
302     std::string backupDirEl1 = parentEl1Dir + bundleInfo.name + BUNDLE_BACKUP_INNER_DIR;
303     std::string backupDirEl2 = parentEl2Dir + bundleInfo.name + BUNDLE_BACKUP_INNER_DIR;
304     std::vector<std::string> backupDirList;
305     backupDirList.emplace_back(backupDirEl1);
306     backupDirList.emplace_back(backupDirEl2);
307 
308     for (const std::string &dir : backupDirList) {
309         bool isDirExisted = false;
310         auto result = InstalldClient::GetInstance()->IsExistDir(dir, isDirExisted);
311         if (result != ERR_OK || isDirExisted) {
312             continue;
313         }
314         APP_LOGI("bundle %{public}s not exist backup dir", bundleInfo.name.c_str());
315         result = InstalldClient::GetInstance()->Mkdir(dir, S_IRWXU | S_IRWXG | S_ISGID,
316             bundleInfo.uid, ServiceConstants::BACKU_HOME_GID);
317         if (result != ERR_OK) {
318             APP_LOGW("bundle %{public}s create backup dir for user %{public}d failed",
319                 bundleInfo.name.c_str(), userId);
320         }
321     }
322 }
323 
CreateBundleLogDir(const BundleInfo & bundleInfo,int32_t userId)324 bool UpdateAppDataMgr::CreateBundleLogDir(const BundleInfo &bundleInfo, int32_t userId)
325 {
326     std::string parentDir = ServiceConstants::BUNDLE_APP_DATA_BASE_DIR + ServiceConstants::BUNDLE_EL[1] +
327         ServiceConstants::PATH_SEPARATOR + std::to_string(userId) + ServiceConstants::LOG;
328     if (!BundleUtil::IsExistDir(parentDir)) {
329         APP_LOGE("parent dir(%{public}s) missing: log", parentDir.c_str());
330         return false;
331     }
332     std::string bundleLogDir = parentDir + bundleInfo.name;
333     bool isExist = false;
334     if (InstalldClient::GetInstance()->IsExistDir(bundleLogDir, isExist) != ERR_OK) {
335         APP_LOGE("path: %{public}s IsExistDir failed", bundleLogDir.c_str());
336         return false;
337     }
338     if (isExist) {
339         APP_LOGD("path: %{public}s is exist", bundleLogDir.c_str());
340         return false;
341     }
342     if (InstalldClient::GetInstance()->Mkdir(
343         bundleLogDir, S_IRWXU | S_IRWXG, bundleInfo.uid, ServiceConstants::LOG_DIR_GID) != ERR_OK) {
344         APP_LOGE("CreateBundleLogDir failed");
345         return false;
346     }
347     return true;
348 }
349 
ProcessFileManagerDir(const std::vector<BundleInfo> & bundleInfos,int32_t userId)350 void UpdateAppDataMgr::ProcessFileManagerDir(const std::vector<BundleInfo> &bundleInfos, int32_t userId)
351 {
352     for (const auto &bundleInfo : bundleInfos) {
353         if (userId != Constants::DEFAULT_USERID && bundleInfo.singleton) {
354             continue;
355         }
356         CreateBundleCloudDir(bundleInfo, userId);
357     }
358 }
359 
CreateBundleCloudDir(const BundleInfo & bundleInfo,int32_t userId)360 bool UpdateAppDataMgr::CreateBundleCloudDir(const BundleInfo &bundleInfo, int32_t userId)
361 {
362     std::string parentDir = "/data/service/el2/%/hmdfs/cloud/data/";
363     parentDir = parentDir.replace(parentDir.find("%"), 1, std::to_string(userId));
364     if (!BundleUtil::IsExistDir(parentDir)) {
365         APP_LOGE("parent dir(%{public}s) missing: cloud", parentDir.c_str());
366         return false;
367     }
368     std::string bundleCloudDir = parentDir + bundleInfo.name;
369     bool isExist = false;
370     if (InstalldClient::GetInstance()->IsExistDir(bundleCloudDir, isExist) != ERR_OK) {
371         APP_LOGE("path: %{private}s IsExistDir failed", bundleCloudDir.c_str());
372         return false;
373     }
374     if (isExist) {
375         APP_LOGD("path: %{private}s is exist", bundleCloudDir.c_str());
376         return false;
377     }
378     if (!InstalldClient::GetInstance()->Mkdir(bundleCloudDir, S_IRWXU | S_IRWXG | S_ISGID,
379         bundleInfo.uid, ServiceConstants::DFS_GID)) {
380         static std::once_flag cloudOnce;
381         std::call_once(cloudOnce, [bundleInfo]() {
382             APP_LOGW("CreateCloudDir failed for bundle %{private}s errno:%{public}d",
383                      bundleInfo.name.c_str(), errno);
384         });
385     }
386     return true;
387 }
388 }  // namespace AppExecFwk
389 }  // namespace OHOS