summaryrefslogtreecommitdiff
path: root/0003-Add-Readonly-Masked-Path-and-RunAsGroup-support-for-.patch
diff options
context:
space:
mode:
Diffstat (limited to '0003-Add-Readonly-Masked-Path-and-RunAsGroup-support-for-.patch')
-rw-r--r--0003-Add-Readonly-Masked-Path-and-RunAsGroup-support-for-.patch642
1 files changed, 642 insertions, 0 deletions
diff --git a/0003-Add-Readonly-Masked-Path-and-RunAsGroup-support-for-.patch b/0003-Add-Readonly-Masked-Path-and-RunAsGroup-support-for-.patch
new file mode 100644
index 0000000..072a5e5
--- /dev/null
+++ b/0003-Add-Readonly-Masked-Path-and-RunAsGroup-support-for-.patch
@@ -0,0 +1,642 @@
+From c1eb46b00ea65fc5601f0d843bc485d087f687e0 Mon Sep 17 00:00:00 2001
+From: jikai <jikai11@huawei.com>
+Date: Mon, 6 Nov 2023 17:31:58 +0800
+Subject: [PATCH 03/14] Add Readonly/Masked Path and RunAsGroup support for cri
+
+Signed-off-by: jikai<jikai11@huawei.com>
+---
+ .../common/cri/v1/v1_cri_security_context.cc | 111 ++++++++++++++++--
+ .../v1/v1_cri_container_manager_service.cc | 16 ++-
+ .../entry/cri/v1alpha/cri_security_context.cc | 110 +++++++++++++++--
+ src/daemon/modules/spec/specs.c | 74 +++++++++++-
+ src/daemon/modules/spec/specs_extend.c | 17 ++-
+ src/daemon/modules/spec/specs_security.c | 19 +--
+ 6 files changed, 294 insertions(+), 53 deletions(-)
+
+diff --git a/src/daemon/common/cri/v1/v1_cri_security_context.cc b/src/daemon/common/cri/v1/v1_cri_security_context.cc
+index f6441f42..930710e0 100644
+--- a/src/daemon/common/cri/v1/v1_cri_security_context.cc
++++ b/src/daemon/common/cri/v1/v1_cri_security_context.cc
+@@ -19,15 +19,28 @@
+ #include <memory>
+
+ namespace CRISecurityV1 {
+-static void ModifyContainerConfig(const runtime::v1::LinuxContainerSecurityContext &sc, container_config *config)
++static void ModifyContainerConfig(const runtime::v1::LinuxContainerSecurityContext &sc, container_config *config, Errors &error)
+ {
++ // none -> ""; username -> username; username, uid -> username; username, uid, gid -> username:gid;
++ // username, gid -> username:gid; uid -> uid; uid, gid -> uid:gid; gid -> error
++ std::string user;
+ if (sc.has_run_as_user()) {
+- free(config->user);
+- config->user = util_strdup_s(std::to_string(sc.run_as_user().value()).c_str());
++ user = std::to_string(sc.run_as_user().value());
+ }
+ if (!sc.run_as_username().empty()) {
++ user = sc.run_as_username();
++ }
++ if (sc.has_run_as_group()) {
++ if (user.empty()) {
++ ERROR("Invalid security context: runAsGroup without runAsUser or runAsUsername");
++ error.SetError("Invalid security context: runAsGroup without runAsUser or runAsUsername");
++ return;
++ }
++ user += ":" + std::to_string(sc.run_as_group().value());
++ }
++ if (!user.empty()) {
+ free(config->user);
+- config->user = util_strdup_s(sc.run_as_username().c_str());
++ config->user = util_strdup_s(user.c_str());
+ }
+ }
+
+@@ -42,6 +55,7 @@ static void ModifyHostConfigCapabilities(const runtime::v1::LinuxContainerSecuri
+ if (!capAdd.empty()) {
+ hostConfig->cap_add = (char **)util_smart_calloc_s(sizeof(char *), capAdd.size());
+ if (hostConfig->cap_add == nullptr) {
++ ERROR("Out of memory");
+ error.SetError("Out of memory");
+ return;
+ }
+@@ -54,6 +68,7 @@ static void ModifyHostConfigCapabilities(const runtime::v1::LinuxContainerSecuri
+ if (!capDrop.empty()) {
+ hostConfig->cap_drop = (char **)util_smart_calloc_s(sizeof(char *), capDrop.size());
+ if (hostConfig->cap_drop == nullptr) {
++ ERROR("Out of memory");
+ error.SetError("Out of memory");
+ return;
+ }
+@@ -74,7 +89,8 @@ static void ModifyHostConfigNoNewPrivs(const runtime::v1::LinuxContainerSecurity
+ }
+
+ if (hostConfig->security_opt_len > (SIZE_MAX / sizeof(char *)) - 1) {
+- error.Errorf("Out of memory");
++ ERROR("The size of security opts exceeds the limit");
++ error.Errorf("The size of security opts exceeds the limit");
+ return;
+ }
+
+@@ -82,6 +98,7 @@ static void ModifyHostConfigNoNewPrivs(const runtime::v1::LinuxContainerSecurity
+ size_t newSize = oldSize + sizeof(char *);
+ int 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");
+ return;
+ }
+@@ -98,12 +115,9 @@ static void ModifyHostConfigscSupplementalGroups(const runtime::v1::LinuxContain
+
+ const google::protobuf::RepeatedField<google::protobuf::int64> &groups = sc.supplemental_groups();
+ if (!groups.empty()) {
+- if (static_cast<size_t>(groups.size()) > SIZE_MAX / sizeof(char *)) {
+- error.SetError("Invalid group size");
+- return;
+- }
+- hostConfig->group_add = (char **)util_common_calloc_s(sizeof(char *) * groups.size());
++ hostConfig->group_add = (char **)util_smart_calloc_s(sizeof(char *), groups.size());
+ if (hostConfig->group_add == nullptr) {
++ ERROR("Out of memory");
+ error.SetError("Out of memory");
+ return;
+ }
+@@ -114,6 +128,64 @@ static void ModifyHostConfigscSupplementalGroups(const runtime::v1::LinuxContain
+ }
+ }
+
++static void ApplyMaskedPathsToHostConfig(const runtime::v1::LinuxContainerSecurityContext &sc, host_config *hostConfig,
++ Errors &error)
++{
++ if (sc.masked_paths_size() <= 0) {
++ return;
++ }
++
++ if (hostConfig->masked_paths_len > ((SIZE_MAX / sizeof(char *)) - sc.masked_paths_size())) {
++ ERROR("The size of masked paths exceeds the limit");
++ error.Errorf("The size of masked paths exceeds the limit");
++ return;
++ }
++
++ char **tmp_masked_paths {nullptr};
++ size_t oldSize = hostConfig->masked_paths_len * sizeof(char *);
++ size_t newSize = oldSize + sc.masked_paths_size() * sizeof(char *);
++ int ret = util_mem_realloc((void **)&tmp_masked_paths, newSize, (void *)hostConfig->masked_paths, oldSize);
++ if (ret != 0) {
++ ERROR("Out of memory");
++ error.Errorf("Out of memory");
++ return;
++ }
++
++ hostConfig->masked_paths = tmp_masked_paths;
++ for (int i = 0; i < sc.masked_paths_size(); ++i) {
++ hostConfig->masked_paths[hostConfig->masked_paths_len++] = util_strdup_s(sc.masked_paths(i).c_str());
++ }
++}
++
++static void ApplyReadonlyPathsToHostConfig(const runtime::v1::LinuxContainerSecurityContext &sc, host_config *hostConfig,
++ Errors &error)
++{
++ if (sc.readonly_paths_size() <= 0) {
++ return;
++ }
++
++ if (hostConfig->readonly_paths_len > ((SIZE_MAX / sizeof(char *)) - sc.readonly_paths_size())) {
++ ERROR("The size of readonly paths exceeds the limit");
++ error.Errorf("The size of readonly paths exceeds the limit");
++ return;
++ }
++
++ char **tmp_readonly_paths {nullptr};
++ size_t oldSize = hostConfig->readonly_paths_len * sizeof(char *);
++ size_t newSize = oldSize + sc.readonly_paths_size() * sizeof(char *);
++ int ret = util_mem_realloc((void **)&tmp_readonly_paths, newSize, (void *)hostConfig->readonly_paths, oldSize);
++ if (ret != 0) {
++ ERROR("Out of memory");
++ error.Errorf("Out of memory");
++ return;
++ }
++
++ hostConfig->readonly_paths = tmp_readonly_paths;
++ for (int i = 0; i < sc.readonly_paths_size(); ++i) {
++ hostConfig->readonly_paths[hostConfig->readonly_paths_len++] = util_strdup_s(sc.readonly_paths(i).c_str());
++ }
++}
++
+ static void ModifyHostConfig(const runtime::v1::LinuxContainerSecurityContext &sc, host_config *hostConfig,
+ Errors &error)
+ {
+@@ -123,6 +195,8 @@ static void ModifyHostConfig(const runtime::v1::LinuxContainerSecurityContext &s
+ ModifyHostConfigCapabilities(sc, hostConfig, error);
+ ModifyHostConfigNoNewPrivs(sc, hostConfig, error);
+ ModifyHostConfigscSupplementalGroups(sc, hostConfig, error);
++ ApplyMaskedPathsToHostConfig(sc, hostConfig, error);
++ ApplyReadonlyPathsToHostConfig(sc, hostConfig, error);
+ }
+
+ static void ModifyContainerNamespaceOptions(const runtime::v1::NamespaceOption &nsOpts,
+@@ -196,11 +270,18 @@ void ApplySandboxSecurityContext(const runtime::v1::LinuxPodSandboxConfig &lc, c
+ *sc->mutable_supplemental_groups() = old.supplemental_groups();
+ sc->set_readonly_rootfs(old.readonly_rootfs());
+ }
+- ModifyContainerConfig(*sc, config);
++ ModifyContainerConfig(*sc, config, error);
++ if (error.NotEmpty()) {
++ ERROR("Failed to modify container config for sandbox");
++ return;
++ }
++
+ ModifyHostConfig(*sc, hc, error);
+ if (error.NotEmpty()) {
++ ERROR("Failed to modify host config for sandbox");
+ return;
+ }
++
+ ModifySandboxNamespaceOptions(sc->namespace_options(), hc);
+ }
+
+@@ -209,9 +290,15 @@ void ApplyContainerSecurityContext(const runtime::v1::LinuxContainerConfig &lc,
+ {
+ if (lc.has_security_context()) {
+ const runtime::v1::LinuxContainerSecurityContext &sc = lc.security_context();
+- ModifyContainerConfig(sc, config);
++ ModifyContainerConfig(sc, config, error);
++ if (error.NotEmpty()) {
++ ERROR("Failed to modify container config for container");
++ return;
++ }
++
+ ModifyHostConfig(sc, hc, error);
+ if (error.NotEmpty()) {
++ ERROR("Failed to modify host config for container");
+ return;
+ }
+ }
+diff --git a/src/daemon/entry/cri/v1/v1_cri_container_manager_service.cc b/src/daemon/entry/cri/v1/v1_cri_container_manager_service.cc
+index 70629591..1f20d2d2 100644
+--- a/src/daemon/entry/cri/v1/v1_cri_container_manager_service.cc
++++ b/src/daemon/entry/cri/v1/v1_cri_container_manager_service.cc
+@@ -128,8 +128,22 @@ void ContainerManagerService::DoUsePodLevelSELinuxConfig(const runtime::v1::Cont
+ return;
+ }
+
++ const char securityOptSep = '=';
++
+ const runtime::v1::LinuxSandboxSecurityContext &context = config.linux().security_context();
+- CRIHelpersV1::ApplySandboxSecurityContextToHostConfig(context, hostconfig, error);
++ std::vector<std::string> selinuxOpts = CRIHelpersV1::GetSELinuxLabelOpts(context.has_selinux_options(),
++ context.selinux_options(), securityOptSep, error);
++ if (error.NotEmpty()) {
++ ERROR("Failed to generate SELinuxLabel options for container %s", error.GetMessage().c_str());
++ error.Errorf("Failed to generate SELinuxLabel options for container %s", error.GetMessage().c_str());
++ return;
++ }
++ CRIHelpersV1::AddSecurityOptsToHostConfig(selinuxOpts, hostconfig, error);
++ if (error.NotEmpty()) {
++ ERROR("Failed to add securityOpts to hostconfig: %s", error.GetMessage().c_str());
++ error.Errorf("Failed to add securityOpts to hostconfig: %s", error.GetMessage().c_str());
++ return;
++ }
+ }
+
+ auto ContainerManagerService::IsSELinuxLabelEmpty(const ::runtime::v1::SELinuxOption &selinuxOption) -> bool
+diff --git a/src/daemon/entry/cri/v1alpha/cri_security_context.cc b/src/daemon/entry/cri/v1alpha/cri_security_context.cc
+index 0535b438..57ec3a63 100644
+--- a/src/daemon/entry/cri/v1alpha/cri_security_context.cc
++++ b/src/daemon/entry/cri/v1alpha/cri_security_context.cc
+@@ -20,15 +20,29 @@
+ #include <memory>
+
+ namespace CRISecurity {
+-static void ModifyContainerConfig(const runtime::v1alpha2::LinuxContainerSecurityContext &sc, container_config *config)
++static void ModifyContainerConfig(const runtime::v1alpha2::LinuxContainerSecurityContext &sc, container_config *config,
++ Errors &error)
+ {
++ // none -> ""; username -> username; username, uid -> username; username, uid, gid -> username:gid;
++ // username, gid -> username:gid; uid -> uid; uid, gid -> uid:gid; gid -> error
++ std::string user;
+ if (sc.has_run_as_user()) {
+- free(config->user);
+- config->user = util_strdup_s(std::to_string(sc.run_as_user().value()).c_str());
++ user = std::to_string(sc.run_as_user().value());
+ }
+ if (!sc.run_as_username().empty()) {
++ user = sc.run_as_username();
++ }
++ if (sc.has_run_as_group()) {
++ if (user.empty()) {
++ ERROR("Invalid security context: runAsGroup without runAsUser or runAsUsername");
++ error.SetError("Invalid security context: runAsGroup without runAsUser or runAsUsername");
++ return;
++ }
++ user += ":" + std::to_string(sc.run_as_group().value());
++ }
++ if (!user.empty()) {
+ free(config->user);
+- config->user = util_strdup_s(sc.run_as_username().c_str());
++ config->user = util_strdup_s(user.c_str());
+ }
+ }
+
+@@ -43,6 +57,7 @@ static void ModifyHostConfigCapabilities(const runtime::v1alpha2::LinuxContainer
+ if (!capAdd.empty()) {
+ hostConfig->cap_add = (char **)util_smart_calloc_s(sizeof(char *), capAdd.size());
+ if (hostConfig->cap_add == nullptr) {
++ ERROR("Out of memory");
+ error.SetError("Out of memory");
+ return;
+ }
+@@ -55,6 +70,7 @@ static void ModifyHostConfigCapabilities(const runtime::v1alpha2::LinuxContainer
+ if (!capDrop.empty()) {
+ hostConfig->cap_drop = (char **)util_smart_calloc_s(sizeof(char *), capDrop.size());
+ if (hostConfig->cap_drop == nullptr) {
++ ERROR("Out of memory");
+ error.SetError("Out of memory");
+ return;
+ }
+@@ -75,7 +91,8 @@ static void ModifyHostConfigNoNewPrivs(const runtime::v1alpha2::LinuxContainerSe
+ }
+
+ if (hostConfig->security_opt_len > (SIZE_MAX / sizeof(char *)) - 1) {
+- error.Errorf("Out of memory");
++ ERROR("The size of security opts exceeds the limit");
++ error.Errorf("The size of security opts exceeds the limit");
+ return;
+ }
+
+@@ -83,6 +100,7 @@ static void ModifyHostConfigNoNewPrivs(const runtime::v1alpha2::LinuxContainerSe
+ size_t newSize = oldSize + sizeof(char *);
+ int 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");
+ return;
+ }
+@@ -99,12 +117,9 @@ static void ModifyHostConfigscSupplementalGroups(const runtime::v1alpha2::LinuxC
+
+ const google::protobuf::RepeatedField<google::protobuf::int64> &groups = sc.supplemental_groups();
+ if (!groups.empty()) {
+- if (static_cast<size_t>(groups.size()) > SIZE_MAX / sizeof(char *)) {
+- error.SetError("Invalid group size");
+- return;
+- }
+- hostConfig->group_add = (char **)util_common_calloc_s(sizeof(char *) * groups.size());
++ hostConfig->group_add = (char **)util_smart_calloc_s(sizeof(char *), groups.size());
+ if (hostConfig->group_add == nullptr) {
++ ERROR("Out of memory");
+ error.SetError("Out of memory");
+ return;
+ }
+@@ -115,6 +130,64 @@ static void ModifyHostConfigscSupplementalGroups(const runtime::v1alpha2::LinuxC
+ }
+ }
+
++static void ApplyMaskedPathsToHostConfig(const runtime::v1alpha2::LinuxContainerSecurityContext &sc, host_config *hostConfig,
++ Errors &error)
++{
++ if (sc.masked_paths_size() <= 0) {
++ return;
++ }
++
++ if (hostConfig->masked_paths_len > ((SIZE_MAX / sizeof(char *)) - sc.masked_paths_size())) {
++ ERROR("The size of masked paths exceeds the limit");
++ error.Errorf("The size of masked paths exceeds the limit");
++ return;
++ }
++
++ char **tmp_masked_paths {nullptr};
++ size_t oldSize = hostConfig->masked_paths_len * sizeof(char *);
++ size_t newSize = oldSize + sc.masked_paths_size() * sizeof(char *);
++ int ret = util_mem_realloc((void **)&tmp_masked_paths, newSize, (void *)hostConfig->masked_paths, oldSize);
++ if (ret != 0) {
++ ERROR("Out of memory");
++ error.Errorf("Out of memory");
++ return;
++ }
++
++ hostConfig->masked_paths = tmp_masked_paths;
++ for (int i = 0; i < sc.masked_paths_size(); ++i) {
++ hostConfig->masked_paths[hostConfig->masked_paths_len++] = util_strdup_s(sc.masked_paths(i).c_str());
++ }
++}
++
++static void ApplyReadonlyPathsToHostConfig(const runtime::v1alpha2::LinuxContainerSecurityContext &sc, host_config *hostConfig,
++ Errors &error)
++{
++ if (sc.readonly_paths_size() <= 0) {
++ return;
++ }
++
++ if (hostConfig->readonly_paths_len > ((SIZE_MAX / sizeof(char *)) - sc.readonly_paths_size())) {
++ ERROR("The size of readonly paths exceeds the limit");
++ error.Errorf("The size of readonly paths exceeds the limit");
++ return;
++ }
++
++ char **tmp_readonly_paths {nullptr};
++ size_t oldSize = hostConfig->readonly_paths_len * sizeof(char *);
++ size_t newSize = oldSize + sc.readonly_paths_size() * sizeof(char *);
++ int ret = util_mem_realloc((void **)&tmp_readonly_paths, newSize, (void *)hostConfig->readonly_paths, oldSize);
++ if (ret != 0) {
++ ERROR("Out of memory");
++ error.Errorf("Out of memory");
++ return;
++ }
++
++ hostConfig->readonly_paths = tmp_readonly_paths;
++ for (int i = 0; i < sc.readonly_paths_size(); ++i) {
++ hostConfig->readonly_paths[hostConfig->readonly_paths_len++] = util_strdup_s(sc.readonly_paths(i).c_str());
++ }
++}
++
+ static void ModifyHostConfig(const runtime::v1alpha2::LinuxContainerSecurityContext &sc, host_config *hostConfig,
+ Errors &error)
+ {
+@@ -124,6 +197,8 @@ static void ModifyHostConfig(const runtime::v1alpha2::LinuxContainerSecurityCont
+ ModifyHostConfigCapabilities(sc, hostConfig, error);
+ ModifyHostConfigNoNewPrivs(sc, hostConfig, error);
+ ModifyHostConfigscSupplementalGroups(sc, hostConfig, error);
++ ApplyMaskedPathsToHostConfig(sc, hostConfig, error);
++ ApplyReadonlyPathsToHostConfig(sc, hostConfig, error);
+ }
+
+ static void ModifyContainerNamespaceOptions(const runtime::v1alpha2::NamespaceOption &nsOpts,
+@@ -179,6 +254,7 @@ void ApplySandboxSecurityContext(const runtime::v1alpha2::LinuxPodSandboxConfig
+ std::unique_ptr<runtime::v1alpha2::LinuxContainerSecurityContext> sc(
+ new (std::nothrow) runtime::v1alpha2::LinuxContainerSecurityContext);
+ if (sc == nullptr) {
++ ERROR("Out of memory");
+ error.SetError("Out of memory");
+ return;
+ }
+@@ -197,9 +273,14 @@ void ApplySandboxSecurityContext(const runtime::v1alpha2::LinuxPodSandboxConfig
+ *sc->mutable_supplemental_groups() = old.supplemental_groups();
+ sc->set_readonly_rootfs(old.readonly_rootfs());
+ }
+- ModifyContainerConfig(*sc, config);
++ ModifyContainerConfig(*sc, config, error);
++ if (error.NotEmpty()) {
++ ERROR("Failed to modify container config for sandbox");
++ return;
++ }
+ ModifyHostConfig(*sc, hc, error);
+ if (error.NotEmpty()) {
++ ERROR("Failed to modify host config for sandbox");
+ return;
+ }
+ ModifySandboxNamespaceOptions(sc->namespace_options(), hc);
+@@ -210,9 +291,14 @@ void ApplyContainerSecurityContext(const runtime::v1alpha2::LinuxContainerConfig
+ {
+ if (lc.has_security_context()) {
+ const runtime::v1alpha2::LinuxContainerSecurityContext &sc = lc.security_context();
+- ModifyContainerConfig(sc, config);
++ ModifyContainerConfig(sc, config, error);
++ if (error.NotEmpty()) {
++ ERROR("Failed to modify container config for container");
++ return;
++ }
+ ModifyHostConfig(sc, hc, error);
+ if (error.NotEmpty()) {
++ ERROR("Failed to modify host config for container");
+ return;
+ }
+ }
+diff --git a/src/daemon/modules/spec/specs.c b/src/daemon/modules/spec/specs.c
+index a7751d1b..95346603 100644
+--- a/src/daemon/modules/spec/specs.c
++++ b/src/daemon/modules/spec/specs.c
+@@ -2133,6 +2133,58 @@ static int generate_security_opt(host_config *hc)
+ }
+ #endif
+
++static int merge_paths(char ***dest_paths, size_t *dest_paths_len, char **src_paths, size_t src_paths_len)
++{
++ if (dest_paths == NULL || dest_paths_len == NULL) {
++ ERROR("Invalid args");
++ return -1;
++ }
++
++ if (src_paths_len > SIZE_MAX / sizeof(char *) ||
++ *dest_paths_len > ((SIZE_MAX / sizeof(char *)) - src_paths_len)) {
++ ERROR("Out of memory");
++ return -1;
++ }
++
++ size_t i;
++ char **tmp_paths = NULL;
++ size_t old_size = *dest_paths_len * sizeof(char *);
++ size_t new_size = old_size + src_paths_len * sizeof(char *);
++ int ret = util_mem_realloc((void **)&tmp_paths, new_size,
++ (void *)*dest_paths, old_size);
++ if (ret != 0) {
++ ERROR("Out of memory");
++ return -1;
++ }
++
++ *dest_paths = tmp_paths;
++ for (i = 0; i < src_paths_len; i++) {
++ (*dest_paths)[(*dest_paths_len)++] = util_strdup_s(src_paths[i]);
++ }
++
++ return 0;
++}
++
++static int merge_masked_paths(oci_runtime_spec *oci_spec, char **masked_paths, size_t masked_paths_len)
++{
++ if (masked_paths == NULL || masked_paths_len == 0) {
++ return 0;
++ }
++
++ return merge_paths(&oci_spec->linux->masked_paths, &oci_spec->linux->masked_paths_len,
++ masked_paths, masked_paths_len);
++}
++
++static int merge_readonly_paths(oci_runtime_spec *oci_spec, char **readonly_paths, size_t readonly_paths_len)
++{
++ if (readonly_paths == NULL || readonly_paths_len == 0) {
++ return 0;
++ }
++
++ return merge_paths(&oci_spec->linux->readonly_paths, &oci_spec->linux->readonly_paths_len,
++ readonly_paths, readonly_paths_len);
++}
++
+ static int merge_security_conf(oci_runtime_spec *oci_spec, host_config *host_spec,
+ container_config_v2_common_config *v2_spec)
+ {
+@@ -2180,6 +2232,18 @@ static int merge_security_conf(oci_runtime_spec *oci_spec, host_config *host_spe
+ }
+ #endif
+
++ ret = merge_masked_paths(oci_spec, host_spec->masked_paths, host_spec->masked_paths_len);
++ if (ret != 0) {
++ ERROR("Failed to merge masked paths");
++ goto out;
++ }
++
++ ret = merge_readonly_paths(oci_spec, host_spec->readonly_paths, host_spec->readonly_paths_len);
++ if (ret != 0) {
++ ERROR("Failed to merge readonly paths");
++ goto out;
++ }
++
+ out:
+ return ret;
+ }
+@@ -2205,11 +2269,6 @@ static int merge_oci_cgroups_path(const char *id, oci_runtime_spec *oci_spec, co
+ return -1;
+ }
+
+- if (make_sure_oci_spec_linux(oci_spec) != 0) {
+- ERROR("Failed to make oci spec linux");
+- return -1;
+- }
+-
+ free(oci_spec->linux->cgroups_path);
+ oci_spec->linux->cgroups_path = merge_container_cgroups_path(id, host_spec);
+
+@@ -2228,6 +2287,11 @@ int merge_all_specs(host_config *host_spec, const char *real_rootfs, container_c
+ char *userns_remap = conf_get_isulad_userns_remap();
+ #endif
+
++ if (make_sure_oci_spec_linux(oci_spec) != 0) {
++ ERROR("Failed to make oci spec linux");
++ return -1;
++ }
++
+ ret = merge_root(oci_spec, real_rootfs, host_spec);
+ if (ret != 0) {
+ ERROR("Failed to merge root");
+diff --git a/src/daemon/modules/spec/specs_extend.c b/src/daemon/modules/spec/specs_extend.c
+index 5ede7936..199cba54 100644
+--- a/src/daemon/modules/spec/specs_extend.c
++++ b/src/daemon/modules/spec/specs_extend.c
+@@ -136,28 +136,21 @@ static int make_linux_uid_gid_mappings(oci_runtime_spec *container, unsigned int
+ unsigned int size)
+ {
+ int ret = 0;
+-
+- ret = make_sure_oci_spec_linux(container);
+- if (ret < 0) {
+- goto out;
+- }
+-
+ if (container->linux->uid_mappings == NULL) {
+ ret = make_one_id_mapping(&(container->linux->uid_mappings), host_uid, size);
+ if (ret < 0) {
+- goto out;
++ return ret;
+ }
+ container->linux->uid_mappings_len++;
+ }
+ if (container->linux->gid_mappings == NULL) {
+ ret = make_one_id_mapping(&(container->linux->gid_mappings), host_gid, size);
+ if (ret < 0) {
+- goto out;
++ return ret;
+ }
+ container->linux->gid_mappings_len++;
+ }
+
+-out:
+ return ret;
+ }
+
+@@ -180,6 +173,12 @@ int make_userns_remap(oci_runtime_spec *container, const char *user_remap)
+ if (host_uid == 0 && host_gid == 0) {
+ return 0;
+ }
++
++ if (make_sure_oci_spec_linux(container) != 0) {
++ ERROR("Failed to make oci spce linux");
++ return -1;
++ }
++
+ ret = make_linux_uid_gid_mappings(container, host_uid, host_gid, size);
+ if (ret) {
+ ERROR("Make linux uid and gid mappings failed");
+diff --git a/src/daemon/modules/spec/specs_security.c b/src/daemon/modules/spec/specs_security.c
+index 08db8d0d..e78cc744 100644
+--- a/src/daemon/modules/spec/specs_security.c
++++ b/src/daemon/modules/spec/specs_security.c
+@@ -879,13 +879,6 @@ int merge_caps(oci_runtime_spec *oci_spec, const char **adds, size_t adds_len, c
+
+ static int make_sure_oci_spec_linux_sysctl(oci_runtime_spec *oci_spec)
+ {
+- int ret = 0;
+-
+- ret = make_sure_oci_spec_linux(oci_spec);
+- if (ret < 0) {
+- return -1;
+- }
+-
+ if (oci_spec->linux->sysctl == NULL) {
+ oci_spec->linux->sysctl = util_common_calloc_s(sizeof(json_map_string_string));
+ if (oci_spec->linux->sysctl == NULL) {
+@@ -904,6 +897,11 @@ int merge_sysctls(oci_runtime_spec *oci_spec, const json_map_string_string *sysc
+ return 0;
+ }
+
++ ret = make_sure_oci_spec_linux(oci_spec);
++ if (ret < 0) {
++ return -1;
++ }
++
+ ret = make_sure_oci_spec_linux_sysctl(oci_spec);
+ if (ret < 0) {
+ goto out;
+@@ -1004,13 +1002,6 @@ static void free_adds_cap_for_system_container(char **adds, size_t adds_len)
+
+ static int make_sure_oci_spec_linux_seccomp(oci_runtime_spec *oci_spec)
+ {
+- int ret = 0;
+-
+- ret = make_sure_oci_spec_linux(oci_spec);
+- if (ret < 0) {
+- return -1;
+- }
+-
+ if (oci_spec->linux->seccomp == NULL) {
+ oci_spec->linux->seccomp = util_common_calloc_s(sizeof(oci_runtime_config_linux_seccomp));
+ if (oci_spec->linux->seccomp == NULL) {
+--
+2.42.0
+