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