Support for dropping inheritable capabilities

Signed-off-by: Derek McGowan <derek@mcg.dev>
This commit is contained in:
Derek McGowan 2023-04-05 10:45:22 -07:00
parent 3c6ddee128
commit d0527e2283
No known key found for this signature in database
GPG Key ID: F58C5D0A4405ACDB
2 changed files with 128 additions and 2 deletions

View File

@ -943,6 +943,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
}
@ -968,6 +973,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 {
@ -996,6 +1011,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)
}

View File

@ -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"
@ -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()
@ -233,6 +319,9 @@ 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) {
@ -240,7 +329,7 @@ func TestDropCaps(t *testing.T) {
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 {
@ -251,6 +340,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_CHOWN") {
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.
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 {
@ -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)
@ -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)