// +build linux package libcontainer import ( "fmt" "os" "strings" "github.com/syndtr/gocapability/capability" ) const allCapabilityTypes = capability.CAPS | capability.BOUNDS 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 newCapWhitelist(caps []string) (*whitelist, error) { l := []capability.Cap{} for _, c := range caps { v, ok := capabilityMap[c] if !ok { return nil, fmt.Errorf("unknown capability %q", c) } l = append(l, v) } pid, err := capability.NewPid(os.Getpid()) if err != nil { return nil, err } return &whitelist{ keep: l, pid: pid, }, nil } type whitelist struct { pid capability.Capabilities keep []capability.Cap } // dropBoundingSet drops the capability bounding set to those specified in the whitelist. func (w *whitelist) dropBoundingSet() error { w.pid.Clear(capability.BOUNDS) w.pid.Set(capability.BOUNDS, w.keep...) return w.pid.Apply(capability.BOUNDS) } // drop drops all capabilities for the current process except those specified in the whitelist. func (w *whitelist) drop() error { w.pid.Clear(allCapabilityTypes) w.pid.Set(allCapabilityTypes, w.keep...) return w.pid.Apply(allCapabilityTypes) }