github.com/gdevillele/moby@v1.13.0/daemon/caps/utils_unix.go (about)

     1  // +build !windows
     2  
     3  package caps
     4  
     5  import (
     6  	"fmt"
     7  	"strings"
     8  
     9  	"github.com/docker/docker/pkg/stringutils"
    10  	"github.com/syndtr/gocapability/capability"
    11  )
    12  
    13  var capabilityList Capabilities
    14  
    15  func init() {
    16  	last := capability.CAP_LAST_CAP
    17  	// hack for RHEL6 which has no /proc/sys/kernel/cap_last_cap
    18  	if last == capability.Cap(63) {
    19  		last = capability.CAP_BLOCK_SUSPEND
    20  	}
    21  	for _, cap := range capability.List() {
    22  		if cap > last {
    23  			continue
    24  		}
    25  		capabilityList = append(capabilityList,
    26  			&CapabilityMapping{
    27  				Key:   "CAP_" + strings.ToUpper(cap.String()),
    28  				Value: cap,
    29  			},
    30  		)
    31  	}
    32  }
    33  
    34  type (
    35  	// CapabilityMapping maps linux capability name to its value of capability.Cap type
    36  	// Capabilities is one of the security systems in Linux Security Module (LSM)
    37  	// framework provided by the kernel.
    38  	// For more details on capabilities, see http://man7.org/linux/man-pages/man7/capabilities.7.html
    39  	CapabilityMapping struct {
    40  		Key   string         `json:"key,omitempty"`
    41  		Value capability.Cap `json:"value,omitempty"`
    42  	}
    43  	// Capabilities contains all CapabilityMapping
    44  	Capabilities []*CapabilityMapping
    45  )
    46  
    47  // String returns <key> of CapabilityMapping
    48  func (c *CapabilityMapping) String() string {
    49  	return c.Key
    50  }
    51  
    52  // GetCapability returns CapabilityMapping which contains specific key
    53  func GetCapability(key string) *CapabilityMapping {
    54  	for _, capp := range capabilityList {
    55  		if capp.Key == key {
    56  			cpy := *capp
    57  			return &cpy
    58  		}
    59  	}
    60  	return nil
    61  }
    62  
    63  // GetAllCapabilities returns all of the capabilities
    64  func GetAllCapabilities() []string {
    65  	output := make([]string, len(capabilityList))
    66  	for i, capability := range capabilityList {
    67  		output[i] = capability.String()
    68  	}
    69  	return output
    70  }
    71  
    72  // TweakCapabilities can tweak capabilities by adding or dropping capabilities
    73  // based on the basics capabilities.
    74  func TweakCapabilities(basics, adds, drops []string) ([]string, error) {
    75  	var (
    76  		newCaps []string
    77  		allCaps = GetAllCapabilities()
    78  	)
    79  
    80  	// FIXME(tonistiigi): docker format is without CAP_ prefix, oci is with prefix
    81  	// Currently they are mixed in here. We should do conversion in one place.
    82  
    83  	// look for invalid cap in the drop list
    84  	for _, cap := range drops {
    85  		if strings.ToLower(cap) == "all" {
    86  			continue
    87  		}
    88  
    89  		if !stringutils.InSlice(allCaps, "CAP_"+cap) {
    90  			return nil, fmt.Errorf("Unknown capability drop: %q", cap)
    91  		}
    92  	}
    93  
    94  	// handle --cap-add=all
    95  	if stringutils.InSlice(adds, "all") {
    96  		basics = allCaps
    97  	}
    98  
    99  	if !stringutils.InSlice(drops, "all") {
   100  		for _, cap := range basics {
   101  			// skip `all` already handled above
   102  			if strings.ToLower(cap) == "all" {
   103  				continue
   104  			}
   105  
   106  			// if we don't drop `all`, add back all the non-dropped caps
   107  			if !stringutils.InSlice(drops, cap[4:]) {
   108  				newCaps = append(newCaps, strings.ToUpper(cap))
   109  			}
   110  		}
   111  	}
   112  
   113  	for _, cap := range adds {
   114  		// skip `all` already handled above
   115  		if strings.ToLower(cap) == "all" {
   116  			continue
   117  		}
   118  
   119  		cap = "CAP_" + cap
   120  
   121  		if !stringutils.InSlice(allCaps, cap) {
   122  			return nil, fmt.Errorf("Unknown capability to add: %q", cap)
   123  		}
   124  
   125  		// add cap if not already in the list
   126  		if !stringutils.InSlice(newCaps, cap) {
   127  			newCaps = append(newCaps, strings.ToUpper(cap))
   128  		}
   129  	}
   130  	return newCaps, nil
   131  }