| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123 |
- //go:build linux
- // +build linux
- package capabilities
- import (
- "sort"
- "strings"
- "github.com/opencontainers/runc/libcontainer/configs"
- "github.com/sirupsen/logrus"
- "github.com/syndtr/gocapability/capability"
- )
- const allCapabilityTypes = capability.CAPS | capability.BOUNDING | capability.AMBIENT
- var (
- capabilityMap map[string]capability.Cap
- capTypes = []capability.CapType{
- capability.BOUNDING,
- capability.PERMITTED,
- capability.INHERITABLE,
- capability.EFFECTIVE,
- capability.AMBIENT,
- }
- )
- func init() {
- capabilityMap = make(map[string]capability.Cap, capability.CAP_LAST_CAP+1)
- for _, c := range capability.List() {
- if c > capability.CAP_LAST_CAP {
- continue
- }
- capabilityMap["CAP_"+strings.ToUpper(c.String())] = c
- }
- }
- // KnownCapabilities returns the list of the known capabilities.
- // Used by `runc features`.
- func KnownCapabilities() []string {
- list := capability.List()
- res := make([]string, len(list))
- for i, c := range list {
- res[i] = "CAP_" + strings.ToUpper(c.String())
- }
- return res
- }
- // New creates a new Caps from the given Capabilities config. Unknown Capabilities
- // or Capabilities that are unavailable in the current environment are ignored,
- // printing a warning instead.
- func New(capConfig *configs.Capabilities) (*Caps, error) {
- var (
- err error
- c Caps
- )
- unknownCaps := make(map[string]struct{})
- c.caps = map[capability.CapType][]capability.Cap{
- capability.BOUNDING: capSlice(capConfig.Bounding, unknownCaps),
- capability.EFFECTIVE: capSlice(capConfig.Effective, unknownCaps),
- capability.INHERITABLE: capSlice(capConfig.Inheritable, unknownCaps),
- capability.PERMITTED: capSlice(capConfig.Permitted, unknownCaps),
- capability.AMBIENT: capSlice(capConfig.Ambient, unknownCaps),
- }
- if c.pid, err = capability.NewPid2(0); err != nil {
- return nil, err
- }
- if err = c.pid.Load(); err != nil {
- return nil, err
- }
- if len(unknownCaps) > 0 {
- logrus.Warn("ignoring unknown or unavailable capabilities: ", mapKeys(unknownCaps))
- }
- return &c, nil
- }
- // capSlice converts the slice of capability names in caps, to their numeric
- // equivalent, and returns them as a slice. Unknown or unavailable capabilities
- // are not returned, but appended to unknownCaps.
- func capSlice(caps []string, unknownCaps map[string]struct{}) []capability.Cap {
- var out []capability.Cap
- for _, c := range caps {
- if v, ok := capabilityMap[c]; !ok {
- unknownCaps[c] = struct{}{}
- } else {
- out = append(out, v)
- }
- }
- return out
- }
- // mapKeys returns the keys of input in sorted order
- func mapKeys(input map[string]struct{}) []string {
- var keys []string
- for c := range input {
- keys = append(keys, c)
- }
- sort.Strings(keys)
- return keys
- }
- // Caps holds the capabilities for a container.
- type Caps struct {
- pid capability.Capabilities
- caps map[capability.CapType][]capability.Cap
- }
- // ApplyBoundingSet sets the capability bounding set to those specified in the whitelist.
- func (c *Caps) ApplyBoundingSet() error {
- c.pid.Clear(capability.BOUNDING)
- c.pid.Set(capability.BOUNDING, c.caps[capability.BOUNDING]...)
- return c.pid.Apply(capability.BOUNDING)
- }
- // Apply sets all the capabilities for the current process in the config.
- func (c *Caps) ApplyCaps() error {
- c.pid.Clear(allCapabilityTypes)
- for _, g := range capTypes {
- c.pid.Set(g, c.caps[g]...)
- }
- return c.pid.Apply(allCapabilityTypes)
- }
|