From 5cb74813f00f9f410d97b332d2c850f05b6cbd6b Mon Sep 17 00:00:00 2001 From: Giuseppe Scrivano Date: Wed, 11 Sep 2019 08:12:25 +0200 Subject: [PATCH 1/2] libocispec: sync from upstream Signed-off-by: Giuseppe Scrivano --- libocispec | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libocispec b/libocispec index f6c15f217a..b4889a45cd 160000 --- a/libocispec +++ b/libocispec @@ -1 +1 @@ -Subproject commit f6c15f217a64dfcafd7fa2d9c51458536f8e70ae +Subproject commit b4889a45cd7f1cccbc1aaaeb01e0b1672423ae41 From fefabffa2816ea343068ed036a86944393db189a Mon Sep 17 00:00:00 2001 From: Giuseppe Scrivano Date: Mon, 9 Sep 2019 13:45:25 +0200 Subject: [PATCH 2/2] seccomp: honor seccomp flags now the OCI runtime specs support to specify seccomp flags to use with the seccomp(2) syscall. The accepted options are: - SECCOMP_FILTER_FLAG_TSYNC - SECCOMP_FILTER_FLAG_SPEC_ALLOW - SECCOMP_FILTER_FLAG_LOG If there is no selection for the flags to use (i.e. there is no seccomp->flags specified), a default configuration is used: SECCOMP_FILTER_FLAG_LOG and SECCOMP_FILTER_FLAG_SPEC_ALLOW. From the man page: SECCOMP_FILTER_FLAG_LOG (since Linux 4.14) All filter return actions except SECCOMP_RET_ALLOW should be logged. An administrator may override this filter flag by preventing specific actions from being logged via the /proc/sys/kernel/seccomp/actions_logged file. SECCOMP_FILTER_FLAG_SPEC_ALLOW (since Linux 4.17) Disable Speculative Store Bypass mitigation. Signed-off-by: Giuseppe Scrivano --- src/libcrun/container.c | 34 ++++++++++++++++++++++++++---- src/libcrun/seccomp.c | 46 +++++++++++++++++++++++++++++++++++------ src/libcrun/seccomp.h | 4 ++-- 3 files changed, 72 insertions(+), 12 deletions(-) diff --git a/src/libcrun/container.c b/src/libcrun/container.c index e647f2827c..9882cbd969 100644 --- a/src/libcrun/container.c +++ b/src/libcrun/container.c @@ -540,7 +540,16 @@ container_entrypoint_init (void *args, const char *notify_socket, if (def->process && !def->process->no_new_privileges) { - ret = libcrun_generate_and_load_seccomp (entrypoint_args->container, entrypoint_args->seccomp_fd, err); + char **seccomp_flags = NULL; + size_t seccomp_flags_len = 0; + + if (def->linux && def->linux->seccomp) + { + seccomp_flags = def->linux->seccomp->flags; + seccomp_flags_len = def->linux->seccomp->flags_len; + } + + ret = libcrun_generate_and_load_seccomp (entrypoint_args->container, entrypoint_args->seccomp_fd, seccomp_flags, seccomp_flags_len, err); if (UNLIKELY (ret < 0)) return ret; } @@ -656,7 +665,16 @@ container_entrypoint (void *args, const char *notify_socket, if (def->process && def->process->no_new_privileges) { - ret = libcrun_generate_and_load_seccomp (entrypoint_args->container, entrypoint_args->seccomp_fd, err); + char **seccomp_flags = NULL; + size_t seccomp_flags_len = 0; + + if (def->linux && def->linux->seccomp) + { + seccomp_flags = def->linux->seccomp->flags; + seccomp_flags_len = def->linux->seccomp->flags_len; + } + + ret = libcrun_generate_and_load_seccomp (entrypoint_args->container, entrypoint_args->seccomp_fd, seccomp_flags, seccomp_flags_len, err); if (UNLIKELY (ret < 0)) return ret; } @@ -1871,6 +1889,8 @@ libcrun_container_exec (libcrun_context_t *context, const char *id, oci_containe gid_t container_gid = process->user ? process->user->gid : 0; const char *cwd; oci_container_process_capabilities *capabilities = NULL; + char **seccomp_flags = NULL; + size_t seccomp_flags_len = 0; close (pipefd0); pipefd0 = -1; @@ -1893,9 +1913,15 @@ libcrun_container_exec (libcrun_context_t *context, const char *id, oci_containe libcrun_fail_with_error ((*err)->status, "%s", (*err)->msg); } + if (container->container_def->linux && container->container_def->linux->seccomp) + { + seccomp_flags = container->container_def->linux->seccomp->flags; + seccomp_flags_len = container->container_def->linux->seccomp->flags_len; + } + if (!process->no_new_privileges) { - ret = libcrun_apply_seccomp (seccomp_fd, err); + ret = libcrun_apply_seccomp (seccomp_fd, seccomp_flags, seccomp_flags_len, err); if (UNLIKELY (ret < 0)) return ret; } @@ -1938,7 +1964,7 @@ libcrun_container_exec (libcrun_context_t *context, const char *id, oci_containe if (process->no_new_privileges) { - ret = libcrun_apply_seccomp (seccomp_fd, err); + ret = libcrun_apply_seccomp (seccomp_fd, seccomp_flags, seccomp_flags_len, err); if (UNLIKELY (ret < 0)) return ret; } diff --git a/src/libcrun/seccomp.c b/src/libcrun/seccomp.c index 63d739b310..6f811bae75 100644 --- a/src/libcrun/seccomp.c +++ b/src/libcrun/seccomp.c @@ -38,6 +38,13 @@ #include #include #include +#include + +static int +syscall_seccomp (unsigned int operation, unsigned int flags, void *args) +{ + return (int) syscall (__NR_seccomp, operation, flags, args); +} unsigned long get_seccomp_operator (const char *name, libcrun_error_t *err) @@ -99,16 +106,37 @@ cleanup_seccompp (void *p) #define cleanup_seccomp __attribute__((cleanup (cleanup_seccompp))) int -libcrun_apply_seccomp (int infd, libcrun_error_t *err) +libcrun_apply_seccomp (int infd, char **seccomp_flags, size_t seccomp_flags_len, libcrun_error_t *err) { int ret; struct sock_fprog seccomp_filter; cleanup_free char *bpf = NULL; + unsigned int flags = 0; size_t len; if (infd < 0) return 0; + + /* if no seccomp flag was specified use a sane default. */ + if (seccomp_flags == NULL) + flags = SECCOMP_FILTER_FLAG_LOG|SECCOMP_FILTER_FLAG_SPEC_ALLOW; + else + { + size_t i = 0; + for (i = 0; i < seccomp_flags_len; i++) + { + if (strcmp (seccomp_flags[i], "SECCOMP_FILTER_FLAG_TSYNC") == 0) + flags |= SECCOMP_FILTER_FLAG_TSYNC; + else if (strcmp (seccomp_flags[i], "SECCOMP_FILTER_FLAG_SPEC_ALLOW") == 0) + flags |= SECCOMP_FILTER_FLAG_SPEC_ALLOW; + else if (strcmp (seccomp_flags[i], "SECCOMP_FILTER_FLAG_LOG") == 0) + flags |= SECCOMP_FILTER_FLAG_LOG; + else + return crun_make_error (err, 0, "unknown seccomp option %s", seccomp_flags[i]); + } + } + ret = read_all_fd (infd, "seccomp.bpf", &bpf, &len, err); if (UNLIKELY (ret < 0)) return ret; @@ -116,15 +144,21 @@ libcrun_apply_seccomp (int infd, libcrun_error_t *err) seccomp_filter.len = len / 8; seccomp_filter.filter = (struct sock_filter *) bpf; - ret = prctl (PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &seccomp_filter); + ret = syscall_seccomp (SECCOMP_SET_MODE_FILTER, flags, &seccomp_filter); if (UNLIKELY (ret < 0)) - return crun_make_error (err, errno, "prctl (PR_SET_SECCOMP)"); + { + /* If any of the flags is not supported, try again without specifying them: */ + if (errno == EINVAL) + ret = syscall_seccomp (SECCOMP_SET_MODE_FILTER, 0, &seccomp_filter); + if (UNLIKELY (ret < 0)) + return crun_make_error (err, errno, "seccomp (SECCOMP_SET_MODE_FILTER)"); + } return 0; } int -libcrun_generate_and_load_seccomp (libcrun_container_t *container, int outfd, libcrun_error_t *err) +libcrun_generate_and_load_seccomp (libcrun_container_t *container, int outfd, char **flags, size_t flags_len, libcrun_error_t *err) { oci_container_linux_seccomp *seccomp = container->container_def->linux->seccomp; int ret; @@ -233,8 +267,8 @@ libcrun_generate_and_load_seccomp (libcrun_container_t *container, int outfd, li return crun_make_error (err, 0, "seccomp_export_bpf"); } - if (lseek (outfd, 0, SEEK_SET) == (off_t) -1) + if (UNLIKELY (lseek (outfd, 0, SEEK_SET) == (off_t) -1)) return crun_make_error (err, 0, "lseek"); - return libcrun_apply_seccomp (outfd, err); + return libcrun_apply_seccomp (outfd, flags, flags_len, err); } diff --git a/src/libcrun/seccomp.h b/src/libcrun/seccomp.h index bccbbdbf44..247ceed91d 100644 --- a/src/libcrun/seccomp.h +++ b/src/libcrun/seccomp.h @@ -26,7 +26,7 @@ # include # include "container.h" -int libcrun_generate_and_load_seccomp (libcrun_container_t *container, int outfd, libcrun_error_t *err); -int libcrun_apply_seccomp (int infd, libcrun_error_t *err); +int libcrun_generate_and_load_seccomp (libcrun_container_t *container, int outfd, char **flags, size_t flags_len, libcrun_error_t *err); +int libcrun_apply_seccomp (int infd, char **flags, size_t flags_len, libcrun_error_t *err); #endif