From 12b64931a90594e837e1f3dc9a0dde5292bb73b5 Mon Sep 17 00:00:00 2001 From: zhongtao Date: Sat, 8 Apr 2023 15:42:30 +0800 Subject: [PATCH 36/46] containers in same sandbox should have same process labels Signed-off-by: zhongtao --- .../cri/cri_container_manager_service_impl.cc | 71 ++++++++++++++++++- .../cri/cri_container_manager_service_impl.h | 5 +- src/daemon/entry/cri/cri_helpers.cc | 31 ++++++++ src/daemon/entry/cri/cri_helpers.h | 3 + 4 files changed, 107 insertions(+), 3 deletions(-) diff --git a/src/daemon/entry/cri/cri_container_manager_service_impl.cc b/src/daemon/entry/cri/cri_container_manager_service_impl.cc index d406496e..a64d222c 100644 --- a/src/daemon/entry/cri/cri_container_manager_service_impl.cc +++ b/src/daemon/entry/cri/cri_container_manager_service_impl.cc @@ -126,8 +126,66 @@ auto ContainerManagerServiceImpl::PackCreateContainerHostConfigSecurityContext( return 0; } +auto ContainerManagerServiceImpl::DoUsePodLevelSELinuxConfig(const runtime::v1alpha2::ContainerConfig &containerConfig, + host_config *hostconfig, const std::string &realPodSandboxID, Errors &error) -> int +{ + int ret = -1; + size_t newSize = 0; + size_t oldSize = 0; + container_inspect *inspect = nullptr; + std::vector selinuxLabelOpts; + char **tmp_security_opt = nullptr; + std::string tmp_str; + + inspect = CRIHelpers::InspectContainer(realPodSandboxID, error, true); + if (error.NotEmpty()) { + return -1; + } + + if (inspect->process_label == nullptr) { + ret = 0; + goto cleanup; + } + + tmp_str = std::string(inspect->process_label); + selinuxLabelOpts = CRIHelpers::GetSELinuxLabelOpts(tmp_str, error); + if (error.NotEmpty()) { + ERROR("Failed to get SELinuxLabelOpts for container %s", containerConfig.metadata().name().c_str()); + goto cleanup; + } + if (selinuxLabelOpts.empty()) { + error.Errorf("SElinuxLabelOpts for container %s is empty", containerConfig.metadata().name().c_str()); + goto cleanup; + } + if (selinuxLabelOpts.size() > (SIZE_MAX / sizeof(char *)) - hostconfig->security_opt_len) { + ERROR("Out of memory"); + error.Errorf("Out of memory"); + goto cleanup; + } + newSize = (hostconfig->security_opt_len + selinuxLabelOpts.size()) * sizeof(char *); + oldSize = hostconfig->security_opt_len * sizeof(char *); + ret = util_mem_realloc((void **)(&tmp_security_opt), newSize, (void *)hostconfig->security_opt, oldSize); + if (ret != 0) { + ERROR("Out of memory"); + error.Errorf("Out of memory"); + goto cleanup; + } + hostconfig->security_opt = tmp_security_opt; + for (const auto &securityOpt : selinuxLabelOpts) { + hostconfig->security_opt[hostconfig->security_opt_len] = util_strdup_s(securityOpt.c_str()); + hostconfig->security_opt_len++; + } + +cleanup: + free_container_inspect(inspect); + return ret; +} + + + auto ContainerManagerServiceImpl::GenerateCreateContainerHostConfig( - const runtime::v1alpha2::ContainerConfig &containerConfig, Errors &error) -> host_config * + const runtime::v1alpha2::ContainerConfig &containerConfig, + const std::string &realPodSandboxID, Errors &error) -> host_config * { host_config *hostconfig = (host_config *)util_common_calloc_s(sizeof(host_config)); if (hostconfig == nullptr) { @@ -159,6 +217,15 @@ auto ContainerManagerServiceImpl::GenerateCreateContainerHostConfig( goto cleanup; } + // If selinux label is not specified in container config, use pod level SELinux config + if (!containerConfig.linux().has_security_context() || + !containerConfig.linux().security_context().has_selinux_options()) { + if (DoUsePodLevelSELinuxConfig(containerConfig, hostconfig, realPodSandboxID, error) != 0) { + error.SetError("Failed to security context to host config"); + goto cleanup; + } + } + return hostconfig; cleanup: @@ -367,7 +434,7 @@ ContainerManagerServiceImpl::GenerateCreateContainerRequest(const std::string &r container_config *custom_config { nullptr }; - host_config *hostconfig = GenerateCreateContainerHostConfig(containerConfig, error); + host_config *hostconfig = GenerateCreateContainerHostConfig(containerConfig, realPodSandboxID, error); if (error.NotEmpty()) { goto cleanup; } diff --git a/src/daemon/entry/cri/cri_container_manager_service_impl.h b/src/daemon/entry/cri/cri_container_manager_service_impl.h index 6ac1cbc4..dcb2cd44 100644 --- a/src/daemon/entry/cri/cri_container_manager_service_impl.h +++ b/src/daemon/entry/cri/cri_container_manager_service_impl.h @@ -83,7 +83,7 @@ private: const std::string &podSandboxRuntime, Errors &error) -> container_create_request *; auto GenerateCreateContainerHostConfig(const runtime::v1alpha2::ContainerConfig &containerConfig, - Errors &error) -> host_config *; + const std::string &realPodSandboxID, Errors &error) -> host_config *; auto GenerateCreateContainerCustomConfig(const std::string &containerName, const std::string &realPodSandboxID, const runtime::v1alpha2::ContainerConfig &containerConfig, const runtime::v1alpha2::PodSandboxConfig &podSandboxConfig, @@ -92,6 +92,9 @@ private: host_config *hostconfig, Errors &error) -> int; auto PackCreateContainerHostConfigSecurityContext(const runtime::v1alpha2::ContainerConfig &containerConfig, host_config *hostconfig, Errors &error) -> int; + auto DoUsePodLevelSELinuxConfig(const runtime::v1alpha2::ContainerConfig &containerConfig, + host_config *hostconfig, + const std::string &realPodSandboxID, Errors &error) -> int; void MakeContainerConfig(const runtime::v1alpha2::ContainerConfig &config, container_config *cConfig, Errors &error); void CreateContainerLogSymlink(const std::string &containerID, Errors &error); diff --git a/src/daemon/entry/cri/cri_helpers.cc b/src/daemon/entry/cri/cri_helpers.cc index 711196ba..2bc6bed7 100644 --- a/src/daemon/entry/cri/cri_helpers.cc +++ b/src/daemon/entry/cri/cri_helpers.cc @@ -619,6 +619,37 @@ auto GetSecurityOpts(const std::string &seccompProfile, const char &separator, E return seccompSecurityOpts; } +auto GetSELinuxLabelOpts(const std::string &selinuxLabel, Errors &error) +-> std::vector +{ + // security Opt Separator Change Version : k8s v1.23.0 (Corresponds to docker 1.11.x) + // New version '=' , old version ':', iSulad cri is based on v18.09, so iSulad cri use new version separator + const char securityOptSep { '=' }; + // LabeSep is consistent with the separator used when parsing labels + const char labeSep { ':' }; + std::vector selinuxOpts { }; + char **labelArr = nullptr; + size_t labelArrLen = 0; + std::vector opts = {"user", "role", "type", "level"}; + std::vector vect; + + labelArr = util_string_split_n(selinuxLabel.c_str(), labeSep, 4); + if (labelArr == nullptr) { + error.Errorf("Invalid selinux label: %s", selinuxLabel.c_str()); + return vect; + } + + labelArrLen = util_array_len((const char **)labelArr); + for (size_t i {}; i < labelArrLen; i++) { + iSuladOpt tmp = { "label", opts[i] + std::string(1, labeSep) + std::string(labelArr[i]), "" }; + selinuxOpts.push_back(tmp); + } + + util_free_array(labelArr); + + return fmtiSuladOpts(selinuxOpts, securityOptSep); +} + auto CreateCheckpoint(CRI::PodSandboxCheckpoint &checkpoint, Errors &error) -> std::string { cri_checkpoint *criCheckpoint { nullptr }; diff --git a/src/daemon/entry/cri/cri_helpers.h b/src/daemon/entry/cri/cri_helpers.h index d50759ad..4ef227d7 100644 --- a/src/daemon/entry/cri/cri_helpers.h +++ b/src/daemon/entry/cri/cri_helpers.h @@ -127,6 +127,9 @@ auto ToIsuladContainerStatus(const runtime::v1alpha2::ContainerStateValue &state auto GetSecurityOpts(const std::string &seccompProfile, const char &separator, Errors &error) -> std::vector; +auto GetSELinuxLabelOpts(const std::string &selinuxLabel, Errors &error) +-> std::vector; + auto CreateCheckpoint(CRI::PodSandboxCheckpoint &checkpoint, Errors &error) -> std::string; void GetCheckpoint(const std::string &jsonCheckPoint, CRI::PodSandboxCheckpoint &checkpoint, Errors &error); -- 2.25.1