diff --git a/VERSION-openeuler b/VERSION-openeuler index 5c640dd82812861a16fab90da940c0ed659751db..31cc6b7a2e196975fbb19aee3d161d8c04bcc783 100644 --- a/VERSION-openeuler +++ b/VERSION-openeuler @@ -1 +1 @@ -18.09.0.117 +18.09.0.118 diff --git a/docker.spec b/docker.spec index 8047210f1abd4d48fe5d29cfe083eef5b6e11ff2..852818a592ad980fcf9678dce56720ed4ea96b6b 100644 --- a/docker.spec +++ b/docker.spec @@ -1,6 +1,6 @@ Name: docker-engine Version: 18.09.0 -Release: 117 +Release: 118 Summary: The open-source application container engine Group: Tools/Docker @@ -212,6 +212,12 @@ fi %endif %changelog +* Sat Sep 11 2021 xiadanni - 18.09.0-118 +- Type:bugfix +- CVE:NA +- SUG:NA +- DESC:update seccomp to fix curl failed + * Wed Sep 08 2021 xiadanni - 18.09.0-117 - Type:bugfix - CVE:NA diff --git a/git-commit b/git-commit index 25d592dce24ba7fd319313defcc5080053ef1a5e..be1a9deed3fca71804cabf520d134cc3dd1355df 100644 --- a/git-commit +++ b/git-commit @@ -1 +1 @@ -cfb8513e11e19660d19486f6a4ac25516f1413cd +fd954b7ca1f4117104df6d54391962d0ae6278ae diff --git a/patch/0193-docker-update-seccomp-to-fix-curl-failed.patch b/patch/0193-docker-update-seccomp-to-fix-curl-failed.patch new file mode 100644 index 0000000000000000000000000000000000000000..ab42e93b737041d4974141e899dcc3eff17be470 --- /dev/null +++ b/patch/0193-docker-update-seccomp-to-fix-curl-failed.patch @@ -0,0 +1,4766 @@ +From ea3919e66adf0d205ec5f0753a2912e131c72fda Mon Sep 17 00:00:00 2001 +From: xiadanni +Date: Sat, 11 Sep 2021 04:50:43 +0800 +Subject: [PATCH] docker:update seccomp to fix curl failed + +It's too rude to directly add clone3 to seccomp whitelist for all users, +which may cause security problems. +Update seccomp pkg to add a new rule errnoRet to define return code for +clone3, as glibc will try to call clone if clone3 returns NOSYS. + +Signed-off-by: xiadanni +--- + .../engine/profiles/seccomp/default.json | 202 +-- + .../engine/profiles/seccomp/default_linux.go | 766 ++++++++ + .../seccomp/fixtures/conditional_include.json | 23 + + .../seccomp/fixtures/default-old-format.json | 1593 +++++++++++++++++ + .../profiles/seccomp/fixtures/example.json | 9 +- + .../engine/profiles/seccomp/generate.go | 4 +- + .../engine/profiles/seccomp/kernel_linux.go | 59 + + .../profiles/seccomp/kernel_linux_test.go | 122 ++ + components/engine/profiles/seccomp/seccomp.go | 217 +-- + .../profiles/seccomp/seccomp_default.go | 663 ------- + .../engine/profiles/seccomp/seccomp_linux.go | 166 ++ + .../engine/profiles/seccomp/seccomp_test.go | 279 ++- + .../profiles/seccomp/seccomp_unsupported.go | 7 +- + .../runtime-spec/specs-go/config.go | 14 +- + 14 files changed, 3201 insertions(+), 923 deletions(-) + mode change 100755 => 100644 components/engine/profiles/seccomp/default.json + create mode 100644 components/engine/profiles/seccomp/default_linux.go + create mode 100644 components/engine/profiles/seccomp/fixtures/conditional_include.json + create mode 100644 components/engine/profiles/seccomp/fixtures/default-old-format.json + mode change 100755 => 100644 components/engine/profiles/seccomp/fixtures/example.json + create mode 100644 components/engine/profiles/seccomp/kernel_linux.go + create mode 100644 components/engine/profiles/seccomp/kernel_linux_test.go + delete mode 100644 components/engine/profiles/seccomp/seccomp_default.go + create mode 100644 components/engine/profiles/seccomp/seccomp_linux.go + +diff --git a/components/engine/profiles/seccomp/default.json b/components/engine/profiles/seccomp/default.json +old mode 100755 +new mode 100644 +index 0d954bb6..fbf3ac83 +--- a/components/engine/profiles/seccomp/default.json ++++ b/components/engine/profiles/seccomp/default.json +@@ -1,5 +1,6 @@ + { + "defaultAction": "SCMP_ACT_ERRNO", ++ "defaultErrnoRet": 1, + "archMap": [ + { + "architecture": "SCMP_ARCH_X86_64", +@@ -65,10 +66,16 @@ + "chmod", + "chown", + "chown32", ++ "clock_adjtime", ++ "clock_adjtime64", + "clock_getres", ++ "clock_getres_time64", + "clock_gettime", ++ "clock_gettime64", + "clock_nanosleep", ++ "clock_nanosleep_time64", + "close", ++ "close_range", + "connect", + "copy_file_range", + "creat", +@@ -80,6 +87,7 @@ + "epoll_ctl", + "epoll_ctl_old", + "epoll_pwait", ++ "epoll_pwait2", + "epoll_wait", + "epoll_wait_old", + "eventfd", +@@ -89,6 +97,7 @@ + "exit", + "exit_group", + "faccessat", ++ "faccessat2", + "fadvise64", + "fadvise64_64", + "fallocate", +@@ -117,6 +126,7 @@ + "ftruncate", + "ftruncate64", + "futex", ++ "futex_time64", + "futimesat", + "getcpu", + "getcwd", +@@ -162,10 +172,15 @@ + "ioctl", + "io_destroy", + "io_getevents", ++ "io_pgetevents", ++ "io_pgetevents_time64", + "ioprio_get", + "ioprio_set", + "io_setup", + "io_submit", ++ "io_uring_enter", ++ "io_uring_register", ++ "io_uring_setup", + "ipc", + "kill", + "lchown", +@@ -183,6 +198,7 @@ + "lstat", + "lstat64", + "madvise", ++ "membarrier", + "memfd_create", + "mincore", + "mkdir", +@@ -199,7 +215,9 @@ + "mq_notify", + "mq_open", + "mq_timedreceive", ++ "mq_timedreceive_time64", + "mq_timedsend", ++ "mq_timedsend_time64", + "mq_unlink", + "mremap", + "msgctl", +@@ -215,17 +233,22 @@ + "_newselect", + "open", + "openat", ++ "openat2", + "pause", ++ "pidfd_open", ++ "pidfd_send_signal", + "pipe", + "pipe2", + "poll", + "ppoll", ++ "ppoll_time64", + "prctl", + "pread64", + "preadv", + "preadv2", + "prlimit64", + "pselect6", ++ "pselect6_time64", + "pwrite64", + "pwritev", + "pwritev2", +@@ -237,6 +260,7 @@ + "recv", + "recvfrom", + "recvmmsg", ++ "recvmmsg_time64", + "recvmsg", + "remap_file_pages", + "removexattr", +@@ -245,6 +269,7 @@ + "renameat2", + "restart_syscall", + "rmdir", ++ "rseq", + "rt_sigaction", + "rt_sigpending", + "rt_sigprocmask", +@@ -252,6 +277,7 @@ + "rt_sigreturn", + "rt_sigsuspend", + "rt_sigtimedwait", ++ "rt_sigtimedwait_time64", + "rt_tgsigqueueinfo", + "sched_getaffinity", + "sched_getattr", +@@ -260,6 +286,7 @@ + "sched_get_priority_min", + "sched_getscheduler", + "sched_rr_get_interval", ++ "sched_rr_get_interval_time64", + "sched_setaffinity", + "sched_setattr", + "sched_setparam", +@@ -271,6 +298,7 @@ + "semget", + "semop", + "semtimedop", ++ "semtimedop_time64", + "send", + "sendfile", + "sendfile64", +@@ -313,6 +341,7 @@ + "sigaltstack", + "signalfd", + "signalfd4", ++ "sigprocmask", + "sigreturn", + "socket", + "socketcall", +@@ -334,12 +363,16 @@ + "time", + "timer_create", + "timer_delete", +- "timerfd_create", +- "timerfd_gettime", +- "timerfd_settime", + "timer_getoverrun", + "timer_gettime", ++ "timer_gettime64", + "timer_settime", ++ "timer_settime64", ++ "timerfd_create", ++ "timerfd_gettime", ++ "timerfd_gettime64", ++ "timerfd_settime", ++ "timerfd_settime64", + "times", + "tkill", + "truncate", +@@ -351,6 +384,7 @@ + "unlinkat", + "utime", + "utimensat", ++ "utimensat_time64", + "utimes", + "vfork", + "vmsplice", +@@ -360,11 +394,18 @@ + "write", + "writev" + ], ++ "action": "SCMP_ACT_ALLOW" ++ }, ++ { ++ "names": [ ++ "process_vm_readv", ++ "process_vm_writev", ++ "ptrace" ++ ], + "action": "SCMP_ACT_ALLOW", +- "args": [], +- "comment": "", +- "includes": {}, +- "excludes": {} ++ "includes": { ++ "minKernel": "4.8" ++ } + }, + { + "names": [ +@@ -375,13 +416,9 @@ + { + "index": 0, + "value": 0, +- "valueTwo": 0, + "op": "SCMP_CMP_EQ" + } +- ], +- "comment": "", +- "includes": {}, +- "excludes": {} ++ ] + }, + { + "names": [ +@@ -392,13 +429,9 @@ + { + "index": 0, + "value": 8, +- "valueTwo": 0, + "op": "SCMP_CMP_EQ" + } +- ], +- "comment": "", +- "includes": {}, +- "excludes": {} ++ ] + }, + { + "names": [ +@@ -409,13 +442,9 @@ + { + "index": 0, + "value": 131072, +- "valueTwo": 0, + "op": "SCMP_CMP_EQ" + } +- ], +- "comment": "", +- "includes": {}, +- "excludes": {} ++ ] + }, + { + "names": [ +@@ -426,13 +455,9 @@ + { + "index": 0, + "value": 131080, +- "valueTwo": 0, + "op": "SCMP_CMP_EQ" + } +- ], +- "comment": "", +- "includes": {}, +- "excludes": {} ++ ] + }, + { + "names": [ +@@ -443,27 +468,20 @@ + { + "index": 0, + "value": 4294967295, +- "valueTwo": 0, + "op": "SCMP_CMP_EQ" + } +- ], +- "comment": "", +- "includes": {}, +- "excludes": {} ++ ] + }, + { + "names": [ + "sync_file_range2" + ], + "action": "SCMP_ACT_ALLOW", +- "args": [], +- "comment": "", + "includes": { + "arches": [ + "ppc64le" + ] +- }, +- "excludes": {} ++ } + }, + { + "names": [ +@@ -475,46 +493,37 @@ + "set_tls" + ], + "action": "SCMP_ACT_ALLOW", +- "args": [], +- "comment": "", + "includes": { + "arches": [ + "arm", + "arm64" + ] +- }, +- "excludes": {} ++ } + }, + { + "names": [ + "arch_prctl" + ], + "action": "SCMP_ACT_ALLOW", +- "args": [], +- "comment": "", + "includes": { + "arches": [ + "amd64", + "x32" + ] +- }, +- "excludes": {} ++ } + }, + { + "names": [ + "modify_ldt" + ], + "action": "SCMP_ACT_ALLOW", +- "args": [], +- "comment": "", + "includes": { + "arches": [ + "amd64", + "x32", + "x86" + ] +- }, +- "excludes": {} ++ } + }, + { + "names": [ +@@ -523,38 +532,39 @@ + "s390_runtime_instr" + ], + "action": "SCMP_ACT_ALLOW", +- "args": [], +- "comment": "", + "includes": { + "arches": [ + "s390", + "s390x" + ] +- }, +- "excludes": {} ++ } + }, + { + "names": [ + "open_by_handle_at" + ], + "action": "SCMP_ACT_ALLOW", +- "args": [], +- "comment": "", + "includes": { + "caps": [ + "CAP_DAC_READ_SEARCH" + ] +- }, +- "excludes": {} ++ } + }, + { + "names": [ + "bpf", + "clone", ++ "clone3", + "fanotify_init", ++ "fsconfig", ++ "fsmount", ++ "fsopen", ++ "fspick", + "lookup_dcookie", + "mount", ++ "move_mount", + "name_to_handle_at", ++ "open_tree", + "perf_event_open", + "quotactl", + "setdomainname", +@@ -566,14 +576,11 @@ + "unshare" + ], + "action": "SCMP_ACT_ALLOW", +- "args": [], +- "comment": "", + "includes": { + "caps": [ + "CAP_SYS_ADMIN" + ] +- }, +- "excludes": {} ++ } + }, + { + "names": [ +@@ -583,13 +590,10 @@ + "args": [ + { + "index": 0, +- "value": 2080505856, +- "valueTwo": 0, ++ "value": 2114060288, + "op": "SCMP_CMP_MASKED_EQ" + } + ], +- "comment": "", +- "includes": {}, + "excludes": { + "caps": [ + "CAP_SYS_ADMIN" +@@ -608,8 +612,7 @@ + "args": [ + { + "index": 1, +- "value": 2080505856, +- "valueTwo": 0, ++ "value": 2114060288, + "op": "SCMP_CMP_MASKED_EQ" + } + ], +@@ -626,81 +629,79 @@ + ] + } + }, ++ { ++ "names": [ ++ "clone3" ++ ], ++ "action": "SCMP_ACT_ERRNO", ++ "errnoRet": 38, ++ "excludes": { ++ "caps": [ ++ "CAP_SYS_ADMIN" ++ ] ++ } ++ }, + { + "names": [ + "reboot" + ], + "action": "SCMP_ACT_ALLOW", +- "args": [], +- "comment": "", + "includes": { + "caps": [ + "CAP_SYS_BOOT" + ] +- }, +- "excludes": {} ++ } + }, + { + "names": [ + "chroot" + ], + "action": "SCMP_ACT_ALLOW", +- "args": [], +- "comment": "", + "includes": { + "caps": [ + "CAP_SYS_CHROOT" + ] +- }, +- "excludes": {} ++ } + }, + { + "names": [ + "delete_module", + "init_module", +- "finit_module", +- "query_module" ++ "finit_module" + ], + "action": "SCMP_ACT_ALLOW", +- "args": [], +- "comment": "", + "includes": { + "caps": [ + "CAP_SYS_MODULE" + ] +- }, +- "excludes": {} ++ } + }, + { + "names": [ + "acct" + ], + "action": "SCMP_ACT_ALLOW", +- "args": [], +- "comment": "", + "includes": { + "caps": [ + "CAP_SYS_PACCT" + ] +- }, +- "excludes": {} ++ } + }, + { + "names": [ + "kcmp", ++ "pidfd_getfd", ++ "process_madvise", + "process_vm_readv", + "process_vm_writev", + "ptrace" + ], + "action": "SCMP_ACT_ALLOW", +- "args": [], +- "comment": "", + "includes": { + "caps": [ + "CAP_SYS_PTRACE" + ] +- }, +- "excludes": {} ++ } + }, + { + "names": [ +@@ -708,14 +709,11 @@ + "ioperm" + ], + "action": "SCMP_ACT_ALLOW", +- "args": [], +- "comment": "", + "includes": { + "caps": [ + "CAP_SYS_RAWIO" + ] +- }, +- "excludes": {} ++ } + }, + { + "names": [ +@@ -724,28 +722,22 @@ + "clock_settime" + ], + "action": "SCMP_ACT_ALLOW", +- "args": [], +- "comment": "", + "includes": { + "caps": [ + "CAP_SYS_TIME" + ] +- }, +- "excludes": {} ++ } + }, + { + "names": [ + "vhangup" + ], + "action": "SCMP_ACT_ALLOW", +- "args": [], +- "comment": "", + "includes": { + "caps": [ + "CAP_SYS_TTY_CONFIG" + ] +- }, +- "excludes": {} ++ } + }, + { + "names": [ +@@ -754,28 +746,22 @@ + "set_mempolicy" + ], + "action": "SCMP_ACT_ALLOW", +- "args": [], +- "comment": "", + "includes": { + "caps": [ + "CAP_SYS_NICE" + ] +- }, +- "excludes": {} ++ } + }, + { + "names": [ + "syslog" + ], + "action": "SCMP_ACT_ALLOW", +- "args": [], +- "comment": "", + "includes": { + "caps": [ + "CAP_SYSLOG" + ] +- }, +- "excludes": {} ++ } + } + ] + } +\ No newline at end of file +diff --git a/components/engine/profiles/seccomp/default_linux.go b/components/engine/profiles/seccomp/default_linux.go +new file mode 100644 +index 00000000..f7d93d2c +--- /dev/null ++++ b/components/engine/profiles/seccomp/default_linux.go +@@ -0,0 +1,766 @@ ++//go:build seccomp ++// +build seccomp ++ ++package seccomp // import "github.com/docker/docker/profiles/seccomp" ++ ++import ( ++ "github.com/opencontainers/runtime-spec/specs-go" ++ "golang.org/x/sys/unix" ++) ++ ++func arches() []Architecture { ++ return []Architecture{ ++ { ++ Arch: specs.ArchX86_64, ++ SubArches: []specs.Arch{specs.ArchX86, specs.ArchX32}, ++ }, ++ { ++ Arch: specs.ArchAARCH64, ++ SubArches: []specs.Arch{specs.ArchARM}, ++ }, ++ { ++ Arch: specs.ArchMIPS64, ++ SubArches: []specs.Arch{specs.ArchMIPS, specs.ArchMIPS64N32}, ++ }, ++ { ++ Arch: specs.ArchMIPS64N32, ++ SubArches: []specs.Arch{specs.ArchMIPS, specs.ArchMIPS64}, ++ }, ++ { ++ Arch: specs.ArchMIPSEL64, ++ SubArches: []specs.Arch{specs.ArchMIPSEL, specs.ArchMIPSEL64N32}, ++ }, ++ { ++ Arch: specs.ArchMIPSEL64N32, ++ SubArches: []specs.Arch{specs.ArchMIPSEL, specs.ArchMIPSEL64}, ++ }, ++ { ++ Arch: specs.ArchS390X, ++ SubArches: []specs.Arch{specs.ArchS390}, ++ }, ++ } ++} ++ ++// DefaultProfile defines the allowed syscalls for the default seccomp profile. ++func DefaultProfile() *Seccomp { ++ nosys := uint(unix.ENOSYS) ++ syscalls := []*Syscall{ ++ { ++ LinuxSyscall: specs.LinuxSyscall{ ++ Names: []string{ ++ "accept", ++ "accept4", ++ "access", ++ "adjtimex", ++ "alarm", ++ "bind", ++ "brk", ++ "capget", ++ "capset", ++ "chdir", ++ "chmod", ++ "chown", ++ "chown32", ++ "clock_adjtime", ++ "clock_adjtime64", ++ "clock_getres", ++ "clock_getres_time64", ++ "clock_gettime", ++ "clock_gettime64", ++ "clock_nanosleep", ++ "clock_nanosleep_time64", ++ "close", ++ "close_range", ++ "connect", ++ "copy_file_range", ++ "creat", ++ "dup", ++ "dup2", ++ "dup3", ++ "epoll_create", ++ "epoll_create1", ++ "epoll_ctl", ++ "epoll_ctl_old", ++ "epoll_pwait", ++ "epoll_pwait2", ++ "epoll_wait", ++ "epoll_wait_old", ++ "eventfd", ++ "eventfd2", ++ "execve", ++ "execveat", ++ "exit", ++ "exit_group", ++ "faccessat", ++ "faccessat2", ++ "fadvise64", ++ "fadvise64_64", ++ "fallocate", ++ "fanotify_mark", ++ "fchdir", ++ "fchmod", ++ "fchmodat", ++ "fchown", ++ "fchown32", ++ "fchownat", ++ "fcntl", ++ "fcntl64", ++ "fdatasync", ++ "fgetxattr", ++ "flistxattr", ++ "flock", ++ "fork", ++ "fremovexattr", ++ "fsetxattr", ++ "fstat", ++ "fstat64", ++ "fstatat64", ++ "fstatfs", ++ "fstatfs64", ++ "fsync", ++ "ftruncate", ++ "ftruncate64", ++ "futex", ++ "futex_time64", ++ "futimesat", ++ "getcpu", ++ "getcwd", ++ "getdents", ++ "getdents64", ++ "getegid", ++ "getegid32", ++ "geteuid", ++ "geteuid32", ++ "getgid", ++ "getgid32", ++ "getgroups", ++ "getgroups32", ++ "getitimer", ++ "getpeername", ++ "getpgid", ++ "getpgrp", ++ "getpid", ++ "getppid", ++ "getpriority", ++ "getrandom", ++ "getresgid", ++ "getresgid32", ++ "getresuid", ++ "getresuid32", ++ "getrlimit", ++ "get_robust_list", ++ "getrusage", ++ "getsid", ++ "getsockname", ++ "getsockopt", ++ "get_thread_area", ++ "gettid", ++ "gettimeofday", ++ "getuid", ++ "getuid32", ++ "getxattr", ++ "inotify_add_watch", ++ "inotify_init", ++ "inotify_init1", ++ "inotify_rm_watch", ++ "io_cancel", ++ "ioctl", ++ "io_destroy", ++ "io_getevents", ++ "io_pgetevents", ++ "io_pgetevents_time64", ++ "ioprio_get", ++ "ioprio_set", ++ "io_setup", ++ "io_submit", ++ "io_uring_enter", ++ "io_uring_register", ++ "io_uring_setup", ++ "ipc", ++ "kill", ++ "lchown", ++ "lchown32", ++ "lgetxattr", ++ "link", ++ "linkat", ++ "listen", ++ "listxattr", ++ "llistxattr", ++ "_llseek", ++ "lremovexattr", ++ "lseek", ++ "lsetxattr", ++ "lstat", ++ "lstat64", ++ "madvise", ++ "membarrier", ++ "memfd_create", ++ "mincore", ++ "mkdir", ++ "mkdirat", ++ "mknod", ++ "mknodat", ++ "mlock", ++ "mlock2", ++ "mlockall", ++ "mmap", ++ "mmap2", ++ "mprotect", ++ "mq_getsetattr", ++ "mq_notify", ++ "mq_open", ++ "mq_timedreceive", ++ "mq_timedreceive_time64", ++ "mq_timedsend", ++ "mq_timedsend_time64", ++ "mq_unlink", ++ "mremap", ++ "msgctl", ++ "msgget", ++ "msgrcv", ++ "msgsnd", ++ "msync", ++ "munlock", ++ "munlockall", ++ "munmap", ++ "nanosleep", ++ "newfstatat", ++ "_newselect", ++ "open", ++ "openat", ++ "openat2", ++ "pause", ++ "pidfd_open", ++ "pidfd_send_signal", ++ "pipe", ++ "pipe2", ++ "poll", ++ "ppoll", ++ "ppoll_time64", ++ "prctl", ++ "pread64", ++ "preadv", ++ "preadv2", ++ "prlimit64", ++ "pselect6", ++ "pselect6_time64", ++ "pwrite64", ++ "pwritev", ++ "pwritev2", ++ "read", ++ "readahead", ++ "readlink", ++ "readlinkat", ++ "readv", ++ "recv", ++ "recvfrom", ++ "recvmmsg", ++ "recvmmsg_time64", ++ "recvmsg", ++ "remap_file_pages", ++ "removexattr", ++ "rename", ++ "renameat", ++ "renameat2", ++ "restart_syscall", ++ "rmdir", ++ "rseq", ++ "rt_sigaction", ++ "rt_sigpending", ++ "rt_sigprocmask", ++ "rt_sigqueueinfo", ++ "rt_sigreturn", ++ "rt_sigsuspend", ++ "rt_sigtimedwait", ++ "rt_sigtimedwait_time64", ++ "rt_tgsigqueueinfo", ++ "sched_getaffinity", ++ "sched_getattr", ++ "sched_getparam", ++ "sched_get_priority_max", ++ "sched_get_priority_min", ++ "sched_getscheduler", ++ "sched_rr_get_interval", ++ "sched_rr_get_interval_time64", ++ "sched_setaffinity", ++ "sched_setattr", ++ "sched_setparam", ++ "sched_setscheduler", ++ "sched_yield", ++ "seccomp", ++ "select", ++ "semctl", ++ "semget", ++ "semop", ++ "semtimedop", ++ "semtimedop_time64", ++ "send", ++ "sendfile", ++ "sendfile64", ++ "sendmmsg", ++ "sendmsg", ++ "sendto", ++ "setfsgid", ++ "setfsgid32", ++ "setfsuid", ++ "setfsuid32", ++ "setgid", ++ "setgid32", ++ "setgroups", ++ "setgroups32", ++ "setitimer", ++ "setpgid", ++ "setpriority", ++ "setregid", ++ "setregid32", ++ "setresgid", ++ "setresgid32", ++ "setresuid", ++ "setresuid32", ++ "setreuid", ++ "setreuid32", ++ "setrlimit", ++ "set_robust_list", ++ "setsid", ++ "setsockopt", ++ "set_thread_area", ++ "set_tid_address", ++ "setuid", ++ "setuid32", ++ "setxattr", ++ "shmat", ++ "shmctl", ++ "shmdt", ++ "shmget", ++ "shutdown", ++ "sigaltstack", ++ "signalfd", ++ "signalfd4", ++ "sigprocmask", ++ "sigreturn", ++ "socket", ++ "socketcall", ++ "socketpair", ++ "splice", ++ "stat", ++ "stat64", ++ "statfs", ++ "statfs64", ++ "statx", ++ "symlink", ++ "symlinkat", ++ "sync", ++ "sync_file_range", ++ "syncfs", ++ "sysinfo", ++ "tee", ++ "tgkill", ++ "time", ++ "timer_create", ++ "timer_delete", ++ "timer_getoverrun", ++ "timer_gettime", ++ "timer_gettime64", ++ "timer_settime", ++ "timer_settime64", ++ "timerfd_create", ++ "timerfd_gettime", ++ "timerfd_gettime64", ++ "timerfd_settime", ++ "timerfd_settime64", ++ "times", ++ "tkill", ++ "truncate", ++ "truncate64", ++ "ugetrlimit", ++ "umask", ++ "uname", ++ "unlink", ++ "unlinkat", ++ "utime", ++ "utimensat", ++ "utimensat_time64", ++ "utimes", ++ "vfork", ++ "vmsplice", ++ "wait4", ++ "waitid", ++ "waitpid", ++ "write", ++ "writev", ++ }, ++ Action: specs.ActAllow, ++ }, ++ }, ++ { ++ LinuxSyscall: specs.LinuxSyscall{ ++ Names: []string{ ++ "process_vm_readv", ++ "process_vm_writev", ++ "ptrace", ++ }, ++ Action: specs.ActAllow, ++ }, ++ Includes: &Filter{ ++ MinKernel: &KernelVersion{4, 8}, ++ }, ++ }, ++ { ++ LinuxSyscall: specs.LinuxSyscall{ ++ Names: []string{"personality"}, ++ Action: specs.ActAllow, ++ Args: []specs.LinuxSeccompArg{ ++ { ++ Index: 0, ++ Value: 0x0, ++ Op: specs.OpEqualTo, ++ }, ++ }, ++ }, ++ }, ++ { ++ LinuxSyscall: specs.LinuxSyscall{ ++ Names: []string{"personality"}, ++ Action: specs.ActAllow, ++ Args: []specs.LinuxSeccompArg{ ++ { ++ Index: 0, ++ Value: 0x0008, ++ Op: specs.OpEqualTo, ++ }, ++ }, ++ }, ++ }, ++ { ++ LinuxSyscall: specs.LinuxSyscall{ ++ Names: []string{"personality"}, ++ Action: specs.ActAllow, ++ Args: []specs.LinuxSeccompArg{ ++ { ++ Index: 0, ++ Value: 0x20000, ++ Op: specs.OpEqualTo, ++ }, ++ }, ++ }, ++ }, ++ { ++ LinuxSyscall: specs.LinuxSyscall{ ++ Names: []string{"personality"}, ++ Action: specs.ActAllow, ++ Args: []specs.LinuxSeccompArg{ ++ { ++ Index: 0, ++ Value: 0x20008, ++ Op: specs.OpEqualTo, ++ }, ++ }, ++ }, ++ }, ++ { ++ LinuxSyscall: specs.LinuxSyscall{ ++ Names: []string{"personality"}, ++ Action: specs.ActAllow, ++ Args: []specs.LinuxSeccompArg{ ++ { ++ Index: 0, ++ Value: 0xffffffff, ++ Op: specs.OpEqualTo, ++ }, ++ }, ++ }, ++ }, ++ { ++ LinuxSyscall: specs.LinuxSyscall{ ++ Names: []string{ ++ "sync_file_range2", ++ }, ++ Action: specs.ActAllow, ++ }, ++ Includes: &Filter{ ++ Arches: []string{"ppc64le"}, ++ }, ++ }, ++ { ++ LinuxSyscall: specs.LinuxSyscall{ ++ Names: []string{ ++ "arm_fadvise64_64", ++ "arm_sync_file_range", ++ "sync_file_range2", ++ "breakpoint", ++ "cacheflush", ++ "set_tls", ++ }, ++ Action: specs.ActAllow, ++ }, ++ Includes: &Filter{ ++ Arches: []string{"arm", "arm64"}, ++ }, ++ }, ++ { ++ LinuxSyscall: specs.LinuxSyscall{ ++ Names: []string{ ++ "arch_prctl", ++ }, ++ Action: specs.ActAllow, ++ }, ++ Includes: &Filter{ ++ Arches: []string{"amd64", "x32"}, ++ }, ++ }, ++ { ++ LinuxSyscall: specs.LinuxSyscall{ ++ Names: []string{ ++ "modify_ldt", ++ }, ++ Action: specs.ActAllow, ++ }, ++ Includes: &Filter{ ++ Arches: []string{"amd64", "x32", "x86"}, ++ }, ++ }, ++ { ++ LinuxSyscall: specs.LinuxSyscall{ ++ Names: []string{ ++ "s390_pci_mmio_read", ++ "s390_pci_mmio_write", ++ "s390_runtime_instr", ++ }, ++ Action: specs.ActAllow, ++ }, ++ Includes: &Filter{ ++ Arches: []string{"s390", "s390x"}, ++ }, ++ }, ++ { ++ LinuxSyscall: specs.LinuxSyscall{ ++ Names: []string{ ++ "open_by_handle_at", ++ }, ++ Action: specs.ActAllow, ++ }, ++ Includes: &Filter{ ++ Caps: []string{"CAP_DAC_READ_SEARCH"}, ++ }, ++ }, ++ { ++ LinuxSyscall: specs.LinuxSyscall{ ++ Names: []string{ ++ "bpf", ++ "clone", ++ "clone3", ++ "fanotify_init", ++ "fsconfig", ++ "fsmount", ++ "fsopen", ++ "fspick", ++ "lookup_dcookie", ++ "mount", ++ "move_mount", ++ "name_to_handle_at", ++ "open_tree", ++ "perf_event_open", ++ "quotactl", ++ "setdomainname", ++ "sethostname", ++ "setns", ++ "syslog", ++ "umount", ++ "umount2", ++ "unshare", ++ }, ++ Action: specs.ActAllow, ++ }, ++ Includes: &Filter{ ++ Caps: []string{"CAP_SYS_ADMIN"}, ++ }, ++ }, ++ { ++ LinuxSyscall: specs.LinuxSyscall{ ++ Names: []string{ ++ "clone", ++ }, ++ Action: specs.ActAllow, ++ Args: []specs.LinuxSeccompArg{ ++ { ++ Index: 0, ++ Value: unix.CLONE_NEWNS | unix.CLONE_NEWUTS | unix.CLONE_NEWIPC | unix.CLONE_NEWUSER | unix.CLONE_NEWPID | unix.CLONE_NEWNET | unix.CLONE_NEWCGROUP, ++ ValueTwo: 0, ++ Op: specs.OpMaskedEqual, ++ }, ++ }, ++ }, ++ Excludes: &Filter{ ++ Caps: []string{"CAP_SYS_ADMIN"}, ++ Arches: []string{"s390", "s390x"}, ++ }, ++ }, ++ { ++ LinuxSyscall: specs.LinuxSyscall{ ++ Names: []string{ ++ "clone", ++ }, ++ Action: specs.ActAllow, ++ Args: []specs.LinuxSeccompArg{ ++ { ++ Index: 1, ++ Value: unix.CLONE_NEWNS | unix.CLONE_NEWUTS | unix.CLONE_NEWIPC | unix.CLONE_NEWUSER | unix.CLONE_NEWPID | unix.CLONE_NEWNET | unix.CLONE_NEWCGROUP, ++ ValueTwo: 0, ++ Op: specs.OpMaskedEqual, ++ }, ++ }, ++ }, ++ Comment: "s390 parameter ordering for clone is different", ++ Includes: &Filter{ ++ Arches: []string{"s390", "s390x"}, ++ }, ++ Excludes: &Filter{ ++ Caps: []string{"CAP_SYS_ADMIN"}, ++ }, ++ }, ++ { ++ LinuxSyscall: specs.LinuxSyscall{ ++ Names: []string{ ++ "clone3", ++ }, ++ Action: specs.ActErrno, ++ ErrnoRet: &nosys, ++ }, ++ Excludes: &Filter{ ++ Caps: []string{"CAP_SYS_ADMIN"}, ++ }, ++ }, ++ { ++ LinuxSyscall: specs.LinuxSyscall{ ++ Names: []string{ ++ "reboot", ++ }, ++ Action: specs.ActAllow, ++ }, ++ Includes: &Filter{ ++ Caps: []string{"CAP_SYS_BOOT"}, ++ }, ++ }, ++ { ++ LinuxSyscall: specs.LinuxSyscall{ ++ Names: []string{ ++ "chroot", ++ }, ++ Action: specs.ActAllow, ++ }, ++ Includes: &Filter{ ++ Caps: []string{"CAP_SYS_CHROOT"}, ++ }, ++ }, ++ { ++ LinuxSyscall: specs.LinuxSyscall{ ++ Names: []string{ ++ "delete_module", ++ "init_module", ++ "finit_module", ++ }, ++ Action: specs.ActAllow, ++ }, ++ Includes: &Filter{ ++ Caps: []string{"CAP_SYS_MODULE"}, ++ }, ++ }, ++ { ++ LinuxSyscall: specs.LinuxSyscall{ ++ Names: []string{ ++ "acct", ++ }, ++ Action: specs.ActAllow, ++ }, ++ Includes: &Filter{ ++ Caps: []string{"CAP_SYS_PACCT"}, ++ }, ++ }, ++ { ++ LinuxSyscall: specs.LinuxSyscall{ ++ Names: []string{ ++ "kcmp", ++ "pidfd_getfd", ++ "process_madvise", ++ "process_vm_readv", ++ "process_vm_writev", ++ "ptrace", ++ }, ++ Action: specs.ActAllow, ++ }, ++ Includes: &Filter{ ++ Caps: []string{"CAP_SYS_PTRACE"}, ++ }, ++ }, ++ { ++ LinuxSyscall: specs.LinuxSyscall{ ++ Names: []string{ ++ "iopl", ++ "ioperm", ++ }, ++ Action: specs.ActAllow, ++ }, ++ Includes: &Filter{ ++ Caps: []string{"CAP_SYS_RAWIO"}, ++ }, ++ }, ++ { ++ LinuxSyscall: specs.LinuxSyscall{ ++ Names: []string{ ++ "settimeofday", ++ "stime", ++ "clock_settime", ++ }, ++ Action: specs.ActAllow, ++ }, ++ Includes: &Filter{ ++ Caps: []string{"CAP_SYS_TIME"}, ++ }, ++ }, ++ { ++ LinuxSyscall: specs.LinuxSyscall{ ++ Names: []string{ ++ "vhangup", ++ }, ++ Action: specs.ActAllow, ++ }, ++ Includes: &Filter{ ++ Caps: []string{"CAP_SYS_TTY_CONFIG"}, ++ }, ++ }, ++ { ++ LinuxSyscall: specs.LinuxSyscall{ ++ Names: []string{ ++ "get_mempolicy", ++ "mbind", ++ "set_mempolicy", ++ }, ++ Action: specs.ActAllow, ++ }, ++ Includes: &Filter{ ++ Caps: []string{"CAP_SYS_NICE"}, ++ }, ++ }, ++ { ++ LinuxSyscall: specs.LinuxSyscall{ ++ Names: []string{ ++ "syslog", ++ }, ++ Action: specs.ActAllow, ++ }, ++ Includes: &Filter{ ++ Caps: []string{"CAP_SYSLOG"}, ++ }, ++ }, ++ } ++ ++ errnoRet := uint(unix.EPERM) ++ return &Seccomp{ ++ LinuxSeccomp: specs.LinuxSeccomp{ ++ DefaultAction: specs.ActErrno, ++ DefaultErrnoRet: &errnoRet, ++ }, ++ ArchMap: arches(), ++ Syscalls: syscalls, ++ } ++} +diff --git a/components/engine/profiles/seccomp/fixtures/conditional_include.json b/components/engine/profiles/seccomp/fixtures/conditional_include.json +new file mode 100644 +index 00000000..09a3d2a7 +--- /dev/null ++++ b/components/engine/profiles/seccomp/fixtures/conditional_include.json +@@ -0,0 +1,23 @@ ++{ ++ "defaultAction": "SCMP_ACT_ERRNO", ++ "syscalls": [ ++ { ++ "names": ["chmod"], ++ "action": "SCMP_ACT_ALLOW" ++ }, ++ { ++ "names": ["syslog"], ++ "action": "SCMP_ACT_ALLOW", ++ "includes": { ++ "caps": ["CAP_SYSLOG"] ++ } ++ }, ++ { ++ "names": ["ptrace"], ++ "action": "SCMP_ACT_ALLOW", ++ "excludes": { ++ "caps": ["CAP_SYS_ADMIN"] ++ } ++ } ++ ] ++} +diff --git a/components/engine/profiles/seccomp/fixtures/default-old-format.json b/components/engine/profiles/seccomp/fixtures/default-old-format.json +new file mode 100644 +index 00000000..0e52bf95 +--- /dev/null ++++ b/components/engine/profiles/seccomp/fixtures/default-old-format.json +@@ -0,0 +1,1593 @@ ++{ ++ "defaultAction": "SCMP_ACT_ERRNO", ++ "architectures": [ ++ "SCMP_ARCH_X86_64", ++ "SCMP_ARCH_X86", ++ "SCMP_ARCH_X32" ++ ], ++ "syscalls": [ ++ { ++ "name": "accept", ++ "action": "SCMP_ACT_ALLOW", ++ "args": [] ++ }, ++ { ++ "name": "accept4", ++ "action": "SCMP_ACT_ALLOW", ++ "args": [] ++ }, ++ { ++ "name": "access", ++ "action": "SCMP_ACT_ALLOW", ++ "args": [] ++ }, ++ { ++ "name": "alarm", ++ "action": "SCMP_ACT_ALLOW", ++ "args": [] ++ }, ++ { ++ "name": "bind", ++ "action": "SCMP_ACT_ALLOW", ++ "args": [] ++ }, ++ { ++ "name": "brk", ++ "action": "SCMP_ACT_ALLOW", ++ "args": [] ++ }, ++ { ++ "name": "capget", ++ "action": "SCMP_ACT_ALLOW", ++ "args": [] ++ }, ++ { ++ "name": "capset", ++ "action": "SCMP_ACT_ALLOW", ++ "args": [] ++ }, ++ { ++ "name": "chdir", ++ "action": "SCMP_ACT_ALLOW", ++ "args": [] ++ }, ++ { ++ "name": "chmod", ++ "action": "SCMP_ACT_ALLOW", ++ "args": [] ++ }, ++ { ++ "name": "chown", ++ "action": "SCMP_ACT_ALLOW", ++ "args": [] ++ }, ++ { ++ "name": "chown32", ++ "action": "SCMP_ACT_ALLOW", ++ "args": [] ++ }, ++ { ++ "name": "clock_getres", ++ "action": "SCMP_ACT_ALLOW", ++ "args": [] ++ }, ++ { ++ "name": "clock_gettime", ++ "action": "SCMP_ACT_ALLOW", ++ "args": [] ++ }, ++ { ++ "name": "clock_nanosleep", ++ "action": "SCMP_ACT_ALLOW", ++ "args": [] ++ }, ++ { ++ "name": "close", ++ "action": "SCMP_ACT_ALLOW", ++ "args": [] ++ }, ++ { ++ "name": "connect", ++ "action": "SCMP_ACT_ALLOW", ++ "args": [] ++ }, ++ { ++ "name": "copy_file_range", ++ "action": "SCMP_ACT_ALLOW", ++ "args": [] ++ }, ++ { ++ "name": "creat", ++ "action": "SCMP_ACT_ALLOW", ++ "args": [] ++ }, ++ { ++ "name": "dup", ++ "action": "SCMP_ACT_ALLOW", ++ "args": [] ++ }, ++ { ++ "name": "dup2", ++ "action": "SCMP_ACT_ALLOW", ++ "args": [] ++ }, ++ { ++ "name": "dup3", ++ "action": "SCMP_ACT_ALLOW", ++ "args": [] ++ }, ++ { ++ "name": "epoll_create", ++ "action": "SCMP_ACT_ALLOW", ++ "args": [] ++ }, ++ { ++ "name": "epoll_create1", ++ "action": "SCMP_ACT_ALLOW", ++ "args": [] ++ }, ++ { ++ "name": "epoll_ctl", ++ "action": "SCMP_ACT_ALLOW", ++ "args": [] ++ }, ++ { ++ "name": "epoll_ctl_old", ++ "action": "SCMP_ACT_ALLOW", ++ "args": [] ++ }, ++ { ++ "name": "epoll_pwait", ++ "action": "SCMP_ACT_ALLOW", ++ "args": [] ++ }, ++ { ++ "name": "epoll_wait", ++ "action": "SCMP_ACT_ALLOW", ++ "args": [] ++ }, ++ { ++ "name": "epoll_wait_old", ++ "action": "SCMP_ACT_ALLOW", ++ "args": [] ++ }, ++ { ++ "name": "eventfd", ++ "action": "SCMP_ACT_ALLOW", ++ "args": [] ++ }, ++ { ++ "name": "eventfd2", ++ "action": "SCMP_ACT_ALLOW", ++ "args": [] ++ }, ++ { ++ "name": "execve", ++ "action": "SCMP_ACT_ALLOW", ++ "args": [] ++ }, ++ { ++ "name": "execveat", ++ "action": "SCMP_ACT_ALLOW", ++ "args": [] ++ }, ++ { ++ "name": "exit", ++ "action": "SCMP_ACT_ALLOW", ++ "args": [] ++ }, ++ { ++ "name": "exit_group", ++ "action": "SCMP_ACT_ALLOW", ++ "args": [] ++ }, ++ { ++ "name": "faccessat", ++ "action": "SCMP_ACT_ALLOW", ++ "args": [] ++ }, ++ { ++ "name": "fadvise64", ++ "action": "SCMP_ACT_ALLOW", ++ "args": [] ++ }, ++ { ++ "name": "fadvise64_64", ++ "action": "SCMP_ACT_ALLOW", ++ "args": [] ++ }, ++ { ++ "name": "fallocate", ++ "action": "SCMP_ACT_ALLOW", ++ "args": [] ++ }, ++ { ++ "name": "fanotify_mark", ++ "action": "SCMP_ACT_ALLOW", ++ "args": [] ++ }, ++ { ++ "name": "fchdir", ++ "action": "SCMP_ACT_ALLOW", ++ "args": [] ++ }, ++ { ++ "name": "fchmod", ++ "action": "SCMP_ACT_ALLOW", ++ "args": [] ++ }, ++ { ++ "name": "fchmodat", ++ "action": "SCMP_ACT_ALLOW", ++ "args": [] ++ }, ++ { ++ "name": "fchown", ++ "action": "SCMP_ACT_ALLOW", ++ "args": [] ++ }, ++ { ++ "name": "fchown32", ++ "action": "SCMP_ACT_ALLOW", ++ "args": [] ++ }, ++ { ++ "name": "fchownat", ++ "action": "SCMP_ACT_ALLOW", ++ "args": [] ++ }, ++ { ++ "name": "fcntl", ++ "action": "SCMP_ACT_ALLOW", ++ "args": [] ++ }, ++ { ++ "name": "fcntl64", ++ "action": "SCMP_ACT_ALLOW", ++ "args": [] ++ }, ++ { ++ "name": "fdatasync", ++ "action": "SCMP_ACT_ALLOW", ++ "args": [] ++ }, ++ { ++ "name": "fgetxattr", ++ "action": "SCMP_ACT_ALLOW", ++ "args": [] ++ }, ++ { ++ "name": "flistxattr", ++ "action": "SCMP_ACT_ALLOW", ++ "args": [] ++ }, ++ { ++ "name": "flock", ++ "action": "SCMP_ACT_ALLOW", ++ "args": [] ++ }, ++ { ++ "name": "fork", ++ "action": "SCMP_ACT_ALLOW", ++ "args": [] ++ }, ++ { ++ "name": "fremovexattr", ++ "action": "SCMP_ACT_ALLOW", ++ "args": [] ++ }, ++ { ++ "name": "fsetxattr", ++ "action": "SCMP_ACT_ALLOW", ++ "args": [] ++ }, ++ { ++ "name": "fstat", ++ "action": "SCMP_ACT_ALLOW", ++ "args": [] ++ }, ++ { ++ "name": "fstat64", ++ "action": "SCMP_ACT_ALLOW", ++ "args": [] ++ }, ++ { ++ "name": "fstatat64", ++ "action": "SCMP_ACT_ALLOW", ++ "args": [] ++ }, ++ { ++ "name": "fstatfs", ++ "action": "SCMP_ACT_ALLOW", ++ "args": [] ++ }, ++ { ++ "name": "fstatfs64", ++ "action": "SCMP_ACT_ALLOW", ++ "args": [] ++ }, ++ { ++ "name": "fsync", ++ "action": "SCMP_ACT_ALLOW", ++ "args": [] ++ }, ++ { ++ "name": "ftruncate", ++ "action": "SCMP_ACT_ALLOW", ++ "args": [] ++ }, ++ { ++ "name": "ftruncate64", ++ "action": "SCMP_ACT_ALLOW", ++ "args": [] ++ }, ++ { ++ "name": "futex", ++ "action": "SCMP_ACT_ALLOW", ++ "args": [] ++ }, ++ { ++ "name": "futimesat", ++ "action": "SCMP_ACT_ALLOW", ++ "args": [] ++ }, ++ { ++ "name": "getcpu", ++ "action": "SCMP_ACT_ALLOW", ++ "args": [] ++ }, ++ { ++ "name": "getcwd", ++ "action": "SCMP_ACT_ALLOW", ++ "args": [] ++ }, ++ { ++ "name": "getdents", ++ "action": "SCMP_ACT_ALLOW", ++ "args": [] ++ }, ++ { ++ "name": "getdents64", ++ "action": "SCMP_ACT_ALLOW", ++ "args": [] ++ }, ++ { ++ "name": "getegid", ++ "action": "SCMP_ACT_ALLOW", ++ "args": [] ++ }, ++ { ++ "name": "getegid32", ++ "action": "SCMP_ACT_ALLOW", ++ "args": [] ++ }, ++ { ++ "name": "geteuid", ++ "action": "SCMP_ACT_ALLOW", ++ "args": [] ++ }, ++ { ++ "name": "geteuid32", ++ "action": "SCMP_ACT_ALLOW", ++ "args": [] ++ }, ++ { ++ "name": "getgid", ++ "action": "SCMP_ACT_ALLOW", ++ "args": [] ++ }, ++ { ++ "name": "getgid32", ++ "action": "SCMP_ACT_ALLOW", ++ "args": [] ++ }, ++ { ++ "name": "getgroups", ++ "action": "SCMP_ACT_ALLOW", ++ "args": [] ++ }, ++ { ++ "name": "getgroups32", ++ "action": "SCMP_ACT_ALLOW", ++ "args": [] ++ }, ++ { ++ "name": "getitimer", ++ "action": "SCMP_ACT_ALLOW", ++ "args": [] ++ }, ++ { ++ "name": "getpeername", ++ "action": "SCMP_ACT_ALLOW", ++ "args": [] ++ }, ++ { ++ "name": "getpgid", ++ "action": "SCMP_ACT_ALLOW", ++ "args": [] ++ }, ++ { ++ "name": "getpgrp", ++ "action": "SCMP_ACT_ALLOW", ++ "args": [] ++ }, ++ { ++ "name": "getpid", ++ "action": "SCMP_ACT_ALLOW", ++ "args": [] ++ }, ++ { ++ "name": "getppid", ++ "action": "SCMP_ACT_ALLOW", ++ "args": [] ++ }, ++ { ++ "name": "getpriority", ++ "action": "SCMP_ACT_ALLOW", ++ "args": [] ++ }, ++ { ++ "name": "getrandom", ++ "action": "SCMP_ACT_ALLOW", ++ "args": [] ++ }, ++ { ++ "name": "getresgid", ++ "action": "SCMP_ACT_ALLOW", ++ "args": [] ++ }, ++ { ++ "name": "getresgid32", ++ "action": "SCMP_ACT_ALLOW", ++ "args": [] ++ }, ++ { ++ "name": "getresuid", ++ "action": "SCMP_ACT_ALLOW", ++ "args": [] ++ }, ++ { ++ "name": "getresuid32", ++ "action": "SCMP_ACT_ALLOW", ++ "args": [] ++ }, ++ { ++ "name": "getrlimit", ++ "action": "SCMP_ACT_ALLOW", ++ "args": [] ++ }, ++ { ++ "name": "get_robust_list", ++ "action": "SCMP_ACT_ALLOW", ++ "args": [] ++ }, ++ { ++ "name": "getrusage", ++ "action": "SCMP_ACT_ALLOW", ++ "args": [] ++ }, ++ { ++ "name": "getsid", ++ "action": "SCMP_ACT_ALLOW", ++ "args": [] ++ }, ++ { ++ "name": "getsockname", ++ "action": "SCMP_ACT_ALLOW", ++ "args": [] ++ }, ++ { ++ "name": "getsockopt", ++ "action": "SCMP_ACT_ALLOW", ++ "args": [] ++ }, ++ { ++ "name": "get_thread_area", ++ "action": "SCMP_ACT_ALLOW", ++ "args": [] ++ }, ++ { ++ "name": "gettid", ++ "action": "SCMP_ACT_ALLOW", ++ "args": [] ++ }, ++ { ++ "name": "gettimeofday", ++ "action": "SCMP_ACT_ALLOW", ++ "args": [] ++ }, ++ { ++ "name": "getuid", ++ "action": "SCMP_ACT_ALLOW", ++ "args": [] ++ }, ++ { ++ "name": "getuid32", ++ "action": "SCMP_ACT_ALLOW", ++ "args": [] ++ }, ++ { ++ "name": "getxattr", ++ "action": "SCMP_ACT_ALLOW", ++ "args": [] ++ }, ++ { ++ "name": "inotify_add_watch", ++ "action": "SCMP_ACT_ALLOW", ++ "args": [] ++ }, ++ { ++ "name": "inotify_init", ++ "action": "SCMP_ACT_ALLOW", ++ "args": [] ++ }, ++ { ++ "name": "inotify_init1", ++ "action": "SCMP_ACT_ALLOW", ++ "args": [] ++ }, ++ { ++ "name": "inotify_rm_watch", ++ "action": "SCMP_ACT_ALLOW", ++ "args": [] ++ }, ++ { ++ "name": "io_cancel", ++ "action": "SCMP_ACT_ALLOW", ++ "args": [] ++ }, ++ { ++ "name": "ioctl", ++ "action": "SCMP_ACT_ALLOW", ++ "args": [] ++ }, ++ { ++ "name": "io_destroy", ++ "action": "SCMP_ACT_ALLOW", ++ "args": [] ++ }, ++ { ++ "name": "io_getevents", ++ "action": "SCMP_ACT_ALLOW", ++ "args": [] ++ }, ++ { ++ "name": "ioprio_get", ++ "action": "SCMP_ACT_ALLOW", ++ "args": [] ++ }, ++ { ++ "name": "ioprio_set", ++ "action": "SCMP_ACT_ALLOW", ++ "args": [] ++ }, ++ { ++ "name": "io_setup", ++ "action": "SCMP_ACT_ALLOW", ++ "args": [] ++ }, ++ { ++ "name": "io_submit", ++ "action": "SCMP_ACT_ALLOW", ++ "args": [] ++ }, ++ { ++ "name": "ipc", ++ "action": "SCMP_ACT_ALLOW", ++ "args": [] ++ }, ++ { ++ "name": "kill", ++ "action": "SCMP_ACT_ALLOW", ++ "args": [] ++ }, ++ { ++ "name": "lchown", ++ "action": "SCMP_ACT_ALLOW", ++ "args": [] ++ }, ++ { ++ "name": "lchown32", ++ "action": "SCMP_ACT_ALLOW", ++ "args": [] ++ }, ++ { ++ "name": "lgetxattr", ++ "action": "SCMP_ACT_ALLOW", ++ "args": [] ++ }, ++ { ++ "name": "link", ++ "action": "SCMP_ACT_ALLOW", ++ "args": [] ++ }, ++ { ++ "name": "linkat", ++ "action": "SCMP_ACT_ALLOW", ++ "args": [] ++ }, ++ { ++ "name": "listen", ++ "action": "SCMP_ACT_ALLOW", ++ "args": [] ++ }, ++ { ++ "name": "listxattr", ++ "action": "SCMP_ACT_ALLOW", ++ "args": [] ++ }, ++ { ++ "name": "llistxattr", ++ "action": "SCMP_ACT_ALLOW", ++ "args": [] ++ }, ++ { ++ "name": "_llseek", ++ "action": "SCMP_ACT_ALLOW", ++ "args": [] ++ }, ++ { ++ "name": "lremovexattr", ++ "action": "SCMP_ACT_ALLOW", ++ "args": [] ++ }, ++ { ++ "name": "lseek", ++ "action": "SCMP_ACT_ALLOW", ++ "args": [] ++ }, ++ { ++ "name": "lsetxattr", ++ "action": "SCMP_ACT_ALLOW", ++ "args": [] ++ }, ++ { ++ "name": "lstat", ++ "action": "SCMP_ACT_ALLOW", ++ "args": [] ++ }, ++ { ++ "name": "lstat64", ++ "action": "SCMP_ACT_ALLOW", ++ "args": [] ++ }, ++ { ++ "name": "madvise", ++ "action": "SCMP_ACT_ALLOW", ++ "args": [] ++ }, ++ { ++ "name": "memfd_create", ++ "action": "SCMP_ACT_ALLOW", ++ "args": [] ++ }, ++ { ++ "name": "mincore", ++ "action": "SCMP_ACT_ALLOW", ++ "args": [] ++ }, ++ { ++ "name": "mkdir", ++ "action": "SCMP_ACT_ALLOW", ++ "args": [] ++ }, ++ { ++ "name": "mkdirat", ++ "action": "SCMP_ACT_ALLOW", ++ "args": [] ++ }, ++ { ++ "name": "mknod", ++ "action": "SCMP_ACT_ALLOW", ++ "args": [] ++ }, ++ { ++ "name": "mknodat", ++ "action": "SCMP_ACT_ALLOW", ++ "args": [] ++ }, ++ { ++ "name": "mlock", ++ "action": "SCMP_ACT_ALLOW", ++ "args": [] ++ }, ++ { ++ "name": "mlock2", ++ "action": "SCMP_ACT_ALLOW", ++ "args": [] ++ }, ++ { ++ "name": "mlockall", ++ "action": "SCMP_ACT_ALLOW", ++ "args": [] ++ }, ++ { ++ "name": "mmap", ++ "action": "SCMP_ACT_ALLOW", ++ "args": [] ++ }, ++ { ++ "name": "mmap2", ++ "action": "SCMP_ACT_ALLOW", ++ "args": [] ++ }, ++ { ++ "name": "mprotect", ++ "action": "SCMP_ACT_ALLOW", ++ "args": [] ++ }, ++ { ++ "name": "mq_getsetattr", ++ "action": "SCMP_ACT_ALLOW", ++ "args": [] ++ }, ++ { ++ "name": "mq_notify", ++ "action": "SCMP_ACT_ALLOW", ++ "args": [] ++ }, ++ { ++ "name": "mq_open", ++ "action": "SCMP_ACT_ALLOW", ++ "args": [] ++ }, ++ { ++ "name": "mq_timedreceive", ++ "action": "SCMP_ACT_ALLOW", ++ "args": [] ++ }, ++ { ++ "name": "mq_timedsend", ++ "action": "SCMP_ACT_ALLOW", ++ "args": [] ++ }, ++ { ++ "name": "mq_unlink", ++ "action": "SCMP_ACT_ALLOW", ++ "args": [] ++ }, ++ { ++ "name": "mremap", ++ "action": "SCMP_ACT_ALLOW", ++ "args": [] ++ }, ++ { ++ "name": "msgctl", ++ "action": "SCMP_ACT_ALLOW", ++ "args": [] ++ }, ++ { ++ "name": "msgget", ++ "action": "SCMP_ACT_ALLOW", ++ "args": [] ++ }, ++ { ++ "name": "msgrcv", ++ "action": "SCMP_ACT_ALLOW", ++ "args": [] ++ }, ++ { ++ "name": "msgsnd", ++ "action": "SCMP_ACT_ALLOW", ++ "args": [] ++ }, ++ { ++ "name": "msync", ++ "action": "SCMP_ACT_ALLOW", ++ "args": [] ++ }, ++ { ++ "name": "munlock", ++ "action": "SCMP_ACT_ALLOW", ++ "args": [] ++ }, ++ { ++ "name": "munlockall", ++ "action": "SCMP_ACT_ALLOW", ++ "args": [] ++ }, ++ { ++ "name": "munmap", ++ "action": "SCMP_ACT_ALLOW", ++ "args": [] ++ }, ++ { ++ "name": "nanosleep", ++ "action": "SCMP_ACT_ALLOW", ++ "args": [] ++ }, ++ { ++ "name": "newfstatat", ++ "action": "SCMP_ACT_ALLOW", ++ "args": [] ++ }, ++ { ++ "name": "_newselect", ++ "action": "SCMP_ACT_ALLOW", ++ "args": [] ++ }, ++ { ++ "name": "open", ++ "action": "SCMP_ACT_ALLOW", ++ "args": [] ++ }, ++ { ++ "name": "openat", ++ "action": "SCMP_ACT_ALLOW", ++ "args": [] ++ }, ++ { ++ "name": "pause", ++ "action": "SCMP_ACT_ALLOW", ++ "args": [] ++ }, ++ { ++ "name": "personality", ++ "action": "SCMP_ACT_ALLOW", ++ "args": [ ++ { ++ "index": 0, ++ "value": 0, ++ "valueTwo": 0, ++ "op": "SCMP_CMP_EQ" ++ } ++ ] ++ }, ++ { ++ "name": "personality", ++ "action": "SCMP_ACT_ALLOW", ++ "args": [ ++ { ++ "index": 0, ++ "value": 8, ++ "valueTwo": 0, ++ "op": "SCMP_CMP_EQ" ++ } ++ ] ++ }, ++ { ++ "name": "personality", ++ "action": "SCMP_ACT_ALLOW", ++ "args": [ ++ { ++ "index": 0, ++ "value": 4294967295, ++ "valueTwo": 0, ++ "op": "SCMP_CMP_EQ" ++ } ++ ] ++ }, ++ { ++ "name": "pipe", ++ "action": "SCMP_ACT_ALLOW", ++ "args": [] ++ }, ++ { ++ "name": "pipe2", ++ "action": "SCMP_ACT_ALLOW", ++ "args": [] ++ }, ++ { ++ "name": "poll", ++ "action": "SCMP_ACT_ALLOW", ++ "args": [] ++ }, ++ { ++ "name": "ppoll", ++ "action": "SCMP_ACT_ALLOW", ++ "args": [] ++ }, ++ { ++ "name": "prctl", ++ "action": "SCMP_ACT_ALLOW", ++ "args": [] ++ }, ++ { ++ "name": "pread64", ++ "action": "SCMP_ACT_ALLOW", ++ "args": [] ++ }, ++ { ++ "name": "preadv", ++ "action": "SCMP_ACT_ALLOW", ++ "args": [] ++ }, ++ { ++ "name": "prlimit64", ++ "action": "SCMP_ACT_ALLOW", ++ "args": [] ++ }, ++ { ++ "name": "pselect6", ++ "action": "SCMP_ACT_ALLOW", ++ "args": [] ++ }, ++ { ++ "name": "pwrite64", ++ "action": "SCMP_ACT_ALLOW", ++ "args": [] ++ }, ++ { ++ "name": "pwritev", ++ "action": "SCMP_ACT_ALLOW", ++ "args": [] ++ }, ++ { ++ "name": "read", ++ "action": "SCMP_ACT_ALLOW", ++ "args": [] ++ }, ++ { ++ "name": "readahead", ++ "action": "SCMP_ACT_ALLOW", ++ "args": [] ++ }, ++ { ++ "name": "readlink", ++ "action": "SCMP_ACT_ALLOW", ++ "args": [] ++ }, ++ { ++ "name": "readlinkat", ++ "action": "SCMP_ACT_ALLOW", ++ "args": [] ++ }, ++ { ++ "name": "readv", ++ "action": "SCMP_ACT_ALLOW", ++ "args": [] ++ }, ++ { ++ "name": "recv", ++ "action": "SCMP_ACT_ALLOW", ++ "args": [] ++ }, ++ { ++ "name": "recvfrom", ++ "action": "SCMP_ACT_ALLOW", ++ "args": [] ++ }, ++ { ++ "name": "recvmmsg", ++ "action": "SCMP_ACT_ALLOW", ++ "args": [] ++ }, ++ { ++ "name": "recvmsg", ++ "action": "SCMP_ACT_ALLOW", ++ "args": [] ++ }, ++ { ++ "name": "remap_file_pages", ++ "action": "SCMP_ACT_ALLOW", ++ "args": [] ++ }, ++ { ++ "name": "removexattr", ++ "action": "SCMP_ACT_ALLOW", ++ "args": [] ++ }, ++ { ++ "name": "rename", ++ "action": "SCMP_ACT_ALLOW", ++ "args": [] ++ }, ++ { ++ "name": "renameat", ++ "action": "SCMP_ACT_ALLOW", ++ "args": [] ++ }, ++ { ++ "name": "renameat2", ++ "action": "SCMP_ACT_ALLOW", ++ "args": [] ++ }, ++ { ++ "name": "restart_syscall", ++ "action": "SCMP_ACT_ALLOW", ++ "args": [] ++ }, ++ { ++ "name": "rmdir", ++ "action": "SCMP_ACT_ALLOW", ++ "args": [] ++ }, ++ { ++ "name": "rt_sigaction", ++ "action": "SCMP_ACT_ALLOW", ++ "args": [] ++ }, ++ { ++ "name": "rt_sigpending", ++ "action": "SCMP_ACT_ALLOW", ++ "args": [] ++ }, ++ { ++ "name": "rt_sigprocmask", ++ "action": "SCMP_ACT_ALLOW", ++ "args": [] ++ }, ++ { ++ "name": "rt_sigqueueinfo", ++ "action": "SCMP_ACT_ALLOW", ++ "args": [] ++ }, ++ { ++ "name": "rt_sigreturn", ++ "action": "SCMP_ACT_ALLOW", ++ "args": [] ++ }, ++ { ++ "name": "rt_sigsuspend", ++ "action": "SCMP_ACT_ALLOW", ++ "args": [] ++ }, ++ { ++ "name": "rt_sigtimedwait", ++ "action": "SCMP_ACT_ALLOW", ++ "args": [] ++ }, ++ { ++ "name": "rt_tgsigqueueinfo", ++ "action": "SCMP_ACT_ALLOW", ++ "args": [] ++ }, ++ { ++ "name": "sched_getaffinity", ++ "action": "SCMP_ACT_ALLOW", ++ "args": [] ++ }, ++ { ++ "name": "sched_getattr", ++ "action": "SCMP_ACT_ALLOW", ++ "args": [] ++ }, ++ { ++ "name": "sched_getparam", ++ "action": "SCMP_ACT_ALLOW", ++ "args": [] ++ }, ++ { ++ "name": "sched_get_priority_max", ++ "action": "SCMP_ACT_ALLOW", ++ "args": [] ++ }, ++ { ++ "name": "sched_get_priority_min", ++ "action": "SCMP_ACT_ALLOW", ++ "args": [] ++ }, ++ { ++ "name": "sched_getscheduler", ++ "action": "SCMP_ACT_ALLOW", ++ "args": [] ++ }, ++ { ++ "name": "sched_rr_get_interval", ++ "action": "SCMP_ACT_ALLOW", ++ "args": [] ++ }, ++ { ++ "name": "sched_setaffinity", ++ "action": "SCMP_ACT_ALLOW", ++ "args": [] ++ }, ++ { ++ "name": "sched_setattr", ++ "action": "SCMP_ACT_ALLOW", ++ "args": [] ++ }, ++ { ++ "name": "sched_setparam", ++ "action": "SCMP_ACT_ALLOW", ++ "args": [] ++ }, ++ { ++ "name": "sched_setscheduler", ++ "action": "SCMP_ACT_ALLOW", ++ "args": [] ++ }, ++ { ++ "name": "sched_yield", ++ "action": "SCMP_ACT_ALLOW", ++ "args": [] ++ }, ++ { ++ "name": "seccomp", ++ "action": "SCMP_ACT_ALLOW", ++ "args": [] ++ }, ++ { ++ "name": "select", ++ "action": "SCMP_ACT_ALLOW", ++ "args": [] ++ }, ++ { ++ "name": "semctl", ++ "action": "SCMP_ACT_ALLOW", ++ "args": [] ++ }, ++ { ++ "name": "semget", ++ "action": "SCMP_ACT_ALLOW", ++ "args": [] ++ }, ++ { ++ "name": "semop", ++ "action": "SCMP_ACT_ALLOW", ++ "args": [] ++ }, ++ { ++ "name": "semtimedop", ++ "action": "SCMP_ACT_ALLOW", ++ "args": [] ++ }, ++ { ++ "name": "send", ++ "action": "SCMP_ACT_ALLOW", ++ "args": [] ++ }, ++ { ++ "name": "sendfile", ++ "action": "SCMP_ACT_ALLOW", ++ "args": [] ++ }, ++ { ++ "name": "sendfile64", ++ "action": "SCMP_ACT_ALLOW", ++ "args": [] ++ }, ++ { ++ "name": "sendmmsg", ++ "action": "SCMP_ACT_ALLOW", ++ "args": [] ++ }, ++ { ++ "name": "sendmsg", ++ "action": "SCMP_ACT_ALLOW", ++ "args": [] ++ }, ++ { ++ "name": "sendto", ++ "action": "SCMP_ACT_ALLOW", ++ "args": [] ++ }, ++ { ++ "name": "setfsgid", ++ "action": "SCMP_ACT_ALLOW", ++ "args": [] ++ }, ++ { ++ "name": "setfsgid32", ++ "action": "SCMP_ACT_ALLOW", ++ "args": [] ++ }, ++ { ++ "name": "setfsuid", ++ "action": "SCMP_ACT_ALLOW", ++ "args": [] ++ }, ++ { ++ "name": "setfsuid32", ++ "action": "SCMP_ACT_ALLOW", ++ "args": [] ++ }, ++ { ++ "name": "setgid", ++ "action": "SCMP_ACT_ALLOW", ++ "args": [] ++ }, ++ { ++ "name": "setgid32", ++ "action": "SCMP_ACT_ALLOW", ++ "args": [] ++ }, ++ { ++ "name": "setgroups", ++ "action": "SCMP_ACT_ALLOW", ++ "args": [] ++ }, ++ { ++ "name": "setgroups32", ++ "action": "SCMP_ACT_ALLOW", ++ "args": [] ++ }, ++ { ++ "name": "setitimer", ++ "action": "SCMP_ACT_ALLOW", ++ "args": [] ++ }, ++ { ++ "name": "setpgid", ++ "action": "SCMP_ACT_ALLOW", ++ "args": [] ++ }, ++ { ++ "name": "setpriority", ++ "action": "SCMP_ACT_ALLOW", ++ "args": [] ++ }, ++ { ++ "name": "setregid", ++ "action": "SCMP_ACT_ALLOW", ++ "args": [] ++ }, ++ { ++ "name": "setregid32", ++ "action": "SCMP_ACT_ALLOW", ++ "args": [] ++ }, ++ { ++ "name": "setresgid", ++ "action": "SCMP_ACT_ALLOW", ++ "args": [] ++ }, ++ { ++ "name": "setresgid32", ++ "action": "SCMP_ACT_ALLOW", ++ "args": [] ++ }, ++ { ++ "name": "setresuid", ++ "action": "SCMP_ACT_ALLOW", ++ "args": [] ++ }, ++ { ++ "name": "setresuid32", ++ "action": "SCMP_ACT_ALLOW", ++ "args": [] ++ }, ++ { ++ "name": "setreuid", ++ "action": "SCMP_ACT_ALLOW", ++ "args": [] ++ }, ++ { ++ "name": "setreuid32", ++ "action": "SCMP_ACT_ALLOW", ++ "args": [] ++ }, ++ { ++ "name": "setrlimit", ++ "action": "SCMP_ACT_ALLOW", ++ "args": [] ++ }, ++ { ++ "name": "set_robust_list", ++ "action": "SCMP_ACT_ALLOW", ++ "args": [] ++ }, ++ { ++ "name": "setsid", ++ "action": "SCMP_ACT_ALLOW", ++ "args": [] ++ }, ++ { ++ "name": "setsockopt", ++ "action": "SCMP_ACT_ALLOW", ++ "args": [] ++ }, ++ { ++ "name": "set_thread_area", ++ "action": "SCMP_ACT_ALLOW", ++ "args": [] ++ }, ++ { ++ "name": "set_tid_address", ++ "action": "SCMP_ACT_ALLOW", ++ "args": [] ++ }, ++ { ++ "name": "setuid", ++ "action": "SCMP_ACT_ALLOW", ++ "args": [] ++ }, ++ { ++ "name": "setuid32", ++ "action": "SCMP_ACT_ALLOW", ++ "args": [] ++ }, ++ { ++ "name": "setxattr", ++ "action": "SCMP_ACT_ALLOW", ++ "args": [] ++ }, ++ { ++ "name": "shmat", ++ "action": "SCMP_ACT_ALLOW", ++ "args": [] ++ }, ++ { ++ "name": "shmctl", ++ "action": "SCMP_ACT_ALLOW", ++ "args": [] ++ }, ++ { ++ "name": "shmdt", ++ "action": "SCMP_ACT_ALLOW", ++ "args": [] ++ }, ++ { ++ "name": "shmget", ++ "action": "SCMP_ACT_ALLOW", ++ "args": [] ++ }, ++ { ++ "name": "shutdown", ++ "action": "SCMP_ACT_ALLOW", ++ "args": [] ++ }, ++ { ++ "name": "sigaltstack", ++ "action": "SCMP_ACT_ALLOW", ++ "args": [] ++ }, ++ { ++ "name": "signalfd", ++ "action": "SCMP_ACT_ALLOW", ++ "args": [] ++ }, ++ { ++ "name": "signalfd4", ++ "action": "SCMP_ACT_ALLOW", ++ "args": [] ++ }, ++ { ++ "name": "sigreturn", ++ "action": "SCMP_ACT_ALLOW", ++ "args": [] ++ }, ++ { ++ "name": "socket", ++ "action": "SCMP_ACT_ALLOW", ++ "args": [] ++ }, ++ { ++ "name": "socketcall", ++ "action": "SCMP_ACT_ALLOW", ++ "args": [] ++ }, ++ { ++ "name": "socketpair", ++ "action": "SCMP_ACT_ALLOW", ++ "args": [] ++ }, ++ { ++ "name": "splice", ++ "action": "SCMP_ACT_ALLOW", ++ "args": [] ++ }, ++ { ++ "name": "stat", ++ "action": "SCMP_ACT_ALLOW", ++ "args": [] ++ }, ++ { ++ "name": "stat64", ++ "action": "SCMP_ACT_ALLOW", ++ "args": [] ++ }, ++ { ++ "name": "statfs", ++ "action": "SCMP_ACT_ALLOW", ++ "args": [] ++ }, ++ { ++ "name": "statfs64", ++ "action": "SCMP_ACT_ALLOW", ++ "args": [] ++ }, ++ { ++ "name": "symlink", ++ "action": "SCMP_ACT_ALLOW", ++ "args": [] ++ }, ++ { ++ "name": "symlinkat", ++ "action": "SCMP_ACT_ALLOW", ++ "args": [] ++ }, ++ { ++ "name": "sync", ++ "action": "SCMP_ACT_ALLOW", ++ "args": [] ++ }, ++ { ++ "name": "sync_file_range", ++ "action": "SCMP_ACT_ALLOW", ++ "args": [] ++ }, ++ { ++ "name": "syncfs", ++ "action": "SCMP_ACT_ALLOW", ++ "args": [] ++ }, ++ { ++ "name": "sysinfo", ++ "action": "SCMP_ACT_ALLOW", ++ "args": [] ++ }, ++ { ++ "name": "syslog", ++ "action": "SCMP_ACT_ALLOW", ++ "args": [] ++ }, ++ { ++ "name": "tee", ++ "action": "SCMP_ACT_ALLOW", ++ "args": [] ++ }, ++ { ++ "name": "tgkill", ++ "action": "SCMP_ACT_ALLOW", ++ "args": [] ++ }, ++ { ++ "name": "time", ++ "action": "SCMP_ACT_ALLOW", ++ "args": [] ++ }, ++ { ++ "name": "timer_create", ++ "action": "SCMP_ACT_ALLOW", ++ "args": [] ++ }, ++ { ++ "name": "timer_delete", ++ "action": "SCMP_ACT_ALLOW", ++ "args": [] ++ }, ++ { ++ "name": "timerfd_create", ++ "action": "SCMP_ACT_ALLOW", ++ "args": [] ++ }, ++ { ++ "name": "timerfd_gettime", ++ "action": "SCMP_ACT_ALLOW", ++ "args": [] ++ }, ++ { ++ "name": "timerfd_settime", ++ "action": "SCMP_ACT_ALLOW", ++ "args": [] ++ }, ++ { ++ "name": "timer_getoverrun", ++ "action": "SCMP_ACT_ALLOW", ++ "args": [] ++ }, ++ { ++ "name": "timer_gettime", ++ "action": "SCMP_ACT_ALLOW", ++ "args": [] ++ }, ++ { ++ "name": "timer_settime", ++ "action": "SCMP_ACT_ALLOW", ++ "args": [] ++ }, ++ { ++ "name": "times", ++ "action": "SCMP_ACT_ALLOW", ++ "args": [] ++ }, ++ { ++ "name": "tkill", ++ "action": "SCMP_ACT_ALLOW", ++ "args": [] ++ }, ++ { ++ "name": "truncate", ++ "action": "SCMP_ACT_ALLOW", ++ "args": [] ++ }, ++ { ++ "name": "truncate64", ++ "action": "SCMP_ACT_ALLOW", ++ "args": [] ++ }, ++ { ++ "name": "ugetrlimit", ++ "action": "SCMP_ACT_ALLOW", ++ "args": [] ++ }, ++ { ++ "name": "umask", ++ "action": "SCMP_ACT_ALLOW", ++ "args": [] ++ }, ++ { ++ "name": "uname", ++ "action": "SCMP_ACT_ALLOW", ++ "args": [] ++ }, ++ { ++ "name": "unlink", ++ "action": "SCMP_ACT_ALLOW", ++ "args": [] ++ }, ++ { ++ "name": "unlinkat", ++ "action": "SCMP_ACT_ALLOW", ++ "args": [] ++ }, ++ { ++ "name": "utime", ++ "action": "SCMP_ACT_ALLOW", ++ "args": [] ++ }, ++ { ++ "name": "utimensat", ++ "action": "SCMP_ACT_ALLOW", ++ "args": [] ++ }, ++ { ++ "name": "utimes", ++ "action": "SCMP_ACT_ALLOW", ++ "args": [] ++ }, ++ { ++ "name": "vfork", ++ "action": "SCMP_ACT_ALLOW", ++ "args": [] ++ }, ++ { ++ "name": "vmsplice", ++ "action": "SCMP_ACT_ALLOW", ++ "args": [] ++ }, ++ { ++ "name": "wait4", ++ "action": "SCMP_ACT_ALLOW", ++ "args": [] ++ }, ++ { ++ "name": "waitid", ++ "action": "SCMP_ACT_ALLOW", ++ "args": [] ++ }, ++ { ++ "name": "waitpid", ++ "action": "SCMP_ACT_ALLOW", ++ "args": [] ++ }, ++ { ++ "name": "write", ++ "action": "SCMP_ACT_ALLOW", ++ "args": [] ++ }, ++ { ++ "name": "writev", ++ "action": "SCMP_ACT_ALLOW", ++ "args": [] ++ }, ++ { ++ "name": "arch_prctl", ++ "action": "SCMP_ACT_ALLOW", ++ "args": [] ++ }, ++ { ++ "name": "modify_ldt", ++ "action": "SCMP_ACT_ALLOW", ++ "args": [] ++ }, ++ { ++ "name": "chroot", ++ "action": "SCMP_ACT_ALLOW", ++ "args": [] ++ }, ++ { ++ "name": "clone", ++ "action": "SCMP_ACT_ALLOW", ++ "args": [ ++ { ++ "index": 0, ++ "value": 2080505856, ++ "valueTwo": 0, ++ "op": "SCMP_CMP_MASKED_EQ" ++ } ++ ] ++ } ++ ] ++} +\ No newline at end of file +diff --git a/components/engine/profiles/seccomp/fixtures/example.json b/components/engine/profiles/seccomp/fixtures/example.json +old mode 100755 +new mode 100644 +index 674ca50f..80c5a315 +--- a/components/engine/profiles/seccomp/fixtures/example.json ++++ b/components/engine/profiles/seccomp/fixtures/example.json +@@ -1,5 +1,6 @@ + { + "defaultAction": "SCMP_ACT_ERRNO", ++ "defaultErrnoRet": 1, + "syscalls": [ + { + "name": "clone", +@@ -7,7 +8,7 @@ + "args": [ + { + "index": 0, +- "value": 2080505856, ++ "value": 2114060288, + "valueTwo": 0, + "op": "SCMP_CMP_MASKED_EQ" + } +@@ -22,6 +23,12 @@ + "name": "close", + "action": "SCMP_ACT_ALLOW", + "args": [] ++ }, ++ { ++ "name": "syslog", ++ "action": "SCMP_ACT_ERRNO", ++ "errnoRet": 12345, ++ "args": [] + } + ] + } +diff --git a/components/engine/profiles/seccomp/generate.go b/components/engine/profiles/seccomp/generate.go +index 32f22bb3..a5d56247 100644 +--- a/components/engine/profiles/seccomp/generate.go ++++ b/components/engine/profiles/seccomp/generate.go +@@ -1,10 +1,10 @@ ++//go:build ignore + // +build ignore + + package main + + import ( + "encoding/json" +- "io/ioutil" + "os" + "path/filepath" + +@@ -26,7 +26,7 @@ func main() { + panic(err) + } + +- if err := ioutil.WriteFile(f, b, 0644); err != nil { ++ if err := os.WriteFile(f, b, 0644); err != nil { + panic(err) + } + } +diff --git a/components/engine/profiles/seccomp/kernel_linux.go b/components/engine/profiles/seccomp/kernel_linux.go +new file mode 100644 +index 00000000..558eabda +--- /dev/null ++++ b/components/engine/profiles/seccomp/kernel_linux.go +@@ -0,0 +1,59 @@ ++package seccomp ++ ++import ( ++ "bytes" ++ "fmt" ++ "sync" ++ ++ "golang.org/x/sys/unix" ++) ++ ++var ( ++ currentKernelVersion *KernelVersion ++ kernelVersionError error ++ once sync.Once ++) ++ ++// getKernelVersion gets the current kernel version. ++func getKernelVersion() (*KernelVersion, error) { ++ once.Do(func() { ++ var uts unix.Utsname ++ if err := unix.Uname(&uts); err != nil { ++ return ++ } ++ // Remove the \x00 from the release for Atoi to parse correctly ++ currentKernelVersion, kernelVersionError = parseRelease(string(uts.Release[:bytes.IndexByte(uts.Release[:], 0)])) ++ }) ++ return currentKernelVersion, kernelVersionError ++} ++ ++// parseRelease parses a string and creates a KernelVersion based on it. ++func parseRelease(release string) (*KernelVersion, error) { ++ var version = KernelVersion{} ++ ++ // We're only make sure we get the "kernel" and "major revision". Sometimes we have ++ // 3.12.25-gentoo, but sometimes we just have 3.12-1-amd64. ++ _, err := fmt.Sscanf(release, "%d.%d", &version.Kernel, &version.Major) ++ if err != nil { ++ return nil, fmt.Errorf("failed to parse kernel version %q: %w", release, err) ++ } ++ return &version, nil ++} ++ ++// kernelGreaterEqualThan checks if the host's kernel version is greater than, or ++// equal to the given kernel version v. Only "kernel version" and "major revision" ++// can be specified (e.g., "3.12") and will be taken into account, which means ++// that 3.12.25-gentoo and 3.12-1-amd64 are considered equal (kernel: 3, major: 12). ++func kernelGreaterEqualThan(minVersion KernelVersion) (bool, error) { ++ kv, err := getKernelVersion() ++ if err != nil { ++ return false, err ++ } ++ if kv.Kernel > minVersion.Kernel { ++ return true, nil ++ } ++ if kv.Kernel == minVersion.Kernel && kv.Major >= minVersion.Major { ++ return true, nil ++ } ++ return false, nil ++} +diff --git a/components/engine/profiles/seccomp/kernel_linux_test.go b/components/engine/profiles/seccomp/kernel_linux_test.go +new file mode 100644 +index 00000000..a56a97a5 +--- /dev/null ++++ b/components/engine/profiles/seccomp/kernel_linux_test.go +@@ -0,0 +1,122 @@ ++package seccomp ++ ++import ( ++ "fmt" ++ "testing" ++) ++ ++func TestGetKernelVersion(t *testing.T) { ++ version, err := getKernelVersion() ++ if err != nil { ++ t.Fatal(err) ++ } ++ if version == nil { ++ t.Fatal("version is nil") ++ } ++ if version.Kernel == 0 { ++ t.Fatal("no kernel version") ++ } ++} ++ ++// TestParseRelease tests the ParseRelease() function ++func TestParseRelease(t *testing.T) { ++ tests := []struct { ++ in string ++ out KernelVersion ++ expectedErr error ++ }{ ++ {in: "3.8", out: KernelVersion{Kernel: 3, Major: 8}}, ++ {in: "3.8.0", out: KernelVersion{Kernel: 3, Major: 8}}, ++ {in: "3.8.0-19-generic", out: KernelVersion{Kernel: 3, Major: 8}}, ++ {in: "3.4.54.longterm-1", out: KernelVersion{Kernel: 3, Major: 4}}, ++ {in: "3.10.0-862.2.3.el7.x86_64", out: KernelVersion{Kernel: 3, Major: 10}}, ++ {in: "3.12.8tag", out: KernelVersion{Kernel: 3, Major: 12}}, ++ {in: "3.12-1-amd64", out: KernelVersion{Kernel: 3, Major: 12}}, ++ {in: "3.12foobar", out: KernelVersion{Kernel: 3, Major: 12}}, ++ {in: "99.999.999-19-generic", out: KernelVersion{Kernel: 99, Major: 999}}, ++ {in: "", expectedErr: fmt.Errorf(`failed to parse kernel version "": EOF`)}, ++ {in: "3", expectedErr: fmt.Errorf(`failed to parse kernel version "3": unexpected EOF`)}, ++ {in: "3.", expectedErr: fmt.Errorf(`failed to parse kernel version "3.": EOF`)}, ++ {in: "3a", expectedErr: fmt.Errorf(`failed to parse kernel version "3a": input does not match format`)}, ++ {in: "3.a", expectedErr: fmt.Errorf(`failed to parse kernel version "3.a": expected integer`)}, ++ {in: "a", expectedErr: fmt.Errorf(`failed to parse kernel version "a": expected integer`)}, ++ {in: "a.a", expectedErr: fmt.Errorf(`failed to parse kernel version "a.a": expected integer`)}, ++ {in: "a.a.a-a", expectedErr: fmt.Errorf(`failed to parse kernel version "a.a.a-a": expected integer`)}, ++ {in: "-3", expectedErr: fmt.Errorf(`failed to parse kernel version "-3": expected integer`)}, ++ {in: "-3.", expectedErr: fmt.Errorf(`failed to parse kernel version "-3.": expected integer`)}, ++ {in: "-3.8", expectedErr: fmt.Errorf(`failed to parse kernel version "-3.8": expected integer`)}, ++ {in: "-3.-8", expectedErr: fmt.Errorf(`failed to parse kernel version "-3.-8": expected integer`)}, ++ {in: "3.-8", expectedErr: fmt.Errorf(`failed to parse kernel version "3.-8": expected integer`)}, ++ } ++ for _, tc := range tests { ++ tc := tc ++ t.Run(tc.in, func(t *testing.T) { ++ version, err := parseRelease(tc.in) ++ if tc.expectedErr != nil { ++ if err == nil { ++ t.Fatal("expected an error") ++ } ++ if err.Error() != tc.expectedErr.Error() { ++ t.Fatalf("expected: %s, got: %s", tc.expectedErr, err) ++ } ++ return ++ } ++ if err != nil { ++ t.Fatal("unexpected error:", err) ++ } ++ if version == nil { ++ t.Fatal("version is nil") ++ } ++ if version.Kernel != tc.out.Kernel || version.Major != tc.out.Major { ++ t.Fatalf("expected: %d.%d, got: %d.%d", tc.out.Kernel, tc.out.Major, version.Kernel, version.Major) ++ } ++ }) ++ } ++} ++ ++func TestKernelGreaterEqualThan(t *testing.T) { ++ // Get the current kernel version, so that we can make test relative to that ++ v, err := getKernelVersion() ++ if err != nil { ++ t.Fatal(err) ++ } ++ ++ tests := []struct { ++ doc string ++ in KernelVersion ++ expected bool ++ }{ ++ { ++ doc: "same version", ++ in: KernelVersion{v.Kernel, v.Major}, ++ expected: true, ++ }, ++ { ++ doc: "kernel minus one", ++ in: KernelVersion{v.Kernel - 1, v.Major}, ++ expected: true, ++ }, ++ { ++ doc: "kernel plus one", ++ in: KernelVersion{v.Kernel + 1, v.Major}, ++ expected: false, ++ }, ++ { ++ doc: "major plus one", ++ in: KernelVersion{v.Kernel, v.Major + 1}, ++ expected: false, ++ }, ++ } ++ for _, tc := range tests { ++ tc := tc ++ t.Run(tc.doc+": "+tc.in.String(), func(t *testing.T) { ++ ok, err := kernelGreaterEqualThan(tc.in) ++ if err != nil { ++ t.Fatal("unexpected error:", err) ++ } ++ if ok != tc.expected { ++ t.Fatalf("expected: %v, got: %v", tc.expected, ok) ++ } ++ }) ++ } ++} +diff --git a/components/engine/profiles/seccomp/seccomp.go b/components/engine/profiles/seccomp/seccomp.go +index 4438670a..45b1e4f7 100644 +--- a/components/engine/profiles/seccomp/seccomp.go ++++ b/components/engine/profiles/seccomp/seccomp.go +@@ -1,160 +1,115 @@ +-// +build linux +- + package seccomp // import "github.com/docker/docker/profiles/seccomp" + + import ( + "encoding/json" +- "errors" + "fmt" ++ "strconv" ++ "strings" + +- "github.com/docker/docker/api/types" + "github.com/opencontainers/runtime-spec/specs-go" +- libseccomp "github.com/seccomp/libseccomp-golang" + ) + +-//go:generate go run -tags 'seccomp' generate.go ++// Seccomp represents the config for a seccomp profile for syscall restriction. ++// It is used to marshal/unmarshal the JSON profiles as accepted by docker, and ++// extends the runtime-spec's specs.LinuxSeccomp, overriding some fields to ++// provide the ability to define conditional rules based on the host's kernel ++// version, architecture, and the container's capabilities. ++type Seccomp struct { ++ specs.LinuxSeccomp ++ ++ // ArchMap contains a list of Architectures and Sub-architectures for the ++ // profile. When generating the profile, this list is expanded to a ++ // []specs.Arch, to propagate the Architectures field of the profile. ++ ArchMap []Architecture `json:"archMap,omitempty"` ++ ++ // Syscalls contains lists of syscall rules. Rules can define conditions ++ // for them to be included or excluded in the resulting profile (based on ++ // on kernel version, architecture, capabilities, etc.). These lists are ++ // expanded to an specs.Syscall When generating the profile, these lists ++ // are expanded to a []specs.LinuxSyscall. ++ Syscalls []*Syscall `json:"syscalls"` ++} + +-// GetDefaultProfile returns the default seccomp profile. +-func GetDefaultProfile(rs *specs.Spec) (*specs.LinuxSeccomp, error) { +- return setupSeccomp(DefaultProfile(), rs) ++// Architecture is used to represent a specific architecture ++// and its sub-architectures ++type Architecture struct { ++ Arch specs.Arch `json:"architecture"` ++ SubArches []specs.Arch `json:"subArchitectures"` + } + +-// LoadProfile takes a json string and decodes the seccomp profile. +-func LoadProfile(body string, rs *specs.Spec) (*specs.LinuxSeccomp, error) { +- var config types.Seccomp +- if err := json.Unmarshal([]byte(body), &config); err != nil { +- return nil, fmt.Errorf("Decoding seccomp profile failed: %v", err) +- } +- return setupSeccomp(&config, rs) ++// Filter is used to conditionally apply Seccomp rules ++type Filter struct { ++ Caps []string `json:"caps,omitempty"` ++ Arches []string `json:"arches,omitempty"` ++ ++ // MinKernel describes the minimum kernel version the rule must be applied ++ // on, in the format "." (e.g. "3.12"). ++ // ++ // When matching the kernel version of the host, minor revisions, and distro- ++ // specific suffixes are ignored, which means that "3.12.25-gentoo", "3.12-1-amd64", ++ // "3.12", and "3.12-rc5" are considered equal (kernel 3, major revision 12). ++ MinKernel *KernelVersion `json:"minKernel,omitempty"` + } + +-var nativeToSeccomp = map[string]types.Arch{ +- "amd64": types.ArchX86_64, +- "arm64": types.ArchAARCH64, +- "mips64": types.ArchMIPS64, +- "mips64n32": types.ArchMIPS64N32, +- "mipsel64": types.ArchMIPSEL64, +- "mipsel64n32": types.ArchMIPSEL64N32, +- "s390x": types.ArchS390X, ++// Syscall is used to match a group of syscalls in Seccomp. It extends the ++// runtime-spec Syscall type, adding a "Name" field for backward compatibility ++// with older JSON representations, additional "Comment" metadata, and conditional ++// rules ("Includes", "Excludes") used to generate a runtime-spec Seccomp profile ++// based on the container (capabilities) and host's (arch, kernel) configuration. ++type Syscall struct { ++ specs.LinuxSyscall ++ // Deprecated: kept for backward compatibility with old JSON profiles, use Names instead ++ Name string `json:"name,omitempty"` ++ Comment string `json:"comment,omitempty"` ++ Includes *Filter `json:"includes,omitempty"` ++ Excludes *Filter `json:"excludes,omitempty"` + } + +-// inSlice tests whether a string is contained in a slice of strings or not. +-// Comparison is case sensitive +-func inSlice(slice []string, s string) bool { +- for _, ss := range slice { +- if s == ss { +- return true +- } +- } +- return false ++// KernelVersion holds information about the kernel. ++type KernelVersion struct { ++ Kernel uint64 // Version of the Kernel (i.e., the "4" in "4.1.2-generic") ++ Major uint64 // Major revision of the Kernel (i.e., the "1" in "4.1.2-generic") + } + +-func setupSeccomp(config *types.Seccomp, rs *specs.Spec) (*specs.LinuxSeccomp, error) { +- if config == nil { +- return nil, nil ++// String implements fmt.Stringer for KernelVersion ++func (k *KernelVersion) String() string { ++ if k.Kernel > 0 || k.Major > 0 { ++ return fmt.Sprintf("%d.%d", k.Kernel, k.Major) + } ++ return "" ++} + +- // No default action specified, no syscalls listed, assume seccomp disabled +- if config.DefaultAction == "" && len(config.Syscalls) == 0 { +- return nil, nil +- } ++// MarshalJSON implements json.Unmarshaler for KernelVersion ++func (k *KernelVersion) MarshalJSON() ([]byte, error) { ++ return json.Marshal(k.String()) ++} + +- newConfig := &specs.LinuxSeccomp{} ++// UnmarshalJSON implements json.Marshaler for KernelVersion ++func (k *KernelVersion) UnmarshalJSON(version []byte) error { ++ var ( ++ ver string ++ err error ++ ) + +- var arch string +- var native, err = libseccomp.GetNativeArch() +- if err == nil { +- arch = native.String() ++ // make sure we have a string ++ if err = json.Unmarshal(version, &ver); err != nil { ++ return fmt.Errorf(`invalid kernel version: %s, expected ".": %v`, string(version), err) + } +- +- if len(config.Architectures) != 0 && len(config.ArchMap) != 0 { +- return nil, errors.New("'architectures' and 'archMap' were specified in the seccomp profile, use either 'architectures' or 'archMap'") ++ if ver == "" { ++ return nil + } +- +- // if config.Architectures == 0 then libseccomp will figure out the architecture to use +- if len(config.Architectures) != 0 { +- for _, a := range config.Architectures { +- newConfig.Architectures = append(newConfig.Architectures, specs.Arch(a)) +- } ++ parts := strings.SplitN(ver, ".", 3) ++ if len(parts) != 2 { ++ return fmt.Errorf(`invalid kernel version: %s, expected "."`, string(version)) + } +- +- if len(config.ArchMap) != 0 { +- for _, a := range config.ArchMap { +- seccompArch, ok := nativeToSeccomp[arch] +- if ok { +- if a.Arch == seccompArch { +- newConfig.Architectures = append(newConfig.Architectures, specs.Arch(a.Arch)) +- for _, sa := range a.SubArches { +- newConfig.Architectures = append(newConfig.Architectures, specs.Arch(sa)) +- } +- break +- } +- } +- } ++ if k.Kernel, err = strconv.ParseUint(parts[0], 10, 8); err != nil { ++ return fmt.Errorf(`invalid kernel version: %s, expected ".": %v`, string(version), err) + } +- +- newConfig.DefaultAction = specs.LinuxSeccompAction(config.DefaultAction) +- +-Loop: +- // Loop through all syscall blocks and convert them to libcontainer format after filtering them +- for _, call := range config.Syscalls { +- if len(call.Excludes.Arches) > 0 { +- if inSlice(call.Excludes.Arches, arch) { +- continue Loop +- } +- } +- if len(call.Excludes.Caps) > 0 { +- for _, c := range call.Excludes.Caps { +- if inSlice(rs.Process.Capabilities.Bounding, c) { +- continue Loop +- } +- } +- } +- if len(call.Includes.Arches) > 0 { +- if !inSlice(call.Includes.Arches, arch) { +- continue Loop +- } +- } +- if len(call.Includes.Caps) > 0 { +- for _, c := range call.Includes.Caps { +- if !inSlice(rs.Process.Capabilities.Bounding, c) { +- continue Loop +- } +- } +- } +- +- if call.Name != "" && len(call.Names) != 0 { +- return nil, errors.New("'name' and 'names' were specified in the seccomp profile, use either 'name' or 'names'") +- } +- +- if call.Name != "" { +- newConfig.Syscalls = append(newConfig.Syscalls, createSpecsSyscall(call.Name, call.Action, call.Args)) +- } +- +- for _, n := range call.Names { +- newConfig.Syscalls = append(newConfig.Syscalls, createSpecsSyscall(n, call.Action, call.Args)) +- } +- } +- +- return newConfig, nil +-} +- +-func createSpecsSyscall(name string, action types.Action, args []*types.Arg) specs.LinuxSyscall { +- newCall := specs.LinuxSyscall{ +- Names: []string{name}, +- Action: specs.LinuxSeccompAction(action), ++ if k.Major, err = strconv.ParseUint(parts[1], 10, 8); err != nil { ++ return fmt.Errorf(`invalid kernel version: %s, expected ".": %v`, string(version), err) + } +- +- // Loop through all the arguments of the syscall and convert them +- for _, arg := range args { +- newArg := specs.LinuxSeccompArg{ +- Index: arg.Index, +- Value: arg.Value, +- ValueTwo: arg.ValueTwo, +- Op: specs.LinuxSeccompOperator(arg.Op), +- } +- +- newCall.Args = append(newCall.Args, newArg) ++ if k.Kernel == 0 && k.Major == 0 { ++ return fmt.Errorf(`invalid kernel version: %s, expected ".": version cannot be 0.0`, string(version)) + } +- return newCall ++ return nil + } +diff --git a/components/engine/profiles/seccomp/seccomp_default.go b/components/engine/profiles/seccomp/seccomp_default.go +deleted file mode 100644 +index ac81c2e0..00000000 +--- a/components/engine/profiles/seccomp/seccomp_default.go ++++ /dev/null +@@ -1,663 +0,0 @@ +-// +build linux,seccomp +- +-package seccomp // import "github.com/docker/docker/profiles/seccomp" +- +-import ( +- "github.com/docker/docker/api/types" +- "golang.org/x/sys/unix" +-) +- +-func arches() []types.Architecture { +- return []types.Architecture{ +- { +- Arch: types.ArchX86_64, +- SubArches: []types.Arch{types.ArchX86, types.ArchX32}, +- }, +- { +- Arch: types.ArchAARCH64, +- SubArches: []types.Arch{types.ArchARM}, +- }, +- { +- Arch: types.ArchMIPS64, +- SubArches: []types.Arch{types.ArchMIPS, types.ArchMIPS64N32}, +- }, +- { +- Arch: types.ArchMIPS64N32, +- SubArches: []types.Arch{types.ArchMIPS, types.ArchMIPS64}, +- }, +- { +- Arch: types.ArchMIPSEL64, +- SubArches: []types.Arch{types.ArchMIPSEL, types.ArchMIPSEL64N32}, +- }, +- { +- Arch: types.ArchMIPSEL64N32, +- SubArches: []types.Arch{types.ArchMIPSEL, types.ArchMIPSEL64}, +- }, +- { +- Arch: types.ArchS390X, +- SubArches: []types.Arch{types.ArchS390}, +- }, +- } +-} +- +-// DefaultProfile defines the whitelist for the default seccomp profile. +-func DefaultProfile() *types.Seccomp { +- syscalls := []*types.Syscall{ +- { +- Names: []string{ +- "accept", +- "accept4", +- "access", +- "adjtimex", +- "alarm", +- "bind", +- "brk", +- "capget", +- "capset", +- "chdir", +- "chmod", +- "chown", +- "chown32", +- "clock_getres", +- "clock_gettime", +- "clock_nanosleep", +- "close", +- "connect", +- "copy_file_range", +- "creat", +- "dup", +- "dup2", +- "dup3", +- "epoll_create", +- "epoll_create1", +- "epoll_ctl", +- "epoll_ctl_old", +- "epoll_pwait", +- "epoll_wait", +- "epoll_wait_old", +- "eventfd", +- "eventfd2", +- "execve", +- "execveat", +- "exit", +- "exit_group", +- "faccessat", +- "fadvise64", +- "fadvise64_64", +- "fallocate", +- "fanotify_mark", +- "fchdir", +- "fchmod", +- "fchmodat", +- "fchown", +- "fchown32", +- "fchownat", +- "fcntl", +- "fcntl64", +- "fdatasync", +- "fgetxattr", +- "flistxattr", +- "flock", +- "fork", +- "fremovexattr", +- "fsetxattr", +- "fstat", +- "fstat64", +- "fstatat64", +- "fstatfs", +- "fstatfs64", +- "fsync", +- "ftruncate", +- "ftruncate64", +- "futex", +- "futimesat", +- "getcpu", +- "getcwd", +- "getdents", +- "getdents64", +- "getegid", +- "getegid32", +- "geteuid", +- "geteuid32", +- "getgid", +- "getgid32", +- "getgroups", +- "getgroups32", +- "getitimer", +- "getpeername", +- "getpgid", +- "getpgrp", +- "getpid", +- "getppid", +- "getpriority", +- "getrandom", +- "getresgid", +- "getresgid32", +- "getresuid", +- "getresuid32", +- "getrlimit", +- "get_robust_list", +- "getrusage", +- "getsid", +- "getsockname", +- "getsockopt", +- "get_thread_area", +- "gettid", +- "gettimeofday", +- "getuid", +- "getuid32", +- "getxattr", +- "inotify_add_watch", +- "inotify_init", +- "inotify_init1", +- "inotify_rm_watch", +- "io_cancel", +- "ioctl", +- "io_destroy", +- "io_getevents", +- "ioprio_get", +- "ioprio_set", +- "io_setup", +- "io_submit", +- "ipc", +- "kill", +- "lchown", +- "lchown32", +- "lgetxattr", +- "link", +- "linkat", +- "listen", +- "listxattr", +- "llistxattr", +- "_llseek", +- "lremovexattr", +- "lseek", +- "lsetxattr", +- "lstat", +- "lstat64", +- "madvise", +- "memfd_create", +- "mincore", +- "mkdir", +- "mkdirat", +- "mknod", +- "mknodat", +- "mlock", +- "mlock2", +- "mlockall", +- "mmap", +- "mmap2", +- "mprotect", +- "mq_getsetattr", +- "mq_notify", +- "mq_open", +- "mq_timedreceive", +- "mq_timedsend", +- "mq_unlink", +- "mremap", +- "msgctl", +- "msgget", +- "msgrcv", +- "msgsnd", +- "msync", +- "munlock", +- "munlockall", +- "munmap", +- "nanosleep", +- "newfstatat", +- "_newselect", +- "open", +- "openat", +- "pause", +- "pipe", +- "pipe2", +- "poll", +- "ppoll", +- "prctl", +- "pread64", +- "preadv", +- "preadv2", +- "prlimit64", +- "pselect6", +- "pwrite64", +- "pwritev", +- "pwritev2", +- "read", +- "readahead", +- "readlink", +- "readlinkat", +- "readv", +- "recv", +- "recvfrom", +- "recvmmsg", +- "recvmsg", +- "remap_file_pages", +- "removexattr", +- "rename", +- "renameat", +- "renameat2", +- "restart_syscall", +- "rmdir", +- "rt_sigaction", +- "rt_sigpending", +- "rt_sigprocmask", +- "rt_sigqueueinfo", +- "rt_sigreturn", +- "rt_sigsuspend", +- "rt_sigtimedwait", +- "rt_tgsigqueueinfo", +- "sched_getaffinity", +- "sched_getattr", +- "sched_getparam", +- "sched_get_priority_max", +- "sched_get_priority_min", +- "sched_getscheduler", +- "sched_rr_get_interval", +- "sched_setaffinity", +- "sched_setattr", +- "sched_setparam", +- "sched_setscheduler", +- "sched_yield", +- "seccomp", +- "select", +- "semctl", +- "semget", +- "semop", +- "semtimedop", +- "send", +- "sendfile", +- "sendfile64", +- "sendmmsg", +- "sendmsg", +- "sendto", +- "setfsgid", +- "setfsgid32", +- "setfsuid", +- "setfsuid32", +- "setgid", +- "setgid32", +- "setgroups", +- "setgroups32", +- "setitimer", +- "setpgid", +- "setpriority", +- "setregid", +- "setregid32", +- "setresgid", +- "setresgid32", +- "setresuid", +- "setresuid32", +- "setreuid", +- "setreuid32", +- "setrlimit", +- "set_robust_list", +- "setsid", +- "setsockopt", +- "set_thread_area", +- "set_tid_address", +- "setuid", +- "setuid32", +- "setxattr", +- "shmat", +- "shmctl", +- "shmdt", +- "shmget", +- "shutdown", +- "sigaltstack", +- "signalfd", +- "signalfd4", +- "sigreturn", +- "socket", +- "socketcall", +- "socketpair", +- "splice", +- "stat", +- "stat64", +- "statfs", +- "statfs64", +- "statx", +- "symlink", +- "symlinkat", +- "sync", +- "sync_file_range", +- "syncfs", +- "sysinfo", +- "tee", +- "tgkill", +- "time", +- "timer_create", +- "timer_delete", +- "timerfd_create", +- "timerfd_gettime", +- "timerfd_settime", +- "timer_getoverrun", +- "timer_gettime", +- "timer_settime", +- "times", +- "tkill", +- "truncate", +- "truncate64", +- "ugetrlimit", +- "umask", +- "uname", +- "unlink", +- "unlinkat", +- "utime", +- "utimensat", +- "utimes", +- "vfork", +- "vmsplice", +- "wait4", +- "waitid", +- "waitpid", +- "write", +- "writev", +- }, +- Action: types.ActAllow, +- Args: []*types.Arg{}, +- }, +- { +- Names: []string{"personality"}, +- Action: types.ActAllow, +- Args: []*types.Arg{ +- { +- Index: 0, +- Value: 0x0, +- Op: types.OpEqualTo, +- }, +- }, +- }, +- { +- Names: []string{"personality"}, +- Action: types.ActAllow, +- Args: []*types.Arg{ +- { +- Index: 0, +- Value: 0x0008, +- Op: types.OpEqualTo, +- }, +- }, +- }, +- { +- Names: []string{"personality"}, +- Action: types.ActAllow, +- Args: []*types.Arg{ +- { +- Index: 0, +- Value: 0x20000, +- Op: types.OpEqualTo, +- }, +- }, +- }, +- { +- Names: []string{"personality"}, +- Action: types.ActAllow, +- Args: []*types.Arg{ +- { +- Index: 0, +- Value: 0x20008, +- Op: types.OpEqualTo, +- }, +- }, +- }, +- { +- Names: []string{"personality"}, +- Action: types.ActAllow, +- Args: []*types.Arg{ +- { +- Index: 0, +- Value: 0xffffffff, +- Op: types.OpEqualTo, +- }, +- }, +- }, +- { +- Names: []string{ +- "sync_file_range2", +- }, +- Action: types.ActAllow, +- Args: []*types.Arg{}, +- Includes: types.Filter{ +- Arches: []string{"ppc64le"}, +- }, +- }, +- { +- Names: []string{ +- "arm_fadvise64_64", +- "arm_sync_file_range", +- "sync_file_range2", +- "breakpoint", +- "cacheflush", +- "set_tls", +- }, +- Action: types.ActAllow, +- Args: []*types.Arg{}, +- Includes: types.Filter{ +- Arches: []string{"arm", "arm64"}, +- }, +- }, +- { +- Names: []string{ +- "arch_prctl", +- }, +- Action: types.ActAllow, +- Args: []*types.Arg{}, +- Includes: types.Filter{ +- Arches: []string{"amd64", "x32"}, +- }, +- }, +- { +- Names: []string{ +- "modify_ldt", +- "clone3", +- }, +- Action: types.ActAllow, +- Args: []*types.Arg{}, +- Includes: types.Filter{ +- Arches: []string{"amd64", "x32", "x86"}, +- }, +- }, +- { +- Names: []string{ +- "s390_pci_mmio_read", +- "s390_pci_mmio_write", +- "s390_runtime_instr", +- }, +- Action: types.ActAllow, +- Args: []*types.Arg{}, +- Includes: types.Filter{ +- Arches: []string{"s390", "s390x"}, +- }, +- }, +- { +- Names: []string{ +- "open_by_handle_at", +- }, +- Action: types.ActAllow, +- Args: []*types.Arg{}, +- Includes: types.Filter{ +- Caps: []string{"CAP_DAC_READ_SEARCH"}, +- }, +- }, +- { +- Names: []string{ +- "bpf", +- "clone", +- "fanotify_init", +- "lookup_dcookie", +- "mount", +- "name_to_handle_at", +- "perf_event_open", +- "quotactl", +- "setdomainname", +- "sethostname", +- "setns", +- "syslog", +- "umount", +- "umount2", +- "unshare", +- }, +- Action: types.ActAllow, +- Args: []*types.Arg{}, +- Includes: types.Filter{ +- Caps: []string{"CAP_SYS_ADMIN"}, +- }, +- }, +- { +- Names: []string{ +- "clone", +- }, +- Action: types.ActAllow, +- Args: []*types.Arg{ +- { +- Index: 0, +- Value: unix.CLONE_NEWNS | unix.CLONE_NEWUTS | unix.CLONE_NEWIPC | unix.CLONE_NEWUSER | unix.CLONE_NEWPID | unix.CLONE_NEWNET, +- ValueTwo: 0, +- Op: types.OpMaskedEqual, +- }, +- }, +- Excludes: types.Filter{ +- Caps: []string{"CAP_SYS_ADMIN"}, +- Arches: []string{"s390", "s390x"}, +- }, +- }, +- { +- Names: []string{ +- "clone", +- }, +- Action: types.ActAllow, +- Args: []*types.Arg{ +- { +- Index: 1, +- Value: unix.CLONE_NEWNS | unix.CLONE_NEWUTS | unix.CLONE_NEWIPC | unix.CLONE_NEWUSER | unix.CLONE_NEWPID | unix.CLONE_NEWNET, +- ValueTwo: 0, +- Op: types.OpMaskedEqual, +- }, +- }, +- Comment: "s390 parameter ordering for clone is different", +- Includes: types.Filter{ +- Arches: []string{"s390", "s390x"}, +- }, +- Excludes: types.Filter{ +- Caps: []string{"CAP_SYS_ADMIN"}, +- }, +- }, +- { +- Names: []string{ +- "reboot", +- }, +- Action: types.ActAllow, +- Args: []*types.Arg{}, +- Includes: types.Filter{ +- Caps: []string{"CAP_SYS_BOOT"}, +- }, +- }, +- { +- Names: []string{ +- "chroot", +- }, +- Action: types.ActAllow, +- Args: []*types.Arg{}, +- Includes: types.Filter{ +- Caps: []string{"CAP_SYS_CHROOT"}, +- }, +- }, +- { +- Names: []string{ +- "delete_module", +- "init_module", +- "finit_module", +- "query_module", +- }, +- Action: types.ActAllow, +- Args: []*types.Arg{}, +- Includes: types.Filter{ +- Caps: []string{"CAP_SYS_MODULE"}, +- }, +- }, +- { +- Names: []string{ +- "acct", +- }, +- Action: types.ActAllow, +- Args: []*types.Arg{}, +- Includes: types.Filter{ +- Caps: []string{"CAP_SYS_PACCT"}, +- }, +- }, +- { +- Names: []string{ +- "kcmp", +- "process_vm_readv", +- "process_vm_writev", +- "ptrace", +- }, +- Action: types.ActAllow, +- Args: []*types.Arg{}, +- Includes: types.Filter{ +- Caps: []string{"CAP_SYS_PTRACE"}, +- }, +- }, +- { +- Names: []string{ +- "iopl", +- "ioperm", +- }, +- Action: types.ActAllow, +- Args: []*types.Arg{}, +- Includes: types.Filter{ +- Caps: []string{"CAP_SYS_RAWIO"}, +- }, +- }, +- { +- Names: []string{ +- "settimeofday", +- "stime", +- "clock_settime", +- }, +- Action: types.ActAllow, +- Args: []*types.Arg{}, +- Includes: types.Filter{ +- Caps: []string{"CAP_SYS_TIME"}, +- }, +- }, +- { +- Names: []string{ +- "vhangup", +- }, +- Action: types.ActAllow, +- Args: []*types.Arg{}, +- Includes: types.Filter{ +- Caps: []string{"CAP_SYS_TTY_CONFIG"}, +- }, +- }, +- { +- Names: []string{ +- "get_mempolicy", +- "mbind", +- "set_mempolicy", +- }, +- Action: types.ActAllow, +- Args: []*types.Arg{}, +- Includes: types.Filter{ +- Caps: []string{"CAP_SYS_NICE"}, +- }, +- }, +- { +- Names: []string{ +- "syslog", +- }, +- Action: types.ActAllow, +- Args: []*types.Arg{}, +- Includes: types.Filter{ +- Caps: []string{"CAP_SYSLOG"}, +- }, +- }, +- } +- +- return &types.Seccomp{ +- DefaultAction: types.ActErrno, +- ArchMap: arches(), +- Syscalls: syscalls, +- } +-} +diff --git a/components/engine/profiles/seccomp/seccomp_linux.go b/components/engine/profiles/seccomp/seccomp_linux.go +new file mode 100644 +index 00000000..4d8fed68 +--- /dev/null ++++ b/components/engine/profiles/seccomp/seccomp_linux.go +@@ -0,0 +1,166 @@ ++//go:generate go run -tags 'seccomp' generate.go ++ ++package seccomp // import "github.com/docker/docker/profiles/seccomp" ++ ++import ( ++ "encoding/json" ++ "errors" ++ "fmt" ++ "runtime" ++ ++ specs "github.com/opencontainers/runtime-spec/specs-go" ++) ++ ++// GetDefaultProfile returns the default seccomp profile. ++func GetDefaultProfile(rs *specs.Spec) (*specs.LinuxSeccomp, error) { ++ return setupSeccomp(DefaultProfile(), rs) ++} ++ ++// LoadProfile takes a json string and decodes the seccomp profile. ++func LoadProfile(body string, rs *specs.Spec) (*specs.LinuxSeccomp, error) { ++ var config Seccomp ++ if err := json.Unmarshal([]byte(body), &config); err != nil { ++ return nil, fmt.Errorf("Decoding seccomp profile failed: %v", err) ++ } ++ return setupSeccomp(&config, rs) ++} ++ ++// libseccomp string => seccomp arch ++var nativeToSeccomp = map[string]specs.Arch{ ++ "x86": specs.ArchX86, ++ "amd64": specs.ArchX86_64, ++ "arm": specs.ArchARM, ++ "arm64": specs.ArchAARCH64, ++ "mips64": specs.ArchMIPS64, ++ "mips64n32": specs.ArchMIPS64N32, ++ "mipsel64": specs.ArchMIPSEL64, ++ "mips3l64n32": specs.ArchMIPSEL64N32, ++ "mipsle": specs.ArchMIPSEL, ++ "ppc": specs.ArchPPC, ++ "ppc64": specs.ArchPPC64, ++ "ppc64le": specs.ArchPPC64LE, ++ "s390": specs.ArchS390, ++ "s390x": specs.ArchS390X, ++} ++ ++// GOARCH => libseccomp string ++var goToNative = map[string]string{ ++ "386": "x86", ++ "amd64": "amd64", ++ "arm": "arm", ++ "arm64": "arm64", ++ "mips64": "mips64", ++ "mips64p32": "mips64n32", ++ "mips64le": "mipsel64", ++ "mips64p32le": "mips3l64n32", ++ "mipsle": "mipsel", ++ "ppc": "ppc", ++ "ppc64": "ppc64", ++ "ppc64le": "ppc64le", ++ "s390": "s390", ++ "s390x": "s390x", ++} ++ ++// inSlice tests whether a string is contained in a slice of strings or not. ++// Comparison is case sensitive ++func inSlice(slice []string, s string) bool { ++ for _, ss := range slice { ++ if s == ss { ++ return true ++ } ++ } ++ return false ++} ++ ++func setupSeccomp(config *Seccomp, rs *specs.Spec) (*specs.LinuxSeccomp, error) { ++ if config == nil { ++ return nil, nil ++ } ++ ++ // No default action specified, no syscalls listed, assume seccomp disabled ++ if config.DefaultAction == "" && len(config.Syscalls) == 0 { ++ return nil, nil ++ } ++ ++ if len(config.Architectures) != 0 && len(config.ArchMap) != 0 { ++ return nil, errors.New("both 'architectures' and 'archMap' are specified in the seccomp profile, use either 'architectures' or 'archMap'") ++ } ++ ++ if len(config.LinuxSeccomp.Syscalls) != 0 { ++ // The Seccomp type overrides the LinuxSeccomp.Syscalls field, ++ // so 'this should never happen' when loaded from JSON, but could ++ // happen if someone constructs the Config from source. ++ return nil, errors.New("the LinuxSeccomp.Syscalls field should be empty") ++ } ++ ++ var ( ++ // Copy all common / standard properties to the output profile ++ newConfig = &config.LinuxSeccomp ++ arch = goToNative[runtime.GOARCH] ++ ) ++ if seccompArch, ok := nativeToSeccomp[arch]; ok { ++ for _, a := range config.ArchMap { ++ if a.Arch == seccompArch { ++ newConfig.Architectures = append(newConfig.Architectures, a.Arch) ++ newConfig.Architectures = append(newConfig.Architectures, a.SubArches...) ++ break ++ } ++ } ++ } ++ ++Loop: ++ // Convert Syscall to OCI runtimes-spec specs.LinuxSyscall after filtering them. ++ for _, call := range config.Syscalls { ++ if call.Name != "" { ++ if len(call.Names) != 0 { ++ return nil, errors.New("both 'name' and 'names' are specified in the seccomp profile, use either 'name' or 'names'") ++ } ++ call.Names = []string{call.Name} ++ } ++ if call.Excludes != nil { ++ if len(call.Excludes.Arches) > 0 { ++ if inSlice(call.Excludes.Arches, arch) { ++ continue Loop ++ } ++ } ++ if len(call.Excludes.Caps) > 0 { ++ for _, c := range call.Excludes.Caps { ++ if inSlice(rs.Process.Capabilities.Bounding, c) { ++ continue Loop ++ } ++ } ++ } ++ if call.Excludes.MinKernel != nil { ++ if ok, err := kernelGreaterEqualThan(*call.Excludes.MinKernel); err != nil { ++ return nil, err ++ } else if ok { ++ continue Loop ++ } ++ } ++ } ++ if call.Includes != nil { ++ if len(call.Includes.Arches) > 0 { ++ if !inSlice(call.Includes.Arches, arch) { ++ continue Loop ++ } ++ } ++ if len(call.Includes.Caps) > 0 { ++ for _, c := range call.Includes.Caps { ++ if !inSlice(rs.Process.Capabilities.Bounding, c) { ++ continue Loop ++ } ++ } ++ } ++ if call.Includes.MinKernel != nil { ++ if ok, err := kernelGreaterEqualThan(*call.Includes.MinKernel); err != nil { ++ return nil, err ++ } else if !ok { ++ continue Loop ++ } ++ } ++ } ++ newConfig.Syscalls = append(newConfig.Syscalls, call.LinuxSyscall) ++ } ++ ++ return newConfig, nil ++} +diff --git a/components/engine/profiles/seccomp/seccomp_test.go b/components/engine/profiles/seccomp/seccomp_test.go +index b0b63ea8..3a401db4 100644 +--- a/components/engine/profiles/seccomp/seccomp_test.go ++++ b/components/engine/profiles/seccomp/seccomp_test.go +@@ -1,32 +1,297 @@ ++//go:build linux + // +build linux + + package seccomp // import "github.com/docker/docker/profiles/seccomp" + + import ( +- "io/ioutil" ++ "encoding/json" ++ "os" ++ "strings" + "testing" + +- "github.com/docker/docker/oci" ++ "github.com/opencontainers/runtime-spec/specs-go" ++ "gotest.tools/v3/assert" + ) + + func TestLoadProfile(t *testing.T) { +- f, err := ioutil.ReadFile("fixtures/example.json") ++ f, err := os.ReadFile("fixtures/example.json") + if err != nil { + t.Fatal(err) + } +- rs := oci.DefaultSpec() +- if _, err := LoadProfile(string(f), &rs); err != nil { ++ rs := createSpec() ++ p, err := LoadProfile(string(f), &rs) ++ if err != nil { ++ t.Fatal(err) ++ } ++ var expectedErrno uint = 12345 ++ var expectedDefaultErrno uint = 1 ++ expected := specs.LinuxSeccomp{ ++ DefaultAction: specs.ActErrno, ++ DefaultErrnoRet: &expectedDefaultErrno, ++ Syscalls: []specs.LinuxSyscall{ ++ { ++ Names: []string{"clone"}, ++ Action: specs.ActAllow, ++ Args: []specs.LinuxSeccompArg{{ ++ Index: 0, ++ Value: 2114060288, ++ ValueTwo: 0, ++ Op: specs.OpMaskedEqual, ++ }}, ++ }, ++ { ++ ++ Names: []string{"open"}, ++ Action: specs.ActAllow, ++ Args: []specs.LinuxSeccompArg{}, ++ }, ++ { ++ Names: []string{"close"}, ++ Action: specs.ActAllow, ++ Args: []specs.LinuxSeccompArg{}, ++ }, ++ { ++ Names: []string{"syslog"}, ++ Action: specs.ActErrno, ++ ErrnoRet: &expectedErrno, ++ Args: []specs.LinuxSeccompArg{}, ++ }, ++ }, ++ } ++ ++ assert.DeepEqual(t, expected, *p) ++} ++ ++func TestLoadProfileWithDefaultErrnoRet(t *testing.T) { ++ var profile = []byte(`{ ++"defaultAction": "SCMP_ACT_ERRNO", ++"defaultErrnoRet": 6 ++}`) ++ rs := createSpec() ++ p, err := LoadProfile(string(profile), &rs) ++ if err != nil { ++ t.Fatal(err) ++ } ++ ++ expectedErrnoRet := uint(6) ++ expected := specs.LinuxSeccomp{ ++ DefaultAction: specs.ActErrno, ++ DefaultErrnoRet: &expectedErrnoRet, ++ } ++ ++ assert.DeepEqual(t, expected, *p) ++} ++ ++func TestLoadProfileWithListenerPath(t *testing.T) { ++ var profile = []byte(`{ ++"defaultAction": "SCMP_ACT_ERRNO", ++"listenerPath": "/var/run/seccompaget.sock", ++"listenerMetadata": "opaque-metadata" ++}`) ++ rs := createSpec() ++ p, err := LoadProfile(string(profile), &rs) ++ if err != nil { ++ t.Fatal(err) ++ } ++ ++ expected := specs.LinuxSeccomp{ ++ DefaultAction: specs.ActErrno, ++ ListenerPath: "/var/run/seccompaget.sock", ++ ListenerMetadata: "opaque-metadata", ++ } ++ ++ assert.DeepEqual(t, expected, *p) ++} ++ ++func TestLoadProfileWithFlag(t *testing.T) { ++ profile := `{"defaultAction": "SCMP_ACT_ERRNO", "flags": ["SECCOMP_FILTER_FLAG_SPEC_ALLOW", "SECCOMP_FILTER_FLAG_LOG"]}` ++ expected := specs.LinuxSeccomp{ ++ DefaultAction: specs.ActErrno, ++ Flags: []specs.LinuxSeccompFlag{"SECCOMP_FILTER_FLAG_SPEC_ALLOW", "SECCOMP_FILTER_FLAG_LOG"}, ++ } ++ rs := createSpec() ++ p, err := LoadProfile(profile, &rs) ++ assert.NilError(t, err) ++ assert.DeepEqual(t, expected, *p) ++} ++ ++// TestLoadProfileValidation tests that invalid profiles produce the correct error. ++func TestLoadProfileValidation(t *testing.T) { ++ tests := []struct { ++ doc string ++ profile string ++ expected string ++ }{ ++ { ++ doc: "conflicting architectures and archMap", ++ profile: `{"defaultAction": "SCMP_ACT_ERRNO", "architectures": ["A", "B", "C"], "archMap": [{"architecture": "A", "subArchitectures": ["B", "C"]}]}`, ++ expected: `use either 'architectures' or 'archMap'`, ++ }, ++ { ++ doc: "conflicting syscall.name and syscall.names", ++ profile: `{"defaultAction": "SCMP_ACT_ERRNO", "syscalls": [{"name": "accept", "names": ["accept"], "action": "SCMP_ACT_ALLOW"}]}`, ++ expected: `use either 'name' or 'names'`, ++ }, ++ } ++ for _, tc := range tests { ++ tc := tc ++ rs := createSpec() ++ t.Run(tc.doc, func(t *testing.T) { ++ _, err := LoadProfile(tc.profile, &rs) ++ assert.ErrorContains(t, err, tc.expected) ++ }) ++ } ++} ++ ++// TestLoadLegacyProfile tests loading a seccomp profile in the old format ++// (before https://github.com/docker/docker/pull/24510) ++func TestLoadLegacyProfile(t *testing.T) { ++ f, err := os.ReadFile("fixtures/default-old-format.json") ++ if err != nil { + t.Fatal(err) + } ++ rs := createSpec() ++ p, err := LoadProfile(string(f), &rs) ++ assert.NilError(t, err) ++ assert.Equal(t, p.DefaultAction, specs.ActErrno) ++ assert.DeepEqual(t, p.Architectures, []specs.Arch{"SCMP_ARCH_X86_64", "SCMP_ARCH_X86", "SCMP_ARCH_X32"}) ++ assert.Equal(t, len(p.Syscalls), 311) ++ expected := specs.LinuxSyscall{ ++ Names: []string{"accept"}, ++ Action: specs.ActAllow, ++ Args: []specs.LinuxSeccompArg{}, ++ } ++ assert.DeepEqual(t, p.Syscalls[0], expected) + } + + func TestLoadDefaultProfile(t *testing.T) { +- f, err := ioutil.ReadFile("default.json") ++ f, err := os.ReadFile("default.json") + if err != nil { + t.Fatal(err) + } +- rs := oci.DefaultSpec() ++ rs := createSpec() + if _, err := LoadProfile(string(f), &rs); err != nil { + t.Fatal(err) + } + } ++ ++func TestUnmarshalDefaultProfile(t *testing.T) { ++ expected := DefaultProfile() ++ if expected == nil { ++ t.Skip("seccomp not supported") ++ } ++ ++ f, err := os.ReadFile("default.json") ++ if err != nil { ++ t.Fatal(err) ++ } ++ var profile Seccomp ++ err = json.Unmarshal(f, &profile) ++ if err != nil { ++ t.Fatal(err) ++ } ++ assert.DeepEqual(t, expected.Architectures, profile.Architectures) ++ assert.DeepEqual(t, expected.ArchMap, profile.ArchMap) ++ assert.DeepEqual(t, expected.DefaultAction, profile.DefaultAction) ++ assert.DeepEqual(t, expected.Syscalls, profile.Syscalls) ++} ++ ++func TestMarshalUnmarshalFilter(t *testing.T) { ++ t.Parallel() ++ tests := []struct { ++ in string ++ out string ++ error bool ++ }{ ++ {in: `{"arches":["s390x"],"minKernel":3}`, error: true}, ++ {in: `{"arches":["s390x"],"minKernel":3.12}`, error: true}, ++ {in: `{"arches":["s390x"],"minKernel":true}`, error: true}, ++ {in: `{"arches":["s390x"],"minKernel":"0.0"}`, error: true}, ++ {in: `{"arches":["s390x"],"minKernel":"3"}`, error: true}, ++ {in: `{"arches":["s390x"],"minKernel":".3"}`, error: true}, ++ {in: `{"arches":["s390x"],"minKernel":"3."}`, error: true}, ++ {in: `{"arches":["s390x"],"minKernel":"true"}`, error: true}, ++ {in: `{"arches":["s390x"],"minKernel":"3.12.1\""}`, error: true}, ++ {in: `{"arches":["s390x"],"minKernel":"4.15abc"}`, error: true}, ++ {in: `{"arches":["s390x"],"minKernel":null}`, out: `{"arches":["s390x"]}`}, ++ {in: `{"arches":["s390x"],"minKernel":""}`, out: `{"arches":["s390x"],"minKernel":""}`}, // FIXME: try to fix omitempty for this ++ {in: `{"arches":["s390x"],"minKernel":"0.5"}`, out: `{"arches":["s390x"],"minKernel":"0.5"}`}, ++ {in: `{"arches":["s390x"],"minKernel":"0.50"}`, out: `{"arches":["s390x"],"minKernel":"0.50"}`}, ++ {in: `{"arches":["s390x"],"minKernel":"5.0"}`, out: `{"arches":["s390x"],"minKernel":"5.0"}`}, ++ {in: `{"arches":["s390x"],"minKernel":"50.0"}`, out: `{"arches":["s390x"],"minKernel":"50.0"}`}, ++ {in: `{"arches":["s390x"],"minKernel":"4.15"}`, out: `{"arches":["s390x"],"minKernel":"4.15"}`}, ++ } ++ for _, tc := range tests { ++ tc := tc ++ t.Run(tc.in, func(t *testing.T) { ++ var filter Filter ++ err := json.Unmarshal([]byte(tc.in), &filter) ++ if tc.error { ++ if err == nil { ++ t.Fatal("expected an error") ++ } else if !strings.Contains(err.Error(), "invalid kernel version") { ++ t.Fatal("unexpected error:", err) ++ } ++ return ++ } ++ if err != nil { ++ t.Fatal(err) ++ } ++ out, err := json.Marshal(filter) ++ if err != nil { ++ t.Fatal(err) ++ } ++ if string(out) != tc.out { ++ t.Fatalf("expected %s, got %s", tc.out, string(out)) ++ } ++ }) ++ } ++} ++ ++func TestLoadConditional(t *testing.T) { ++ f, err := os.ReadFile("fixtures/conditional_include.json") ++ if err != nil { ++ t.Fatal(err) ++ } ++ tests := []struct { ++ doc string ++ cap string ++ expected []string ++ }{ ++ {doc: "no caps", expected: []string{"chmod", "ptrace"}}, ++ {doc: "with syslog", cap: "CAP_SYSLOG", expected: []string{"chmod", "syslog", "ptrace"}}, ++ {doc: "no ptrace", cap: "CAP_SYS_ADMIN", expected: []string{"chmod"}}, ++ } ++ ++ for _, tc := range tests { ++ tc := tc ++ t.Run(tc.doc, func(t *testing.T) { ++ rs := createSpec(tc.cap) ++ p, err := LoadProfile(string(f), &rs) ++ if err != nil { ++ t.Fatal(err) ++ } ++ if len(p.Syscalls) != len(tc.expected) { ++ t.Fatalf("expected %d syscalls in profile, have %d", len(tc.expected), len(p.Syscalls)) ++ } ++ for i, v := range p.Syscalls { ++ if v.Names[0] != tc.expected[i] { ++ t.Fatalf("expected %s syscall, have %s", tc.expected[i], v.Names[0]) ++ } ++ } ++ }) ++ } ++} ++ ++// createSpec() creates a minimum spec for testing ++func createSpec(caps ...string) specs.Spec { ++ rs := specs.Spec{ ++ Process: &specs.Process{ ++ Capabilities: &specs.LinuxCapabilities{}, ++ }, ++ } ++ if caps != nil { ++ rs.Process.Capabilities.Bounding = append(rs.Process.Capabilities.Bounding, caps...) ++ } ++ return rs ++} +diff --git a/components/engine/profiles/seccomp/seccomp_unsupported.go b/components/engine/profiles/seccomp/seccomp_unsupported.go +index 67e06401..d337695e 100644 +--- a/components/engine/profiles/seccomp/seccomp_unsupported.go ++++ b/components/engine/profiles/seccomp/seccomp_unsupported.go +@@ -1,12 +1,9 @@ ++//go:build linux && !seccomp + // +build linux,!seccomp + + package seccomp // import "github.com/docker/docker/profiles/seccomp" + +-import ( +- "github.com/docker/docker/api/types" +-) +- + // DefaultProfile returns a nil pointer on unsupported systems. +-func DefaultProfile() *types.Seccomp { ++func DefaultProfile() *Seccomp { + return nil + } +diff --git a/components/engine/vendor/github.com/opencontainers/runtime-spec/specs-go/config.go b/components/engine/vendor/github.com/opencontainers/runtime-spec/specs-go/config.go +index 46049b3b..54e35fd3 100644 +--- a/components/engine/vendor/github.com/opencontainers/runtime-spec/specs-go/config.go ++++ b/components/engine/vendor/github.com/opencontainers/runtime-spec/specs-go/config.go +@@ -559,9 +559,10 @@ type VMImage struct { + + // LinuxSeccomp represents syscall restrictions + type LinuxSeccomp struct { +- DefaultAction LinuxSeccompAction `json:"defaultAction"` +- Architectures []Arch `json:"architectures,omitempty"` +- Syscalls []LinuxSyscall `json:"syscalls,omitempty"` ++ DefaultAction LinuxSeccompAction `json:"defaultAction"` ++ DefaultErrnoRet *uint `json:"defaultErrnoRet,omitempty"` ++ Architectures []Arch `json:"architectures,omitempty"` ++ Syscalls []LinuxSyscall `json:"syscalls,omitempty"` + } + + // Arch used for additional architectures +@@ -626,9 +627,10 @@ type LinuxSeccompArg struct { + + // LinuxSyscall is used to match a syscall in Seccomp + type LinuxSyscall struct { +- Names []string `json:"names"` +- Action LinuxSeccompAction `json:"action"` +- Args []LinuxSeccompArg `json:"args,omitempty"` ++ Names []string `json:"names"` ++ Action LinuxSeccompAction `json:"action"` ++ Args []LinuxSeccompArg `json:"args,omitempty"` ++ ErrnoRet *uint `json:"errnoRet,omitempty"` + } + + // LinuxIntelRdt has container runtime resource constraints +-- +2.27.0 + diff --git a/series.conf b/series.conf index 743320fd88a50140a6e12705fde323f9bde4ac15..d2ecd50cb0fcfb1e593e67dcac644c9f5a8879bd 100644 --- a/series.conf +++ b/series.conf @@ -190,4 +190,5 @@ patch/0189-docker-fix-Access-to-remapped-root-allows-privilege-.patch patch/0190-docker-fix-CVE-2021-21285.patch patch/0191-rollback-if-docker-restart-when-doing-BlkDiscard.patch patch/0192-docker-add-clone3-to-seccomp-whitelist-to-fix-curl-f.patch +patch/0193-docker-update-seccomp-to-fix-curl-failed.patch #end