• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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