From 069b7697645b3ae3db0f0a75ce2c0b883cf0670d Mon Sep 17 00:00:00 2001 From: Mateusz Hobgarski Date: Tue, 5 Sep 2023 14:31:28 +0000 Subject: [PATCH 1/2] RDK-42156: Add support for seccomp in spec files --- bundle/lib/include/DobbySpecConfig.h | 2 + bundle/lib/source/DobbySpecConfig.cpp | 122 +++++++++++++++++- .../OciConfigJson1.0.2-dobby.template | 13 ++ .../OciConfigJsonVM1.0.2-dobby.template | 13 ++ 4 files changed, 149 insertions(+), 1 deletion(-) diff --git a/bundle/lib/include/DobbySpecConfig.h b/bundle/lib/include/DobbySpecConfig.h index d34ec686..2e077b85 100644 --- a/bundle/lib/include/DobbySpecConfig.h +++ b/bundle/lib/include/DobbySpecConfig.h @@ -142,6 +142,7 @@ class DobbySpecConfig : public DobbyConfig JSON_FIELD_PROCESSOR(processCpu); JSON_FIELD_PROCESSOR(processDevices); JSON_FIELD_PROCESSOR(processCapabilities); + JSON_FIELD_PROCESSOR(processSeccomp); #undef JSON_FIELD_PROCESSOR @@ -154,6 +155,7 @@ class DobbySpecConfig : public DobbyConfig const Json::Value& pluginData); bool processRdkPlugins(const Json::Value& value, ctemplate::TemplateDictionary* dictionary); + bool processSeccompAction(const Json::Value& value) const; private: template diff --git a/bundle/lib/source/DobbySpecConfig.cpp b/bundle/lib/source/DobbySpecConfig.cpp index 30547e0b..6f6fec0f 100644 --- a/bundle/lib/source/DobbySpecConfig.cpp +++ b/bundle/lib/source/DobbySpecConfig.cpp @@ -154,6 +154,15 @@ static const ctemplate::StaticTemplateString PLUGIN_NAME = static const ctemplate::StaticTemplateString PLUGIN_DATA = STS_INIT(PLUGIN_DATA, "PLUGIN_DATA"); +static const ctemplate::StaticTemplateString SECCOMP_ENABLED = + STS_INIT(SECCOMP_ENABLED, "SECCOMP_ENABLED"); +static const ctemplate::StaticTemplateString SECCOMP_DEFAULT_ACTION = + STS_INIT(SECCOMP_DEFAULT_ACTION, "SECCOMP_DEFAULT_ACTION"); +static const ctemplate::StaticTemplateString SECCOMP_ACTION = + STS_INIT(SECCOMP_ACTION, "SECCOMP_ACTION"); +static const ctemplate::StaticTemplateString SECCOMP_SYSCALLS = + STS_INIT(SECCOMP_SYSCALLS, "SECCOMP_SYSCALLS"); + // Flags that are set as various parts of the json spec file is parsed #define JSON_FLAG_ENV (0x1U << 1) @@ -177,6 +186,7 @@ static const ctemplate::StaticTemplateString PLUGIN_DATA = #define JSON_FLAG_CAPABILITIES (0x1U << 19) #define JSON_FLAG_FILECAPABILITIES (0x1U << 20) #define JSON_FLAG_VPU (0x1U << 21) +#define JSON_FLAG_SECCOMP (0x1U << 22) int DobbySpecConfig::mNumCores = -1; @@ -488,7 +498,8 @@ bool DobbySpecConfig::parseSpec(ctemplate::TemplateDictionary* dictionary, { "syslog", { JSON_FLAG_SYSLOG, &DobbySpecConfig::processSyslog } }, { "cpu", { JSON_FLAG_CPU, &DobbySpecConfig::processCpu } }, { "devices", { JSON_FLAG_DEVICES, &DobbySpecConfig::processDevices } }, - { "capabilities", { JSON_FLAG_CAPABILITIES, &DobbySpecConfig::processCapabilities } } + { "capabilities", { JSON_FLAG_CAPABILITIES, &DobbySpecConfig::processCapabilities } }, + { "seccomp", { JSON_FLAG_SECCOMP, &DobbySpecConfig::processSeccomp } } }; // step 1 - parse the 'dobby' spec document @@ -2537,6 +2548,115 @@ bool DobbySpecConfig::processCapabilities(const Json::Value& value, return true; } +// ----------------------------------------------------------------------------- +/** + * @brief Processes the seccomp field of the json spec + * + * Example json: + * + * "seccomp": { + * "defaultAction": "SCMP_ACT_ALLOW", + * "syscalls": { + * "names": [ + * "getcwd", + * "chmod" + * ], + * "action": "SCMP_ACT_ERRNO" + * } + * } + * + * This adds extra capabilities to the container. + * + * @param[in] value The json spec document from the client + * @param[in] dictionary Pointer to the OCI dictionary to populate + * + * @return true if correctly processed the value, otherwise false. + */ +bool DobbySpecConfig::processSeccomp(const Json::Value& value, + ctemplate::TemplateDictionary* dictionary) +{ + if (!value.isObject()) + { + AI_LOG_ERROR("invalid 'seccomp' field"); + return false; + } + + const Json::Value& defaultAction = value["defaultAction"]; + if (!processSeccompAction(defaultAction)) + { + AI_LOG_ERROR("invalid 'seccomp.defaultAction' field"); + return false; + } + + const Json::Value& syscalls = value["syscalls"]; + if (!syscalls.isObject()) + { + AI_LOG_ERROR("invalid 'seccomp.syscalls' field"); + return false; + } + + const Json::Value& action = syscalls["action"]; + if (!processSeccompAction(action)) + { + AI_LOG_ERROR("invalid 'seccomp.syscalls.action' field"); + return false; + } + + const Json::Value& names = syscalls["names"]; + if (!names.isArray()) + { + AI_LOG_ERROR("invalid 'seccomp.syscalls.names' field"); + return false; + } + + std::stringstream ss; + if (names.size() > 0) + { + for (int i = 0; i < (int)names.size() - 1; ++i) + { + const Json::Value& entry = names[i]; + if (!entry.isString()) + { + AI_LOG_ERROR("invalid 'seccomp.syscalls.names[%d]' field", i); + return false; + } + + ss << "\"" << entry.asString() << "\", "; + } + + ss << "\"" << names[names.size() - 1].asString() << "\""; + } + else + { + AI_LOG_ERROR("empty 'seccomp.syscalls.names' array"); + return false; + } + + dictionary->SetValue(SECCOMP_DEFAULT_ACTION, defaultAction.asString()); + dictionary->SetValue(SECCOMP_ACTION, action.asString()); + dictionary->SetValue(SECCOMP_SYSCALLS, ss.str()); + dictionary->ShowSection(SECCOMP_ENABLED); + + return true; +} + +bool DobbySpecConfig::processSeccompAction(const Json::Value& value) const +{ + if (!value.isString()) + { + return false; + } + + static const std::vector actions{"SCMP_ACT_ERRNO", "SCMP_ACT_ALLOW"}; + + if (std::find(actions.begin(), actions.end(), value.asString()) == actions.end()) + { + return false; + } + + return true; +} + // ----------------------------------------------------------------------------- /** * @brief Inserts rdkPlugin json into existing json diff --git a/bundle/lib/source/templates/OciConfigJson1.0.2-dobby.template b/bundle/lib/source/templates/OciConfigJson1.0.2-dobby.template index 5b1ae686..9bd0afe2 100644 --- a/bundle/lib/source/templates/OciConfigJson1.0.2-dobby.template +++ b/bundle/lib/source/templates/OciConfigJson1.0.2-dobby.template @@ -279,6 +279,19 @@ static const char* ociJsonTemplate = R"JSON( {{/ADDITIONAL_GIDS}} ], {{/USERNS_ENABLED}} + {{#SECCOMP_ENABLED}} + "seccomp": { + "defaultAction": "{{SECCOMP_DEFAULT_ACTION}}", + "syscalls": [ + { + "action": "{{SECCOMP_ACTION}}", + "names": [ + {{SECCOMP_SYSCALLS}} + ] + } + ] + }, + {{/SECCOMP_ENABLED}} "devices": [ {{#ADDITIONAL_DEVICE_NODES}} { diff --git a/bundle/lib/source/templates/OciConfigJsonVM1.0.2-dobby.template b/bundle/lib/source/templates/OciConfigJsonVM1.0.2-dobby.template index 735c37a5..51c253b4 100644 --- a/bundle/lib/source/templates/OciConfigJsonVM1.0.2-dobby.template +++ b/bundle/lib/source/templates/OciConfigJsonVM1.0.2-dobby.template @@ -290,6 +290,19 @@ static const char* ociJsonTemplate = R"JSON( {{/ADDITIONAL_GIDS}} ], {{/USERNS_ENABLED}} + {{#SECCOMP_ENABLED}} + "seccomp": { + "defaultAction": "{{SECCOMP_DEFAULT_ACTION}}", + "syscalls": [ + { + "action": "{{SECCOMP_ACTION}}", + "names": [ + {{SECCOMP_SYSCALLS}} + ] + } + ] + }, + {{/SECCOMP_ENABLED}} "devices": [ {{#ADDITIONAL_DEVICE_NODES}} { From aabe71c3884cf5bf766e58aeda965684a003b7d2 Mon Sep 17 00:00:00 2001 From: Mateusz Hobgarski Date: Wed, 6 Sep 2023 09:20:18 +0000 Subject: [PATCH 2/2] RDK-42156: Comment added. Method renamed --- bundle/lib/include/DobbySpecConfig.h | 2 +- bundle/lib/source/DobbySpecConfig.cpp | 14 +++++++++++--- 2 files changed, 12 insertions(+), 4 deletions(-) diff --git a/bundle/lib/include/DobbySpecConfig.h b/bundle/lib/include/DobbySpecConfig.h index 2e077b85..bc10574a 100644 --- a/bundle/lib/include/DobbySpecConfig.h +++ b/bundle/lib/include/DobbySpecConfig.h @@ -155,7 +155,7 @@ class DobbySpecConfig : public DobbyConfig const Json::Value& pluginData); bool processRdkPlugins(const Json::Value& value, ctemplate::TemplateDictionary* dictionary); - bool processSeccompAction(const Json::Value& value) const; + bool validateSeccompAction(const Json::Value& value) const; private: template diff --git a/bundle/lib/source/DobbySpecConfig.cpp b/bundle/lib/source/DobbySpecConfig.cpp index 6f6fec0f..adeaae05 100644 --- a/bundle/lib/source/DobbySpecConfig.cpp +++ b/bundle/lib/source/DobbySpecConfig.cpp @@ -2582,7 +2582,7 @@ bool DobbySpecConfig::processSeccomp(const Json::Value& value, } const Json::Value& defaultAction = value["defaultAction"]; - if (!processSeccompAction(defaultAction)) + if (!validateSeccompAction(defaultAction)) { AI_LOG_ERROR("invalid 'seccomp.defaultAction' field"); return false; @@ -2596,7 +2596,7 @@ bool DobbySpecConfig::processSeccomp(const Json::Value& value, } const Json::Value& action = syscalls["action"]; - if (!processSeccompAction(action)) + if (!validateSeccompAction(action)) { AI_LOG_ERROR("invalid 'seccomp.syscalls.action' field"); return false; @@ -2640,7 +2640,15 @@ bool DobbySpecConfig::processSeccomp(const Json::Value& value, return true; } -bool DobbySpecConfig::processSeccompAction(const Json::Value& value) const +// ----------------------------------------------------------------------------- +/** + * @brief Validates the seccomp action field value + * + * @param[in] value seccomp action field value + * + * @return true if correct seccomp action value, otherwise false. + */ +bool DobbySpecConfig::validateSeccompAction(const Json::Value& value) const { if (!value.isString()) {