From 4614846d381df0581d2ec162b072fba84448615d Mon Sep 17 00:00:00 2001 From: "Wiktor S. Ovalle Correa" Date: Tue, 2 Feb 2021 16:27:20 +0100 Subject: [PATCH] [EGD-5590] Fix boot config procedure Boot config procedure was outdated and didn't actually work --- board/linux/libiosyscalls/src/iosyscalls.cpp | 1 - .../endpoints/update/UpdateMuditaOS.cpp | 6 +- .../bootconfig/include/boot/bootconfig.hpp | 2 +- .../bootconfig/include/boot/bootconstants.hpp | 2 +- module-utils/bootconfig/src/bootconfig.cpp | 90 +++++++++++-------- 5 files changed, 59 insertions(+), 42 deletions(-) diff --git a/board/linux/libiosyscalls/src/iosyscalls.cpp b/board/linux/libiosyscalls/src/iosyscalls.cpp index c8a2dd9de6aaede7420475b43982ab23b54a716a..924feafae63d95bcec8301757b426e00d0f206c8 100644 --- a/board/linux/libiosyscalls/src/iosyscalls.cpp +++ b/board/linux/libiosyscalls/src/iosyscalls.cpp @@ -21,7 +21,6 @@ namespace constexpr const char *LINUX_PATHS[]{"/dev/", "/etc/", - "/sys/.boot.json", "/usr/share", "/run/user", "/home", diff --git a/module-services/service-desktop/endpoints/update/UpdateMuditaOS.cpp b/module-services/service-desktop/endpoints/update/UpdateMuditaOS.cpp index 114b7524fb29994849142262d7704685986d7092..99f962a2559da5d27ebf70fe53261cc49726ca63 100644 --- a/module-services/service-desktop/endpoints/update/UpdateMuditaOS.cpp +++ b/module-services/service-desktop/endpoints/update/UpdateMuditaOS.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2017-2020, Mudita Sp. z.o.o. All rights reserved. +// Copyright (c) 2017-2021, Mudita Sp. z.o.o. All rights reserved. // For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md #include "UpdateMuditaOS.hpp" @@ -293,7 +293,7 @@ void UpdateMuditaOS::getChecksumInfo(const std::string &infoLine, std::string &f std::size_t lastSpacePos = infoLine.find_last_of(' '); if (lastSpacePos > 0) { filePath = infoLine.substr(0, lastSpacePos); - const std::string fileCRC32Str = infoLine.substr(lastSpacePos + 1, boot::consts::crc_char_size - 1); + const std::string fileCRC32Str = infoLine.substr(lastSpacePos + 1, boot::consts::crc_char_size); if (fileCRC32Long != nullptr) { *fileCRC32Long = strtoull(fileCRC32Str.c_str(), nullptr, boot::consts::crc_radix); informDebug("getChecksumInfo filePath: %s fileCRC32Str: %s fileCRC32Long: %lu fileCRC32Hex: %lX", @@ -388,7 +388,7 @@ updateos::UpdateError UpdateMuditaOS::updateBootJSON() auto *fpCRC = std::fopen(bootJSONAbsoulte.c_str(), "w"); if (fpCRC != nullptr) { - std::array crcBuf; + std::array crcBuf; snprintf(crcBuf.data(), crcBuf.size(), "%lX", bootJSONAbsoulteCRC); std::fwrite(crcBuf.data(), 1, boot::consts::crc_char_size, fpCRC); std::fclose(fpCRC); diff --git a/module-utils/bootconfig/include/boot/bootconfig.hpp b/module-utils/bootconfig/include/boot/bootconfig.hpp index 7e0287dfaefb808a29ec468958fe43c84140cecd..5455c804e34592c2449dfb92388d98eb0cfa786b 100644 --- a/module-utils/bootconfig/include/boot/bootconfig.hpp +++ b/module-utils/bootconfig/include/boot/bootconfig.hpp @@ -60,10 +60,10 @@ namespace boot { return m_os_root_path; } - void updateTimestamp(); private: bool loadBootConfig(const std::filesystem::path &bootJsonPath); + void updateBootJson(const std::filesystem::path &bootJsonPath); std::filesystem::path getCurrentBootJSON(); private: diff --git a/module-utils/bootconfig/include/boot/bootconstants.hpp b/module-utils/bootconfig/include/boot/bootconstants.hpp index e8be5ae85929127c96851eadd30c764516c035c4..c31c04a56132e6f126fe667a8eaad796fb71ac00 100644 --- a/module-utils/bootconfig/include/boot/bootconstants.hpp +++ b/module-utils/bootconfig/include/boot/bootconstants.hpp @@ -5,7 +5,7 @@ namespace boot::consts { inline constexpr auto tar_buf = 8192 * 4; - inline constexpr auto crc_char_size = 9; + inline constexpr auto crc_char_size = 8; inline constexpr auto crc_radix = 16; inline constexpr auto ext_crc32 = ".crc32"; inline constexpr auto crc_buf = 1024; diff --git a/module-utils/bootconfig/src/bootconfig.cpp b/module-utils/bootconfig/src/bootconfig.cpp index 2384eb3a7626f1447d4af1d81fd0a53765d61834..4aa4dd299c0e8710fbd3ccc9e4a985cbe92e15e3 100644 --- a/module-utils/bootconfig/src/bootconfig.cpp +++ b/module-utils/bootconfig/src/bootconfig.cpp @@ -16,29 +16,21 @@ #include #include +#include + +#include +#include +#include + namespace boot { namespace { - bool writeToFile(const std::filesystem::path &file, const std::string &stringToWrite) - { - auto fp = fopen(file.c_str(), "w"); - if (!fp) { - return false; - } - - size_t dataWritten = fwrite(stringToWrite.c_str(), stringToWrite.length(), 1, fp); - - fclose(fp); - - return dataWritten == 1; - } - bool updateFileCRC32(const std::filesystem::path &file) { auto fp = fopen(file.c_str(), "r"); if (!fp) { - LOG_WARN("updateFileCRC32 can't open file %s for write", file.c_str()); + LOG_WARN("updateFileCRC32 can't open file %s for read", file.c_str()); return false; } auto fpCloseAct = gsl::finally([fp] { fclose(fp); }); @@ -52,13 +44,13 @@ namespace boot return false; } - std::array crc32Buf; + std::array crc32Buf; if (int written = sprintf(crc32Buf.data(), "%08" PRIX32, fileCRC32); - written != boot::consts::crc_char_size - 1) { + written != boot::consts::crc_char_size) { LOG_INFO("updateFileCRC32 can't prepare string for crc32, sprintf returned %d instead of %d", written, - boot::consts::crc_char_size - 1); + boot::consts::crc_char_size); return false; } @@ -117,10 +109,9 @@ namespace boot } auto fpCloseAct = gsl::finally([fp] { fclose(fp); }); - std::array crcBuf; - - if (size_t readSize = std::fread(crcBuf.data(), 1, boot::consts::crc_char_size, fp); - readSize != boot::consts::crc_char_size) { + std::array crcBuf; + size_t readSize = std::fread(crcBuf.data(), 1, boot::consts::crc_char_size, fp); + if (readSize != boot::consts::crc_char_size) { LOG_ERROR("verifyCRC fread on %s returned different size then %d [%zu]", crcFilePath.c_str(), boot::consts::crc_char_size, @@ -128,7 +119,8 @@ namespace boot return false; } - const unsigned long crc32Read = strtoull(crcBuf.data(), nullptr, boot::consts::crc_radix); + crcBuf[boot::consts::crc_char_size] = 0; + const unsigned long crc32Read = strtoull(crcBuf.data(), nullptr, boot::consts::crc_radix); LOG_INFO("verifyCRC read %s string:\"%s\" hex:%08lX", crcFilePath.c_str(), crcBuf.data(), crc32Read); return verifyCRC(file, crc32Read); @@ -137,6 +129,7 @@ namespace boot BootConfig::BootConfig() : m_os_root_path(purefs::dir::getRootDiskPath()) {} + json11::Json BootConfig::to_json() const { return json11::Json::object{ @@ -152,6 +145,7 @@ namespace boot {boot::json::os_git_branch, std::string(GIT_BRANCH)}}}, {boot::json::bootloader, json11::Json::object{{boot::json::os_version, m_bootloader_version}}}}; } + int BootConfig::load() { return !loadBootConfig(getCurrentBootJSON()); @@ -186,22 +180,45 @@ namespace boot return 0; } - void BootConfig::updateTimestamp() + void BootConfig::updateBootJson(const std::filesystem::path &bootJsonPath) { m_timestamp = utils::time::Timestamp().str("%c"); - LOG_INFO("vfs::updateTimestamp \"%s\"", to_json().dump().c_str()); - if (writeToFile(m_boot_json, to_json().dump())) { - updateFileCRC32(m_boot_json); + struct statvfs stat; + if (statvfs(purefs::dir::getRootDiskPath().c_str(), &stat)) + LOG_ERROR("%s: Failed to stat vfs", bootJsonPath.c_str()); + + auto remount_ro{true}; + auto flags = stat.f_flag & ~MS_RDONLY; + if (mount(NULL, purefs::dir::getRootDiskPath().c_str(), NULL, flags | MS_REMOUNT, NULL)) { + LOG_WARN("%s: Failed to remount filesystem R/W - it's fine for a Linux FS", bootJsonPath.c_str()); + remount_ro = false; + } + + LOG_INFO("Writing new %s..", bootJsonPath.c_str()); + std::ofstream file(bootJsonPath); + if (file.is_open()) { + file << to_json().dump() << std::flush; + if (!file.good()) + LOG_ERROR("%s: Error while writing a file", bootJsonPath.c_str()); + file.close(); + updateFileCRC32(bootJsonPath); + } + else { + LOG_ERROR("%s: Failed to open file", bootJsonPath.c_str()); } + + if (remount_ro) + if (mount(NULL, purefs::dir::getRootDiskPath().c_str(), NULL, flags | MS_RDONLY | MS_REMOUNT, NULL)) + LOG_ERROR("%s: Failed to remount filesystem back to RO", bootJsonPath.c_str()); } + bool BootConfig::loadBootConfig(const std::filesystem::path &bootJsonPath) { std::string parseErrors = ""; std::string jsonContents = loadFileAsString(bootJsonPath); - LOG_INFO("vfs::getOSRootFromJSON parsing %s", bootJsonPath.c_str()); - LOG_INFO("vfs::getOSRootFromJSON \"%s\"", jsonContents.c_str()); + LOG_INFO("parsed %s: \"%s\"", bootJsonPath.c_str(), jsonContents.c_str()); m_boot_json_parsed = json11::Json::parse(jsonContents, parseErrors); @@ -224,18 +241,19 @@ namespace boot m_boot_json = bootJsonPath; m_timestamp = utils::time::Timestamp().str("%c"); m_os_version = std::string(VERSION); - LOG_WARN("vfs::getOSRootFromJSON failed to parse %s: \"%s\"", bootJsonPath.c_str(), parseErrors.c_str()); + LOG_WARN("%s failed to parse %s: \"%s\"", __FUNCTION__, bootJsonPath.c_str(), parseErrors.c_str()); return false; } } + std::filesystem::path BootConfig::getCurrentBootJSON() { - if (readAndVerifyCRC(purefs::file::boot_json)) { - return purefs::createPath(purefs::dir::getRootDiskPath(), purefs::file::boot_json); + auto boot_json_path = purefs::dir::getRootDiskPath() / purefs::file::boot_json; + if (!readAndVerifyCRC(boot_json_path)) { + LOG_INFO("CRC check failed on %s", boot_json_path.c_str()); + // replace broken .boot.json with a default one + updateBootJson(boot_json_path); } - LOG_INFO("vfs::getCurrentBootJSON crc check failed on %s", purefs::file::boot_json); - // replace broken .boot.json with a default one - writeToFile(purefs::dir::getRootDiskPath() / purefs::file::boot_json, to_json().dump()); - return purefs::createPath(purefs::dir::getRootDiskPath(), purefs::file::boot_json); + return boot_json_path; } } // namespace boot