diff options
Diffstat (limited to 'meta-openbmc-mods/meta-common/recipes-phosphor/ipmi/phosphor-ipmi-host/0064-Update-provisioning-mode-filter-logic.patch')
-rw-r--r-- | meta-openbmc-mods/meta-common/recipes-phosphor/ipmi/phosphor-ipmi-host/0064-Update-provisioning-mode-filter-logic.patch | 301 |
1 files changed, 301 insertions, 0 deletions
diff --git a/meta-openbmc-mods/meta-common/recipes-phosphor/ipmi/phosphor-ipmi-host/0064-Update-provisioning-mode-filter-logic.patch b/meta-openbmc-mods/meta-common/recipes-phosphor/ipmi/phosphor-ipmi-host/0064-Update-provisioning-mode-filter-logic.patch new file mode 100644 index 000000000..5cd8b3ec4 --- /dev/null +++ b/meta-openbmc-mods/meta-common/recipes-phosphor/ipmi/phosphor-ipmi-host/0064-Update-provisioning-mode-filter-logic.patch @@ -0,0 +1,301 @@ +From dcfce847654bd7e2475ad74bedf569b6120701dd Mon Sep 17 00:00:00 2001 +From: Richard Marian Thomaiyar <richard.marian.thomaiyar@linux.intel.com> +Date: Tue, 18 Jun 2019 19:42:30 +0530 +Subject: [PATCH 1/1] Update provisioning mode filter logic + +Updated provisioning mode filtering logic support. Based on the +RestrictionMode property, Host (system) interface commands will be +filtered as per the allowed list in ProvisionedHostWhitelist once +POST complete is achieved. No commands will be allowed in +ProvisionedHostDisabled after POST complete and in all other cases +filterning logic will not be applied. + +Tested +1. Verified the filtering logic through EFI shell and made sure +filtering logic is applied when RestrictionMode is in +ProvisionedHostWhitelist mode +2. Verified no filtering logic is applied in normal modes +3. Made sure BIOS is able to execute commands, which are not in +whitelist (Note: New whitelist conf is under review). + +Change-Id: I7a14e827d70e2d8d6975e600a0fd00e2a790bc22 +Signed-off-by: Richard Marian Thomaiyar <richard.marian.thomaiyar@linux.intel.com> +Signed-off-by: James Feist <james.feist@linux.intel.com> +--- + whitelist-filter.cpp | 191 ++++++++++++++++++++++++++++++------------- + 1 file changed, 136 insertions(+), 55 deletions(-) + +diff --git a/whitelist-filter.cpp b/whitelist-filter.cpp +index 9f1e7c8..53461b4 100644 +--- a/whitelist-filter.cpp ++++ b/whitelist-filter.cpp +@@ -25,6 +25,7 @@ namespace + */ + class WhitelistFilter + { ++ + public: + WhitelistFilter(); + ~WhitelistFilter() = default; +@@ -35,17 +36,24 @@ class WhitelistFilter + + private: + void postInit(); +- void cacheRestrictedMode(); ++ void cacheRestrictedAndPostCompleteMode(); + void handleRestrictedModeChange(sdbusplus::message::message& m); ++ void handlePostCompleteChange(sdbusplus::message::message& m); + ipmi::Cc filterMessage(ipmi::message::Request::ptr request); + +- bool restrictedMode = true; ++ sdbusplus::xyz::openbmc_project::Control::Security::server:: ++ RestrictionMode::Modes restrictionMode = ++ sdbusplus::xyz::openbmc_project::Control::Security::server:: ++ RestrictionMode::Modes::ProvisionedHostWhitelist; ++ bool postCompleted = false; + std::shared_ptr<sdbusplus::asio::connection> bus; +- std::unique_ptr<settings::Objects> objects; + std::unique_ptr<sdbusplus::bus::match::match> modeChangeMatch; ++ std::unique_ptr<sdbusplus::bus::match::match> postCompleteMatch; + + static constexpr const char restrictionModeIntf[] = + "xyz.openbmc_project.Control.Security.RestrictionMode"; ++ static constexpr const char* systemOsStatusIntf = ++ "xyz.openbmc_project.State.OperatingSystem.Status"; + }; + + WhitelistFilter::WhitelistFilter() +@@ -63,43 +71,83 @@ WhitelistFilter::WhitelistFilter() + post_work([this]() { postInit(); }); + } + +-void WhitelistFilter::cacheRestrictedMode() ++void WhitelistFilter::cacheRestrictedAndPostCompleteMode() + { + using namespace sdbusplus::xyz::openbmc_project::Control::Security::server; ++ + std::string restrictionModeSetting; + std::string restrictionModeService; ++ std::string systemOsStatusPath; ++ std::string systemOsStatusService; + try + { +- restrictionModeSetting = objects->map.at(restrictionModeIntf).at(0); ++ auto objects = settings::Objects( ++ *bus, std::vector<settings::Interface>({restrictionModeIntf})); ++ auto postCompleteObj = settings::Objects( ++ *bus, std::vector<settings::Interface>({systemOsStatusIntf})); ++ ++ restrictionModeSetting = objects.map.at(restrictionModeIntf).at(0); + restrictionModeService = +- objects->service(restrictionModeSetting, restrictionModeIntf); ++ objects.service(restrictionModeSetting, restrictionModeIntf); ++ ++ systemOsStatusPath = postCompleteObj.map.at(systemOsStatusIntf).at(0); ++ systemOsStatusService = ++ postCompleteObj.service(systemOsStatusPath, systemOsStatusIntf); + } + catch (const std::out_of_range& e) + { +- log<level::ERR>( +- "Could not look up restriction mode interface from cache"); ++ log<level::INFO>( ++ "Could not initialize provisioning mode, defaulting to restricted"); ++ return; ++ } ++ catch (const std::exception&) ++ { ++ log<level::INFO>( ++ "Could not initialize provisioning mode, defaulting to restricted"); + return; + } ++ + bus->async_method_call( + [this](boost::system::error_code ec, ipmi::Value v) { + if (ec) + { +- log<level::ERR>("Error in RestrictionMode Get"); +- // Fail-safe to true. +- restrictedMode = true; ++ log<level::INFO>("Could not initialize provisioning mode, " ++ "defaulting to restricted"); + return; + } + auto mode = std::get<std::string>(v); +- auto restrictionMode = +- RestrictionMode::convertModesFromString(mode); +- restrictedMode = +- (restrictionMode == RestrictionMode::Modes::Whitelist); +- log<level::INFO>((restrictedMode ? "Set restrictedMode = true" +- : "Set restrictedMode = false")); ++ restrictionMode = RestrictionMode::convertModesFromString(mode); ++ log<level::INFO>( ++ "Read restriction mode", ++ entry("VALUE=%d", static_cast<int>(restrictionMode))); + }, + restrictionModeService, restrictionModeSetting, + "org.freedesktop.DBus.Properties", "Get", restrictionModeIntf, + "RestrictionMode"); ++ ++ bus->async_method_call( ++ [this](boost::system::error_code ec, const ipmi::Value& v) { ++ if (ec) ++ { ++ log<level::ERR>("Error in OperatingSystemState Get"); ++ postCompleted = true; ++ return; ++ } ++ auto value = std::get<std::string>(v); ++ if (value == "Standby") ++ { ++ postCompleted = true; ++ } ++ else ++ { ++ postCompleted = false; ++ } ++ log<level::INFO>("Read POST complete value", ++ entry("VALUE=%d", postCompleted)); ++ }, ++ systemOsStatusService, systemOsStatusPath, ++ "org.freedesktop.DBus.Properties", "Get", systemOsStatusIntf, ++ "OperatingSystemState"); + } + + void WhitelistFilter::handleRestrictedModeChange(sdbusplus::message::message& m) +@@ -112,61 +160,94 @@ void WhitelistFilter::handleRestrictedModeChange(sdbusplus::message::message& m) + { + if (property.first == "RestrictionMode") + { +- RestrictionMode::Modes restrictionMode = +- RestrictionMode::convertModesFromString( +- std::get<std::string>(property.second)); +- restrictedMode = +- (restrictionMode == RestrictionMode::Modes::Whitelist); +- log<level::INFO>((restrictedMode +- ? "Updated restrictedMode = true" +- : "Updated restrictedMode = false")); ++ restrictionMode = RestrictionMode::convertModesFromString( ++ std::get<std::string>(property.second)); ++ log<level::INFO>( ++ "Updated restriction mode", ++ entry("VALUE=%d", static_cast<int>(restrictionMode))); + } + } + } +- +-void WhitelistFilter::postInit() ++void WhitelistFilter::handlePostCompleteChange(sdbusplus::message::message& m) + { +- objects = std::make_unique<settings::Objects>( +- *bus, std::vector<settings::Interface>({restrictionModeIntf})); +- if (!objects) ++ std::string intf; ++ std::vector<std::pair<std::string, ipmi::Value>> propertyList; ++ m.read(intf, propertyList); ++ for (const auto& property : propertyList) + { +- log<level::ERR>( +- "Failed to create settings object; defaulting to restricted mode"); +- return; ++ if (property.first == "OperatingSystemState") ++ { ++ std::string value = std::get<std::string>(property.second); ++ if (value == "Standby") ++ { ++ postCompleted = true; ++ } ++ else ++ { ++ postCompleted = false; ++ } ++ log<level::INFO>(postCompleted ? "Updated to POST Complete" ++ : "Updated to !POST Complete"); ++ } + } +- ++} ++void WhitelistFilter::postInit() ++{ + // Initialize restricted mode +- cacheRestrictedMode(); ++ cacheRestrictedAndPostCompleteMode(); + // Wait for changes on Restricted mode +- std::string filterStr; +- try +- { +- filterStr = sdbusplus::bus::match::rules::propertiesChanged( +- objects->map.at(restrictionModeIntf).at(0), restrictionModeIntf); +- } +- catch (const std::out_of_range& e) +- { +- log<level::ERR>("Failed to determine restriction mode filter string"); +- return; +- } ++ namespace rules = sdbusplus::bus::match::rules; ++ const std::string filterStrModeChange = ++ rules::type::signal() + rules::member("PropertiesChanged") + ++ rules::interface("org.freedesktop.DBus.Properties") + ++ rules::argN(0, restrictionModeIntf); ++ ++ const std::string filterStrPostComplete = ++ rules::type::signal() + rules::member("PropertiesChanged") + ++ rules::interface("org.freedesktop.DBus.Properties") + ++ rules::argN(0, systemOsStatusIntf); ++ + modeChangeMatch = std::make_unique<sdbusplus::bus::match::match>( +- *bus, filterStr, [this](sdbusplus::message::message& m) { ++ *bus, filterStrModeChange, [this](sdbusplus::message::message& m) { + handleRestrictedModeChange(m); + }); ++ postCompleteMatch = std::make_unique<sdbusplus::bus::match::match>( ++ *bus, filterStrPostComplete, [this](sdbusplus::message::message& m) { ++ handlePostCompleteChange(m); ++ }); + } + + ipmi::Cc WhitelistFilter::filterMessage(ipmi::message::Request::ptr request) + { +- if (request->ctx->channel == ipmi::channelSystemIface && restrictedMode) ++ using namespace sdbusplus::xyz::openbmc_project::Control::Security::server; ++ ++ if (request->ctx->channel == ipmi::channelSystemIface && ++ (restrictionMode != RestrictionMode::Modes::None && ++ restrictionMode != RestrictionMode::Modes::Provisioning)) + { +- if (!std::binary_search( +- whitelist.cbegin(), whitelist.cend(), +- std::make_pair(request->ctx->netFn, request->ctx->cmd))) ++ if (!postCompleted) ++ { ++ // Allow all commands, till POST is not completed ++ return ipmi::ccSuccess; ++ } ++ switch (restrictionMode) + { +- log<level::ERR>("Net function not whitelisted", +- entry("NETFN=0x%X", int(request->ctx->netFn)), +- entry("CMD=0x%X", int(request->ctx->cmd))); +- return ipmi::ccInsufficientPrivilege; ++ case RestrictionMode::Modes::ProvisionedHostWhitelist: ++ { ++ if (!std::binary_search( ++ whitelist.cbegin(), whitelist.cend(), ++ std::make_pair(request->ctx->netFn, request->ctx->cmd))) ++ { ++ log<level::ERR>( ++ "Net function not whitelisted", ++ entry("NETFN=0x%X", int(request->ctx->netFn)), ++ entry("CMD=0x%X", int(request->ctx->cmd))); ++ return ipmi::ccInsufficientPrivilege; ++ } ++ break; ++ } ++ default: // for whitelist, blacklist & HostDisabled ++ return ipmi::ccInsufficientPrivilege; + } + } + return ipmi::ccSuccess; +-- +2.17.1 + |