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 "module_utils.h"
17 #include <cerrno>
18 #include <cstdio>
19 #include <dirent.h>
20 #include <sys/mount.h>
21 #include <sys/stat.h>
22 #include <sys/types.h>
23 #include <thread>
24 #include <fcntl.h>
25 #include "init_reboot.h"
26 #include "if_system_ability_manager.h"
27 #include "iremote_object.h"
28 #include "iservice_registry.h"
29 #include "directory_ex.h"
30 #include "file_ex.h"
31 #include "log/log.h"
32 #include "package/package.h"
33 #include "parameter.h"
34 #include "parameters.h"
35 #include "singleton.h"
36 #include "utils.h"
37 #include "module_constants.h"
38 #include "module_file.h"
39
40 namespace OHOS {
41 namespace SysInstaller {
42 using namespace Updater;
43
44 namespace {
45 constexpr const char *BOOT_COMPLETE_PARAM = "bootevent.boot.completed";
46 constexpr const char *BOOT_SUCCESS_VALUE = "true";
47 constexpr int32_t PARAM_VALUE_SIZE = 10;
48 constexpr std::chrono::milliseconds WAIT_FOR_FILE_TIME(5);
49 constexpr uint32_t BYTE_SIZE = 8;
50 constexpr mode_t ALL_PERMISSIONS = 0777;
51 constexpr const char *PREFIXES[] = {UPDATE_INSTALL_DIR, UPDATE_ACTIVE_DIR, UPDATE_BACKUP_DIR, MODULE_PREINSTALL_DIR};
52 }
53
CreateDirIfNeeded(const std::string & fpInfo,mode_t mode)54 bool CreateDirIfNeeded(const std::string &fpInfo, mode_t mode)
55 {
56 struct stat statData;
57
58 if (stat(fpInfo.c_str(), &statData) != 0) {
59 if (errno == ENOENT) {
60 if (mkdir(fpInfo.c_str(), mode) != 0) {
61 LOG(ERROR) << "Could not mkdir " << fpInfo;
62 return false;
63 }
64 } else {
65 LOG(ERROR) << "Could not stat " << fpInfo;
66 return false;
67 }
68 } else {
69 if (!S_ISDIR(statData.st_mode)) {
70 LOG(ERROR) << fpInfo << " exists and is not a directory";
71 return false;
72 }
73 }
74
75 // Need to manually call chmod because mkdir will create a folder with
76 // permissions mode & ~umask.
77 if (chmod(fpInfo.c_str(), mode) != 0) {
78 LOG(WARNING) << "Could not chmod " << fpInfo;
79 }
80 return true;
81 }
82
CheckPathExists(const std::string & path)83 bool CheckPathExists(const std::string &path)
84 {
85 struct stat buffer;
86 return stat(path.c_str(), &buffer) == 0;
87 }
88
CheckFileSuffix(const std::string & file,const std::string & suffix)89 bool CheckFileSuffix(const std::string &file, const std::string &suffix)
90 {
91 std::size_t pos = file.find_last_of('.');
92 if (pos == std::string::npos) {
93 LOG(ERROR) << "Invalid file name " << file;
94 return false;
95 }
96 std::string fileSuffix = file.substr(pos);
97 return fileSuffix == suffix;
98 }
99
GetFileName(const std::string & file)100 std::string GetFileName(const std::string &file)
101 {
102 std::size_t startPos = file.find_last_of('/') + 1;
103 std::size_t endPos = file.find_last_of('.');
104 return file.substr(startPos, endPos - startPos);
105 }
106
107 // Get hmpName from path such as "/data/module_update_package/hmpName/sa1.zip"
GetHmpName(const std::string & filePath)108 std::string GetHmpName(const std::string &filePath)
109 {
110 std::size_t endPos = filePath.find_last_of('/');
111 if (endPos == std::string::npos) {
112 LOG(ERROR) << "Invalid package path " << filePath;
113 return "";
114 }
115
116 std::size_t startPos = 0;
117 for (auto &iter : PREFIXES) {
118 if (StartsWith(filePath, iter)) {
119 startPos = strlen(iter) + 1;
120 break;
121 }
122 }
123 if (startPos == 0 || startPos >= endPos) {
124 LOG(ERROR) << "Invalid package path " << filePath;
125 return "";
126 }
127 return filePath.substr(startPos, endPos - startPos);
128 }
129
WaitForFile(const std::string & fpInfo,const std::chrono::nanoseconds & timeout)130 bool WaitForFile(const std::string &fpInfo, const std::chrono::nanoseconds &timeout)
131 {
132 Timer timer;
133 bool hasSlept = false;
134 while (timer.duration() < timeout) {
135 struct stat buffer;
136 if (stat(fpInfo.c_str(), &buffer) != -1) {
137 if (hasSlept) {
138 LOG(INFO) << "wait for '" << fpInfo << "' took " << timer;
139 }
140 return true;
141 }
142 std::this_thread::sleep_for(WAIT_FOR_FILE_TIME);
143 hasSlept = true;
144 }
145 LOG(ERROR) << "wait for '" << fpInfo << "' timed out and took " << timer;
146 return false;
147 }
148
StartsWith(const std::string & str,const std::string & prefix)149 bool StartsWith(const std::string &str, const std::string &prefix)
150 {
151 return str.substr(0, prefix.size()) == prefix;
152 }
153
ReadFullyAtOffset(int fd,uint8_t * data,size_t count,off_t offset)154 bool ReadFullyAtOffset(int fd, uint8_t *data, size_t count, off_t offset)
155 {
156 while (count > 0) {
157 ssize_t readSize = pread(fd, data, count, offset);
158 if (readSize <= 0) {
159 return false;
160 }
161 data += readSize;
162 count -= static_cast<size_t>(readSize);
163 offset += readSize;
164 }
165 return true;
166 }
167
WriteFullyAtOffset(int fd,const uint8_t * data,size_t count,off_t offset)168 bool WriteFullyAtOffset(int fd, const uint8_t *data, size_t count, off_t offset)
169 {
170 while (count > 0) {
171 ssize_t writeSize = pwrite(fd, data, count, offset);
172 if (writeSize <= 0) {
173 return false;
174 }
175 data += writeSize;
176 count -= static_cast<size_t>(writeSize);
177 offset += writeSize;
178 }
179 return true;
180 }
181
ReadLE16(const uint8_t * buff)182 uint16_t ReadLE16(const uint8_t *buff)
183 {
184 if (buff == nullptr) {
185 LOG(ERROR) << "buff is null";
186 return 0;
187 }
188 uint16_t value16 = buff[0];
189 value16 += static_cast<uint16_t>(buff[1] << BYTE_SIZE);
190 return value16;
191 }
192
ReadLE32(const uint8_t * buff)193 uint32_t ReadLE32(const uint8_t *buff)
194 {
195 if (buff == nullptr) {
196 LOG(ERROR) << "buff is null";
197 return 0;
198 }
199 uint16_t low = ReadLE16(buff);
200 uint16_t high = ReadLE16(buff + sizeof(uint16_t));
201 uint32_t value = ((static_cast<uint32_t>(high)) << (BYTE_SIZE * sizeof(uint16_t))) | low;
202 return value;
203 }
204
operator <<(std::ostream & os,const Timer & timer)205 std::ostream &operator<<(std::ostream &os, const Timer &timer)
206 {
207 os << timer.duration().count() << "ms";
208 return os;
209 }
210
GetRealPath(const std::string & filePath)211 std::string GetRealPath(const std::string &filePath)
212 {
213 char fpInfo[PATH_MAX] = {'\0'};
214 if (realpath(filePath.c_str(), fpInfo) == nullptr) {
215 LOG(ERROR) << "get real path fail " << filePath;
216 return "";
217 }
218 if (!CheckPathExists(fpInfo)) {
219 LOG(ERROR) << "path " << fpInfo << " doesn't exist";
220 return "";
221 }
222 std::string realPath(fpInfo);
223 return realPath;
224 }
225
RevertImageCert(const std::string & hmpName,bool revertMore)226 __attribute__((weak)) bool RevertImageCert(const std::string &hmpName, bool revertMore)
227 {
228 LOG(INFO) << "Revert image cert, default is true";
229 return true;
230 }
231
VerityInfoWrite(const ModuleFile & file)232 __attribute__((weak)) bool VerityInfoWrite(const ModuleFile &file)
233 {
234 LOG(INFO) << "VerityInfoWrite, default is true.";
235 return true;
236 }
237
PrepareFileToDestDir(const std::string & pkgPath,const std::string & outPath)238 __attribute__((weak)) bool PrepareFileToDestDir(const std::string &pkgPath, const std::string &outPath)
239 {
240 if (ExtraPackageDir(pkgPath.c_str(), nullptr, nullptr, outPath.c_str()) != 0) {
241 LOG(ERROR) << "Failed to unpack hmp package " << pkgPath;
242 return false;
243 }
244 return true;
245 }
246
SetModuleVersion(const ModuleFile & file)247 __attribute__((weak)) void SetModuleVersion(const ModuleFile &file)
248 {
249 LOG(INFO) << "Set module version.";
250 }
251
Revert(const std::string & hmpName,bool reboot)252 void Revert(const std::string &hmpName, bool reboot)
253 {
254 LOG(INFO) << "RevertAndReboot, reboot: " << reboot << "; hmpName: " << hmpName;
255 std::string installPath = std::string(UPDATE_INSTALL_DIR) + "/" + hmpName;
256 if (CheckPathExists(installPath)) {
257 if (!ForceRemoveDirectory(installPath)) {
258 LOG(ERROR) << "Failed to remove installPath: " << installPath << " err=" << errno;
259 return;
260 }
261 }
262 struct stat statData;
263 std::string activePath = std::string(UPDATE_ACTIVE_DIR) + "/" + hmpName;
264 int ret = stat(activePath.c_str(), &statData);
265 if (ret != 0) {
266 LOG(ERROR) << "Failed to access " << activePath << " err=" << errno;
267 return;
268 }
269 if (!ForceRemoveDirectory(activePath)) {
270 LOG(ERROR) << "Failed to remove " << activePath << " err=" << errno;
271 return;
272 }
273
274 std::string backupPath = std::string(UPDATE_BACKUP_DIR) + "/" + hmpName;
275 if (CheckPathExists(backupPath)) {
276 ret = rename(backupPath.c_str(), activePath.c_str());
277 if (ret != 0) {
278 LOG(ERROR) << "Failed to rename " << backupPath << " to " << activePath << " err=" << errno;
279 }
280 if (ret == 0 && chmod(activePath.c_str(), statData.st_mode & ALL_PERMISSIONS) != 0) {
281 LOG(ERROR) << "Failed to restore original permissions for " << activePath << " err=" << errno;
282 }
283 }
284 RevertImageCert(hmpName, true);
285 sync();
286 if (reboot) {
287 LOG(INFO) << "Rebooting";
288 DoReboot("module_update revert.");
289 }
290 }
291
IsHotSa(int32_t saId)292 bool IsHotSa(int32_t saId)
293 {
294 std::vector<int32_t> onDemandSaIds;
295 sptr<ISystemAbilityManager> samgr = SystemAbilityManagerClient::GetInstance().GetSystemAbilityManager();
296 if (samgr == nullptr) {
297 LOG(ERROR) << "get system ability manager error";
298 return false;
299 }
300 samgr->GetOnDemandSystemAbilityIds(onDemandSaIds);
301 if (onDemandSaIds.empty()) {
302 LOG(ERROR) << "get ondemand saIds fail";
303 return false;
304 }
305 if (find(onDemandSaIds.begin(), onDemandSaIds.end(), saId) == onDemandSaIds.end()) {
306 LOG(INFO) << "this is not an ondemand sa, saId=" << saId;
307 return false;
308 }
309 return true;
310 }
311
IsRunning(int32_t saId)312 bool IsRunning(int32_t saId)
313 {
314 sptr<ISystemAbilityManager> samgr = SystemAbilityManagerClient::GetInstance().GetSystemAbilityManager();
315 if (samgr == nullptr) {
316 LOG(ERROR) << "get system ability manager error";
317 return false;
318 }
319 auto object = samgr->CheckSystemAbility(saId);
320 if (object == nullptr) {
321 LOG(INFO) << "sa not exists, saId=" << saId;
322 return false;
323 }
324 return true;
325 }
326
CheckBootComplete(void)327 bool CheckBootComplete(void)
328 {
329 char value[PARAM_VALUE_SIZE] = "";
330 int ret = GetParameter(BOOT_COMPLETE_PARAM, "", value, PARAM_VALUE_SIZE);
331 if (ret < 0) {
332 LOG(ERROR) << "Failed to get parameter " << BOOT_COMPLETE_PARAM;
333 return false;
334 }
335 return strcmp(value, BOOT_SUCCESS_VALUE) == 0;
336 }
337
GetDeviceSaSdkVersion(void)338 std::string GetDeviceSaSdkVersion(void)
339 {
340 std::string sdkVersion = system::GetParameter("const.build.sa_sdk_version", "");
341 if (sdkVersion.empty()) {
342 LOG(ERROR) << "get device sa sdk version failed.";
343 return sdkVersion;
344 }
345 return sdkVersion;
346 }
347
GetDeviceApiVersion(void)348 int GetDeviceApiVersion(void)
349 {
350 std::string apiVersion = system::GetParameter("const.ohos.apiversion", "");
351 if (apiVersion.empty()) {
352 LOG(ERROR) << "get device api version failed.";
353 return 0;
354 }
355 return Utils::String2Int<int>(apiVersion, Utils::N_DEC);
356 }
357
GetContentFromZip(const std::string & zipPath,const std::string & fpInfo)358 std::string GetContentFromZip(const std::string &zipPath, const std::string &fpInfo)
359 {
360 ModuleZipHelper helper(zipPath);
361 if (!helper.IsValid()) {
362 LOG(ERROR) << "Failed to open file: " << zipPath;
363 return "";
364 }
365 std::string content;
366 if (!ExtractZipFile(helper, fpInfo, content)) {
367 LOG(ERROR) << "Failed to extract: " << fpInfo << " from package: " << zipPath;
368 return "";
369 }
370 return content;
371 }
372
RemoveSpecifiedDir(const std::string & fpInfo,bool keepDir)373 bool RemoveSpecifiedDir(const std::string &fpInfo, bool keepDir)
374 {
375 if (!CheckPathExists(fpInfo)) {
376 return false;
377 }
378 LOG(INFO) << "Clear specified dir: " << fpInfo << "; keepdir: " << keepDir;
379 if (!keepDir) {
380 if (!ForceRemoveDirectory(fpInfo)) {
381 LOG(WARNING) << "Failed to remove: " << fpInfo << ", err: " << errno;
382 return false;
383 }
384 return true;
385 }
386 if (!std::filesystem::is_directory(fpInfo)) {
387 LOG(WARNING) << "The file is not a directory: " << fpInfo.c_str();
388 return false;
389 }
390 bool ret = true;
391 for (const auto &entry : std::filesystem::directory_iterator(fpInfo)) {
392 std::error_code errorCode;
393 LOG(INFO) << "deleted " << entry.path().c_str() << ";";
394 if (!std::filesystem::remove_all(entry.path(), errorCode)) {
395 LOG(ERROR) << "Failed to deleted " << entry.path().c_str() << "; errorCode: " << errorCode.value();
396 ret = false;
397 }
398 }
399 return ret;
400 }
401
CheckAndUpdateRevertResult(const std::string & hmpPath,const std::string & resultInfo,const std::string & keyWord)402 bool CheckAndUpdateRevertResult(const std::string &hmpPath, const std::string &resultInfo, const std::string &keyWord)
403 {
404 if (resultInfo.find(keyWord) == std::string::npos) {
405 return false;
406 }
407 std::ifstream ifs { MODULE_RESULT_PATH };
408 if (!ifs.is_open()) {
409 LOG(ERROR) << "ifs open result_file fail" << strerror(errno);
410 return false;
411 }
412 std::string line;
413 std::vector<std::string> lines;
414 bool ret = false;
415 while (getline(ifs, line)) {
416 if (line.find(hmpPath) == std::string::npos) {
417 lines.push_back(line);
418 continue;
419 }
420 std::vector<std::string> results = Utils::SplitString(line, ";");
421 if (results.size() < 3) { // 3: hmp|result|msg
422 LOG(ERROR) << "Split result fail: " << line;
423 continue;
424 }
425 if (results[1] != "0") { // 1: index of result
426 lines.push_back(line);
427 continue;
428 }
429 ret = true;
430 lines.push_back(resultInfo);
431 }
432 ifs.close();
433 std::ofstream outfile(MODULE_RESULT_PATH, std::ios::binary | std::ios::trunc);
434 if (!outfile) {
435 LOG(ERROR) << "ofs open result_file fail" << strerror(errno);
436 return false;
437 }
438 for (const auto &info : lines) {
439 outfile << info;
440 }
441 LOG(INFO) << "Update revert result succ";
442 sync();
443 return ret;
444 }
445
GetCurrentHmpName(void)446 std::string GetCurrentHmpName(void)
447 {
448 std::vector<std::string> files;
449 GetDirFiles(MODULE_PREINSTALL_DIR, files);
450 for (const auto &file : files) {
451 if (!CheckFileSuffix(file, MODULE_PACKAGE_SUFFIX)) {
452 continue;
453 }
454 std::string hmpName = GetHmpName(file);
455 if (hmpName.empty()) {
456 continue;
457 }
458 return hmpName;
459 }
460 return "";
461 }
462
NotifyBmsRevert(const std::string & hmpName,bool record)463 int32_t NotifyBmsRevert(const std::string &hmpName, bool record)
464 {
465 LOG(INFO) << "Start to collect module name which contains hap or hsp, record is " << record;
466 SetParameter(BMS_START_INSTALL, NOTIFY_BMS_REVERT);
467 std::string preInstalledPath = std::string(MODULE_PREINSTALL_DIR) + "/" + hmpName + "/" + HMP_INFO_NAME;
468 std::unique_ptr<ModuleFile> moduleFile = ModuleFile::Open(preInstalledPath);
469 if (moduleFile == nullptr) {
470 LOG(ERROR) << "Invalid preinstalled file " << preInstalledPath;
471 return -1;
472 }
473 int32_t result = 0;
474 std::ostringstream oss;
475 oss << BMS_START_INSTALL << "=" << NOTIFY_BMS_REVERT << "\n";
476 for (const auto &[key, value] : moduleFile->GetVersionInfo().moduleMap) {
477 if (value.bundleInfoList.empty()) {
478 continue;
479 }
480 std::string attr = std::string(BMS_RESULT_PREFIX) + "." + key;
481 if (!record && SetParameter(attr.c_str(), BMS_INSTALL_FAIL) != 0) {
482 LOG(WARNING) << "Failed to set module params: " << attr;
483 result++;
484 }
485 oss << attr << "=" << BMS_INSTALL_FAIL << "\n";
486 }
487 if (record) {
488 if (!OHOS::SaveStringToFile(MODULE_UPDATE_PARAMS_FILE, oss.str(), false)) {
489 LOG(ERROR) << "save revert params to file fail";
490 }
491 }
492 return result;
493 }
494 } // namespace SysInstaller
495 } // namespace OHOS