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