mirror of
https://github.com/opencontainers/runc.git
synced 2026-07-11 06:03:57 +08:00
4e179bddca
Since Linux 4.3 ambient capabilities are available. If set these allow unprivileged child processes to inherit capabilities, while at present there is no means to set capabilities on non root processes, other than via filesystem capabilities which are not usually supported in image formats. With ambient capabilities non root processes can be given capabilities as well, and so the main reason to use root in containers goes away, and capabilities work as expected. The code falls back to the existing behaviour if ambient capabilities are not supported. Signed-off-by: Justin Cormack <justin.cormack@docker.com>
70 lines
1.6 KiB
Go
70 lines
1.6 KiB
Go
// +build linux
|
|
|
|
package libcontainer
|
|
|
|
import (
|
|
"fmt"
|
|
"os"
|
|
"strings"
|
|
|
|
"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 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)
|
|
}
|