seccomp: Seccomp: embed oci-spec LinuxSeccomp, add support for seccomp flags
This patch, similar to d92739713c
, embeds the
`LinuxSeccomp` type of the runtime-spec, so that we can support all options
provided by the spec, and decorates it with our own fields.
With this, profiles can make use of the recently added "Flags" field, to
specify flags that must be passed to seccomp(2) when installing the filter.
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
This commit is contained in:
parent
bfd4b64600
commit
0ef7e727d2
|
@ -740,8 +740,10 @@ func DefaultProfile() *Seccomp {
|
|||
}
|
||||
|
||||
return &Seccomp{
|
||||
DefaultAction: specs.ActErrno,
|
||||
ArchMap: arches(),
|
||||
Syscalls: syscalls,
|
||||
LinuxSeccomp: specs.LinuxSeccomp{
|
||||
DefaultAction: specs.ActErrno,
|
||||
},
|
||||
ArchMap: arches(),
|
||||
Syscalls: syscalls,
|
||||
}
|
||||
}
|
||||
|
|
|
@ -10,15 +10,12 @@ import (
|
|||
)
|
||||
|
||||
// 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 {
|
||||
DefaultAction specs.LinuxSeccompAction `json:"defaultAction"`
|
||||
DefaultErrnoRet *uint `json:"defaultErrnoRet,omitempty"`
|
||||
ListenerPath string `json:"listenerPath,omitempty"`
|
||||
ListenerMetadata string `json:"listenerMetadata,omitempty"`
|
||||
|
||||
// Architectures is kept to maintain backward compatibility with the old
|
||||
// seccomp profile.
|
||||
Architectures []specs.Arch `json:"architectures,omitempty"`
|
||||
specs.LinuxSeccomp
|
||||
|
||||
// ArchMap contains a list of Architectures and Sub-architectures for the
|
||||
// profile. When generating the profile, this list is expanded to a
|
||||
|
|
|
@ -82,18 +82,22 @@ func setupSeccomp(config *Seccomp, rs *specs.Spec) (*specs.LinuxSeccomp, error)
|
|||
return nil, nil
|
||||
}
|
||||
|
||||
newConfig := &specs.LinuxSeccomp{}
|
||||
|
||||
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 config.Architectures == 0 then libseccomp will figure out the architecture to use
|
||||
if len(config.Architectures) != 0 {
|
||||
newConfig.Architectures = config.Architectures
|
||||
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")
|
||||
}
|
||||
|
||||
arch := goToNative[runtime.GOARCH]
|
||||
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 {
|
||||
|
@ -104,11 +108,6 @@ func setupSeccomp(config *Seccomp, rs *specs.Spec) (*specs.LinuxSeccomp, error)
|
|||
}
|
||||
}
|
||||
|
||||
newConfig.DefaultAction = config.DefaultAction
|
||||
newConfig.DefaultErrnoRet = config.DefaultErrnoRet
|
||||
newConfig.ListenerPath = config.ListenerPath
|
||||
newConfig.ListenerMetadata = config.ListenerMetadata
|
||||
|
||||
Loop:
|
||||
// Convert Syscall to OCI runtimes-spec specs.LinuxSyscall after filtering them.
|
||||
for _, call := range config.Syscalls {
|
||||
|
|
|
@ -100,6 +100,18 @@ func TestLoadProfileWithListenerPath(t *testing.T) {
|
|||
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 {
|
||||
|
|
Loading…
Reference in New Issue