123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126 |
- package caps // import "github.com/docker/docker/oci/caps"
- import (
- "fmt"
- "strings"
- "github.com/docker/docker/errdefs"
- )
- var (
- allCaps []string
- // knownCapabilities is a map of all known capabilities, using capability
- // name as index. Nil values indicate that the capability is known, but either
- // not supported by the Kernel, or not available in the current environment,
- // for example, when running Docker-in-Docker with restricted capabilities.
- //
- // Capabilities are one of the security systems in Linux Security Module (LSM)
- // framework provided by the kernel.
- // For more details on capabilities, see http://man7.org/linux/man-pages/man7/capabilities.7.html
- knownCaps map[string]*struct{}
- )
- // GetAllCapabilities returns all capabilities that are availeble in the current
- // environment.
- func GetAllCapabilities() []string {
- initCaps()
- return allCaps
- }
- // knownCapabilities returns a map of all known capabilities, using capability
- // name as index. Nil values indicate that the capability is known, but either
- // not supported by the Kernel, or not available in the current environment, for
- // example, when running Docker-in-Docker with restricted capabilities.
- func knownCapabilities() map[string]*struct{} {
- initCaps()
- return knownCaps
- }
- // inSlice tests whether a string is contained in a slice of strings or not.
- func inSlice(slice []string, s string) bool {
- for _, ss := range slice {
- if s == ss {
- return true
- }
- }
- return false
- }
- const allCapabilities = "ALL"
- // NormalizeLegacyCapabilities normalizes, and validates CapAdd/CapDrop capabilities
- // by upper-casing them, and adding a CAP_ prefix (if not yet present).
- //
- // This function also accepts the "ALL" magic-value, that's used by CapAdd/CapDrop.
- func NormalizeLegacyCapabilities(caps []string) ([]string, error) {
- var (
- normalized []string
- capabilityList = knownCapabilities()
- )
- for _, c := range caps {
- c = strings.ToUpper(c)
- if c == allCapabilities {
- normalized = append(normalized, c)
- continue
- }
- if !strings.HasPrefix(c, "CAP_") {
- c = "CAP_" + c
- }
- if v, ok := capabilityList[c]; !ok {
- return nil, errdefs.InvalidParameter(fmt.Errorf("unknown capability: %q", c))
- } else if v == nil {
- return nil, errdefs.InvalidParameter(fmt.Errorf("capability not supported by your kernel or not available in the current environment: %q", c))
- }
- normalized = append(normalized, c)
- }
- return normalized, nil
- }
- // TweakCapabilities tweaks capabilities by adding, dropping, or overriding
- // capabilities in the basics capabilities list.
- func TweakCapabilities(basics, adds, drops []string, privileged bool) ([]string, error) {
- switch {
- case privileged:
- // Privileged containers get all capabilities
- return GetAllCapabilities(), nil
- case len(adds) == 0 && len(drops) == 0:
- // Nothing to tweak; we're done
- return basics, nil
- }
- capDrop, err := NormalizeLegacyCapabilities(drops)
- if err != nil {
- return nil, err
- }
- capAdd, err := NormalizeLegacyCapabilities(adds)
- if err != nil {
- return nil, err
- }
- var caps []string
- switch {
- case inSlice(capAdd, allCapabilities):
- // Add all capabilities except ones on capDrop
- for _, c := range GetAllCapabilities() {
- if !inSlice(capDrop, c) {
- caps = append(caps, c)
- }
- }
- case inSlice(capDrop, allCapabilities):
- // "Drop" all capabilities; use what's in capAdd instead
- caps = capAdd
- default:
- // First drop some capabilities
- for _, c := range basics {
- if !inSlice(capDrop, c) {
- caps = append(caps, c)
- }
- }
- // Then add the list of capabilities from capAdd
- caps = append(caps, capAdd...)
- }
- return caps, nil
- }
|