1
0
Fork 0
mirror of https://github.com/moby/moby.git synced 2022-11-09 12:21:53 -05:00
moby--moby/profiles/seccomp/seccomp.go
Sebastiaan van Stijn 0ef7e727d2
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>
2021-07-17 15:57:54 +02:00

115 lines
4.3 KiB
Go

package seccomp // import "github.com/docker/docker/profiles/seccomp"
import (
"encoding/json"
"fmt"
"strconv"
"strings"
"github.com/opencontainers/runtime-spec/specs-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"`
}
// 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"`
}
// 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 "<kernel version>.<major revision>" (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"`
}
// 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"`
}
// 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")
}
// 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 ""
}
// MarshalJSON implements json.Unmarshaler for KernelVersion
func (k *KernelVersion) MarshalJSON() ([]byte, error) {
return json.Marshal(k.String())
}
// UnmarshalJSON implements json.Marshaler for KernelVersion
func (k *KernelVersion) UnmarshalJSON(version []byte) error {
var (
ver string
err error
)
// make sure we have a string
if err = json.Unmarshal(version, &ver); err != nil {
return fmt.Errorf(`invalid kernel version: %s, expected "<kernel>.<major>": %v`, string(version), err)
}
if ver == "" {
return nil
}
parts := strings.SplitN(ver, ".", 3)
if len(parts) != 2 {
return fmt.Errorf(`invalid kernel version: %s, expected "<kernel>.<major>"`, string(version))
}
if k.Kernel, err = strconv.ParseUint(parts[0], 10, 8); err != nil {
return fmt.Errorf(`invalid kernel version: %s, expected "<kernel>.<major>": %v`, string(version), err)
}
if k.Major, err = strconv.ParseUint(parts[1], 10, 8); err != nil {
return fmt.Errorf(`invalid kernel version: %s, expected "<kernel>.<major>": %v`, string(version), err)
}
if k.Kernel == 0 && k.Major == 0 {
return fmt.Errorf(`invalid kernel version: %s, expected "<kernel>.<major>": version cannot be 0.0`, string(version))
}
return nil
}