diff --git a/virtrust/src/virtrust/CMakeLists.txt b/virtrust/src/virtrust/CMakeLists.txt index b57c3319dea25888fc251fd777cc6badbc13d3c2..ca78eaeb457924e796f932b4a3ad867879fa1499 100644 --- a/virtrust/src/virtrust/CMakeLists.txt +++ b/virtrust/src/virtrust/CMakeLists.txt @@ -77,7 +77,7 @@ target_include_directories( PRIVATE ${CMAKE_DEPS_INCLUDEDIR} ${CMAKE_CURRENT_BINARY_DIR}/src $) -target_link_libraries(virtrust-shared PRIVATE Deps::spdlog boundscheck) +target_link_libraries(virtrust-shared PRIVATE Deps::spdlog Deps::secure_c) target_link_libraries( virtrust-shared diff --git a/virtrust/src/virtrust/api/domain.cpp b/virtrust/src/virtrust/api/domain.cpp index b6c0574cee48975f224be4070b240d8e54fadca6..de5a9533a34b80f74af73d20fbc58526abb9bbc6 100644 --- a/virtrust/src/virtrust/api/domain.cpp +++ b/virtrust/src/virtrust/api/domain.cpp @@ -8,6 +8,7 @@ #include #include +#include #include #include "spdlog/fmt/fmt.h" @@ -310,7 +311,7 @@ VirtrustRc CheckCreateDomainName(const std::string &arg, std::string &domainName } // 处理--name=***或-n=***或-n***** bool isLongContainsName = arg.length() > 7 && arg.substr(0, 7) == "--name="; // 7是--name=的长度 - bool isShortContainsName = arg.length() > 3 && arg.substr(0, 2) == "-n"; // 这里大于3是处理-n并且紧跟字符的情况 + bool isShortContainsName = arg.length() > 3 && arg.substr(0, 2) == "-n"; // 这里大于3是处理-n并且紧跟字符的情况 if (isLongContainsName || isShortContainsName) { if (isLongContainsName || (isLongContainsName && arg.find('=') != std::string::npos)) { domainName = arg.substr(arg.find('=') + 1); @@ -638,7 +639,8 @@ VirtrustRc CheckCreateArgs(const std::vector &args) auto &arg = args[pos]; if (arg.empty() || arg.size() > CREATE_ARGS_MAX_STRING_LENGTH) { VIRTRUST_LOG_ERROR("|CheckCreateArgs|END|returnF||Arg with index {} not valid, " - "length needs to be between {} and {}.", pos, 1, CREATE_ARGS_MAX_STRING_LENGTH); + "length needs to be between {} and {}.", + pos, 1, CREATE_ARGS_MAX_STRING_LENGTH); return VirtrustRc::ERROR; } } @@ -933,50 +935,61 @@ VirtrustRc DomainStart(const std::unique_ptr &conn, const std::string & bool isOnlyTsb) { VIRTRUST_LOG_DEBUG("|DomainStart||START||start domainName: {}, isonlyTsb:{}", domainName, isOnlyTsb); + + // First, check conn is not null pointer if (conn == nullptr) { VIRTRUST_LOG_ERROR("|DomainStart|END|returnF|| ConnCtx is nullptr."); return VirtrustRc::ERROR; } + + // Perform file lock FileLock fileLock(LOCK_FILE); if (!fileLock.IsLocked()) { return VirtrustRc::ERROR; } - if (conn == nullptr) { - VIRTRUST_LOG_ERROR("|DomainStart|END|returnF||conn is nullptr"); + + // NOTE check for flags, currenty we only support: DOMAIN_START_NONE + // Libvirt does no checking and it is up to the hypervisor to refuse to start the domain if it cannot provide the + // requested CPU. With QEMU this means no checking is done at all since the default behavior of QEMU is to emit + // warnings, but start the domain anyway. + if (flags != DOMAIN_START_NONE) { + VIRTRUST_LOG_ERROR("flags only support: {}", static_cast(DOMAIN_START_NONE)); return VirtrustRc::ERROR; } - // 如果带--only-tsb仅更新tsb资源 + + std::string uuid; + if (isOnlyTsb) { - std::string uuidStr = domainName; - VIRTRUST_LOG_INFO("only update tsb resource"); - if (domainName.size() != 36) { // UUIDchang长度为36 - VIRTRUST_LOG_DEBUG("|DomainStart|END|returnF||invalid domain UUID: {}", domainName); + // HACK if --only-tsb enabled, the input domainName is actually the uuid (very hacky) + uuid = domainName; + VIRTRUST_LOG_INFO("only start tsb resource"); + // Check if the input uuid is valid + if (uuid.size() != 36) { // UUIDchang长度为36 + VIRTRUST_LOG_DEBUG("|DomainStart|END|returnF||invalid domain UUID: {}", uuid); return VirtrustRc::ERROR; } - if (StartVRoot(uuidStr.data()) != 0) { - VIRTRUST_LOG_DEBUG("|DomainStart|END|returnF||start vRoot failed,UUID: {}", domainName); + if (StartVRoot(uuid.data()) != 0) { + VIRTRUST_LOG_DEBUG("|DomainStart|END|returnF||start vRoot failed,UUID: {}", uuid); return VirtrustRc::ERROR; } - VIRTRUST_LOG_DEBUG("|DomainStart||END|returnS|start domainName: {} success", domainName); - return VirtrustRc::OK; - } - if (flags != DOMAIN_START_NONE) { - VIRTRUST_LOG_ERROR("flags only support: {}", static_cast(DOMAIN_START_NONE)); - return VirtrustRc::ERROR; + VIRTRUST_LOG_DEBUG("|DomainStart||END|returnS|start domainName (only-tsb mode): {} success", uuid); + return VirtrustRc::OK; // unconditionally exit } + + // Get domain instance auto domain = std::make_unique(conn, domainName); if (domain->Get() == nullptr) { VIRTRUST_LOG_ERROR("failed to find domain: {}", domainName); return VirtrustRc::ERROR; } - std::string uuid = GetUUIDStr(domain->Get()); - auto tsbRc = StartVRoot(uuid.data()); - if (tsbRc != 0) { - VIRTRUST_LOG_ERROR("start vRoot failed: {}", domainName); - return VirtrustRc::ERROR; - } + // Get actual UUID from + uuid = GetUUIDStr(domain->Get()); + + // Since Starting VRoot and check guest can run in parallel, use std::async + auto asyncStartVRoot = std::async(&StartVRoot, uuid.data()); + // Secure Start Check (include mounting, hashing, and sending measures to tsb) VIRTRUST_LOG_INFO("Perform checking on: {} before start", domainName); if (!CheckGuestBeforeStart(domainName, uuid)) { VIRTRUST_LOG_ERROR("Check domain failed,domainName: {}", domainName); @@ -986,6 +999,14 @@ VirtrustRc DomainStart(const std::unique_ptr &conn, const std::string & return VirtrustRc::ERROR; } + // Make async join the main thread + auto startVRootRc = asyncStartVRoot.get(); + if (startVRootRc != 0) { + VIRTRUST_LOG_ERROR("Start vRoot failed: {}", uuid); + return VirtrustRc::ERROR; + } + + // Start Domain with libvirt api if (Libvirt::GetInstance().virDomainCreateWithFlags(domain->Get(), flags) < 0) { VIRTRUST_LOG_ERROR("failed to start domain: {}", domainName); if (StopVRoot(uuid.data()) != 0) { diff --git a/virtrust/src/virtrust/base/str_utils.h b/virtrust/src/virtrust/base/str_utils.h index 39cea020e4af60116f07461316ebe1d1c17f593f..cadd5ab85a509527e2f3dc8b40b262ed169ccac0 100644 --- a/virtrust/src/virtrust/base/str_utils.h +++ b/virtrust/src/virtrust/base/str_utils.h @@ -9,6 +9,7 @@ #include #include +#include #include #include #include