1 /*
2  * Copyright (c) 2022-2024 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 "module_ipc/service.h"
17 
18 #include <algorithm>
19 #include <chrono>
20 #include <cerrno>
21 #include <cstddef>
22 #include <cstdint>
23 #include <cstring>
24 #include <regex>
25 
26 #include <fcntl.h>
27 #include <iomanip>
28 #include <sys/stat.h>
29 #include <sys/types.h>
30 #include <sys/vfs.h>
31 
32 #include <directory_ex.h>
33 
34 #include "ability_manager_client.h"
35 #include "accesstoken_kit.h"
36 #include "b_anony/b_anony.h"
37 #include "b_error/b_error.h"
38 #include "b_error/b_excep_utils.h"
39 #include "b_file_info.h"
40 #include "b_json/b_json_cached_entity.h"
41 #include "b_jsonutil/b_jsonutil.h"
42 #include "b_ohos/startup/backup_para.h"
43 #include "b_process/b_multiuser.h"
44 #include "b_radar/b_radar.h"
45 #include "b_resources/b_constants.h"
46 #include "b_sa/b_sa_utils.h"
47 #include "bundle_mgr_client.h"
48 #include "filemgmt_libhilog.h"
49 #include "hisysevent.h"
50 #include "hitrace_meter.h"
51 #include "ipc_skeleton.h"
52 #include "access_token.h"
53 #include "tokenid_kit.h"
54 #include "module_app_gallery/app_gallery_dispose_proxy.h"
55 #include "module_external/bms_adapter.h"
56 #include "module_external/sms_adapter.h"
57 #include "module_ipc/svc_backup_connection.h"
58 #include "module_ipc/svc_restore_deps_manager.h"
59 #include "module_notify/notify_work_service.h"
60 #include "parameter.h"
61 #include "parameters.h"
62 #include "system_ability_definition.h"
63 
64 namespace OHOS::FileManagement::Backup {
65 using namespace std;
66 
MakeDetailList(const vector<BundleName> & bundleNames)67 vector<BIncrementalData> Service::MakeDetailList(const vector<BundleName> &bundleNames)
68 {
69     vector<BIncrementalData> bundleDetails {};
70     for (auto bundleName : bundleNames) {
71         bundleDetails.emplace_back(BIncrementalData {bundleName, 0});
72     }
73     return bundleDetails;
74 }
75 
Finish()76 ErrCode Service::Finish()
77 {
78     HITRACE_METER_NAME(HITRACE_TAG_FILEMANAGEMENT, __PRETTY_FUNCTION__);
79     try {
80         VerifyCaller(session_->GetScenario());
81         session_->Finish();
82         OnAllBundlesFinished(BError(BError::Codes::OK));
83         return BError(BError::Codes::OK);
84     } catch (const BError &e) {
85         ReleaseOnException();
86         HILOGE("Failde to Finish");
87         return e.GetCode();
88     }
89 }
90 
PublishFile(const BFileInfo & fileInfo)91 ErrCode Service::PublishFile(const BFileInfo &fileInfo)
92 {
93     HITRACE_METER_NAME(HITRACE_TAG_FILEMANAGEMENT, __PRETTY_FUNCTION__);
94     try {
95         VerifyCaller(IServiceReverse::Scenario::RESTORE);
96         if (!fileInfo.fileName.empty()) {
97             HILOGE("Forbit to use publishFile with fileName for App");
98             return EPERM;
99         }
100         auto backUpConnection = session_->GetExtConnection(fileInfo.owner);
101         if (backUpConnection == nullptr) {
102             HILOGE("PublishFile error, backUpConnection is empty");
103             return BError(BError::Codes::SA_INVAL_ARG);
104         }
105         auto proxy = backUpConnection->GetBackupExtProxy();
106         if (!proxy) {
107             HILOGE("PublishFile error, Extension backup Proxy is empty");
108             return BError(BError::Codes::SA_INVAL_ARG);
109         }
110         ErrCode res = proxy->PublishFile(fileInfo.fileName);
111         if (res) {
112             HILOGE("Failed to publish file for backup extension");
113         }
114         return res;
115     } catch (const BError &e) {
116         return e.GetCode();
117     } catch (const exception &e) {
118         HILOGI("Catched an unexpected low-level exception %{public}s", e.what());
119         return EPERM;
120     } catch (...) {
121         HILOGI("Unexpected exception");
122         return EPERM;
123     }
124 }
125 
AppFileReady(const string & fileName,UniqueFd fd,int32_t errCode)126 ErrCode Service::AppFileReady(const string &fileName, UniqueFd fd, int32_t errCode)
127 {
128     HITRACE_METER_NAME(HITRACE_TAG_FILEMANAGEMENT, __PRETTY_FUNCTION__);
129     try {
130         string callerName = VerifyCallerAndGetCallerName();
131         if (fileName.find('/') != string::npos) {
132             throw BError(BError::Codes::SA_INVAL_ARG, "Filename is not valid");
133         }
134         if (fileName == BConstants::EXT_BACKUP_MANAGE) {
135             fd = session_->OnBundleExtManageInfo(callerName, move(fd));
136         }
137         session_->GetServiceReverseProxy()->BackupOnFileReady(callerName, fileName, move(fd), errCode);
138         FileReadyRadarReport(callerName, fileName, errCode, session_->GetScenario());
139         if (session_->OnBundleFileReady(callerName, fileName)) {
140             auto backUpConnection = session_->GetExtConnection(callerName);
141             if (backUpConnection == nullptr) {
142                 HILOGE("AppFileReady error, backUpConnection is empty");
143                 return BError(BError::Codes::SA_INVAL_ARG);
144             }
145             auto proxy = backUpConnection->GetBackupExtProxy();
146             if (!proxy) {
147                 HILOGE("AppFileReady error, Extension backup Proxy is empty");
148                 return BError(BError::Codes::SA_INVAL_ARG);
149             }
150             // 通知extension清空缓存
151             proxy->HandleClear();
152             // 清除Timer
153             session_->StopFwkTimer(callerName);
154             session_->StopExtTimer(callerName);
155             // 通知TOOL 备份完成
156             session_->GetServiceReverseProxy()->BackupOnBundleFinished(BError(BError::Codes::OK), callerName);
157             BundleEndRadarReport(callerName, BError(BError::Codes::OK), session_->GetScenario());
158             // 断开extension
159             backUpConnection->DisconnectBackupExtAbility();
160             ClearSessionAndSchedInfo(callerName);
161         }
162         OnAllBundlesFinished(BError(BError::Codes::OK));
163         return BError(BError::Codes::OK);
164     } catch (const BError &e) {
165         return e.GetCode(); // 任意异常产生,终止监听该任务
166     } catch (const exception &e) {
167         HILOGI("Catched an unexpected low-level exception %{public}s", e.what());
168         return EPERM;
169     } catch (...) {
170         HILOGI("Unexpected exception");
171         return EPERM;
172     }
173 }
174 
AppDone(ErrCode errCode)175 ErrCode Service::AppDone(ErrCode errCode)
176 {
177     HITRACE_METER_NAME(HITRACE_TAG_FILEMANAGEMENT, __PRETTY_FUNCTION__);
178     try {
179         if (session_ == nullptr) {
180             HILOGE("App finish error, session info is empty");
181             return BError(BError::Codes::SA_INVAL_ARG);
182         }
183         string callerName = VerifyCallerAndGetCallerName();
184         HILOGI("Begin, callerName is: %{public}s, errCode: %{public}d", callerName.c_str(), errCode);
185         if (session_->OnBundleFileReady(callerName) || errCode != BError(BError::Codes::OK)) {
186             std::shared_ptr<ExtensionMutexInfo> mutexPtr = GetExtensionMutex(callerName);
187             if (mutexPtr == nullptr) {
188                 HILOGE("extension mutex ptr is nullptr");
189                 return BError(BError::Codes::SA_INVAL_ARG);
190             }
191             std::lock_guard<std::mutex> lock(mutexPtr->callbackMutex);
192             auto backUpConnection = session_->GetExtConnection(callerName);
193             if (backUpConnection == nullptr) {
194                 HILOGE("App finish error, backUpConnection is empty");
195                 return BError(BError::Codes::SA_INVAL_ARG);
196             }
197             auto proxy = backUpConnection->GetBackupExtProxy();
198             if (!proxy) {
199                 throw BError(BError::Codes::SA_INVAL_ARG, "Extension backup Proxy is empty");
200             }
201             proxy->HandleClear();
202             session_->StopFwkTimer(callerName);
203             session_->StopExtTimer(callerName);
204             backUpConnection->DisconnectBackupExtAbility();
205             ClearSessionAndSchedInfo(callerName);
206             NotifyCallerCurAppDone(errCode, callerName);
207         }
208         RemoveExtensionMutex(callerName);
209         OnAllBundlesFinished(BError(BError::Codes::OK));
210         return BError(BError::Codes::OK);
211     } catch (const BError &e) {
212         ReleaseOnException();
213         HILOGE("AppDone error, err code is: %{public}d", e.GetCode());
214         return e.GetCode(); // 任意异常产生,终止监听该任务
215     } catch (const exception &e) {
216         ReleaseOnException();
217         HILOGI("Catched an unexpected low-level exception %{public}s", e.what());
218         return EPERM;
219     } catch (...) {
220         HILOGI("Unexpected exception");
221         return EPERM;
222     }
223 }
224 
LaunchBackupExtension(const BundleName & bundleName)225 ErrCode Service::LaunchBackupExtension(const BundleName &bundleName)
226 {
227     HITRACE_METER_NAME(HITRACE_TAG_FILEMANAGEMENT, __PRETTY_FUNCTION__);
228     try {
229         HILOGI("begin %{public}s", bundleName.data());
230         IServiceReverse::Scenario scenario = session_->GetScenario();
231         BConstants::ExtensionAction action;
232         if (scenario == IServiceReverse::Scenario::BACKUP || scenario == IServiceReverse::Scenario::CLEAN) {
233             action = BConstants::ExtensionAction::BACKUP;
234         } else if (scenario == IServiceReverse::Scenario::RESTORE) {
235             action = BConstants::ExtensionAction::RESTORE;
236         } else {
237             throw BError(BError::Codes::SA_INVAL_ARG, "Failed to scenario");
238         }
239         if (SAUtils::IsSABundleName(bundleName)) {
240             return LaunchBackupSAExtension(bundleName);
241         }
242         AAFwk::Want want;
243         SetWant(want, bundleName, action);
244         auto backUpConnection = session_->GetExtConnection(bundleName);
245         if (backUpConnection == nullptr) {
246             HILOGE("LaunchBackupExtension error, backUpConnection is empty");
247             return BError(BError::Codes::SA_INVAL_ARG);
248         }
249         if (backUpConnection->IsExtAbilityConnected() && !backUpConnection->WaitDisconnectDone()) {
250             HILOGE("LaunchBackupExtension error, WaitDisconnectDone failed");
251             return BError(BError::Codes::SA_INVAL_ARG);
252         }
253         ErrCode ret = backUpConnection->ConnectBackupExtAbility(want, session_->GetSessionUserId());
254         if (ret) {
255             HILOGE("ConnectBackupExtAbility faild, bundleName:%{public}s, ret:%{public}d", bundleName.c_str(), ret);
256             ExtensionConnectFailRadarReport(bundleName, ret, scenario);
257             return BError(BError::Codes::SA_BOOT_EXT_FAIL);
258         }
259         return BError(BError::Codes::OK);
260     } catch (const BError &e) {
261         return e.GetCode();
262     } catch (const exception &e) {
263         HILOGI("Catched an unexpected low-level exception %{public}s", e.what());
264         return EPERM;
265     } catch (...) {
266         HILOGI("Unexpected exception");
267         return EPERM;
268     }
269 }
270 
SetWant(AAFwk::Want & want,const BundleName & bundleName,const BConstants::ExtensionAction & action)271 void Service::SetWant(AAFwk::Want &want, const BundleName &bundleName, const BConstants::ExtensionAction &action)
272 {
273     BJsonUtil::BundleDetailInfo bundleDetail = BJsonUtil::ParseBundleNameIndexStr(bundleName);
274     string backupExtName = session_->GetBackupExtName(bundleName); /* new device app ext name */
275     HILOGI("BackupExtName: %{public}s, bundleName: %{public}s", backupExtName.data(), bundleName.data());
276     string versionName = session_->GetBundleVersionName(bundleName); /* old device app version name */
277     int64_t versionCode = session_->GetBundleVersionCode(bundleName); /* old device app version code */
278     RestoreTypeEnum restoreType = session_->GetBundleRestoreType(bundleName); /* app restore type */
279     string bundleExtInfo = session_->GetBackupExtInfo(bundleName);
280     HILOGI("BundleExtInfo is:%{public}s", GetAnonyString(bundleExtInfo).c_str());
281     want.SetElementName(bundleDetail.bundleName, backupExtName);
282     want.SetParam(BConstants::EXTENSION_ACTION_PARA, static_cast<int>(action));
283     want.SetParam(BConstants::EXTENSION_VERSION_CODE_PARA, static_cast<long>(versionCode));
284     want.SetParam(BConstants::EXTENSION_RESTORE_TYPE_PARA, static_cast<int>(restoreType));
285     want.SetParam(BConstants::EXTENSION_VERSION_NAME_PARA, versionName);
286     want.SetParam(BConstants::EXTENSION_RESTORE_EXT_INFO_PARA, bundleExtInfo);
287     want.SetParam(BConstants::EXTENSION_BACKUP_EXT_INFO_PARA, bundleExtInfo);
288     want.SetParam(BConstants::EXTENSION_APP_CLONE_INDEX_PARA, bundleDetail.bundleIndex);
289 }
290 
GetSupportBackupBundleNames(vector<BJsonEntityCaps::BundleInfo> & backupInfos,bool isIncBackup,const std::vector<std::string> & srcBundleNames)291 std::vector<std::string> Service::GetSupportBackupBundleNames(vector<BJsonEntityCaps::BundleInfo> &backupInfos,
292     bool isIncBackup, const std::vector<std::string> &srcBundleNames)
293 {
294     HILOGI("Begin");
295     std::vector<std::string> supportBackupNames;
296     for (auto info : backupInfos) {
297         HILOGI("Current backupInfo bundleName:%{public}s, index:%{public}d, extName:%{public}s", info.name.c_str(),
298             info.appIndex, info.extensionName.c_str());
299         std::string bundleNameIndexInfo = BJsonUtil::BuildBundleNameIndexInfo(info.name, info.appIndex);
300         if (!info.allToBackup) {
301             if (isIncBackup) {
302                 session_->GetServiceReverseProxy()->IncrementalBackupOnBundleStarted(
303                     BError(BError::Codes::SA_FORBID_BACKUP_RESTORE), bundleNameIndexInfo);
304             } else {
305                 session_->GetServiceReverseProxy()->BackupOnBundleStarted(
306                     BError(BError::Codes::SA_FORBID_BACKUP_RESTORE), bundleNameIndexInfo);
307             }
308             BundleBeginRadarReport(bundleNameIndexInfo, BError(BError::Codes::SA_FORBID_BACKUP_RESTORE).GetCode(),
309                 IServiceReverse::Scenario::BACKUP);
310             continue;
311         }
312         supportBackupNames.emplace_back(bundleNameIndexInfo);
313     }
314     HandleNotSupportBundleNames(srcBundleNames, supportBackupNames, isIncBackup);
315     HILOGI("End");
316     return supportBackupNames;
317 }
318 
SetCurrentSessProperties(BJsonEntityCaps::BundleInfo & info,std::map<std::string,bool> & isClearDataFlags,const std::string & bundleNameIndexInfo)319 void Service::SetCurrentSessProperties(BJsonEntityCaps::BundleInfo &info,
320     std::map<std::string, bool> &isClearDataFlags, const std::string &bundleNameIndexInfo)
321 {
322     HILOGI("Begin");
323     if (session_ == nullptr) {
324         HILOGE("Set currrent session properties error, session is empty");
325         return;
326     }
327     session_->SetBundleDataSize(bundleNameIndexInfo, info.spaceOccupied);
328     auto iter = isClearDataFlags.find(bundleNameIndexInfo);
329     if (iter != isClearDataFlags.end()) {
330         session_->SetClearDataFlag(bundleNameIndexInfo, iter->second);
331     }
332     HILOGI("End");
333 }
334 
HandleNotSupportBundleNames(const std::vector<std::string> & srcBundleNames,std::vector<std::string> & supportBundleNames,bool isIncBackup)335 void Service::HandleNotSupportBundleNames(const std::vector<std::string> &srcBundleNames,
336     std::vector<std::string> &supportBundleNames, bool isIncBackup)
337 {
338     for (auto bundleName : srcBundleNames) {
339         auto it = std::find(supportBundleNames.begin(), supportBundleNames.end(), bundleName);
340         if (it != supportBundleNames.end()) {
341             continue;
342         }
343         HILOGE("bundleName:%{public}s, can not find from supportBundleNames", bundleName.c_str());
344         if (isIncBackup) {
345             session_->GetServiceReverseProxy()->IncrementalBackupOnBundleStarted(
346                 BError(BError::Codes::SA_BUNDLE_INFO_EMPTY), bundleName);
347         } else {
348             session_->GetServiceReverseProxy()->BackupOnBundleStarted(
349                 BError(BError::Codes::SA_BUNDLE_INFO_EMPTY), bundleName);
350         }
351     }
352 }
353 }
354