mirror of
				https://github.com/moby/moby.git
				synced 2022-11-09 12:21:53 -05:00 
			
		
		
		
	
		
			
				
	
	
		
			139 lines
		
	
	
	
		
			3.3 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
			
		
		
	
	
			139 lines
		
	
	
	
		
			3.3 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
package caps // import "github.com/docker/docker/daemon/caps"
 | 
						|
 | 
						|
import (
 | 
						|
	"fmt"
 | 
						|
	"strings"
 | 
						|
 | 
						|
	"github.com/syndtr/gocapability/capability"
 | 
						|
)
 | 
						|
 | 
						|
var capabilityList Capabilities
 | 
						|
 | 
						|
func init() {
 | 
						|
	last := capability.CAP_LAST_CAP
 | 
						|
	// hack for RHEL6 which has no /proc/sys/kernel/cap_last_cap
 | 
						|
	if last == capability.Cap(63) {
 | 
						|
		last = capability.CAP_BLOCK_SUSPEND
 | 
						|
	}
 | 
						|
	for _, cap := range capability.List() {
 | 
						|
		if cap > last {
 | 
						|
			continue
 | 
						|
		}
 | 
						|
		capabilityList = append(capabilityList,
 | 
						|
			&CapabilityMapping{
 | 
						|
				Key:   "CAP_" + strings.ToUpper(cap.String()),
 | 
						|
				Value: cap,
 | 
						|
			},
 | 
						|
		)
 | 
						|
	}
 | 
						|
}
 | 
						|
 | 
						|
type (
 | 
						|
	// CapabilityMapping maps linux capability name to its value of capability.Cap type
 | 
						|
	// Capabilities is 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
 | 
						|
	CapabilityMapping struct {
 | 
						|
		Key   string         `json:"key,omitempty"`
 | 
						|
		Value capability.Cap `json:"value,omitempty"`
 | 
						|
	}
 | 
						|
	// Capabilities contains all CapabilityMapping
 | 
						|
	Capabilities []*CapabilityMapping
 | 
						|
)
 | 
						|
 | 
						|
// String returns <key> of CapabilityMapping
 | 
						|
func (c *CapabilityMapping) String() string {
 | 
						|
	return c.Key
 | 
						|
}
 | 
						|
 | 
						|
// GetCapability returns CapabilityMapping which contains specific key
 | 
						|
func GetCapability(key string) *CapabilityMapping {
 | 
						|
	for _, capp := range capabilityList {
 | 
						|
		if capp.Key == key {
 | 
						|
			cpy := *capp
 | 
						|
			return &cpy
 | 
						|
		}
 | 
						|
	}
 | 
						|
	return nil
 | 
						|
}
 | 
						|
 | 
						|
// GetAllCapabilities returns all of the capabilities
 | 
						|
func GetAllCapabilities() []string {
 | 
						|
	output := make([]string, len(capabilityList))
 | 
						|
	for i, capability := range capabilityList {
 | 
						|
		output[i] = capability.String()
 | 
						|
	}
 | 
						|
	return output
 | 
						|
}
 | 
						|
 | 
						|
// inSlice tests whether a string is contained in a slice of strings or not.
 | 
						|
// Comparison is case insensitive
 | 
						|
func inSlice(slice []string, s string) bool {
 | 
						|
	for _, ss := range slice {
 | 
						|
		if strings.ToLower(s) == strings.ToLower(ss) {
 | 
						|
			return true
 | 
						|
		}
 | 
						|
	}
 | 
						|
	return false
 | 
						|
}
 | 
						|
 | 
						|
// TweakCapabilities can tweak capabilities by adding or dropping capabilities
 | 
						|
// based on the basics capabilities.
 | 
						|
func TweakCapabilities(basics, adds, drops []string) ([]string, error) {
 | 
						|
	var (
 | 
						|
		newCaps []string
 | 
						|
		allCaps = GetAllCapabilities()
 | 
						|
	)
 | 
						|
 | 
						|
	// FIXME(tonistiigi): docker format is without CAP_ prefix, oci is with prefix
 | 
						|
	// Currently they are mixed in here. We should do conversion in one place.
 | 
						|
 | 
						|
	// look for invalid cap in the drop list
 | 
						|
	for _, cap := range drops {
 | 
						|
		if strings.ToLower(cap) == "all" {
 | 
						|
			continue
 | 
						|
		}
 | 
						|
 | 
						|
		if !inSlice(allCaps, "CAP_"+cap) {
 | 
						|
			return nil, fmt.Errorf("Unknown capability drop: %q", cap)
 | 
						|
		}
 | 
						|
	}
 | 
						|
 | 
						|
	// handle --cap-add=all
 | 
						|
	if inSlice(adds, "all") {
 | 
						|
		basics = allCaps
 | 
						|
	}
 | 
						|
 | 
						|
	if !inSlice(drops, "all") {
 | 
						|
		for _, cap := range basics {
 | 
						|
			// skip `all` already handled above
 | 
						|
			if strings.ToLower(cap) == "all" {
 | 
						|
				continue
 | 
						|
			}
 | 
						|
 | 
						|
			// if we don't drop `all`, add back all the non-dropped caps
 | 
						|
			if !inSlice(drops, cap[4:]) {
 | 
						|
				newCaps = append(newCaps, strings.ToUpper(cap))
 | 
						|
			}
 | 
						|
		}
 | 
						|
	}
 | 
						|
 | 
						|
	for _, cap := range adds {
 | 
						|
		// skip `all` already handled above
 | 
						|
		if strings.ToLower(cap) == "all" {
 | 
						|
			continue
 | 
						|
		}
 | 
						|
 | 
						|
		cap = "CAP_" + cap
 | 
						|
 | 
						|
		if !inSlice(allCaps, cap) {
 | 
						|
			return nil, fmt.Errorf("Unknown capability to add: %q", cap)
 | 
						|
		}
 | 
						|
 | 
						|
		// add cap if not already in the list
 | 
						|
		if !inSlice(newCaps, cap) {
 | 
						|
			newCaps = append(newCaps, strings.ToUpper(cap))
 | 
						|
		}
 | 
						|
	}
 | 
						|
	return newCaps, nil
 | 
						|
}
 |