• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2021 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 #include "include/updater/updater.h"
16 #include <cerrno>
17 #include <chrono>
18 #include <cstdio>
19 #include <iomanip>
20 #include <string>
21 #include <sched.h>
22 #include <syscall.h>
23 #include <sys/prctl.h>
24 #include <sys/stat.h>
25 #include <sys/statvfs.h>
26 #include <sys/wait.h>
27 #include <thread>
28 #include <unistd.h>
29 #include <vector>
30 #include <algorithm>
31 #include "fs_manager/mount.h"
32 #include "language/language_ui.h"
33 #include "log/dump.h"
34 #include "log/log.h"
35 #include "package/hash_data_verifier.h"
36 #include "package/pkg_manager.h"
37 #include "package/packages_info.h"
38 #include "parameter.h"
39 #include "misc_info/misc_info.h"
40 #ifdef WITH_SELINUX
41 #include <policycoreutils.h>
42 #include "selinux/selinux.h"
43 #endif // WITH_SELINUX
44 #ifdef UPDATER_USE_PTABLE
45 #include "ptable_parse/ptable_manager.h"
46 #endif
47 #include "scope_guard.h"
48 #include "updater/hardware_fault_retry.h"
49 #include "updater/updater_preprocess.h"
50 #include "updater/updater_const.h"
51 #include "updater_main.h"
52 #include "updater_ui_stub.h"
53 #include "utils.h"
54 #include "write_state/write_state.h"
55 #include "slot_info/slot_info.h"
56 
57 namespace Updater {
58 using Updater::Utils::SplitString;
59 using Updater::Utils::Trim;
60 using namespace Hpackage;
61 
62 int g_percentage = 100;
63 int g_tmpProgressValue;
64 int g_tmpValue;
65 
SetBinaryDeathSig(void)66 static void SetBinaryDeathSig(void)
67 {
68     if (Utils::IsUpdaterMode()) {
69         LOG(INFO) << "no need set death sig, when updater mode";
70         return;
71     }
72     if (prctl(PR_SET_PDEATHSIG, SIGTERM) == -1) {
73         LOG(ERROR) << "prctl failed " << strerror(errno);
74     }
75 }
76 
ExtractUpdaterBinary(PkgManager::PkgManagerPtr manager,std::string & packagePath,const std::string & updaterBinary)77 int32_t ExtractUpdaterBinary(PkgManager::PkgManagerPtr manager, std::string &packagePath,
78     const std::string &updaterBinary)
79 {
80     UPDATER_INIT_RECORD;
81     PkgManager::StreamPtr outStream = nullptr;
82     int32_t ret = manager->CreatePkgStream(outStream,  GetWorkPath() + updaterBinary,
83         0, PkgStream::PkgStreamType_Write);
84     if (ret != PKG_SUCCESS) {
85         LOG(ERROR) << "ExtractUpdaterBinary create stream fail";
86         UPDATER_LAST_WORD(UPDATE_CORRUPT, "ExtractUpdaterBinary create stream fail");
87         return UPDATE_CORRUPT;
88     }
89     ret = manager->ExtractFile(updaterBinary, outStream);
90     if (ret != PKG_SUCCESS) {
91         LOG(ERROR) << "ExtractUpdaterBinary extract file failed";
92         UPDATER_LAST_WORD(UPDATE_CORRUPT, "ExtractUpdaterBinary extract file failed");
93         return UPDATE_CORRUPT;
94     }
95     HashDataVerifier verifier {manager};
96     if (!verifier.LoadHashDataAndPkcs7(packagePath) ||
97         !verifier.VerifyHashData("build_tools/", updaterBinary, outStream)) {
98         LOG(ERROR) << "verify updater_binary failed";
99         UPDATER_LAST_WORD(UPDATE_CORRUPT, "verify updater_binary failed");
100         return UPDATE_CORRUPT;
101     }
102     manager->ClosePkgStream(outStream);
103     return UPDATE_SUCCESS;
104 }
105 
GetUpdatePackageInfo(PkgManager::PkgManagerPtr pkgManager,const std::string & path)106 int GetUpdatePackageInfo(PkgManager::PkgManagerPtr pkgManager, const std::string &path)
107 {
108     std::vector<std::string> components;
109     if (pkgManager == nullptr) {
110         LOG(ERROR) << "pkgManager is nullptr";
111         return UPDATE_CORRUPT;
112     }
113     int32_t ret = pkgManager->LoadPackage(path, Utils::GetCertName(), components);
114     if (ret != PKG_SUCCESS) {
115         LOG(INFO) << "LoadPackage fail ret :"<< ret;
116         return ret;
117     }
118     return PKG_SUCCESS;
119 }
120 
IsSpaceCapacitySufficient(const UpdaterParams & upParams)121 UpdaterStatus IsSpaceCapacitySufficient(const UpdaterParams &upParams)
122 {
123     UPDATER_INIT_RECORD;
124     std::vector<uint64_t> stashSizeList = GetStashSizeList(upParams);
125     if (stashSizeList.size() == 0) {
126         LOG(ERROR) << "get stash size error";
127         UPDATER_LAST_WORD(UPDATE_ERROR, "get stash size error");
128         return UPDATE_ERROR;
129     }
130     uint64_t maxStashSize =  *max_element(stashSizeList.begin(), stashSizeList.end());
131     LOG(INFO) << "get max stash size: " << maxStashSize;
132     uint64_t totalPkgSize = maxStashSize + MIN_UPDATE_SPACE;
133     LOG(INFO) << "needed totalPkgSize = " << totalPkgSize;
134     if (CheckStatvfs(totalPkgSize) != UPDATE_SUCCESS) {
135         LOG(ERROR) << "CheckStatvfs error";
136         UPDATER_LAST_WORD(UPDATE_ERROR, "CheckStatvfs error");
137         return UPDATE_ERROR;
138     }
139     return UPDATE_SUCCESS;
140 }
141 
ConvertStrToLongLong(PkgManager::StreamPtr outStream,int64_t & value)142 static bool ConvertStrToLongLong(PkgManager::StreamPtr outStream, int64_t &value)
143 {
144     UPDATER_INIT_RECORD;
145     PkgBuffer data {};
146     if (outStream == nullptr) {
147         LOG(ERROR) << "outStream is nullptr";
148         UPDATER_LAST_WORD(UPDATE_CORRUPT, "outStream is nullptr");
149         return false;
150     }
151     outStream->GetBuffer(data);
152     if (data.buffer == nullptr) {
153         LOG(ERROR) << "data.buffer is nullptr";
154         UPDATER_LAST_WORD(UPDATE_CORRUPT, "data.buffer is nullptr");
155         return false;
156     }
157     std::string str(reinterpret_cast<char*>(data.buffer), data.length);
158     if (!Utils::ConvertToLongLong(str, value)) {
159         LOG(ERROR) << "ConvertToLongLong failed";
160         UPDATER_LAST_WORD(UPDATE_CORRUPT, "ConvertToLongLong failed");
161         return false;
162     }
163     return true;
164 }
165 
GetStashSizeList(const UpdaterParams & upParams)166 std::vector<uint64_t> GetStashSizeList(const UpdaterParams &upParams)
167 {
168     UPDATER_INIT_RECORD;
169     const std::string maxStashFileName = "all_max_stash";
170     std::vector<uint64_t> stashSizeList;
171     for (unsigned int i = upParams.pkgLocation; i < upParams.updatePackage.size(); i++) {
172         PkgManager::PkgManagerPtr pkgManager = Hpackage::PkgManager::CreatePackageInstance();
173         if (pkgManager == nullptr) {
174             LOG(ERROR) << "pkgManager is nullptr";
175             UPDATER_LAST_WORD(UPDATE_CORRUPT, "pkgManager is nullptr");
176             return std::vector<uint64_t> {};
177         }
178         ON_SCOPE_EXIT(releasePackage) {
179             PkgManager::ReleasePackageInstance(pkgManager);
180         };
181 
182         std::vector<std::string> fileIds;
183         if (pkgManager->LoadPackageWithoutUnPack(upParams.updatePackage[i], fileIds) != PKG_SUCCESS) {
184             LOG(ERROR) << "LoadPackageWithoutUnPack failed " << upParams.updatePackage[i];
185             UPDATER_LAST_WORD(UPDATE_CORRUPT, "LoadPackageWithoutUnPack failed");
186             return std::vector<uint64_t> {};
187         }
188 
189         const FileInfo *info = pkgManager->GetFileInfo(maxStashFileName);
190         if (info == nullptr) {
191             LOG(INFO) << "all_max_stash not exist " << upParams.updatePackage[i];
192             stashSizeList.push_back(0);
193             continue;
194         }
195 
196         PkgManager::StreamPtr outStream = nullptr;
197         int ret = pkgManager->CreatePkgStream(outStream, maxStashFileName, info->unpackedSize,
198             PkgStream::PkgStreamType_MemoryMap);
199         if (outStream == nullptr || ret != PKG_SUCCESS) {
200             LOG(ERROR) << "Create stream fail " << maxStashFileName << " in " << upParams.updatePackage[i];
201             UPDATER_LAST_WORD(UPDATE_CORRUPT, "CreatePkgStream failed");
202             return std::vector<uint64_t> {};
203         }
204 
205         if (pkgManager->ExtractFile(maxStashFileName, outStream) != PKG_SUCCESS) {
206             LOG(ERROR) << "ExtractFile fail " << maxStashFileName << " in " << upParams.updatePackage[i];
207             UPDATER_LAST_WORD(UPDATE_CORRUPT, "ExtractFile failed");
208             return std::vector<uint64_t> {};
209         }
210         int64_t maxStashSize = 0;
211         if (!ConvertStrToLongLong(outStream, maxStashSize)) {
212             UPDATER_LAST_WORD(UPDATE_CORRUPT, "ConvertStrToLongLong failed");
213             return std::vector<uint64_t> {};
214         }
215         stashSizeList.push_back(static_cast<uint64_t>(maxStashSize));
216     }
217     return stashSizeList;
218 }
219 
CheckStatvfs(const uint64_t totalPkgSize)220 int CheckStatvfs(const uint64_t totalPkgSize)
221 {
222     UPDATER_INIT_RECORD;
223     struct statvfs64 updaterVfs;
224     if (access("/sdcard/updater", 0) == 0) {
225         if (statvfs64("/sdcard", &updaterVfs) < 0) {
226             LOG(ERROR) << "Statvfs read /sdcard error!";
227             UPDATER_LAST_WORD(UPDATE_ERROR, "Statvfs read /sdcard error!");
228             return UPDATE_ERROR;
229         }
230     } else {
231         if (statvfs64("/data", &updaterVfs) < 0) {
232             LOG(ERROR) << "Statvfs read /data error!";
233             UPDATER_LAST_WORD(UPDATE_ERROR, "Statvfs read /data error!");
234             return UPDATE_ERROR;
235         }
236     }
237     LOG(INFO) << "Number of free blocks = " << updaterVfs.f_bfree << ", Number of free inodes = " << updaterVfs.f_ffree;
238     if (static_cast<uint64_t>(updaterVfs.f_bfree) * static_cast<uint64_t>(updaterVfs.f_bsize) <= totalPkgSize) {
239         LOG(ERROR) << "Can not update, free space is not enough";
240         UPDATER_UI_INSTANCE.ShowUpdInfo(TR(UPD_SPACE_NOTENOUGH), true);
241         UPDATER_UI_INSTANCE.Sleep(UI_SHOW_DURATION);
242         UPDATER_LAST_WORD(UPDATE_ERROR, "Can not update, free space is not enough");
243         return UPDATE_ERROR;
244     }
245     return UPDATE_SUCCESS;
246 }
247 
GetTmpProgressValue()248 int GetTmpProgressValue()
249 {
250     return g_tmpProgressValue;
251 }
252 
SetTmpProgressValue(int value)253 void SetTmpProgressValue(int value)
254 {
255     g_tmpProgressValue = value;
256 }
257 
ProgressSmoothHandler(int beginProgress,int endProgress,UpdaterParams upParams,bool isFinish)258 void ProgressSmoothHandler(int beginProgress, int endProgress,
259     [[maybe_unused]] UpdaterParams upParams, [[maybe_unused]] bool isFinish)
260 {
261     if (endProgress < 0 || endProgress > FULL_PERCENT_PROGRESS || beginProgress < 0) {
262         return;
263     }
264     while (beginProgress < endProgress) {
265         int increase = (endProgress - beginProgress) / PROGRESS_VALUE_CONST;
266         beginProgress += increase;
267         if (beginProgress >= endProgress || increase == 0) {
268             break;
269         } else {
270             UPDATER_UI_INSTANCE.ShowProgress(beginProgress);
271             UPDATER_UI_INSTANCE.Sleep(SHOW_FULL_PROGRESS_TIME);
272         }
273     }
274 }
275 
PreStartBinaryEntry(const std::string & path)276 __attribute__((weak)) bool PreStartBinaryEntry([[maybe_unused]] const std::string &path)
277 {
278     LOG(INFO) << "pre binary process";
279     return true;
280 }
281 
282 float g_progressRatio = 1.0;
283 
SetTotalProgressRatio(float ratio)284 void SetTotalProgressRatio(float ratio)
285 {
286     g_progressRatio = ratio;
287 }
288 
GetTotalProgressRatio()289 float GetTotalProgressRatio()
290 {
291     return g_progressRatio;
292 }
293 
IsUpdateBasePkg(UpdaterParams & upParams)294 bool IsUpdateBasePkg(UpdaterParams &upParams)
295 {
296     for (auto pkgPath : upParams.updatePackage) {
297         if (pkgPath.find("_base") != std::string::npos) {
298             LOG(INFO) << "this update include base pkg";
299             return true;
300         }
301     }
302     return false;
303 }
304 
SetUpdateSlotParam(UpdaterParams & upParams,bool isUpdateCurrSlot)305 UpdaterStatus SetUpdateSlotParam(UpdaterParams &upParams, bool isUpdateCurrSlot)
306 {
307     if (!Utils::IsVabDevice()) {
308         return UPDATE_SUCCESS;
309     }
310     if (!isUpdateCurrSlot && upParams.updatePackage.size() == 1) {
311         std::string pkgPath = upParams.updatePackage[0];
312         if (pkgPath.find("updater.zip") != std::string::npos) {
313             isUpdateCurrSlot = true;
314         }
315     }
316     int currentSlot = GetCurrentSlot();
317     if (currentSlot < 1 || currentSlot > 2) { // 2 : max slot
318         LOG(ERROR) << "GetCurrentSlot failed";
319         return UPDATE_ERROR;
320     }
321     bool isUpdateSlotA = (currentSlot == SLOT_A && isUpdateCurrSlot) ||
322         (currentSlot == SLOT_B && !isUpdateCurrSlot);
323     int updateSlot = isUpdateSlotA ? SLOT_A : SLOT_B;
324     if (!Utils::SetUpdateSlot(updateSlot)) {
325         LOG(ERROR) << "set update.part.slot fail";
326         return UPDATE_ERROR;
327     }
328     return UPDATE_SUCCESS;
329 }
330 
SetUpdateSuffixParam()331 UpdaterStatus SetUpdateSuffixParam()
332 {
333     std::string updateSuffix = "";
334     GetPartitionSuffix(updateSuffix);
335     if (!Utils::SetUpdateSuffix(updateSuffix)) {
336         LOG(ERROR) << "set update.part.suffix fail";
337         return UPDATE_ERROR;
338     }
339     return UPDATE_SUCCESS;
340 }
341 
ClearUpdateSlotParam()342 UpdaterStatus ClearUpdateSlotParam()
343 {
344     if (!Utils::IsVabDevice()) {
345         return UPDATE_SUCCESS;
346     }
347     int updateSlot = -10; // -10 : default value
348     if (!Utils::SetUpdateSlot(updateSlot)) {
349         LOG(ERROR) << "clear update.part.slot fail";
350         return UPDATE_ERROR;
351     }
352     return UPDATE_SUCCESS;
353 }
354 
ClearUpdateSuffixParam()355 UpdaterStatus ClearUpdateSuffixParam()
356 {
357     std::string updateSuffix = " ";
358     if (!Utils::SetUpdateSuffix(updateSuffix)) {
359         LOG(ERROR) << "clear update.part.suffix fail";
360         return UPDATE_ERROR;
361     }
362     return UPDATE_SUCCESS;
363 }
364 
IsNeedMountData(UpdaterParams & upParams,PackageUpdateMode updateMode)365 bool IsNeedMountData(UpdaterParams &upParams, PackageUpdateMode updateMode)
366 {
367     return updateMode != SDCARD_UPDATE || upParams.sdExtMode == SDCARD_UPDATE_FROM_DEV ||
368         upParams.sdExtMode == SDCARD_UPDATE_FROM_DATA || Utils::CheckUpdateMode(Updater::SDCARD_INTRAL_MODE) ||
369         Utils::CheckUpdateMode(Updater::FACTORY_INTERNAL_MODE);
370 }
371 
IsNeedMountMetadata(UpdaterParams & upParams,PackageUpdateMode updateMode)372 bool IsNeedMountMetadata(UpdaterParams &upParams, PackageUpdateMode updateMode)
373 {
374     return Utils::IsVabDevice() && updateMode == HOTA_UPDATE;
375 }
376 
DoInstallUpdaterBinfile(PkgManager::PkgManagerPtr pkgManager,UpdaterParams & upParams,PackageUpdateMode updateMode)377 UpdaterStatus DoInstallUpdaterBinfile(PkgManager::PkgManagerPtr pkgManager, UpdaterParams &upParams,
378     PackageUpdateMode updateMode)
379 {
380     UPDATER_INIT_RECORD;
381     UPDATER_UI_INSTANCE.ShowProgressPage();
382     if (upParams.callbackProgress == nullptr) {
383         LOG(ERROR) << "CallbackProgress is nullptr";
384         UPDATER_LAST_WORD(UPDATE_CORRUPT, "CallbackProgress is nullptr");
385         return UPDATE_CORRUPT;
386     }
387     upParams.callbackProgress(GetTotalProgressRatio() * (upParams.initialProgress * FULL_PERCENT_PROGRESS));
388     if (pkgManager == nullptr) {
389         LOG(ERROR) << "pkgManager is nullptr";
390         UPDATER_LAST_WORD(UPDATE_CORRUPT, "pkgManager is nullptr");
391         return UPDATE_CORRUPT;
392     }
393 
394     if (SetupPartitions(IsNeedMountData(upParams, updateMode), IsNeedMountMetadata(upParams, updateMode)) != 0) {
395         UPDATER_UI_INSTANCE.ShowUpdInfo(TR(UPD_SETPART_FAIL), true);
396         UPDATER_LAST_WORD(UPDATE_ERROR, "SetupPartitions failed");
397         return UPDATE_ERROR;
398     }
399 
400     if (upParams.retryCount > 0) {
401         LOG(INFO) << "Retry for " << upParams.retryCount << " time(s)";
402     }
403 
404     // 获取zip信息
405     int ret = GetUpdatePackageInfo(pkgManager, STREAM_ZIP_PATH);
406     if (ret != 0) {
407         LOG(ERROR) << "get update package info fail";
408         UPDATER_LAST_WORD(UPDATE_CORRUPT, "GetUpdatePackageInfo failed");
409         return UPDATE_CORRUPT;
410     }
411     if (!PreStartBinaryEntry(upParams.updateBin[upParams.pkgLocation])) {
412         LOG(ERROR) << "pre binary process failed";
413         UPDATER_LAST_WORD(UPDATE_ERROR, "PreStartBinaryEntry failed");
414         return UPDATE_ERROR;
415     }
416 
417     g_tmpProgressValue = 0;
418     // 从bin文件开启进程
419     UpdaterStatus updateRet = StartUpdaterProc(pkgManager, upParams);
420     if (updateRet != UPDATE_SUCCESS) {
421         UPDATER_UI_INSTANCE.ShowUpdInfo(TR(UPD_INSTALL_FAIL));
422         UPDATER_LAST_WORD(updateRet, "StartUpdaterProc failed");
423         LOG(ERROR) << "Install package failed.";
424     }
425     if (WriteResult(upParams.updateBin[upParams.pkgLocation],
426         updateRet == UPDATE_SUCCESS ? "verify_success" : "verify_fail") != UPDATE_SUCCESS) {
427         LOG(ERROR) << "write update state fail";
428     }
429     return updateRet;
430 }
431 
DoInstallUpdaterPackage(PkgManager::PkgManagerPtr pkgManager,UpdaterParams & upParams,PackageUpdateMode updateMode)432 UpdaterStatus DoInstallUpdaterPackage(PkgManager::PkgManagerPtr pkgManager, UpdaterParams &upParams,
433     PackageUpdateMode updateMode)
434 {
435     UPDATER_INIT_RECORD;
436     UPDATER_UI_INSTANCE.ShowProgressPage();
437     if (upParams.callbackProgress == nullptr) {
438         LOG(ERROR) << "CallbackProgress is nullptr";
439         UPDATER_LAST_WORD(UPDATE_CORRUPT, "CallbackProgress is nullptr");
440         return UPDATE_CORRUPT;
441     }
442     upParams.callbackProgress(upParams.initialProgress * FULL_PERCENT_PROGRESS);
443     if (pkgManager == nullptr) {
444         LOG(ERROR) << "pkgManager is nullptr";
445         UPDATER_LAST_WORD(UPDATE_CORRUPT, "pkgManager is nullptr");
446         return UPDATE_CORRUPT;
447     }
448 
449     if (SetupPartitions(IsNeedMountData(upParams, updateMode), IsNeedMountMetadata(upParams, updateMode)) != 0) {
450         UPDATER_UI_INSTANCE.ShowUpdInfo(TR(UPD_SETPART_FAIL), true);
451         UPDATER_LAST_WORD(UPDATE_ERROR, "SetupPartitions failed");
452         return UPDATE_ERROR;
453     }
454 
455     if (upParams.retryCount > 0) {
456         LOG(INFO) << "Retry for " << upParams.retryCount << " time(s)";
457     }
458     int ret = GetUpdatePackageInfo(pkgManager, upParams.updatePackage[upParams.pkgLocation]);
459     if (ret != 0) {
460         LOG(ERROR) << "get update package info fail";
461         UPDATER_LAST_WORD(UPDATE_CORRUPT, "GetUpdatePackageInfo failed");
462         return UPDATE_CORRUPT;
463     }
464     if (!PreStartBinaryEntry(upParams.updatePackage[upParams.pkgLocation])) {
465         LOG(ERROR) << "pre binary process failed";
466         UPDATER_LAST_WORD(UPDATE_ERROR, "PreStartBinaryEntry failed");
467         return UPDATE_ERROR;
468     }
469 
470     g_tmpProgressValue = 0;
471     UpdaterStatus updateRet = StartUpdaterProc(pkgManager, upParams);
472     if (updateRet != UPDATE_SUCCESS) {
473         UPDATER_UI_INSTANCE.ShowUpdInfo(TR(UPD_INSTALL_FAIL));
474         UPDATER_LAST_WORD(updateRet, "StartUpdaterProc failed");
475         LOG(ERROR) << "Install package failed.";
476     }
477     if (WriteResult(upParams.updatePackage[upParams.pkgLocation],
478         updateRet == UPDATE_SUCCESS ? "verify_success" : "verify_fail") != UPDATE_SUCCESS) {
479         LOG(ERROR) << "write update state fail";
480     }
481     return updateRet;
482 }
483 
484 namespace {
SetProgress(const std::vector<std::string> & output,UpdaterParams & upParams)485 void SetProgress(const std::vector<std::string> &output, UpdaterParams &upParams)
486 {
487     if (upParams.callbackProgress == nullptr) {
488         LOG(ERROR) << "CallbackProgress is nullptr";
489         return;
490     }
491     if (output.size() < DEFAULT_PROCESS_NUM) {
492         LOG(ERROR) << "check output fail";
493         return;
494     }
495     auto outputInfo = Trim(output[1]);
496     float frac = 0;
497     if (!Utils::ConvertToFloat(output[1], frac)) {
498         LOG(ERROR) << "ConvertToFloat failed";
499         return;
500     }
501     int tmpProgressValue = 0;
502     if (frac >= -EPSINON && frac <= EPSINON) {
503         return;
504     } else {
505         tmpProgressValue = static_cast<int>(frac * g_percentage);
506     }
507     if (frac >= FULL_EPSINON && g_tmpValue + g_percentage < FULL_PERCENT_PROGRESS) {
508         g_tmpValue += g_percentage;
509         g_tmpProgressValue = g_tmpValue;
510         upParams.callbackProgress(GetTotalProgressRatio() * (g_tmpProgressValue *
511             upParams.currentPercentage + upParams.initialProgress * FULL_PERCENT_PROGRESS));
512         return;
513     }
514     g_tmpProgressValue = tmpProgressValue + g_tmpValue;
515     if (g_tmpProgressValue == 0) {
516         return;
517     }
518     upParams.callbackProgress(GetTotalProgressRatio() * (g_tmpProgressValue *
519         upParams.currentPercentage + upParams.initialProgress * FULL_PERCENT_PROGRESS));
520 }
521 }
522 
HandleChildOutput(const std::string & buffer,int32_t bufferLen,bool & retryUpdate,UpdaterParams & upParams)523 void HandleChildOutput(const std::string &buffer, int32_t bufferLen, bool &retryUpdate, UpdaterParams &upParams)
524 {
525     if (bufferLen == 0) {
526         return;
527     }
528     std::string str = buffer;
529     std::vector<std::string> output = SplitString(str, ":");
530     if (output.size() < DEFAULT_PROCESS_NUM) {
531         LOG(ERROR) << "check output fail";
532         return;
533     }
534     auto outputHeader = Trim(output[0]);
535     if (outputHeader == "write_log") {
536         auto outputInfo = Trim(output[1]);
537         LOG(INFO) << outputInfo;
538     } else if (outputHeader == "retry_update") {
539         retryUpdate = true;
540         auto outputInfo = Trim(output[1]);
541         HardwareFaultRetry::GetInstance().SetFaultInfo(outputInfo);
542     } else if (outputHeader == "ui_log") {
543         auto outputInfo = Trim(output[1]);
544     } else if (outputHeader == "show_progress") {
545         g_tmpValue = g_tmpProgressValue;
546         auto outputInfo = Trim(output[1]);
547         float frac;
548         std::vector<std::string> progress = SplitString(outputInfo, ",");
549         if (progress.size() != DEFAULT_PROCESS_NUM) {
550             LOG(ERROR) << "show progress with wrong arguments";
551         } else {
552             if (!Utils::ConvertToFloat(progress[0], frac)) {
553                 LOG(ERROR) << "ConvertToFloat failed";
554                 return;
555             }
556             g_percentage = static_cast<int>(frac * FULL_PERCENT_PROGRESS);
557         }
558     } else if (outputHeader == "set_progress") {
559         SetProgress(output, upParams);
560     } else if (outputHeader == "set_binary_tids") {
561         UpdateBinaryTids(output, upParams);
562     } else {
563         LOG(WARNING) << "Child process returns unexpected message.";
564     }
565 }
566 
ExcuteSubProc(const UpdaterParams & upParams,const std::string & fullPath,int pipeWrite)567 void ExcuteSubProc(const UpdaterParams &upParams, const std::string &fullPath, int pipeWrite)
568 {
569     UPDATER_INIT_RECORD;
570     SetBinaryDeathSig();
571     // Set process scheduler to normal if current scheduler is
572     // SCHED_FIFO, which may cause bad performance.
573     int policy = syscall(SYS_sched_getscheduler, getpid());
574     if (policy == -1) {
575         LOG(INFO) << "Cannnot get current process scheduler";
576     } else if (policy == SCHED_FIFO) {
577         LOG(DEBUG) << "Current process with scheduler SCHED_FIFO";
578         struct sched_param sp = {
579             .sched_priority = 0,
580         };
581         if (syscall(SYS_sched_setscheduler, getpid(), SCHED_OTHER, &sp) < 0) {
582             LOG(WARNING) << "Cannot set current process schedule with SCHED_OTHER";
583         }
584     }
585     const std::string retryPara = upParams.retryCount > 0 ? "retry=1" : "retry=0";
586     int ret = -1;
587     if (upParams.updateBin.size() > 0) {
588         LOG(INFO) << "Binary Path:" << upParams.updateBin[upParams.pkgLocation].c_str();
589         ret = execl(fullPath.c_str(), fullPath.c_str(), upParams.updateBin[upParams.pkgLocation].c_str(),
590             std::to_string(pipeWrite).c_str(), retryPara.c_str(), nullptr);
591     } else if (upParams.updatePackage.size() > 0) {
592         LOG(INFO) << "Binary Path:" << upParams.updatePackage[upParams.pkgLocation].c_str();
593         ret = execl(fullPath.c_str(), fullPath.c_str(), upParams.updatePackage[upParams.pkgLocation].c_str(),
594             std::to_string(pipeWrite).c_str(), retryPara.c_str(), nullptr);
595     }
596     if (ret < 0) {
597         LOG(ERROR) << "Execute updater binary failed, errno = " << errno;
598         UPDATER_LAST_WORD(UPDATE_ERROR, "Execute updater binary failed, errno = ", errno);
599         exit(-1);
600     }
601 }
602 
HandlePipeMsg(UpdaterParams & upParams,int pipeRead,bool & retryUpdate)603 UpdaterStatus HandlePipeMsg(UpdaterParams &upParams, int pipeRead, bool &retryUpdate)
604 {
605     UPDATER_INIT_RECORD;
606     char buffer[MAX_BUFFER_SIZE] = {0};
607     FILE* fromChild = fdopen(pipeRead, "r");
608     if (fromChild == nullptr) {
609         LOG(ERROR) << "fdopen pipeRead failed";
610         UPDATER_LAST_WORD(UPDATE_ERROR, "fdopen pipeRead failed");
611         return UPDATE_ERROR;
612     }
613     while (fgets(buffer, MAX_BUFFER_SIZE - 1, fromChild) != nullptr) {
614         char *pch = strrchr(buffer, '\n');
615         if (pch != nullptr) {
616             *pch = '\0';
617         }
618         if (strstr(buffer, "subProcessResult") != nullptr) {
619             LOG(INFO) << "subProcessResult: " << buffer;
620             break;
621         }
622         HandleChildOutput(buffer, MAX_BUFFER_SIZE, retryUpdate, upParams);
623     }
624     LOG(INFO) << "HandlePipeMsg end";
625     fclose(fromChild);
626     return UPDATE_SUCCESS;
627 }
628 
CheckProcStatus(UpdaterParams & upParams,bool retryUpdate)629 UpdaterStatus CheckProcStatus(UpdaterParams &upParams, bool retryUpdate)
630 {
631     int status;
632     ON_SCOPE_EXIT(resetBinaryPid) {
633         upParams.binaryPid = -1;
634     };
635     if (waitpid(upParams.binaryPid, &status, 0) == -1) {
636         LOG(ERROR) << "waitpid error";
637         return UPDATE_ERROR;
638     }
639     if (retryUpdate) {
640         return UPDATE_RETRY;
641     }
642 
643     if (!WIFEXITED(status) || WEXITSTATUS(status) != 0) {
644         if (WIFEXITED(status)) {
645             LOG(ERROR) << "exited, status= " << WEXITSTATUS(status);
646         } else if (WIFSIGNALED(status)) {
647             LOG(ERROR) << "killed by signal " << WTERMSIG(status);
648         } else if (WIFSTOPPED(status)) {
649             LOG(ERROR) << "stopped by signal " << WSTOPSIG(status);
650         }
651         return UPDATE_ERROR;
652     }
653     LOG(DEBUG) << "Updater process finished.";
654     return UPDATE_SUCCESS;
655 }
656 
GetBinaryPathFromBin(PkgManager::PkgManagerPtr pkgManager,UpdaterParams & upParams)657 static std::string GetBinaryPathFromBin(PkgManager::PkgManagerPtr pkgManager, UpdaterParams &upParams)
658 {
659     std::string fullPath = GetWorkPath() + std::string(UPDATER_BINARY);
660     (void)Utils::DeleteFile(fullPath);
661     std::string toolPath = "/data/updater/update_stream.zip";
662     if (ExtractUpdaterBinary(pkgManager, toolPath, UPDATER_BINARY) != 0) {
663         LOG(INFO) << "There is no valid updater_binary in package, use updater_binary in device";
664         fullPath = "/bin/updater_binary";
665     }
666 
667 #ifdef UPDATER_UT
668     fullPath = "/data/updater/updater_binary";
669 #endif
670     return fullPath;
671 }
672 
GetBinaryPath(PkgManager::PkgManagerPtr pkgManager,UpdaterParams & upParams)673 static std::string GetBinaryPath(PkgManager::PkgManagerPtr pkgManager, UpdaterParams &upParams)
674 {
675     std::string fullPath = GetWorkPath() + std::string(UPDATER_BINARY);
676     (void)Utils::DeleteFile(fullPath);
677     if (access("/data/updater/rollback", F_OK) == 0) {
678         LOG(INFO) << "There is rollback, use updater_binary in device";
679         fullPath = "/bin/updater_binary";
680     } else if (ExtractUpdaterBinary(pkgManager, upParams.updatePackage[upParams.pkgLocation], UPDATER_BINARY) != 0) {
681         LOG(INFO) << "There is no valid updater_binary in package, use updater_binary in device";
682         fullPath = "/bin/updater_binary";
683     }
684 
685 #ifdef UPDATER_UT
686     fullPath = "/data/updater/updater_binary";
687 #endif
688     return fullPath;
689 }
690 
GetFullPath(PkgManager::PkgManagerPtr pkgManager,UpdaterParams & upParams)691 static std::string GetFullPath(PkgManager::PkgManagerPtr pkgManager, UpdaterParams &upParams)
692 {
693     std::string fullPath = "";
694     if (upParams.updateBin.size() > 0) {
695         fullPath = GetBinaryPathFromBin(pkgManager, upParams);
696     } else if (upParams.updatePackage.size() > 0) {
697         fullPath = GetBinaryPath(pkgManager, upParams);
698     }
699     if (chmod(fullPath.c_str(), S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH) != 0) {
700         LOG(ERROR) << "Failed to change mode";
701     }
702     return fullPath;
703 }
704 
StartUpdaterProc(PkgManager::PkgManagerPtr pkgManager,UpdaterParams & upParams)705 UpdaterStatus StartUpdaterProc(PkgManager::PkgManagerPtr pkgManager, UpdaterParams &upParams)
706 {
707     UPDATER_INIT_RECORD;
708     if (pkgManager == nullptr) {
709         LOG(ERROR) << "pkgManager is nullptr";
710         UPDATER_LAST_WORD(UPDATE_CORRUPT, "pkgManager is nullptr");
711         return UPDATE_CORRUPT;
712     }
713     int pfd[DEFAULT_PIPE_NUM]; /* communication between parent and child */
714     if (pipe(pfd) < 0) {
715         LOG(ERROR) << "Create pipe failed: ";
716         UPDATER_LAST_WORD(UPDATE_ERROR, "Create pipe failed");
717         return UPDATE_ERROR;
718     }
719     int pipeRead = pfd[0];
720     int pipeWrite = pfd[1];
721     std::string fullPath = GetFullPath(pkgManager, upParams);
722 #ifdef WITH_SELINUX
723     Restorecon(fullPath.c_str());
724 #endif // WITH_SELINUX
725     pid_t pid = fork();
726     if (pid < 0) {
727         ERROR_CODE(CODE_FORK_FAIL);
728         upParams.binaryPid = -1;
729         UPDATER_LAST_WORD(UPDATE_ERROR, "fork failed");
730         close(pipeRead);
731         close(pipeWrite);
732         return UPDATE_ERROR;
733     }
734     if (pid == 0) { // child
735         #ifdef WITH_SELINUX
736         setcon("u:r:updater_binary:s0");
737         #endif // WITH_SELINUX
738         close(pipeRead);   // close read endpoint
739         ExcuteSubProc(upParams, fullPath, pipeWrite);
740     }
741     upParams.binaryPid = pid;
742     close(pipeWrite); // close write endpoint
743     bool retryUpdate = false;
744     if (HandlePipeMsg(upParams, pipeRead, retryUpdate) != UPDATE_SUCCESS) {
745         UPDATER_LAST_WORD(UPDATE_ERROR, "HandlePipeMsg failed");
746         return UPDATE_ERROR;
747     }
748     return CheckProcStatus(upParams, retryUpdate);
749 }
750 
GetWorkPath()751 std::string GetWorkPath()
752 {
753     if (Utils::IsUpdaterMode()) {
754         return G_WORK_PATH;
755     }
756 
757     return std::string(SYS_INSTALLER_PATH) + "/";
758 }
759 } // namespace Updater
760