Merge pull request #8356 from dmcgowan/drop-inheritable-capabilities
Support for dropping inheritable capabilities
This commit is contained in:
commit
782ad19f6c
@ -961,6 +961,11 @@ func WithCapabilities(caps []string) SpecOpts {
|
|||||||
s.Process.Capabilities.Bounding = caps
|
s.Process.Capabilities.Bounding = caps
|
||||||
s.Process.Capabilities.Effective = caps
|
s.Process.Capabilities.Effective = caps
|
||||||
s.Process.Capabilities.Permitted = caps
|
s.Process.Capabilities.Permitted = caps
|
||||||
|
if len(caps) == 0 {
|
||||||
|
s.Process.Capabilities.Inheritable = nil
|
||||||
|
} else if len(s.Process.Capabilities.Inheritable) > 0 {
|
||||||
|
filterCaps(&s.Process.Capabilities.Inheritable, caps)
|
||||||
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
@ -986,6 +991,16 @@ func removeCap(caps *[]string, s string) {
|
|||||||
*caps = newcaps
|
*caps = newcaps
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func filterCaps(caps *[]string, filters []string) {
|
||||||
|
var newcaps []string
|
||||||
|
for _, c := range *caps {
|
||||||
|
if capsContain(filters, c) {
|
||||||
|
newcaps = append(newcaps, c)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
*caps = newcaps
|
||||||
|
}
|
||||||
|
|
||||||
// WithAddedCapabilities adds the provided capabilities
|
// WithAddedCapabilities adds the provided capabilities
|
||||||
func WithAddedCapabilities(caps []string) SpecOpts {
|
func WithAddedCapabilities(caps []string) SpecOpts {
|
||||||
return func(_ context.Context, _ Client, _ *containers.Container, s *Spec) error {
|
return func(_ context.Context, _ Client, _ *containers.Container, s *Spec) error {
|
||||||
@ -1014,6 +1029,7 @@ func WithDroppedCapabilities(caps []string) SpecOpts {
|
|||||||
&s.Process.Capabilities.Bounding,
|
&s.Process.Capabilities.Bounding,
|
||||||
&s.Process.Capabilities.Effective,
|
&s.Process.Capabilities.Effective,
|
||||||
&s.Process.Capabilities.Permitted,
|
&s.Process.Capabilities.Permitted,
|
||||||
|
&s.Process.Capabilities.Inheritable,
|
||||||
} {
|
} {
|
||||||
removeCap(cl, c)
|
removeCap(cl, c)
|
||||||
}
|
}
|
||||||
|
@ -24,6 +24,7 @@ import (
|
|||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/containerd/containerd/containers"
|
"github.com/containerd/containerd/containers"
|
||||||
|
"github.com/containerd/containerd/pkg/cap"
|
||||||
"github.com/containerd/containerd/pkg/testutil"
|
"github.com/containerd/containerd/pkg/testutil"
|
||||||
"github.com/containerd/continuity/fs/fstest"
|
"github.com/containerd/continuity/fs/fstest"
|
||||||
specs "github.com/opencontainers/runtime-spec/specs-go"
|
specs "github.com/opencontainers/runtime-spec/specs-go"
|
||||||
@ -216,6 +217,91 @@ sys:x:3:root,bin,adm
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// withAllKnownCaps sets all known capabilities.
|
||||||
|
// This function differs from the exported function
|
||||||
|
// by also setting inheritable capabilities.
|
||||||
|
func withAllKnownCaps(s *specs.Spec) error {
|
||||||
|
caps := cap.Known()
|
||||||
|
if err := WithCapabilities(caps)(context.Background(), nil, nil, s); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
s.Process.Capabilities.Inheritable = caps
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestSetCaps(t *testing.T) {
|
||||||
|
t.Parallel()
|
||||||
|
|
||||||
|
var s specs.Spec
|
||||||
|
|
||||||
|
// Add base set of capabilities
|
||||||
|
if err := WithCapabilities([]string{"CAP_CHOWN"})(context.Background(), nil, nil, &s); err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
for i, cl := range [][]string{
|
||||||
|
s.Process.Capabilities.Bounding,
|
||||||
|
s.Process.Capabilities.Effective,
|
||||||
|
s.Process.Capabilities.Permitted,
|
||||||
|
} {
|
||||||
|
if !capsContain(cl, "CAP_CHOWN") {
|
||||||
|
t.Errorf("cap list %d does not contain added cap", i)
|
||||||
|
}
|
||||||
|
if len(cl) != 1 {
|
||||||
|
t.Errorf("cap list %d does not have only 1 cap", i)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if len(s.Process.Capabilities.Inheritable) != 0 {
|
||||||
|
t.Errorf("inheritable cap list is not empty")
|
||||||
|
}
|
||||||
|
|
||||||
|
// Add all caps then overwrite with single cap
|
||||||
|
if err := withAllKnownCaps(&s); err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
if err := WithCapabilities([]string{"CAP_CHOWN"})(context.Background(), nil, nil, &s); err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
for i, cl := range [][]string{
|
||||||
|
s.Process.Capabilities.Bounding,
|
||||||
|
s.Process.Capabilities.Effective,
|
||||||
|
s.Process.Capabilities.Permitted,
|
||||||
|
s.Process.Capabilities.Inheritable,
|
||||||
|
} {
|
||||||
|
if !capsContain(cl, "CAP_CHOWN") {
|
||||||
|
t.Errorf("cap list %d does not contain added cap", i)
|
||||||
|
}
|
||||||
|
if len(cl) != 1 {
|
||||||
|
t.Errorf("cap list %d does not have only 1 cap", i)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Add all caps, drop single cap, then overwrite with single cap
|
||||||
|
if err := withAllKnownCaps(&s); err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
if err := WithDroppedCapabilities([]string{"CAP_CHOWN"})(context.Background(), nil, nil, &s); err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
if err := WithCapabilities([]string{"CAP_CHOWN"})(context.Background(), nil, nil, &s); err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
for i, cl := range [][]string{
|
||||||
|
s.Process.Capabilities.Bounding,
|
||||||
|
s.Process.Capabilities.Effective,
|
||||||
|
s.Process.Capabilities.Permitted,
|
||||||
|
} {
|
||||||
|
if !capsContain(cl, "CAP_CHOWN") {
|
||||||
|
t.Errorf("cap list %d does not contain added cap", i)
|
||||||
|
}
|
||||||
|
if len(cl) != 1 {
|
||||||
|
t.Errorf("cap list %d does not have only 1 cap", i)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if len(s.Process.Capabilities.Inheritable) != 0 {
|
||||||
|
t.Errorf("inheritable cap list is not empty")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func TestAddCaps(t *testing.T) {
|
func TestAddCaps(t *testing.T) {
|
||||||
t.Parallel()
|
t.Parallel()
|
||||||
|
|
||||||
@ -233,6 +319,9 @@ func TestAddCaps(t *testing.T) {
|
|||||||
t.Errorf("cap list %d does not contain added cap", i)
|
t.Errorf("cap list %d does not contain added cap", i)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if len(s.Process.Capabilities.Inheritable) != 0 {
|
||||||
|
t.Errorf("inheritable cap list is not empty")
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestDropCaps(t *testing.T) {
|
func TestDropCaps(t *testing.T) {
|
||||||
@ -240,7 +329,7 @@ func TestDropCaps(t *testing.T) {
|
|||||||
|
|
||||||
var s specs.Spec
|
var s specs.Spec
|
||||||
|
|
||||||
if err := WithAllKnownCapabilities(context.Background(), nil, nil, &s); err != nil {
|
if err := withAllKnownCaps(&s); err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
if err := WithDroppedCapabilities([]string{"CAP_CHOWN"})(context.Background(), nil, nil, &s); err != nil {
|
if err := WithDroppedCapabilities([]string{"CAP_CHOWN"})(context.Background(), nil, nil, &s); err != nil {
|
||||||
@ -251,6 +340,7 @@ func TestDropCaps(t *testing.T) {
|
|||||||
s.Process.Capabilities.Bounding,
|
s.Process.Capabilities.Bounding,
|
||||||
s.Process.Capabilities.Effective,
|
s.Process.Capabilities.Effective,
|
||||||
s.Process.Capabilities.Permitted,
|
s.Process.Capabilities.Permitted,
|
||||||
|
s.Process.Capabilities.Inheritable,
|
||||||
} {
|
} {
|
||||||
if capsContain(cl, "CAP_CHOWN") {
|
if capsContain(cl, "CAP_CHOWN") {
|
||||||
t.Errorf("cap list %d contains dropped cap", i)
|
t.Errorf("cap list %d contains dropped cap", i)
|
||||||
@ -258,7 +348,7 @@ func TestDropCaps(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Add all capabilities back and drop a different cap.
|
// Add all capabilities back and drop a different cap.
|
||||||
if err := WithAllKnownCapabilities(context.Background(), nil, nil, &s); err != nil {
|
if err := withAllKnownCaps(&s); err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
if err := WithDroppedCapabilities([]string{"CAP_FOWNER"})(context.Background(), nil, nil, &s); err != nil {
|
if err := WithDroppedCapabilities([]string{"CAP_FOWNER"})(context.Background(), nil, nil, &s); err != nil {
|
||||||
@ -269,6 +359,7 @@ func TestDropCaps(t *testing.T) {
|
|||||||
s.Process.Capabilities.Bounding,
|
s.Process.Capabilities.Bounding,
|
||||||
s.Process.Capabilities.Effective,
|
s.Process.Capabilities.Effective,
|
||||||
s.Process.Capabilities.Permitted,
|
s.Process.Capabilities.Permitted,
|
||||||
|
s.Process.Capabilities.Inheritable,
|
||||||
} {
|
} {
|
||||||
if capsContain(cl, "CAP_FOWNER") {
|
if capsContain(cl, "CAP_FOWNER") {
|
||||||
t.Errorf("cap list %d contains dropped cap", i)
|
t.Errorf("cap list %d contains dropped cap", i)
|
||||||
@ -289,6 +380,25 @@ func TestDropCaps(t *testing.T) {
|
|||||||
s.Process.Capabilities.Bounding,
|
s.Process.Capabilities.Bounding,
|
||||||
s.Process.Capabilities.Effective,
|
s.Process.Capabilities.Effective,
|
||||||
s.Process.Capabilities.Permitted,
|
s.Process.Capabilities.Permitted,
|
||||||
|
s.Process.Capabilities.Inheritable,
|
||||||
|
} {
|
||||||
|
if len(cl) != 0 {
|
||||||
|
t.Errorf("cap list %d is not empty", i)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Add all capabilities back and drop all
|
||||||
|
if err := withAllKnownCaps(&s); err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
if err := WithCapabilities(nil)(context.Background(), nil, nil, &s); err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
for i, cl := range [][]string{
|
||||||
|
s.Process.Capabilities.Bounding,
|
||||||
|
s.Process.Capabilities.Effective,
|
||||||
|
s.Process.Capabilities.Permitted,
|
||||||
|
s.Process.Capabilities.Inheritable,
|
||||||
} {
|
} {
|
||||||
if len(cl) != 0 {
|
if len(cl) != 0 {
|
||||||
t.Errorf("cap list %d is not empty", i)
|
t.Errorf("cap list %d is not empty", i)
|
||||||
|
Loading…
Reference in New Issue
Block a user