diff --git a/util/entitlements/security/security_linux.go b/util/entitlements/security/security_linux.go index 0f285fb2edd1a..2944b756e9c2f 100644 --- a/util/entitlements/security/security_linux.go +++ b/util/entitlements/security/security_linux.go @@ -4,9 +4,11 @@ import ( "context" "fmt" "os" + "sort" "github.com/containerd/containerd/containers" "github.com/containerd/containerd/oci" + "github.com/containerd/containerd/pkg/cap" "github.com/containerd/containerd/pkg/userns" specs "github.com/opencontainers/runtime-spec/specs-go" "github.com/pkg/errors" @@ -17,46 +19,11 @@ import ( // WithInsecureSpec sets spec with All capability. func WithInsecureSpec() oci.SpecOpts { return func(_ context.Context, _ oci.Client, _ *containers.Container, s *specs.Spec) error { - addCaps := []string{ - "CAP_FSETID", - "CAP_KILL", - "CAP_FOWNER", - "CAP_MKNOD", - "CAP_CHOWN", - "CAP_DAC_OVERRIDE", - "CAP_NET_RAW", - "CAP_SETGID", - "CAP_SETUID", - "CAP_SETPCAP", - "CAP_SETFCAP", - "CAP_NET_BIND_SERVICE", - "CAP_SYS_CHROOT", - "CAP_AUDIT_WRITE", - "CAP_MAC_ADMIN", - "CAP_MAC_OVERRIDE", - "CAP_DAC_READ_SEARCH", - "CAP_SYS_PTRACE", - "CAP_SYS_MODULE", - "CAP_SYSLOG", - "CAP_SYS_RAWIO", - "CAP_SYS_ADMIN", - "CAP_LINUX_IMMUTABLE", - "CAP_SYS_BOOT", - "CAP_SYS_NICE", - "CAP_SYS_PACCT", - "CAP_SYS_TTY_CONFIG", - "CAP_SYS_TIME", - "CAP_WAKE_ALARM", - "CAP_AUDIT_READ", - "CAP_AUDIT_CONTROL", - "CAP_SYS_RESOURCE", - "CAP_BLOCK_SUSPEND", - "CAP_IPC_LOCK", - "CAP_IPC_OWNER", - "CAP_LEASE", - "CAP_NET_ADMIN", - "CAP_NET_BROADCAST", + addCaps, err := getAllCaps() + if err != nil { + return err } + s.Process.Capabilities.Bounding = append(s.Process.Capabilities.Bounding, addCaps...) s.Process.Capabilities.Ambient = append(s.Process.Capabilities.Ambient, addCaps...) s.Process.Capabilities.Effective = append(s.Process.Capabilities.Effective, addCaps...) @@ -160,3 +127,68 @@ func getFreeLoopID() (int, error) { } return 0, errors.Errorf("error getting free loop device: %v", uerr) } + +func getAllCaps() ([]string, error) { + // allCaps provides a list of capabilities to be granted, some of the capabilities might not be available + // if that's the case, capabilities are skipped and warning is printed + allCaps := []string{ + "CAP_FSETID", + "CAP_KILL", + "CAP_FOWNER", + "CAP_MKNOD", + "CAP_CHOWN", + "CAP_DAC_OVERRIDE", + "CAP_NET_RAW", + "CAP_SETGID", + "CAP_SETUID", + "CAP_SETPCAP", + "CAP_SETFCAP", + "CAP_NET_BIND_SERVICE", + "CAP_SYS_CHROOT", + "CAP_AUDIT_WRITE", + "CAP_MAC_ADMIN", + "CAP_MAC_OVERRIDE", + "CAP_DAC_READ_SEARCH", + "CAP_SYS_PTRACE", + "CAP_SYS_MODULE", + "CAP_SYSLOG", + "CAP_SYS_RAWIO", + "CAP_SYS_ADMIN", + "CAP_LINUX_IMMUTABLE", + "CAP_SYS_BOOT", + "CAP_SYS_NICE", + "CAP_SYS_PACCT", + "CAP_SYS_TTY_CONFIG", + "CAP_SYS_TIME", + "CAP_WAKE_ALARM", + "CAP_AUDIT_READ", + "CAP_AUDIT_CONTROL", + "CAP_SYS_RESOURCE", + "CAP_BLOCK_SUSPEND", + "CAP_IPC_LOCK", + "CAP_IPC_OWNER", + "CAP_LEASE", + "CAP_NET_ADMIN", + "CAP_NET_BROADCAST", + } + + availableCaps, err := cap.Current() + if err != nil { + return nil, fmt.Errorf("error getting available capabilities: %s", err) + } + + // sort availableCaps to perform binary search on them + sort.Strings(availableCaps) + + addCaps := make([]string, 0, len(allCaps)) + + for _, cap := range allCaps { + if idx := sort.SearchStrings(availableCaps, cap); idx < len(availableCaps) && availableCaps[idx] == cap { + addCaps = append(addCaps, cap) + } else { + logrus.Warnf("capability %s can't be granted in insecure mode", cap) + } + } + + return addCaps, nil +}