github.com/tompao/docker@v1.9.1/daemon/execdriver/utils.go (about)

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