• 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/stat.h>
24 #include <sys/statvfs.h>
25 #include <sys/wait.h>
26 #include <thread>
27 #include <unistd.h>
28 #include <vector>
29 #include <algorithm>
30 #include "fs_manager/mount.h"
31 #include "language/language_ui.h"
32 #include "log/dump.h"
33 #include "log/log.h"
34 #include "package/hash_data_verifier.h"
35 #include "package/pkg_manager.h"
36 #include "package/packages_info.h"
37 #include "parameter.h"
38 #include "misc_info/misc_info.h"
39 #ifdef WITH_SELINUX
40 #include <policycoreutils.h>
41 #include "selinux/selinux.h"
42 #endif // WITH_SELINUX
43 #ifdef UPDATER_USE_PTABLE
44 #include "ptable_parse/ptable_manager.h"
45 #endif
46 #include "scope_guard.h"
47 #include "updater/hwfault_retry.h"
48 #include "updater/updater_preprocess.h"
49 #include "updater/updater_const.h"
50 #include "updater_main.h"
51 #include "updater_ui_stub.h"
52 #include "utils.h"
53 #include "write_state/write_state.h"
54 
55 namespace Updater {
56 using Updater::Utils::SplitString;
57 using Updater::Utils::Trim;
58 using namespace Hpackage;
59 
60 int g_percentage = 100;
61 int g_tmpProgressValue;
62 int g_tmpValue;
63 
ExtractUpdaterBinary(PkgManager::PkgManagerPtr manager,std::string & packagePath,const std::string & updaterBinary)64 int32_t ExtractUpdaterBinary(PkgManager::PkgManagerPtr manager, std::string &packagePath,
65     const std::string &updaterBinary)
66 {
67     UPDATER_INIT_RECORD;
68     PkgManager::StreamPtr outStream = nullptr;
69     int32_t ret = manager->CreatePkgStream(outStream,  GetWorkPath() + updaterBinary,
70         0, PkgStream::PkgStreamType_Write);
71     if (ret != PKG_SUCCESS) {
72         LOG(ERROR) << "ExtractUpdaterBinary create stream fail";
73         UPDATER_LAST_WORD(UPDATE_CORRUPT, "ExtractUpdaterBinary create stream fail");
74         return UPDATE_CORRUPT;
75     }
76     ret = manager->ExtractFile(updaterBinary, outStream);
77     if (ret != PKG_SUCCESS) {
78         LOG(ERROR) << "ExtractUpdaterBinary extract file failed";
79         UPDATER_LAST_WORD(UPDATE_CORRUPT, "ExtractUpdaterBinary extract file failed");
80         return UPDATE_CORRUPT;
81     }
82     HashDataVerifier verifier {manager};
83     if (!verifier.LoadHashDataAndPkcs7(packagePath) ||
84         !verifier.VerifyHashData("build_tools/", updaterBinary, outStream)) {
85         LOG(ERROR) << "verify updater_binary failed";
86         UPDATER_LAST_WORD(UPDATE_CORRUPT, "verify updater_binary failed");
87         return UPDATE_CORRUPT;
88     }
89     manager->ClosePkgStream(outStream);
90     return UPDATE_SUCCESS;
91 }
92 
GetUpdatePackageInfo(PkgManager::PkgManagerPtr pkgManager,const std::string & path)93 int GetUpdatePackageInfo(PkgManager::PkgManagerPtr pkgManager, const std::string &path)
94 {
95     std::vector<std::string> components;
96     if (pkgManager == nullptr) {
97         LOG(ERROR) << "pkgManager is nullptr";
98         return UPDATE_CORRUPT;
99     }
100     int32_t ret = pkgManager->LoadPackage(path, Utils::GetCertName(), components);
101     if (ret != PKG_SUCCESS) {
102         LOG(INFO) << "LoadPackage fail ret :"<< ret;
103         return ret;
104     }
105     return PKG_SUCCESS;
106 }
107 
IsSpaceCapacitySufficient(const UpdaterParams & upParams)108 UpdaterStatus IsSpaceCapacitySufficient(const UpdaterParams &upParams)
109 {
110     UPDATER_INIT_RECORD;
111     std::vector<uint64_t> stashSizeList = GetStashSizeList(upParams);
112     if (stashSizeList.size() == 0) {
113         LOG(ERROR) << "get stash size error";
114         UPDATER_LAST_WORD(UPDATE_ERROR, "get stash size error");
115         return UPDATE_ERROR;
116     }
117     uint64_t maxStashSize =  *max_element(stashSizeList.begin(), stashSizeList.end());
118     LOG(INFO) << "get max stash size: " << maxStashSize;
119     uint64_t totalPkgSize = maxStashSize + MIN_UPDATE_SPACE;
120     LOG(INFO) << "needed totalPkgSize = " << totalPkgSize;
121     if (CheckStatvfs(totalPkgSize) != UPDATE_SUCCESS) {
122         LOG(ERROR) << "CheckStatvfs error";
123         UPDATER_LAST_WORD(UPDATE_ERROR, "CheckStatvfs error");
124         return UPDATE_ERROR;
125     }
126     return UPDATE_SUCCESS;
127 }
128 
ConvertStrToLongLong(PkgManager::StreamPtr outStream,int64_t & value)129 static bool ConvertStrToLongLong(PkgManager::StreamPtr outStream, int64_t &value)
130 {
131     UPDATER_INIT_RECORD;
132     PkgBuffer data {};
133     if (outStream == nullptr) {
134         LOG(ERROR) << "outStream is nullptr";
135         UPDATER_LAST_WORD(UPDATE_CORRUPT, "outStream is nullptr");
136         return false;
137     }
138     outStream->GetBuffer(data);
139     if (data.buffer == nullptr) {
140         LOG(ERROR) << "data.buffer is nullptr";
141         UPDATER_LAST_WORD(UPDATE_CORRUPT, "data.buffer is nullptr");
142         return false;
143     }
144     std::string str(reinterpret_cast<char*>(data.buffer), data.length);
145     if (!Utils::ConvertToLongLong(str, value)) {
146         LOG(ERROR) << "ConvertToLongLong failed";
147         UPDATER_LAST_WORD(UPDATE_CORRUPT, "ConvertToLongLong failed");
148         return false;
149     }
150     return true;
151 }
152 
GetStashSizeList(const UpdaterParams & upParams)153 std::vector<uint64_t> GetStashSizeList(const UpdaterParams &upParams)
154 {
155     UPDATER_INIT_RECORD;
156     const std::string maxStashFileName = "all_max_stash";
157     std::vector<uint64_t> stashSizeList;
158     for (unsigned int i = upParams.pkgLocation; i < upParams.updatePackage.size(); i++) {
159         PkgManager::PkgManagerPtr pkgManager = Hpackage::PkgManager::CreatePackageInstance();
160         if (pkgManager == nullptr) {
161             LOG(ERROR) << "pkgManager is nullptr";
162             UPDATER_LAST_WORD(UPDATE_CORRUPT, "pkgManager is nullptr");
163             return std::vector<uint64_t> {};
164         }
165         ON_SCOPE_EXIT(releasePackage) {
166             PkgManager::ReleasePackageInstance(pkgManager);
167         };
168 
169         std::vector<std::string> fileIds;
170         if (pkgManager->LoadPackageWithoutUnPack(upParams.updatePackage[i], fileIds) != PKG_SUCCESS) {
171             LOG(ERROR) << "LoadPackageWithoutUnPack failed " << upParams.updatePackage[i];
172             UPDATER_LAST_WORD(UPDATE_CORRUPT, "LoadPackageWithoutUnPack failed");
173             return std::vector<uint64_t> {};
174         }
175 
176         const FileInfo *info = pkgManager->GetFileInfo(maxStashFileName);
177         if (info == nullptr) {
178             LOG(INFO) << "all_max_stash not exist " << upParams.updatePackage[i];
179             stashSizeList.push_back(0);
180             continue;
181         }
182 
183         PkgManager::StreamPtr outStream = nullptr;
184         int ret = pkgManager->CreatePkgStream(outStream, maxStashFileName, info->unpackedSize,
185             PkgStream::PkgStreamType_MemoryMap);
186         if (outStream == nullptr || ret != PKG_SUCCESS) {
187             LOG(ERROR) << "Create stream fail " << maxStashFileName << " in " << upParams.updatePackage[i];
188             UPDATER_LAST_WORD(UPDATE_CORRUPT, "CreatePkgStream failed");
189             return std::vector<uint64_t> {};
190         }
191 
192         if (pkgManager->ExtractFile(maxStashFileName, outStream) != PKG_SUCCESS) {
193             LOG(ERROR) << "ExtractFile fail " << maxStashFileName << " in " << upParams.updatePackage[i];
194             UPDATER_LAST_WORD(UPDATE_CORRUPT, "ExtractFile failed");
195             return std::vector<uint64_t> {};
196         }
197         int64_t maxStashSize = 0;
198         if (!ConvertStrToLongLong(outStream, maxStashSize)) {
199             UPDATER_LAST_WORD(UPDATE_CORRUPT, "ConvertStrToLongLong failed");
200             return std::vector<uint64_t> {};
201         }
202         stashSizeList.push_back(static_cast<uint64_t>(maxStashSize));
203     }
204     return stashSizeList;
205 }
206 
CheckStatvfs(const uint64_t totalPkgSize)207 int CheckStatvfs(const uint64_t totalPkgSize)
208 {
209     UPDATER_INIT_RECORD;
210     struct statvfs64 updaterVfs;
211     if (access("/sdcard/updater", 0) == 0) {
212         if (statvfs64("/sdcard", &updaterVfs) < 0) {
213             LOG(ERROR) << "Statvfs read /sdcard error!";
214             UPDATER_LAST_WORD(UPDATE_ERROR, "Statvfs read /sdcard error!");
215             return UPDATE_ERROR;
216         }
217     } else {
218         if (statvfs64("/data", &updaterVfs) < 0) {
219             LOG(ERROR) << "Statvfs read /data error!";
220             UPDATER_LAST_WORD(UPDATE_ERROR, "Statvfs read /data error!");
221             return UPDATE_ERROR;
222         }
223     }
224     LOG(INFO) << "Number of free blocks = " << updaterVfs.f_bfree << ", Number of free inodes = " << updaterVfs.f_ffree;
225     if (static_cast<uint64_t>(updaterVfs.f_bfree) * static_cast<uint64_t>(updaterVfs.f_bsize) <= totalPkgSize) {
226         LOG(ERROR) << "Can not update, free space is not enough";
227         UPDATER_UI_INSTANCE.ShowUpdInfo(TR(UPD_SPACE_NOTENOUGH), true);
228         UPDATER_UI_INSTANCE.Sleep(UI_SHOW_DURATION);
229         UPDATER_LAST_WORD(UPDATE_ERROR, "Can not update, free space is not enough");
230         return UPDATE_ERROR;
231     }
232     return UPDATE_SUCCESS;
233 }
234 
GetTmpProgressValue()235 int GetTmpProgressValue()
236 {
237     return g_tmpProgressValue;
238 }
239 
SetTmpProgressValue(int value)240 void SetTmpProgressValue(int value)
241 {
242     g_tmpProgressValue = value;
243 }
244 
ProgressSmoothHandler(int beginProgress,int endProgress)245 void ProgressSmoothHandler(int beginProgress, int endProgress)
246 {
247     if (endProgress < 0 || endProgress > FULL_PERCENT_PROGRESS || beginProgress < 0) {
248         return;
249     }
250     while (beginProgress < endProgress) {
251         int increase = (endProgress - beginProgress) / PROGRESS_VALUE_CONST;
252         beginProgress += increase;
253         if (beginProgress >= endProgress || increase == 0) {
254             break;
255         } else {
256             UPDATER_UI_INSTANCE.ShowProgress(beginProgress);
257             UPDATER_UI_INSTANCE.Sleep(SHOW_FULL_PROGRESS_TIME);
258         }
259     }
260 }
261 
PreStartBinaryEntry(const std::string & path)262 __attribute__((weak)) bool PreStartBinaryEntry([[maybe_unused]] const std::string &path)
263 {
264     LOG(INFO) << "pre binary process";
265     return true;
266 }
267 
DoInstallUpdaterPackage(PkgManager::PkgManagerPtr pkgManager,UpdaterParams & upParams,PackageUpdateMode updateMode)268 UpdaterStatus DoInstallUpdaterPackage(PkgManager::PkgManagerPtr pkgManager, UpdaterParams &upParams,
269     PackageUpdateMode updateMode)
270 {
271     UPDATER_INIT_RECORD;
272     UPDATER_UI_INSTANCE.ShowProgressPage();
273     if (upParams.callbackProgress == nullptr) {
274         LOG(ERROR) << "CallbackProgress is nullptr";
275         UPDATER_LAST_WORD(UPDATE_CORRUPT, "CallbackProgress is nullptr");
276         return UPDATE_CORRUPT;
277     }
278     upParams.callbackProgress(upParams.initialProgress * FULL_PERCENT_PROGRESS);
279     if (pkgManager == nullptr) {
280         LOG(ERROR) << "pkgManager is nullptr";
281         UPDATER_LAST_WORD(UPDATE_CORRUPT, "pkgManager is nullptr");
282         return UPDATE_CORRUPT;
283     }
284 
285     if (SetupPartitions(updateMode != SDCARD_UPDATE || upParams.sdExtMode == SDCARD_UPDATE_FROM_DEV ||
286         upParams.sdExtMode == SDCARD_UPDATE_FROM_DATA || Utils::CheckUpdateMode(Updater::SDCARD_INTRAL_MODE) ||
287         Utils::CheckUpdateMode(Updater::FACTORY_INTERNAL_MODE)) != 0) {
288         UPDATER_UI_INSTANCE.ShowUpdInfo(TR(UPD_SETPART_FAIL), true);
289         UPDATER_LAST_WORD(UPDATE_ERROR, "SetupPartitions failed");
290         return UPDATE_ERROR;
291     }
292 
293     if (upParams.retryCount > 0) {
294         LOG(INFO) << "Retry for " << upParams.retryCount << " time(s)";
295     }
296     int ret = GetUpdatePackageInfo(pkgManager, upParams.updatePackage[upParams.pkgLocation]);
297     if (ret != 0) {
298         LOG(ERROR) << "get update package info fail";
299         UPDATER_LAST_WORD(UPDATE_CORRUPT, "GetUpdatePackageInfo failed");
300         return UPDATE_CORRUPT;
301     }
302     if (!PreStartBinaryEntry(upParams.updatePackage[upParams.pkgLocation])) {
303         LOG(ERROR) << "pre binary process failed";
304         UPDATER_LAST_WORD(UPDATE_ERROR, "PreStartBinaryEntry failed");
305         return UPDATE_ERROR;
306     }
307 
308     g_tmpProgressValue = 0;
309     UpdaterStatus updateRet = StartUpdaterProc(pkgManager, upParams);
310     if (updateRet != UPDATE_SUCCESS) {
311         UPDATER_UI_INSTANCE.ShowUpdInfo(TR(UPD_INSTALL_FAIL));
312         UPDATER_LAST_WORD(updateRet, "StartUpdaterProc failed");
313         LOG(ERROR) << "Install package failed.";
314     }
315     if (WriteResult(upParams.updatePackage[upParams.pkgLocation],
316         updateRet == UPDATE_SUCCESS ? "verify_success" : "verify_fail") != UPDATE_SUCCESS) {
317         LOG(ERROR) << "write update state fail";
318     }
319     return updateRet;
320 }
321 
322 namespace {
SetProgress(const std::vector<std::string> & output,UpdaterParams & upParams)323 void SetProgress(const std::vector<std::string> &output, UpdaterParams &upParams)
324 {
325     if (upParams.callbackProgress == nullptr) {
326         LOG(ERROR) << "CallbackProgress is nullptr";
327         return;
328     }
329     if (output.size() < DEFAULT_PROCESS_NUM) {
330         LOG(ERROR) << "check output fail";
331         return;
332     }
333     auto outputInfo = Trim(output[1]);
334     float frac = 0;
335     if (!Utils::ConvertToFloat(output[1], frac)) {
336         LOG(ERROR) << "ConvertToFloat failed";
337         return;
338     }
339     int tmpProgressValue = 0;
340     if (frac >= -EPSINON && frac <= EPSINON) {
341         return;
342     } else {
343         tmpProgressValue = static_cast<int>(frac * g_percentage);
344     }
345     if (frac >= FULL_EPSINON && g_tmpValue + g_percentage < FULL_PERCENT_PROGRESS) {
346         g_tmpValue += g_percentage;
347         g_tmpProgressValue = g_tmpValue;
348         upParams.callbackProgress(g_tmpProgressValue *
349             upParams.currentPercentage + upParams.initialProgress * FULL_PERCENT_PROGRESS);
350         return;
351     }
352     g_tmpProgressValue = tmpProgressValue + g_tmpValue;
353     if (g_tmpProgressValue == 0) {
354         return;
355     }
356     upParams.callbackProgress(g_tmpProgressValue *
357         upParams.currentPercentage + upParams.initialProgress * FULL_PERCENT_PROGRESS);
358 }
359 }
360 
HandleChildOutput(const std::string & buffer,int32_t bufferLen,bool & retryUpdate,UpdaterParams & upParams)361 void HandleChildOutput(const std::string &buffer, int32_t bufferLen, bool &retryUpdate, UpdaterParams &upParams)
362 {
363     if (bufferLen == 0) {
364         return;
365     }
366     std::string str = buffer;
367     std::vector<std::string> output = SplitString(str, ":");
368     if (output.size() < DEFAULT_PROCESS_NUM) {
369         LOG(ERROR) << "check output fail";
370         return;
371     }
372     auto outputHeader = Trim(output[0]);
373     if (outputHeader == "write_log") {
374         auto outputInfo = Trim(output[1]);
375         LOG(INFO) << outputInfo;
376     } else if (outputHeader == "retry_update") {
377         retryUpdate = true;
378         auto outputInfo = Trim(output[1]);
379         HwFaultRetry::GetInstance().SetFaultInfo(outputInfo);
380     } else if (outputHeader == "ui_log") {
381         auto outputInfo = Trim(output[1]);
382     } else if (outputHeader == "show_progress") {
383         g_tmpValue = g_tmpProgressValue;
384         auto outputInfo = Trim(output[1]);
385         float frac;
386         std::vector<std::string> progress = SplitString(outputInfo, ",");
387         if (progress.size() != DEFAULT_PROCESS_NUM) {
388             LOG(ERROR) << "show progress with wrong arguments";
389         } else {
390             if (!Utils::ConvertToFloat(progress[0], frac)) {
391                 LOG(ERROR) << "ConvertToFloat failed";
392                 return;
393             }
394             g_percentage = static_cast<int>(frac * FULL_PERCENT_PROGRESS);
395         }
396     } else if (outputHeader == "set_progress") {
397         SetProgress(output, upParams);
398     } else {
399         LOG(WARNING) << "Child process returns unexpected message.";
400     }
401 }
402 
ExcuteSubProc(const UpdaterParams & upParams,const std::string & fullPath,int pipeWrite)403 void ExcuteSubProc(const UpdaterParams &upParams, const std::string &fullPath, int pipeWrite)
404 {
405     UPDATER_INIT_RECORD;
406     // Set process scheduler to normal if current scheduler is
407     // SCHED_FIFO, which may cause bad performance.
408     int policy = syscall(SYS_sched_getscheduler, getpid());
409     if (policy == -1) {
410         LOG(INFO) << "Cannnot get current process scheduler";
411     } else if (policy == SCHED_FIFO) {
412         LOG(DEBUG) << "Current process with scheduler SCHED_FIFO";
413         struct sched_param sp = {
414             .sched_priority = 0,
415         };
416         if (syscall(SYS_sched_setscheduler, getpid(), SCHED_OTHER, &sp) < 0) {
417             LOG(WARNING) << "Cannot set current process schedule with SCHED_OTHER";
418         }
419     }
420     const std::string retryPara = upParams.retryCount > 0 ? "retry=1" : "retry=0";
421     execl(fullPath.c_str(), fullPath.c_str(), upParams.updatePackage[upParams.pkgLocation].c_str(),
422             std::to_string(pipeWrite).c_str(), retryPara.c_str(), nullptr);
423     LOG(ERROR) << "Execute updater binary failed";
424     UPDATER_LAST_WORD(UPDATE_ERROR, "Execute updater binary failed");
425     exit(-1);
426 }
427 
HandlePipeMsg(UpdaterParams & upParams,int pipeRead,bool & retryUpdate)428 UpdaterStatus HandlePipeMsg(UpdaterParams &upParams, int pipeRead, bool &retryUpdate)
429 {
430     UPDATER_INIT_RECORD;
431     char buffer[MAX_BUFFER_SIZE] = {0};
432     FILE* fromChild = fdopen(pipeRead, "r");
433     if (fromChild == nullptr) {
434         LOG(ERROR) << "fdopen pipeRead failed";
435         UPDATER_LAST_WORD(UPDATE_ERROR, "fdopen pipeRead failed");
436         return UPDATE_ERROR;
437     }
438     while (fgets(buffer, MAX_BUFFER_SIZE - 1, fromChild) != nullptr) {
439         char *pch = strrchr(buffer, '\n');
440         if (pch != nullptr) {
441             *pch = '\0';
442         }
443         if (strstr(buffer, "subProcessResult") != nullptr) {
444             LOG(INFO) << "subProcessResult: " << buffer;
445             break;
446         }
447         HandleChildOutput(buffer, MAX_BUFFER_SIZE, retryUpdate, upParams);
448     }
449     LOG(INFO) << "HandlePipeMsg end";
450     fclose(fromChild);
451     return UPDATE_SUCCESS;
452 }
453 
CheckProcStatus(pid_t pid,bool retryUpdate)454 UpdaterStatus CheckProcStatus(pid_t pid, bool retryUpdate)
455 {
456     int status;
457     if (waitpid(pid, &status, 0) == -1) {
458         LOG(ERROR) << "waitpid error";
459         return UPDATE_ERROR;
460     }
461     if (retryUpdate) {
462         return UPDATE_RETRY;
463     }
464 
465     if (!WIFEXITED(status) || WEXITSTATUS(status) != 0) {
466         if (WIFEXITED(status)) {
467             LOG(ERROR) << "exited, status= " << WEXITSTATUS(status);
468         } else if (WIFSIGNALED(status)) {
469             LOG(ERROR) << "killed by signal " << WTERMSIG(status);
470         } else if (WIFSTOPPED(status)) {
471             LOG(ERROR) << "stopped by signal " << WSTOPSIG(status);
472         }
473         return UPDATE_ERROR;
474     }
475     LOG(DEBUG) << "Updater process finished.";
476     return UPDATE_SUCCESS;
477 }
478 
GetBinaryPath(PkgManager::PkgManagerPtr pkgManager,UpdaterParams & upParams)479 static std::string GetBinaryPath(PkgManager::PkgManagerPtr pkgManager, UpdaterParams &upParams)
480 {
481     std::string fullPath = GetWorkPath() + std::string(UPDATER_BINARY);
482     (void)Utils::DeleteFile(fullPath);
483 
484     if (ExtractUpdaterBinary(pkgManager, upParams.updatePackage[upParams.pkgLocation], UPDATER_BINARY) != 0) {
485         LOG(INFO) << "There is no valid updater_binary in package, use updater_binary in device";
486         fullPath = "/bin/updater_binary";
487     }
488 
489 #ifdef UPDATER_UT
490     fullPath = "/data/updater/updater_binary";
491 #endif
492     return fullPath;
493 }
494 
StartUpdaterProc(PkgManager::PkgManagerPtr pkgManager,UpdaterParams & upParams)495 UpdaterStatus StartUpdaterProc(PkgManager::PkgManagerPtr pkgManager, UpdaterParams &upParams)
496 {
497     UPDATER_INIT_RECORD;
498     int pfd[DEFAULT_PIPE_NUM]; /* communication between parent and child */
499     if (pipe(pfd) < 0) {
500         LOG(ERROR) << "Create pipe failed: ";
501         UPDATER_LAST_WORD(UPDATE_ERROR, "Create pipe failed");
502         return UPDATE_ERROR;
503     }
504     if (pkgManager == nullptr) {
505         LOG(ERROR) << "pkgManager is nullptr";
506         UPDATER_LAST_WORD(UPDATE_CORRUPT, "pkgManager is nullptr");
507         return UPDATE_CORRUPT;
508     }
509 
510     int pipeRead = pfd[0];
511     int pipeWrite = pfd[1];
512     std::string fullPath = GetBinaryPath(pkgManager, upParams);
513     if (chmod(fullPath.c_str(), S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH) != 0) {
514         LOG(ERROR) << "Failed to change mode";
515     }
516 
517 #ifdef WITH_SELINUX
518     Restorecon(fullPath.c_str());
519 #endif // WITH_SELINUX
520 
521     pid_t pid = fork();
522     if (pid < 0) {
523         ERROR_CODE(CODE_FORK_FAIL);
524         UPDATER_LAST_WORD(UPDATE_ERROR, "fork failed");
525         return UPDATE_ERROR;
526     }
527 
528     if (pid == 0) { // child
529         #ifdef WITH_SELINUX
530         setcon("u:r:updater_binary:s0");
531         #endif // WITH_SELINUX
532         close(pipeRead);   // close read endpoint
533         ExcuteSubProc(upParams, fullPath, pipeWrite);
534     }
535 
536     close(pipeWrite); // close write endpoint
537     bool retryUpdate = false;
538     if (HandlePipeMsg(upParams, pipeRead, retryUpdate) != UPDATE_SUCCESS) {
539         UPDATER_LAST_WORD(UPDATE_ERROR, "HandlePipeMsg failed");
540         return UPDATE_ERROR;
541     }
542 
543     return CheckProcStatus(pid, retryUpdate);
544 }
545 
GetWorkPath()546 std::string GetWorkPath()
547 {
548     if (Utils::IsUpdaterMode()) {
549         return G_WORK_PATH;
550     }
551 
552     return std::string(SYS_INSTALLER_PATH) + "/";
553 }
554 } // namespace Updater
555