Skip to content

Commit f8fa8bf

Browse files
committed
seccomp: add support for flags
List of seccomp flags defined in runtime-spec: * SECCOMP_FILTER_FLAG_TSYNC * SECCOMP_FILTER_FLAG_LOG * SECCOMP_FILTER_FLAG_SPEC_ALLOW Signed-off-by: Alban Crequy <albancrequy@microsoft.com>
1 parent 2436322 commit f8fa8bf

File tree

4 files changed

+87
-5
lines changed

4 files changed

+87
-5
lines changed

libcontainer/configs/config.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@ type IDMap struct {
3333
type Seccomp struct {
3434
DefaultAction Action `json:"default_action"`
3535
Architectures []string `json:"architectures"`
36+
Flags []string `json:"flags"`
3637
Syscalls []*Syscall `json:"syscalls"`
3738
DefaultErrnoRet *uint `json:"default_errno_ret"`
3839
ListenerPath string `json:"listener_path,omitempty"`

libcontainer/seccomp/seccomp_linux.go

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -86,6 +86,29 @@ func InitSeccomp(config *configs.Seccomp) (int, error) {
8686
}
8787
}
8888

89+
// Add extra flags
90+
for _, flag := range config.Flags {
91+
switch flag {
92+
case "SECCOMP_FILTER_FLAG_TSYNC":
93+
// libseccomp-golang always use filterAttrTsync when
94+
// possible so all goroutines will receive the same
95+
// rules, so there is nothing to do. It does not make
96+
// sense to apply the seccomp filter on only one
97+
// thread; other threads will be terminated after exec
98+
// anyway.
99+
case "SECCOMP_FILTER_FLAG_LOG":
100+
if err := filter.SetLogBit(true); err != nil {
101+
return -1, fmt.Errorf("error adding log flag to seccomp filter: %w", err)
102+
}
103+
case "SECCOMP_FILTER_FLAG_SPEC_ALLOW":
104+
if err := filter.SetSSB(true); err != nil {
105+
return -1, fmt.Errorf("error adding SSB flag to seccomp filter: %w", err)
106+
}
107+
default:
108+
return -1, fmt.Errorf("seccomp flags %q not yet supported by runc", flag)
109+
}
110+
}
111+
89112
// Unset no new privs bit
90113
if err := filter.SetNoNewPrivsBit(false); err != nil {
91114
return -1, fmt.Errorf("error setting no new privileges: %w", err)

libcontainer/specconv/spec_linux.go

Lines changed: 11 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1016,14 +1016,20 @@ func SetupSeccomp(config *specs.LinuxSeccomp) (*configs.Seccomp, error) {
10161016
return nil, nil
10171017
}
10181018

1019-
// We don't currently support seccomp flags.
1020-
if len(config.Flags) != 0 {
1021-
return nil, errors.New("seccomp flags are not yet supported by runc")
1022-
}
1023-
10241019
newConfig := new(configs.Seccomp)
10251020
newConfig.Syscalls = []*configs.Syscall{}
10261021

1022+
// The list of flags defined in runtime-spec is a subset of the flags
1023+
// in the seccomp() syscall
1024+
for _, flag := range config.Flags {
1025+
switch flag {
1026+
case "SECCOMP_FILTER_FLAG_TSYNC", "SECCOMP_FILTER_FLAG_LOG", "SECCOMP_FILTER_FLAG_SPEC_ALLOW":
1027+
newConfig.Flags = append(newConfig.Flags, string(flag))
1028+
default:
1029+
return nil, fmt.Errorf("seccomp flags %q not yet supported by runc", flag)
1030+
}
1031+
}
1032+
10271033
if len(config.Architectures) > 0 {
10281034
newConfig.Architectures = []string{}
10291035
for _, arch := range config.Architectures {

tests/integration/seccomp.bats

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,58 @@ function teardown() {
6666
[[ "$output" == *"Network is down"* ]]
6767
}
6868

69+
@test "runc run [seccomp] (SECCOMP_FILTER_FLAG_LOG)" {
70+
requires_kernel 4.14 # SECCOMP_FILTER_FLAG_LOG appeared in Linux 4.14
71+
update_config ' .process.args = ["/bin/sh", "-c", "mkdir /dev/shm/foo"]
72+
| .process.noNewPrivileges = false
73+
| .linux.seccomp = {
74+
"defaultAction":"SCMP_ACT_ALLOW",
75+
"architectures":["SCMP_ARCH_X86","SCMP_ARCH_X32"],
76+
"flags":["SECCOMP_FILTER_FLAG_LOG"],
77+
"syscalls":[{"names":["mkdir"], "action":"SCMP_ACT_ERRNO"}]
78+
}'
79+
80+
# This test checks that the log flag is accepted but does not check the
81+
# audit log
82+
runc run test_busybox
83+
[ "$status" -ne 0 ]
84+
[[ "$output" == *"mkdir:"*"/dev/shm/foo"*"Operation not permitted"* ]]
85+
}
86+
87+
@test "runc run [seccomp] (SECCOMP_FILTER_FLAG_SPEC_ALLOW)" {
88+
requires_kernel 4.17 # SECCOMP_FILTER_FLAG_SPEC_ALLOW appeared in Linux 4.17
89+
update_config ' .process.args = ["/bin/sh", "-c", "mkdir /dev/shm/foo"]
90+
| .process.noNewPrivileges = false
91+
| .linux.seccomp = {
92+
"defaultAction":"SCMP_ACT_ALLOW",
93+
"architectures":["SCMP_ARCH_X86","SCMP_ARCH_X32"],
94+
"flags":["SECCOMP_FILTER_FLAG_SPEC_ALLOW"],
95+
"syscalls":[{"names":["mkdir"], "action":"SCMP_ACT_ERRNO"}]
96+
}'
97+
98+
# This test checks that the SSB flag is accepted but does not check the
99+
# result
100+
runc run test_busybox
101+
[ "$status" -ne 0 ]
102+
[[ "$output" == *"mkdir:"*"/dev/shm/foo"*"Operation not permitted"* ]]
103+
}
104+
105+
@test "runc run [seccomp] (SECCOMP_FILTER_FLAG_TSYNC)" {
106+
update_config ' .process.args = ["/bin/sh", "-c", "mkdir /dev/shm/foo"]
107+
| .process.noNewPrivileges = false
108+
| .linux.seccomp = {
109+
"defaultAction":"SCMP_ACT_ALLOW",
110+
"architectures":["SCMP_ARCH_X86","SCMP_ARCH_X32"],
111+
"flags":["SECCOMP_FILTER_FLAG_TSYNC"],
112+
"syscalls":[{"names":["mkdir"], "action":"SCMP_ACT_ERRNO"}]
113+
}'
114+
115+
# This test checks that the tsync flag is accepted
116+
runc run test_busybox
117+
[ "$status" -ne 0 ]
118+
[[ "$output" == *"mkdir:"*"/dev/shm/foo"*"Operation not permitted"* ]]
119+
}
120+
69121
@test "runc run [seccomp] (SCMP_ACT_KILL)" {
70122
update_config ' .process.args = ["/bin/sh", "-c", "mkdir /dev/shm/foo"]
71123
| .process.noNewPrivileges = false

0 commit comments

Comments
 (0)