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