Merge pull request #38380 from olljanat/capabilities-support
Add support for exact list of capabilities + capAdd / capDrop refactor
This commit is contained in:
commit
5801c04345
12 changed files with 281 additions and 84 deletions
|
@ -473,6 +473,11 @@ func (s *containerRouter) postContainersCreate(ctx context.Context, w http.Respo
|
|||
hostConfig.KernelMemoryTCP = 0
|
||||
}
|
||||
|
||||
// Ignore Capabilities because it was added in API 1.40.
|
||||
if hostConfig != nil && versions.LessThan(version, "1.40") {
|
||||
hostConfig.Capabilities = nil
|
||||
}
|
||||
|
||||
ccr, err := s.backend.ContainerCreate(types.ContainerCreateConfig{
|
||||
Name: name,
|
||||
Config: config,
|
||||
|
|
|
@ -645,14 +645,22 @@ definitions:
|
|||
$ref: "#/definitions/Mount"
|
||||
|
||||
# Applicable to UNIX platforms
|
||||
Capabilities:
|
||||
type: "array"
|
||||
description: |
|
||||
A list of kernel capabilities to be available for container (this overrides the default set).
|
||||
|
||||
Conflicts with options 'CapAdd' and 'CapDrop'"
|
||||
items:
|
||||
type: "string"
|
||||
CapAdd:
|
||||
type: "array"
|
||||
description: "A list of kernel capabilities to add to the container."
|
||||
description: "A list of kernel capabilities to add to the container. Conflicts with option 'Capabilities'"
|
||||
items:
|
||||
type: "string"
|
||||
CapDrop:
|
||||
type: "array"
|
||||
description: "A list of kernel capabilities to drop from the container."
|
||||
description: "A list of kernel capabilities to drop from the container. Conflicts with option 'Capabilities'"
|
||||
items:
|
||||
type: "string"
|
||||
Dns:
|
||||
|
|
|
@ -370,9 +370,10 @@ type HostConfig struct {
|
|||
// Applicable to UNIX platforms
|
||||
CapAdd strslice.StrSlice // List of kernel capabilities to add to the container
|
||||
CapDrop strslice.StrSlice // List of kernel capabilities to remove from the container
|
||||
DNS []string `json:"Dns"` // List of DNS server to lookup
|
||||
DNSOptions []string `json:"DnsOptions"` // List of DNSOption to look for
|
||||
DNSSearch []string `json:"DnsSearch"` // List of DNSSearch to look for
|
||||
Capabilities []string `json:"Capabilities"` // List of kernel capabilities to be available for container (this overrides the default set)
|
||||
DNS []string `json:"Dns"` // List of DNS server to lookup
|
||||
DNSOptions []string `json:"DnsOptions"` // List of DNSOption to look for
|
||||
DNSSearch []string `json:"DnsSearch"` // List of DNSSearch to look for
|
||||
ExtraHosts []string // List of extra hosts
|
||||
GroupAdd []string // List of additional groups that the container process will run as
|
||||
IpcMode IpcMode // IPC namespace to use for the container
|
||||
|
|
|
@ -15,6 +15,7 @@ import (
|
|||
"github.com/docker/docker/daemon/network"
|
||||
"github.com/docker/docker/errdefs"
|
||||
"github.com/docker/docker/image"
|
||||
"github.com/docker/docker/oci/caps"
|
||||
"github.com/docker/docker/opts"
|
||||
"github.com/docker/docker/pkg/signal"
|
||||
"github.com/docker/docker/pkg/system"
|
||||
|
@ -295,12 +296,35 @@ func validateHostConfig(hostConfig *containertypes.HostConfig, platform string)
|
|||
if err := validateRestartPolicy(hostConfig.RestartPolicy); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := validateCapabilities(hostConfig); err != nil {
|
||||
return err
|
||||
}
|
||||
if !hostConfig.Isolation.IsValid() {
|
||||
return errors.Errorf("invalid isolation '%s' on %s", hostConfig.Isolation, runtime.GOOS)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func validateCapabilities(hostConfig *containertypes.HostConfig) error {
|
||||
if len(hostConfig.CapAdd) > 0 && hostConfig.Capabilities != nil {
|
||||
return errdefs.InvalidParameter(errors.Errorf("conflicting options: Capabilities and CapAdd"))
|
||||
}
|
||||
if len(hostConfig.CapDrop) > 0 && hostConfig.Capabilities != nil {
|
||||
return errdefs.InvalidParameter(errors.Errorf("conflicting options: Capabilities and CapDrop"))
|
||||
}
|
||||
if _, err := caps.NormalizeLegacyCapabilities(hostConfig.CapAdd); err != nil {
|
||||
return errors.Wrap(err, "invalid CapAdd")
|
||||
}
|
||||
if _, err := caps.NormalizeLegacyCapabilities(hostConfig.CapDrop); err != nil {
|
||||
return errors.Wrap(err, "invalid CapDrop")
|
||||
}
|
||||
if err := caps.ValidateCapabilities(hostConfig.Capabilities); err != nil {
|
||||
return errors.Wrap(err, "invalid Capabilities")
|
||||
}
|
||||
// TODO consider returning warnings if "Privileged" is combined with Capabilities, CapAdd and/or CapDrop
|
||||
return nil
|
||||
}
|
||||
|
||||
// validateHealthCheck validates the healthcheck params of Config
|
||||
func validateHealthCheck(healthConfig *containertypes.HealthConfig) error {
|
||||
if healthConfig == nil {
|
||||
|
|
|
@ -14,6 +14,7 @@ import (
|
|||
"github.com/docker/docker/container"
|
||||
daemonconfig "github.com/docker/docker/daemon/config"
|
||||
"github.com/docker/docker/oci"
|
||||
"github.com/docker/docker/oci/caps"
|
||||
"github.com/docker/docker/pkg/idtools"
|
||||
"github.com/docker/docker/pkg/mount"
|
||||
volumemounts "github.com/docker/docker/volume/mounts"
|
||||
|
@ -762,7 +763,11 @@ func (daemon *Daemon) createSpec(c *container.Container) (retSpec *specs.Spec, e
|
|||
if err := setNamespaces(daemon, &s, c); err != nil {
|
||||
return nil, fmt.Errorf("linux spec namespaces: %v", err)
|
||||
}
|
||||
if err := oci.SetCapabilities(&s, c.HostConfig.CapAdd, c.HostConfig.CapDrop, c.HostConfig.Privileged); err != nil {
|
||||
capabilities, err := caps.TweakCapabilities(oci.DefaultCapabilities(), c.HostConfig.CapAdd, c.HostConfig.CapDrop, c.HostConfig.Capabilities, c.HostConfig.Privileged)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("linux spec capabilities: %v", err)
|
||||
}
|
||||
if err := oci.SetCapabilities(&s, capabilities); err != nil {
|
||||
return nil, fmt.Errorf("linux spec capabilities: %v", err)
|
||||
}
|
||||
if err := setSeccomp(daemon, &s, c); err != nil {
|
||||
|
|
|
@ -10,6 +10,7 @@ import (
|
|||
containertypes "github.com/docker/docker/api/types/container"
|
||||
"github.com/docker/docker/container"
|
||||
"github.com/docker/docker/oci"
|
||||
"github.com/docker/docker/oci/caps"
|
||||
"github.com/docker/docker/pkg/sysinfo"
|
||||
"github.com/docker/docker/pkg/system"
|
||||
"github.com/opencontainers/runtime-spec/specs-go"
|
||||
|
@ -368,7 +369,11 @@ func (daemon *Daemon) createSpecLinuxFields(c *container.Container, s *specs.Spe
|
|||
}
|
||||
s.Root.Path = "rootfs"
|
||||
s.Root.Readonly = c.HostConfig.ReadonlyRootfs
|
||||
if err := oci.SetCapabilities(s, c.HostConfig.CapAdd, c.HostConfig.CapDrop, c.HostConfig.Privileged); err != nil {
|
||||
capabilities, err := caps.TweakCapabilities(oci.DefaultCapabilities(), c.HostConfig.CapAdd, c.HostConfig.CapDrop, c.HostConfig.Capabilities, c.HostConfig.Privileged)
|
||||
if err != nil {
|
||||
return fmt.Errorf("linux spec capabilities: %v", err)
|
||||
}
|
||||
if err := oci.SetCapabilities(s, capabilities); err != nil {
|
||||
return fmt.Errorf("linux spec capabilities: %v", err)
|
||||
}
|
||||
devPermissions, err := oci.AppendDevicePermissionsFromCgroupRules(nil, c.HostConfig.DeviceCgroupRules)
|
||||
|
|
|
@ -37,6 +37,9 @@ keywords: "API, Docker, rcli, REST, documentation"
|
|||
* `GET /service/{id}` now returns `MaxReplicas` as part of the `Placement`.
|
||||
* `POST /service/create` and `POST /services/(id or name)/update` now take the field `MaxReplicas`
|
||||
as part of the service `Placement`, allowing to specify maximum replicas per node for the service.
|
||||
* `GET /containers` now returns `Capabilities` field as part of the `HostConfig`.
|
||||
* `GET /containers/{id}` now returns `Capabilities` field as part of the `HostConfig`.
|
||||
* `POST /containers/create` now takes `Capabilities` field to set exact list kernel capabilities to be available for container (this overrides the default set).
|
||||
|
||||
## V1.39 API changes
|
||||
|
||||
|
|
|
@ -1377,6 +1377,8 @@ func (s *DockerSuite) TestPostContainersCreateWithStringOrSliceCmd(c *check.C) {
|
|||
}
|
||||
|
||||
// regression #14318
|
||||
// for backward compatibility testing with and without CAP_ prefix
|
||||
// and with upper and lowercase
|
||||
func (s *DockerSuite) TestPostContainersCreateWithStringOrSliceCapAddDrop(c *check.C) {
|
||||
// Windows doesn't support CapAdd/CapDrop
|
||||
testRequires(c, DaemonIsLinux)
|
||||
|
@ -1384,7 +1386,7 @@ func (s *DockerSuite) TestPostContainersCreateWithStringOrSliceCapAddDrop(c *che
|
|||
Image string
|
||||
CapAdd string
|
||||
CapDrop string
|
||||
}{"busybox", "NET_ADMIN", "SYS_ADMIN"}
|
||||
}{"busybox", "NET_ADMIN", "cap_sys_admin"}
|
||||
res, _, err := request.Post("/containers/create?name=capaddtest0", request.JSONBody(config))
|
||||
c.Assert(err, checker.IsNil)
|
||||
c.Assert(res.StatusCode, checker.Equals, http.StatusCreated)
|
||||
|
@ -1393,8 +1395,8 @@ func (s *DockerSuite) TestPostContainersCreateWithStringOrSliceCapAddDrop(c *che
|
|||
Image: "busybox",
|
||||
}
|
||||
hostConfig := containertypes.HostConfig{
|
||||
CapAdd: []string{"NET_ADMIN", "SYS_ADMIN"},
|
||||
CapDrop: []string{"SETGID"},
|
||||
CapAdd: []string{"net_admin", "SYS_ADMIN"},
|
||||
CapDrop: []string{"SETGID", "CAP_SETPCAP"},
|
||||
}
|
||||
|
||||
cli, err := client.NewClientWithOpts(client.FromEnv)
|
||||
|
|
|
@ -13,6 +13,7 @@ import (
|
|||
"github.com/docker/docker/api/types/container"
|
||||
"github.com/docker/docker/api/types/network"
|
||||
"github.com/docker/docker/api/types/versions"
|
||||
"github.com/docker/docker/client"
|
||||
ctr "github.com/docker/docker/integration/internal/container"
|
||||
"github.com/docker/docker/internal/test/request"
|
||||
"github.com/docker/docker/oci"
|
||||
|
@ -225,6 +226,131 @@ func TestCreateWithCustomMaskedPaths(t *testing.T) {
|
|||
}
|
||||
}
|
||||
|
||||
func TestCreateWithCapabilities(t *testing.T) {
|
||||
skip.If(t, testEnv.DaemonInfo.OSType == "windows", "FIXME: test should be able to run on LCOW")
|
||||
skip.If(t, versions.LessThan(testEnv.DaemonAPIVersion(), "1.40"), "Capabilities was added in API v1.40")
|
||||
|
||||
defer setupTest(t)()
|
||||
ctx := context.Background()
|
||||
clientNew := request.NewAPIClient(t)
|
||||
clientOld := request.NewAPIClient(t, client.WithVersion("1.39"))
|
||||
|
||||
testCases := []struct {
|
||||
doc string
|
||||
hostConfig container.HostConfig
|
||||
expected []string
|
||||
expectedError string
|
||||
oldClient bool
|
||||
}{
|
||||
{
|
||||
doc: "no capabilities",
|
||||
hostConfig: container.HostConfig{},
|
||||
},
|
||||
{
|
||||
doc: "empty capabilities",
|
||||
hostConfig: container.HostConfig{
|
||||
Capabilities: []string{},
|
||||
},
|
||||
expected: []string{},
|
||||
},
|
||||
{
|
||||
doc: "valid capabilities",
|
||||
hostConfig: container.HostConfig{
|
||||
Capabilities: []string{"CAP_NET_RAW", "CAP_SYS_CHROOT"},
|
||||
},
|
||||
expected: []string{"CAP_NET_RAW", "CAP_SYS_CHROOT"},
|
||||
},
|
||||
{
|
||||
doc: "invalid capabilities",
|
||||
hostConfig: container.HostConfig{
|
||||
Capabilities: []string{"NET_RAW"},
|
||||
},
|
||||
expectedError: `invalid Capabilities: unknown capability: "NET_RAW"`,
|
||||
},
|
||||
{
|
||||
doc: "duplicate capabilities",
|
||||
hostConfig: container.HostConfig{
|
||||
Capabilities: []string{"CAP_SYS_NICE", "CAP_SYS_NICE"},
|
||||
},
|
||||
expected: []string{"CAP_SYS_NICE", "CAP_SYS_NICE"},
|
||||
},
|
||||
{
|
||||
doc: "capabilities API v1.39",
|
||||
hostConfig: container.HostConfig{
|
||||
Capabilities: []string{"CAP_NET_RAW", "CAP_SYS_CHROOT"},
|
||||
},
|
||||
expected: nil,
|
||||
oldClient: true,
|
||||
},
|
||||
{
|
||||
doc: "empty capadd",
|
||||
hostConfig: container.HostConfig{
|
||||
Capabilities: []string{"CAP_NET_ADMIN"},
|
||||
CapAdd: []string{},
|
||||
},
|
||||
expected: []string{"CAP_NET_ADMIN"},
|
||||
},
|
||||
{
|
||||
doc: "empty capdrop",
|
||||
hostConfig: container.HostConfig{
|
||||
Capabilities: []string{"CAP_NET_ADMIN"},
|
||||
CapDrop: []string{},
|
||||
},
|
||||
expected: []string{"CAP_NET_ADMIN"},
|
||||
},
|
||||
{
|
||||
doc: "capadd capdrop",
|
||||
hostConfig: container.HostConfig{
|
||||
CapAdd: []string{"SYS_NICE", "CAP_SYS_NICE"},
|
||||
CapDrop: []string{"SYS_NICE", "CAP_SYS_NICE"},
|
||||
},
|
||||
},
|
||||
{
|
||||
doc: "conflict with capadd",
|
||||
hostConfig: container.HostConfig{
|
||||
Capabilities: []string{"CAP_NET_ADMIN"},
|
||||
CapAdd: []string{"SYS_NICE"},
|
||||
},
|
||||
expectedError: `conflicting options: Capabilities and CapAdd`,
|
||||
},
|
||||
{
|
||||
doc: "conflict with capdrop",
|
||||
hostConfig: container.HostConfig{
|
||||
Capabilities: []string{"CAP_NET_ADMIN"},
|
||||
CapDrop: []string{"NET_RAW"},
|
||||
},
|
||||
expectedError: `conflicting options: Capabilities and CapDrop`,
|
||||
},
|
||||
}
|
||||
|
||||
for _, tc := range testCases {
|
||||
tc := tc
|
||||
t.Run(tc.doc, func(t *testing.T) {
|
||||
t.Parallel()
|
||||
client := clientNew
|
||||
if tc.oldClient {
|
||||
client = clientOld
|
||||
}
|
||||
|
||||
c, err := client.ContainerCreate(context.Background(),
|
||||
&container.Config{Image: "busybox"},
|
||||
&tc.hostConfig,
|
||||
&network.NetworkingConfig{},
|
||||
"",
|
||||
)
|
||||
if tc.expectedError == "" {
|
||||
assert.NilError(t, err)
|
||||
ci, err := client.ContainerInspect(ctx, c.ID)
|
||||
assert.NilError(t, err)
|
||||
assert.Check(t, ci.HostConfig != nil)
|
||||
assert.DeepEqual(t, tc.expected, ci.HostConfig.Capabilities)
|
||||
} else {
|
||||
assert.ErrorContains(t, err, tc.expectedError)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestCreateWithCustomReadonlyPaths(t *testing.T) {
|
||||
skip.If(t, testEnv.DaemonInfo.OSType != "linux")
|
||||
|
||||
|
|
|
@ -4,6 +4,7 @@ import (
|
|||
"fmt"
|
||||
"strings"
|
||||
|
||||
"github.com/docker/docker/errdefs"
|
||||
"github.com/syndtr/gocapability/capability"
|
||||
)
|
||||
|
||||
|
@ -67,73 +68,102 @@ func GetAllCapabilities() []string {
|
|||
}
|
||||
|
||||
// inSlice tests whether a string is contained in a slice of strings or not.
|
||||
// Comparison is case insensitive
|
||||
func inSlice(slice []string, s string) bool {
|
||||
for _, ss := range slice {
|
||||
if strings.ToLower(s) == strings.ToLower(ss) {
|
||||
if s == ss {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
// TweakCapabilities can tweak capabilities by adding or dropping capabilities
|
||||
// based on the basics capabilities.
|
||||
func TweakCapabilities(basics, adds, drops []string) ([]string, error) {
|
||||
var (
|
||||
newCaps []string
|
||||
allCaps = GetAllCapabilities()
|
||||
)
|
||||
const allCapabilities = "ALL"
|
||||
|
||||
// FIXME(tonistiigi): docker format is without CAP_ prefix, oci is with prefix
|
||||
// Currently they are mixed in here. We should do conversion in one place.
|
||||
// NormalizeLegacyCapabilities normalizes, and validates CapAdd/CapDrop capabilities
|
||||
// by upper-casing them, and adding a CAP_ prefix (if not yet present).
|
||||
//
|
||||
// This function also accepts the "ALL" magic-value, that's used by CapAdd/CapDrop.
|
||||
func NormalizeLegacyCapabilities(caps []string) ([]string, error) {
|
||||
var normalized []string
|
||||
|
||||
// look for invalid cap in the drop list
|
||||
for _, cap := range drops {
|
||||
if strings.ToLower(cap) == "all" {
|
||||
valids := GetAllCapabilities()
|
||||
for _, c := range caps {
|
||||
c = strings.ToUpper(c)
|
||||
if c == allCapabilities {
|
||||
normalized = append(normalized, c)
|
||||
continue
|
||||
}
|
||||
|
||||
if !inSlice(allCaps, "CAP_"+cap) {
|
||||
return nil, fmt.Errorf("Unknown capability drop: %q", cap)
|
||||
if !strings.HasPrefix(c, "CAP_") {
|
||||
c = "CAP_" + c
|
||||
}
|
||||
if !inSlice(valids, c) {
|
||||
return nil, errdefs.InvalidParameter(fmt.Errorf("unknown capability: %q", c))
|
||||
}
|
||||
normalized = append(normalized, c)
|
||||
}
|
||||
|
||||
// handle --cap-add=all
|
||||
if inSlice(adds, "all") {
|
||||
basics = allCaps
|
||||
}
|
||||
|
||||
if !inSlice(drops, "all") {
|
||||
for _, cap := range basics {
|
||||
// skip `all` already handled above
|
||||
if strings.ToLower(cap) == "all" {
|
||||
continue
|
||||
}
|
||||
|
||||
// if we don't drop `all`, add back all the non-dropped caps
|
||||
if !inSlice(drops, cap[4:]) {
|
||||
newCaps = append(newCaps, strings.ToUpper(cap))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for _, cap := range adds {
|
||||
// skip `all` already handled above
|
||||
if strings.ToLower(cap) == "all" {
|
||||
continue
|
||||
}
|
||||
|
||||
cap = "CAP_" + cap
|
||||
|
||||
if !inSlice(allCaps, cap) {
|
||||
return nil, fmt.Errorf("Unknown capability to add: %q", cap)
|
||||
}
|
||||
|
||||
// add cap if not already in the list
|
||||
if !inSlice(newCaps, cap) {
|
||||
newCaps = append(newCaps, strings.ToUpper(cap))
|
||||
}
|
||||
}
|
||||
return newCaps, nil
|
||||
return normalized, nil
|
||||
}
|
||||
|
||||
// ValidateCapabilities validates if caps only contains valid capabilities
|
||||
func ValidateCapabilities(caps []string) error {
|
||||
valids := GetAllCapabilities()
|
||||
for _, c := range caps {
|
||||
if !inSlice(valids, c) {
|
||||
return errdefs.InvalidParameter(fmt.Errorf("unknown capability: %q", c))
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// TweakCapabilities tweaks capabilities by adding, dropping, or overriding
|
||||
// capabilities in the basics capabilities list.
|
||||
func TweakCapabilities(basics, adds, drops, capabilities []string, privileged bool) ([]string, error) {
|
||||
switch {
|
||||
case privileged:
|
||||
// Privileged containers get all capabilities
|
||||
return GetAllCapabilities(), nil
|
||||
case capabilities != nil:
|
||||
// Use custom set of capabilities
|
||||
if err := ValidateCapabilities(capabilities); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return capabilities, nil
|
||||
case len(adds) == 0 && len(drops) == 0:
|
||||
// Nothing to tweak; we're done
|
||||
return basics, nil
|
||||
}
|
||||
|
||||
capDrop, err := NormalizeLegacyCapabilities(drops)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
capAdd, err := NormalizeLegacyCapabilities(adds)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var caps []string
|
||||
|
||||
switch {
|
||||
case inSlice(capAdd, allCapabilities):
|
||||
// Add all capabilities except ones on capDrop
|
||||
for _, c := range GetAllCapabilities() {
|
||||
if !inSlice(capDrop, c) {
|
||||
caps = append(caps, c)
|
||||
}
|
||||
}
|
||||
case inSlice(capDrop, allCapabilities):
|
||||
// "Drop" all capabilities; use what's in capAdd instead
|
||||
caps = capAdd
|
||||
default:
|
||||
// First drop some capabilities
|
||||
for _, c := range basics {
|
||||
if !inSlice(capDrop, c) {
|
||||
caps = append(caps, c)
|
||||
}
|
||||
}
|
||||
// Then add the list of capabilities from capAdd
|
||||
caps = append(caps, capAdd...)
|
||||
}
|
||||
return caps, nil
|
||||
}
|
||||
|
|
|
@ -11,7 +11,8 @@ func iPtr(i int64) *int64 { return &i }
|
|||
func u32Ptr(i int64) *uint32 { u := uint32(i); return &u }
|
||||
func fmPtr(i int64) *os.FileMode { fm := os.FileMode(i); return &fm }
|
||||
|
||||
func defaultCapabilities() []string {
|
||||
// DefaultCapabilities returns a Linux kernel default capabilities
|
||||
func DefaultCapabilities() []string {
|
||||
return []string{
|
||||
"CAP_CHOWN",
|
||||
"CAP_DAC_OVERRIDE",
|
||||
|
@ -59,10 +60,10 @@ func DefaultLinuxSpec() specs.Spec {
|
|||
Version: specs.Version,
|
||||
Process: &specs.Process{
|
||||
Capabilities: &specs.LinuxCapabilities{
|
||||
Bounding: defaultCapabilities(),
|
||||
Permitted: defaultCapabilities(),
|
||||
Inheritable: defaultCapabilities(),
|
||||
Effective: defaultCapabilities(),
|
||||
Bounding: DefaultCapabilities(),
|
||||
Permitted: DefaultCapabilities(),
|
||||
Inheritable: DefaultCapabilities(),
|
||||
Effective: DefaultCapabilities(),
|
||||
},
|
||||
},
|
||||
Root: &specs.Root{},
|
||||
|
|
15
oci/oci.go
15
oci/oci.go
|
@ -5,7 +5,6 @@ import (
|
|||
"regexp"
|
||||
"strconv"
|
||||
|
||||
"github.com/docker/docker/oci/caps"
|
||||
specs "github.com/opencontainers/runtime-spec/specs-go"
|
||||
)
|
||||
|
||||
|
@ -14,19 +13,7 @@ var deviceCgroupRuleRegex = regexp.MustCompile("^([acb]) ([0-9]+|\\*):([0-9]+|\\
|
|||
|
||||
// SetCapabilities sets the provided capabilities on the spec
|
||||
// All capabilities are added if privileged is true
|
||||
func SetCapabilities(s *specs.Spec, add, drop []string, privileged bool) error {
|
||||
var (
|
||||
caplist []string
|
||||
err error
|
||||
)
|
||||
if privileged {
|
||||
caplist = caps.GetAllCapabilities()
|
||||
} else {
|
||||
caplist, err = caps.TweakCapabilities(s.Process.Capabilities.Bounding, add, drop)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
func SetCapabilities(s *specs.Spec, caplist []string) error {
|
||||
s.Process.Capabilities.Effective = caplist
|
||||
s.Process.Capabilities.Bounding = caplist
|
||||
s.Process.Capabilities.Permitted = caplist
|
||||
|
|
Loading…
Add table
Reference in a new issue