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