| // +build linux |
| |
| package libcontainer |
| |
| import ( |
| "fmt" |
| "os" |
| "strings" |
| |
| "github.com/opencontainers/runc/libcontainer/configs" |
| "github.com/syndtr/gocapability/capability" |
| ) |
| |
| const allCapabilityTypes = capability.CAPS | capability.BOUNDS | capability.AMBS |
| |
| var capabilityMap map[string]capability.Cap |
| |
| func init() { |
| capabilityMap = make(map[string]capability.Cap) |
| last := capability.CAP_LAST_CAP |
| // workaround 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 |
| } |
| capKey := fmt.Sprintf("CAP_%s", strings.ToUpper(cap.String())) |
| capabilityMap[capKey] = cap |
| } |
| } |
| |
| func newContainerCapList(capConfig *configs.Capabilities) (*containerCapabilities, error) { |
| bounding := []capability.Cap{} |
| for _, c := range capConfig.Bounding { |
| v, ok := capabilityMap[c] |
| if !ok { |
| return nil, fmt.Errorf("unknown capability %q", c) |
| } |
| bounding = append(bounding, v) |
| } |
| effective := []capability.Cap{} |
| for _, c := range capConfig.Effective { |
| v, ok := capabilityMap[c] |
| if !ok { |
| return nil, fmt.Errorf("unknown capability %q", c) |
| } |
| effective = append(effective, v) |
| } |
| inheritable := []capability.Cap{} |
| for _, c := range capConfig.Inheritable { |
| v, ok := capabilityMap[c] |
| if !ok { |
| return nil, fmt.Errorf("unknown capability %q", c) |
| } |
| inheritable = append(inheritable, v) |
| } |
| permitted := []capability.Cap{} |
| for _, c := range capConfig.Permitted { |
| v, ok := capabilityMap[c] |
| if !ok { |
| return nil, fmt.Errorf("unknown capability %q", c) |
| } |
| permitted = append(permitted, v) |
| } |
| ambient := []capability.Cap{} |
| for _, c := range capConfig.Ambient { |
| v, ok := capabilityMap[c] |
| if !ok { |
| return nil, fmt.Errorf("unknown capability %q", c) |
| } |
| ambient = append(ambient, v) |
| } |
| pid, err := capability.NewPid(os.Getpid()) |
| if err != nil { |
| return nil, err |
| } |
| return &containerCapabilities{ |
| bounding: bounding, |
| effective: effective, |
| inheritable: inheritable, |
| permitted: permitted, |
| ambient: ambient, |
| pid: pid, |
| }, nil |
| } |
| |
| type containerCapabilities struct { |
| pid capability.Capabilities |
| bounding []capability.Cap |
| effective []capability.Cap |
| inheritable []capability.Cap |
| permitted []capability.Cap |
| ambient []capability.Cap |
| } |
| |
| // ApplyBoundingSet sets the capability bounding set to those specified in the whitelist. |
| func (c *containerCapabilities) ApplyBoundingSet() error { |
| c.pid.Clear(capability.BOUNDS) |
| c.pid.Set(capability.BOUNDS, c.bounding...) |
| return c.pid.Apply(capability.BOUNDS) |
| } |
| |
| // Apply sets all the capabilities for the current process in the config. |
| func (c *containerCapabilities) ApplyCaps() error { |
| c.pid.Clear(allCapabilityTypes) |
| c.pid.Set(capability.BOUNDS, c.bounding...) |
| c.pid.Set(capability.PERMITTED, c.permitted...) |
| c.pid.Set(capability.INHERITABLE, c.inheritable...) |
| c.pid.Set(capability.EFFECTIVE, c.effective...) |
| c.pid.Set(capability.AMBIENT, c.ambient...) |
| return c.pid.Apply(allCapabilityTypes) |
| } |