Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[release/1.7] Support for dropping inheritable capabilities #10469

Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 16 additions & 0 deletions oci/spec_opts.go
Original file line number Diff line number Diff line change
Expand Up @@ -955,6 +955,11 @@ func WithCapabilities(caps []string) SpecOpts {
s.Process.Capabilities.Bounding = caps
s.Process.Capabilities.Effective = 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
}
Expand All @@ -980,6 +985,16 @@ func removeCap(caps *[]string, s string) {
*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
func WithAddedCapabilities(caps []string) SpecOpts {
return func(_ context.Context, _ Client, _ *containers.Container, s *Spec) error {
Expand Down Expand Up @@ -1008,6 +1023,7 @@ func WithDroppedCapabilities(caps []string) SpecOpts {
&s.Process.Capabilities.Bounding,
&s.Process.Capabilities.Effective,
&s.Process.Capabilities.Permitted,
&s.Process.Capabilities.Inheritable,
} {
removeCap(cl, c)
}
Expand Down
114 changes: 112 additions & 2 deletions oci/spec_opts_linux_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ import (
"testing"

"github.com/containerd/containerd/containers"
"github.com/containerd/containerd/pkg/cap"
"github.com/containerd/containerd/pkg/testutil"
"github.com/containerd/continuity/fs/fstest"
specs "github.com/opencontainers/runtime-spec/specs-go"
Expand Down Expand Up @@ -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) {
t.Parallel()

Expand All @@ -233,14 +319,17 @@ func TestAddCaps(t *testing.T) {
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) {
t.Parallel()

var s specs.Spec

if err := WithAllKnownCapabilities(context.Background(), nil, nil, &s); err != nil {
if err := withAllKnownCaps(&s); err != nil {
t.Fatal(err)
}
if err := WithDroppedCapabilities([]string{"CAP_CHOWN"})(context.Background(), nil, nil, &s); err != nil {
Expand All @@ -251,14 +340,15 @@ func TestDropCaps(t *testing.T) {
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 contains dropped cap", i)
}
}

// 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)
}
if err := WithDroppedCapabilities([]string{"CAP_FOWNER"})(context.Background(), nil, nil, &s); err != nil {
Expand All @@ -269,6 +359,7 @@ func TestDropCaps(t *testing.T) {
s.Process.Capabilities.Bounding,
s.Process.Capabilities.Effective,
s.Process.Capabilities.Permitted,
s.Process.Capabilities.Inheritable,
} {
if capsContain(cl, "CAP_FOWNER") {
t.Errorf("cap list %d contains dropped cap", i)
Expand All @@ -289,6 +380,25 @@ func TestDropCaps(t *testing.T) {
s.Process.Capabilities.Bounding,
s.Process.Capabilities.Effective,
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 {
t.Errorf("cap list %d is not empty", i)
Expand Down