diff options
author | Stephen Cprek <smcprek@us.ibm.com> | 2017-10-31 13:01:30 -0500 |
---|---|---|
committer | Daniel M. Crowell <dcrowell@us.ibm.com> | 2017-11-19 15:54:51 -0500 |
commit | 81279c1d146d8ee920494c7817cdd72f165dd373 (patch) | |
tree | d616d0914823c8c25592e8276e0610ba1c9d2a28 /src/usr/runtime | |
parent | 63a026113332464fc3bcc73369ba35bfe8f62b6f (diff) | |
download | talos-hostboot-81279c1d146d8ee920494c7817cdd72f165dd373.tar.gz talos-hostboot-81279c1d146d8ee920494c7817cdd72f165dd373.zip |
Secure Boot: Fix lid load from HB reserved memory issues at runtime
- Force all PNOR sections we load from HB rserved memory to be secure
Only exception is the RINGOVD section, in which we use a fake header
- Add fake header when Secureboot compiled out or a section is never
signed as there is no secure header preserved in virtual memory
RTC: 171708
RTC: 180063
Change-Id: Ibbbd7be24ee7b199e73451c63b2c2d1f86a2c2d8
Reviewed-on: http://ralgit01.raleigh.ibm.com/gerrit1/49020
Tested-by: Jenkins Server <pfd-jenkins+hostboot@us.ibm.com>
Reviewed-by: Nicholas E. Bofferding <bofferdn@us.ibm.com>
Tested-by: Jenkins OP Build CI <op-jenkins+hostboot@us.ibm.com>
Tested-by: Jenkins OP HW <op-hw-jenkins+hostboot@us.ibm.com>
Reviewed-by: Marshall J. Wilks <mjwilks@us.ibm.com>
Tested-by: FSP CI Jenkins <fsp-CI-jenkins+hostboot@us.ibm.com>
Reviewed-by: Michael Baiocchi <mbaiocch@us.ibm.com>
Reviewed-by: Daniel M. Crowell <dcrowell@us.ibm.com>
Diffstat (limited to 'src/usr/runtime')
-rw-r--r-- | src/usr/runtime/common/runtime_utils.C | 18 | ||||
-rw-r--r-- | src/usr/runtime/populate_hbruntime.C | 16 | ||||
-rw-r--r-- | src/usr/runtime/preverifiedlidmgr.C | 66 | ||||
-rw-r--r-- | src/usr/runtime/test/testpreverifiedlidmgr.H | 13 |
4 files changed, 96 insertions, 17 deletions
diff --git a/src/usr/runtime/common/runtime_utils.C b/src/usr/runtime/common/runtime_utils.C index 04a42f502..7b900389f 100644 --- a/src/usr/runtime/common/runtime_utils.C +++ b/src/usr/runtime/common/runtime_utils.C @@ -58,4 +58,22 @@ bool isPreVerifiedSection(const PNOR::SectionId i_section) return l_result; } +bool isPreVerifiedSectionSecure(const PNOR::SectionId i_section) +{ + bool l_result = false; + auto it = find_if(preVerifiedPnorSections.begin(), + preVerifiedPnorSections.end(), + [&i_section](const PreVerifyPair& p) + { + return p.first == i_section; + }); + + if (it != preVerifiedPnorSections.end()) + { + l_result = it->second; + } + + return l_result; +} + }
\ No newline at end of file diff --git a/src/usr/runtime/populate_hbruntime.C b/src/usr/runtime/populate_hbruntime.C index 199b55ecb..eb7a5a7b5 100644 --- a/src/usr/runtime/populate_hbruntime.C +++ b/src/usr/runtime/populate_hbruntime.C @@ -76,7 +76,6 @@ #include <pnor/pnor_reasoncodes.H> #include <runtime/common/runtime_utils.H> - namespace RUNTIME { @@ -557,7 +556,8 @@ errlHndl_t fill_RsvMem_hbData(uint64_t & io_start_address, return l_elog; } -errlHndl_t hbResvLoadSecureSection (const PNOR::SectionId i_sec) +errlHndl_t hbResvLoadSecureSection (const PNOR::SectionId i_sec, + bool i_verified) { TRACFCOMP( g_trac_runtime,ENTER_MRK"hbResvloadSecureSection() sec %s", PNOR::SectionIdToString(i_sec)); @@ -603,16 +603,18 @@ errlHndl_t hbResvLoadSecureSection (const PNOR::SectionId i_sec) auto l_pnorVaddr = l_info.vaddr; auto l_imgSize = l_info.size; - // If section is signed, only the protected size was loaded into memory -#ifdef CONFIG_SECUREBOOT - if (l_info.secure) + // If section is signed, only the protected size was loaded into memory + if (i_verified) { +#ifdef CONFIG_SECUREBOOT l_imgSize = l_info.secureProtectedPayloadSize; // Include secure header l_pnorVaddr -= PAGESIZE; +#endif + // Add size for secure header. + // NOTE: if SB compiled out, a header will be injected later l_imgSize += PAGESIZE; } -#endif // Load Pnor section into HB reserved memory l_elog = PreVerifiedLidMgr::loadFromPnor(i_sec, l_pnorVaddr, l_imgSize); @@ -1070,7 +1072,7 @@ errlHndl_t populate_HbRsvMem(uint64_t i_nodeId) // Handle all Pre verified PNOR sections for (const auto & secIdPair : preVerifiedPnorSections) { - l_elog = hbResvLoadSecureSection(secIdPair.first); + l_elog = hbResvLoadSecureSection(secIdPair.first, secIdPair.second); if (l_elog) { break; diff --git a/src/usr/runtime/preverifiedlidmgr.C b/src/usr/runtime/preverifiedlidmgr.C index 16cf15c10..62671860f 100644 --- a/src/usr/runtime/preverifiedlidmgr.C +++ b/src/usr/runtime/preverifiedlidmgr.C @@ -36,6 +36,8 @@ #include <arch/ppc.H> #include <targeting/common/target.H> #include <targeting/common/attributes.H> +#include <secureboot/containerheader.H> +#include <runtime/common/runtime_utils.H> extern trace_desc_t *g_trac_runtime; @@ -47,6 +49,8 @@ PreVerifiedLidMgr::ResvMemInfo PreVerifiedLidMgr::cv_resvMemInfo {}; PreVerifiedLidMgr::ResvMemInfo PreVerifiedLidMgr::cv_phypResvMemInfo {}; mutex_t PreVerifiedLidMgr::cv_mutex = MUTEX_INITIALIZER; mutex_t PreVerifiedLidMgr::cv_loadImageMutex = MUTEX_INITIALIZER; +bool PreVerifiedLidMgr::cv_addFakeHdrs = false; +PNOR::SectionId PreVerifiedLidMgr::cv_curPnorSecId = PNOR::INVALID_SECTION; /******************** Public Methods @@ -156,6 +160,27 @@ errlHndl_t PreVerifiedLidMgr::_loadFromPnor(const PNOR::SectionId i_sec, TRACFCOMP(g_trac_runtime, ENTER_MRK"PreVerifiedLidMgr::_loadFromPnor - sec %s", PNOR::SectionIdToString(i_sec)); +#ifdef CONFIG_SECUREBOOT + // If SB compiled in, only add fake secure header if the section is never + // signed. e.g. RINGOVD section + // Otherwise always add fake secure header when SB compiled out + if (!RUNTIME::isPreVerifiedSectionSecure(i_sec)) + { +#endif + // Check if Header is mising + if (!PNOR::cmpSecurebootMagicNumber( + reinterpret_cast<uint8_t*>(i_addr))) + { + TRACFCOMP(g_trac_runtime, "PreVerifiedLidMgr::_loadFromPnor adding fake header to %s", + PNOR::SectionIdToString(i_sec)); + // Add fake headers to pnor loads + cv_addFakeHdrs = true; + cv_curPnorSecId = i_sec; + } +#ifdef CONFIG_SECUREBOOT + } +#endif + errlHndl_t l_errl = nullptr; do { @@ -206,10 +231,11 @@ errlHndl_t PreVerifiedLidMgr::_loadFromPnor(const PNOR::SectionId i_sec, { char l_lidStr[Util::lidIdStrLength] {}; snprintf (l_lidStr, Util::lidIdStrLength, "%08X",l_lids.lid); + assert(i_size > PAGE_SIZE, "PreVerifiedLidMgr::_loadFromPnor - caller did not include size of header for total size"); l_errl = RUNTIME::setNextHbRsvMemEntry(HDAT::RHB_TYPE_VERIFIED_LIDS, cv_pResvMemInfo->rangeId, cv_pResvMemInfo->curAddr+PAGE_SIZE, - i_size, + i_size-PAGE_SIZE, l_lidStr); if(l_errl) { @@ -253,6 +279,10 @@ errlHndl_t PreVerifiedLidMgr::_loadFromPnor(const PNOR::SectionId i_sec, } while(0); + // Force fake header bool to be false and clear cur PNOR section id + cv_addFakeHdrs = false; + cv_curPnorSecId = PNOR::INVALID_SECTION; + TRACFCOMP( g_trac_runtime, EXIT_MRK"PreVerifiedLidMgr::_loadFromPnor"); mutex_unlock(&cv_loadImageMutex); @@ -271,6 +301,9 @@ errlHndl_t PreVerifiedLidMgr::_loadFromMCL(const uint32_t i_lidId, TRACFCOMP(g_trac_runtime, ENTER_MRK"PreVerifiedLidMgr::_loadFromMCL lid = 0x%X", i_lidId); + // Force fake header bool to be false in MCL path + cv_addFakeHdrs = false; + errlHndl_t l_errl = nullptr; // Switch to Different Memory Info for PHYP component @@ -396,11 +429,32 @@ errlHndl_t PreVerifiedLidMgr::loadImage(const uint64_t i_imgAddr, TRACDCOMP(g_trac_runtime, "PreVerifiedLidMgr::loadImage - curAddr 0x%X, size 0x%X, vaddr 0x%X", cv_pResvMemInfo->curAddr, i_imgSize, l_tmpVaddr); - // Include Header page from pnor image. - // NOTE: Do not use aligned size for memcpy - memcpy(reinterpret_cast<void*>(l_tmpVaddr), - reinterpret_cast<void*>(i_imgAddr), - i_imgSize); + // Inject a fake header when loading from PNOR and secureboot is compiled + // out. + if(cv_addFakeHdrs) + { + TRACDCOMP(g_trac_runtime, "PreVerifiedLidMgr::loadImage fake header load"); + SECUREBOOT::ContainerHeader l_fakeHdr(i_imgSize, + SectionIdToString(cv_curPnorSecId)); + // Inject Fake header into reserved memory + memcpy(reinterpret_cast<void*>(l_tmpVaddr), + l_fakeHdr.fakeHeader(), + PAGE_SIZE); + // Include rest of image after header + // NOTE: Do not use aligned size for memcpy + assert(i_imgSize > PAGE_SIZE, "PreVerifiedLidMgr::loadImage - caller did not include size of header for total size"); + memcpy(reinterpret_cast<void*>(l_tmpVaddr+PAGE_SIZE), + reinterpret_cast<void*>(i_imgAddr), + i_imgSize-PAGE_SIZE); + } + else + { + TRACDCOMP(g_trac_runtime, "PreVerifiedLidMgr::loadImage default load"); + // NOTE: Do not use aligned size for memcpy + memcpy(reinterpret_cast<void*>(l_tmpVaddr), + reinterpret_cast<void*>(i_imgAddr), + i_imgSize); + } l_errl = RUNTIME::unmapVirtAddr(l_tmpVaddr); if(l_errl) diff --git a/src/usr/runtime/test/testpreverifiedlidmgr.H b/src/usr/runtime/test/testpreverifiedlidmgr.H index 3863ed27e..26879574e 100644 --- a/src/usr/runtime/test/testpreverifiedlidmgr.H +++ b/src/usr/runtime/test/testpreverifiedlidmgr.H @@ -83,7 +83,8 @@ class PreVerifiedLidMgrTest : public CxxTest::TestSuite // Handle all Pre verified PNOR sections for (const auto & secIdPair : RUNTIME::preVerifiedPnorSections) { - l_errl = RUNTIME::hbResvLoadSecureSection(secIdPair.first); + l_errl = RUNTIME::hbResvLoadSecureSection(secIdPair.first, + secIdPair.second); if (l_errl) { errlCommit(l_errl, RUNTIME_COMP_ID); @@ -100,16 +101,20 @@ class PreVerifiedLidMgrTest : public CxxTest::TestSuite // Each section has 2 lids each (Header, Content) except the RINGOVD // section. It only has 1 or is inhibited in secure mode size_t l_numSections = RUNTIME::preVerifiedPnorSections.size(); - size_t l_expectedLids = (2 * l_numSections) - 1; + // See utillidpnor.C for more info on num of lids + size_t l_expectedLids = (2 * l_numSections); if (SECUREBOOT::enabled()) { - l_expectedLids--; + // RINGOVD not permitted in secure mode + l_expectedLids -= 2; } // Ensure the expected number of lids were loaded. if (l_preVerLidMgr.cv_lidsLoaded.size() != l_expectedLids) { - TS_FAIL("testLoadFromPnor> Num of lids loaded not correct"); + TS_FAIL("testLoadFromPnor> Num of lids loaded not correct %d expected %d", + l_preVerLidMgr.cv_lidsLoaded.size(), + l_expectedLids); break; } |