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. type Seccomp struct { DefaultAction specs.LinuxSeccompAction `json:"defaultAction"` // Architectures is kept to maintain backward compatibility with the old // seccomp profile. Architectures []specs.Arch `json:"architectures,omitempty"` ArchMap []Architecture `json:"archMap,omitempty"` 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 "." (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 type Syscall struct { Name string `json:"name,omitempty"` Names []string `json:"names,omitempty"` Action specs.LinuxSeccompAction `json:"action"` Args []*specs.LinuxSeccompArg `json:"args"` Comment string `json:"comment"` Includes Filter `json:"includes"` Excludes Filter `json:"excludes"` } // 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 ".": %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 "."`, string(version)) } if k.Kernel, err = strconv.ParseUint(parts[0], 10, 8); err != nil { return fmt.Errorf(`invalid kernel version: %s, expected ".": %v`, string(version), err) } if k.Major, err = strconv.ParseUint(parts[1], 10, 8); err != nil { return fmt.Errorf(`invalid kernel version: %s, expected ".": %v`, string(version), err) } if k.Kernel == 0 && k.Major == 0 { return fmt.Errorf(`invalid kernel version: %s, expected ".": version cannot be 0.0`, string(version)) } return nil }