From 02167555e702316fe14cc963f9e978e9f66f59ba Mon Sep 17 00:00:00 2001 From: chengzrz Date: Fri, 24 Dec 2021 10:47:31 +0800 Subject: [PATCH 05/22] Seccomp optimization Signed-off-by: chengzrz --- src/common/constants.h | 2 + src/daemon/modules/spec/specs_security.c | 112 +++++++++++++++++++---- src/utils/cutils/utils.c | 54 ++++++----- 3 files changed, 128 insertions(+), 40 deletions(-) diff --git a/src/common/constants.h b/src/common/constants.h index 60fb9abe..294f4b78 100644 --- a/src/common/constants.h +++ b/src/common/constants.h @@ -142,6 +142,8 @@ extern "C" { /* RUNPATH is defined by -DRUNPATH=$value when execute cmake, default is "/var/run" */ #define CLIENT_RUNDIR RUNPATH"/isula" +#define SCMP_ARCH_X86_64 "SCMP_ARCH_X86_64" +#define SCMP_ARCH_AARCH64 "SCMP_ARCH_AARCH64" typedef enum { CONTAINER_STATUS_UNKNOWN = 0, diff --git a/src/daemon/modules/spec/specs_security.c b/src/daemon/modules/spec/specs_security.c index 658c2e1f..8a8b2d86 100644 --- a/src/daemon/modules/spec/specs_security.c +++ b/src/daemon/modules/spec/specs_security.c @@ -457,45 +457,123 @@ static bool meet_filtering_rules(const docker_seccomp *seccomp, const docker_sec return meet_include_arch && meet_include_cap && meet_exclude_arch && meet_exclude_cap; } -static size_t docker_seccomp_arches_count(const docker_seccomp *docker_seccomp_spec) +static size_t docker_seccomp_arches_count(const char* seccomp_architecture, const docker_seccomp *docker_seccomp_spec) { size_t count = 0; size_t i = 0; - for (i = 0; i < docker_seccomp_spec->arch_map_len; i++) { - count += docker_seccomp_spec->arch_map[i]->sub_architectures_len + 1; + + if (seccomp_architecture == NULL) { + ERROR("Invalid input seccomp architecture"); + return -1; + } + + for (i = 0; i < docker_seccomp_spec->arch_map_len; ++i) { + if (docker_seccomp_spec->arch_map[i] == NULL || docker_seccomp_spec->arch_map[i]->architecture == NULL) { + continue; + } + if (strcmp(seccomp_architecture, docker_seccomp_spec->arch_map[i]->architecture) == 0) { + count = docker_seccomp_spec->arch_map[i]->sub_architectures_len + 1; + break; + } + } + + if (count == 0) { + ERROR("seccomp architecture not found"); + count = -1; } + return count; } -static int dup_architectures_to_oci_spec(const docker_seccomp *docker_seccomp_spec, +static int dup_architectures_to_oci_spec(const char* seccomp_architecture, const docker_seccomp *docker_seccomp_spec, oci_runtime_config_linux_seccomp *oci_seccomp_spec) { + size_t i = 0; + size_t j = 0; size_t arch_size = 0; - arch_size = docker_seccomp_arches_count(docker_seccomp_spec); - if (arch_size != 0) { - size_t i; - size_t j; - if (arch_size > (SIZE_MAX / sizeof(char *))) { - return -1; - } - oci_seccomp_spec->architectures = util_common_calloc_s(arch_size * sizeof(char *)); - if (oci_seccomp_spec->architectures == NULL) { - return -1; + if (seccomp_architecture == NULL) { + oci_seccomp_spec->architectures_len = 0; + return 0; + } + + arch_size = docker_seccomp_arches_count(seccomp_architecture, docker_seccomp_spec); + if (arch_size < 0) { + ERROR("Failed to get arches count from docker seccomp spec"); + return -1; + } + + oci_seccomp_spec->architectures = util_common_calloc_s(arch_size * sizeof(char *)); + if (oci_seccomp_spec->architectures == NULL) { + ERROR("Failed to calloc memory for architectures in seccomp spec"); + return -1; + } + + for (i = 0; i < docker_seccomp_spec->arch_map_len; ++i) { + if (docker_seccomp_spec->arch_map[i] == NULL || docker_seccomp_spec->arch_map[i]->architecture == NULL) { + continue; } - for (i = 0; i < docker_seccomp_spec->arch_map_len; i++) { + if (strcmp(seccomp_architecture, docker_seccomp_spec->arch_map[i]->architecture) == 0) { oci_seccomp_spec->architectures[oci_seccomp_spec->architectures_len++] = util_strdup_s(docker_seccomp_spec->arch_map[i]->architecture); - for (j = 0; j < docker_seccomp_spec->arch_map[i]->sub_architectures_len; j++) { + + for (j = 0; j < docker_seccomp_spec->arch_map[i]->sub_architectures_len; ++j) { oci_seccomp_spec->architectures[oci_seccomp_spec->architectures_len++] = util_strdup_s(docker_seccomp_spec->arch_map[i]->sub_architectures[j]); } + break; } } return 0; } +// return 0 when normalized_arch has been properly set into seccomp spec +static int normalized_arch_to_seccomp_arch(const char *host_arch, const docker_seccomp *docker_seccomp_spec, + oci_runtime_config_linux_seccomp *oci_seccomp_spec) +{ + INFO("host architecture is %s", host_arch); + // x86 archs + if (strcasecmp(host_arch, "386") == 0 || strcasecmp(host_arch, "amd64") == 0) { + return dup_architectures_to_oci_spec(SCMP_ARCH_X86_64, docker_seccomp_spec, oci_seccomp_spec); + } + // arm archs + if (strcasecmp(host_arch, "arm64") == 0 || strcasecmp(host_arch, "arm") == 0) { + return dup_architectures_to_oci_spec(SCMP_ARCH_AARCH64, docker_seccomp_spec, oci_seccomp_spec); + } + //other archs + return dup_architectures_to_oci_spec(NULL, docker_seccomp_spec, oci_seccomp_spec); +} + +static int load_architectures_into_oci_spec(const docker_seccomp *docker_seccomp_spec, + oci_runtime_config_linux_seccomp *oci_seccomp_spec) +{ + int ret = 0; + char *host_os = NULL; + char *host_arch = NULL; + char *host_variant = NULL; + + ret = util_normalized_host_os_arch(&host_os, &host_arch, &host_variant); + if (ret != 0) { + ERROR("get host os and arch for import failed"); + isulad_try_set_error_message("get host os and arch for import failed"); + goto out; + } + + ret = normalized_arch_to_seccomp_arch(host_arch, docker_seccomp_spec, oci_seccomp_spec); + if (ret != 0) { + ERROR("transfer normalized arch to seccomp arch failed"); + isulad_try_set_error_message("transfer normalized arch to seccomp arch failed"); + goto out; + } + +out: + free(host_os); + free(host_arch); + free(host_variant); + return ret; +} + static int dup_syscall_args_to_oci_spec(const docker_seccomp_syscalls_element *docker_syscall, defs_syscall *oci_syscall) { @@ -606,7 +684,7 @@ static oci_runtime_config_linux_seccomp *trans_docker_seccomp_to_oci_format(cons oci_seccomp_spec->default_action = util_strdup_s(docker_seccomp_spec->default_action); // architectures - if (dup_architectures_to_oci_spec(docker_seccomp_spec, oci_seccomp_spec)) { + if (load_architectures_into_oci_spec(docker_seccomp_spec, oci_seccomp_spec)) { goto out; } diff --git a/src/utils/cutils/utils.c b/src/utils/cutils/utils.c index a647f7bc..278a72c5 100644 --- a/src/utils/cutils/utils.c +++ b/src/utils/cutils/utils.c @@ -1353,6 +1353,7 @@ static char *get_cpu_variant() int util_normalized_host_os_arch(char **host_os, char **host_arch, char **host_variant) { int ret = 0; + int i = 0; struct utsname uts; char *tmp_variant = NULL; @@ -1367,20 +1368,31 @@ int util_normalized_host_os_arch(char **host_os, char **host_arch, char **host_v goto out; } + const char *arch_map[][2] = { { "i386", "386" }, + { "x86_64", "amd64" }, + { "x86-64", "amd64" }, + { "aarch64", "arm64" }, + { "armhf", "arm" }, + { "armel", "arm" }, + { "mips64le", "mips64le" }, + { "mips64el", "mips64le" } + }; + + const char *variant_map[][2] = { { "5", "v5" }, + { "6", "v6" }, + { "7", "v7" }, + { "8", "v8" } + }; + *host_os = util_strings_to_lower(uts.sysname); + *host_arch = util_strdup_s(uts.machine); - if (strcasecmp("i386", uts.machine) == 0) { - *host_arch = util_strdup_s("386"); - } else if ((strcasecmp("x86_64", uts.machine) == 0) || (strcasecmp("x86-64", uts.machine) == 0)) { - *host_arch = util_strdup_s("amd64"); - } else if (strcasecmp("aarch64", uts.machine) == 0) { - *host_arch = util_strdup_s("arm64"); - } else if ((strcasecmp("armhf", uts.machine) == 0) || (strcasecmp("armel", uts.machine) == 0)) { - *host_arch = util_strdup_s("arm"); - } else if ((strcasecmp("mips64le", uts.machine) == 0) || (strcasecmp("mips64el", uts.machine) == 0)) { - *host_arch = util_strdup_s("mips64le"); - } else { - *host_arch = util_strdup_s(uts.machine); + for (i = 0; i < sizeof(arch_map) / sizeof(arch_map[0]); ++i) { + if (strcasecmp(uts.machine, arch_map[i][0]) == 0) { + free(*host_arch); + *host_arch = util_strdup_s(arch_map[i][1]); + break; + } } if (!strcmp(*host_arch, "arm") || !strcmp(*host_arch, "arm64")) { @@ -1394,17 +1406,13 @@ int util_normalized_host_os_arch(char **host_os, char **host_arch, char **host_v *host_variant = util_strdup_s("v7"); } else if (!strcmp(*host_arch, "arm") && *host_variant != NULL) { tmp_variant = *host_variant; - *host_variant = NULL; - if (!strcmp(tmp_variant, "5")) { - *host_variant = util_strdup_s("v5"); - } else if (!strcmp(tmp_variant, "6")) { - *host_variant = util_strdup_s("v6"); - } else if (!strcmp(tmp_variant, "7")) { - *host_variant = util_strdup_s("v7"); - } else if (!strcmp(tmp_variant, "8")) { - *host_variant = util_strdup_s("v8"); - } else { - *host_variant = util_strdup_s(tmp_variant); + *host_variant = util_strdup_s(tmp_variant); + for (i = 0; i < sizeof(variant_map) / sizeof(variant_map[0]); ++i) { + if (!strcmp(tmp_variant, variant_map[i][0])) { + free(*host_variant); + *host_variant = util_strdup_s(variant_map[i][1]); + break; + } } free(tmp_variant); tmp_variant = NULL; -- 2.25.1