...

Source file src/github.com/opencontainers/runc/libcontainer/capabilities/capabilities.go

Documentation: github.com/opencontainers/runc/libcontainer/capabilities

     1  //go:build linux
     2  // +build linux
     3  
     4  package capabilities
     5  
     6  import (
     7  	"sort"
     8  	"strings"
     9  
    10  	"github.com/opencontainers/runc/libcontainer/configs"
    11  	"github.com/sirupsen/logrus"
    12  	"github.com/syndtr/gocapability/capability"
    13  )
    14  
    15  const allCapabilityTypes = capability.CAPS | capability.BOUNDING | capability.AMBIENT
    16  
    17  var (
    18  	capabilityMap map[string]capability.Cap
    19  	capTypes      = []capability.CapType{
    20  		capability.BOUNDING,
    21  		capability.PERMITTED,
    22  		capability.INHERITABLE,
    23  		capability.EFFECTIVE,
    24  		capability.AMBIENT,
    25  	}
    26  )
    27  
    28  func init() {
    29  	capabilityMap = make(map[string]capability.Cap, capability.CAP_LAST_CAP+1)
    30  	for _, c := range capability.List() {
    31  		if c > capability.CAP_LAST_CAP {
    32  			continue
    33  		}
    34  		capabilityMap["CAP_"+strings.ToUpper(c.String())] = c
    35  	}
    36  }
    37  
    38  // KnownCapabilities returns the list of the known capabilities.
    39  // Used by `runc features`.
    40  func KnownCapabilities() []string {
    41  	list := capability.List()
    42  	res := make([]string, len(list))
    43  	for i, c := range list {
    44  		res[i] = "CAP_" + strings.ToUpper(c.String())
    45  	}
    46  	return res
    47  }
    48  
    49  // New creates a new Caps from the given Capabilities config. Unknown Capabilities
    50  // or Capabilities that are unavailable in the current environment are ignored,
    51  // printing a warning instead.
    52  func New(capConfig *configs.Capabilities) (*Caps, error) {
    53  	var (
    54  		err error
    55  		c   Caps
    56  	)
    57  
    58  	unknownCaps := make(map[string]struct{})
    59  	c.caps = map[capability.CapType][]capability.Cap{
    60  		capability.BOUNDING:    capSlice(capConfig.Bounding, unknownCaps),
    61  		capability.EFFECTIVE:   capSlice(capConfig.Effective, unknownCaps),
    62  		capability.INHERITABLE: capSlice(capConfig.Inheritable, unknownCaps),
    63  		capability.PERMITTED:   capSlice(capConfig.Permitted, unknownCaps),
    64  		capability.AMBIENT:     capSlice(capConfig.Ambient, unknownCaps),
    65  	}
    66  	if c.pid, err = capability.NewPid2(0); err != nil {
    67  		return nil, err
    68  	}
    69  	if err = c.pid.Load(); err != nil {
    70  		return nil, err
    71  	}
    72  	if len(unknownCaps) > 0 {
    73  		logrus.Warn("ignoring unknown or unavailable capabilities: ", mapKeys(unknownCaps))
    74  	}
    75  	return &c, nil
    76  }
    77  
    78  // capSlice converts the slice of capability names in caps, to their numeric
    79  // equivalent, and returns them as a slice. Unknown or unavailable capabilities
    80  // are not returned, but appended to unknownCaps.
    81  func capSlice(caps []string, unknownCaps map[string]struct{}) []capability.Cap {
    82  	var out []capability.Cap
    83  	for _, c := range caps {
    84  		if v, ok := capabilityMap[c]; !ok {
    85  			unknownCaps[c] = struct{}{}
    86  		} else {
    87  			out = append(out, v)
    88  		}
    89  	}
    90  	return out
    91  }
    92  
    93  // mapKeys returns the keys of input in sorted order
    94  func mapKeys(input map[string]struct{}) []string {
    95  	var keys []string
    96  	for c := range input {
    97  		keys = append(keys, c)
    98  	}
    99  	sort.Strings(keys)
   100  	return keys
   101  }
   102  
   103  // Caps holds the capabilities for a container.
   104  type Caps struct {
   105  	pid  capability.Capabilities
   106  	caps map[capability.CapType][]capability.Cap
   107  }
   108  
   109  // ApplyBoundingSet sets the capability bounding set to those specified in the whitelist.
   110  func (c *Caps) ApplyBoundingSet() error {
   111  	c.pid.Clear(capability.BOUNDING)
   112  	c.pid.Set(capability.BOUNDING, c.caps[capability.BOUNDING]...)
   113  	return c.pid.Apply(capability.BOUNDING)
   114  }
   115  
   116  // Apply sets all the capabilities for the current process in the config.
   117  func (c *Caps) ApplyCaps() error {
   118  	c.pid.Clear(allCapabilityTypes)
   119  	for _, g := range capTypes {
   120  		c.pid.Set(g, c.caps[g]...)
   121  	}
   122  	return c.pid.Apply(allCapabilityTypes)
   123  }
   124  

View as plain text