Skip to content

Commit c60a5fd

Browse files
Merge pull request #3099 from crosbymichael/export-caps
Add additional capability handling opts
2 parents ef45e4f + bdd84ab commit c60a5fd

2 files changed

Lines changed: 104 additions & 3 deletions

File tree

oci/spec_opts.go

Lines changed: 60 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ import (
3333
"github.com/containerd/containerd/namespaces"
3434
"github.com/containerd/containerd/platforms"
3535
"github.com/containerd/continuity/fs"
36-
"github.com/opencontainers/image-spec/specs-go/v1"
36+
v1 "github.com/opencontainers/image-spec/specs-go/v1"
3737
"github.com/opencontainers/runc/libcontainer/user"
3838
specs "github.com/opencontainers/runtime-spec/specs-go"
3939
"github.com/pkg/errors"
@@ -741,9 +741,11 @@ func WithCapabilities(caps []string) SpecOpts {
741741
}
742742

743743
// WithAllCapabilities sets all linux capabilities for the process
744-
var WithAllCapabilities = WithCapabilities(getAllCapabilities())
744+
var WithAllCapabilities = WithCapabilities(GetAllCapabilities())
745745

746-
func getAllCapabilities() []string {
746+
// GetAllCapabilities returns all caps up to CAP_LAST_CAP
747+
// or CAP_BLOCK_SUSPEND on RHEL6
748+
func GetAllCapabilities() []string {
747749
last := capability.CAP_LAST_CAP
748750
// hack for RHEL6 which has no /proc/sys/kernel/cap_last_cap
749751
if last == capability.Cap(63) {
@@ -759,6 +761,61 @@ func getAllCapabilities() []string {
759761
return caps
760762
}
761763

764+
func capsContain(caps []string, s string) bool {
765+
for _, c := range caps {
766+
if c == s {
767+
return true
768+
}
769+
}
770+
return false
771+
}
772+
773+
func removeCap(caps *[]string, s string) {
774+
for i, c := range *caps {
775+
if c == s {
776+
*caps = append((*caps)[:i], (*caps)[i+1:]...)
777+
}
778+
}
779+
}
780+
781+
// WithAddedCapabilities adds the provided capabilities
782+
func WithAddedCapabilities(caps []string) SpecOpts {
783+
return func(_ context.Context, _ Client, _ *containers.Container, s *Spec) error {
784+
setCapabilities(s)
785+
for _, c := range caps {
786+
for _, cl := range []*[]string{
787+
&s.Process.Capabilities.Bounding,
788+
&s.Process.Capabilities.Effective,
789+
&s.Process.Capabilities.Permitted,
790+
&s.Process.Capabilities.Inheritable,
791+
} {
792+
if !capsContain(*cl, c) {
793+
*cl = append(*cl, c)
794+
}
795+
}
796+
}
797+
return nil
798+
}
799+
}
800+
801+
// WithDroppedCapabilities removes the provided capabilities
802+
func WithDroppedCapabilities(caps []string) SpecOpts {
803+
return func(_ context.Context, _ Client, _ *containers.Container, s *Spec) error {
804+
setCapabilities(s)
805+
for _, c := range caps {
806+
for _, cl := range []*[]string{
807+
&s.Process.Capabilities.Bounding,
808+
&s.Process.Capabilities.Effective,
809+
&s.Process.Capabilities.Permitted,
810+
&s.Process.Capabilities.Inheritable,
811+
} {
812+
removeCap(cl, c)
813+
}
814+
}
815+
return nil
816+
}
817+
}
818+
762819
// WithAmbientCapabilities set the Linux ambient capabilities for the process
763820
// Ambient capabilities should only be set for non-root users or the caller should
764821
// understand how these capabilities are used and set

oci/spec_opts_test.go

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -422,3 +422,47 @@ func TestWithImageConfigArgs(t *testing.T) {
422422
t.Fatal(err)
423423
}
424424
}
425+
426+
func TestAddCaps(t *testing.T) {
427+
t.Parallel()
428+
429+
var s specs.Spec
430+
431+
if err := WithAddedCapabilities([]string{"CAP_CHOWN"})(nil, nil, nil, &s); err != nil {
432+
t.Fatal(err)
433+
}
434+
for i, cl := range [][]string{
435+
s.Process.Capabilities.Bounding,
436+
s.Process.Capabilities.Effective,
437+
s.Process.Capabilities.Permitted,
438+
s.Process.Capabilities.Inheritable,
439+
} {
440+
if !capsContain(cl, "CAP_CHOWN") {
441+
t.Errorf("cap list %d does not contain added cap", i)
442+
}
443+
}
444+
}
445+
446+
func TestDropCaps(t *testing.T) {
447+
t.Parallel()
448+
449+
var s specs.Spec
450+
451+
if err := WithAllCapabilities(nil, nil, nil, &s); err != nil {
452+
t.Fatal(err)
453+
}
454+
if err := WithDroppedCapabilities([]string{"CAP_CHOWN"})(nil, nil, nil, &s); err != nil {
455+
t.Fatal(err)
456+
}
457+
458+
for i, cl := range [][]string{
459+
s.Process.Capabilities.Bounding,
460+
s.Process.Capabilities.Effective,
461+
s.Process.Capabilities.Permitted,
462+
s.Process.Capabilities.Inheritable,
463+
} {
464+
if capsContain(cl, "CAP_CHOWN") {
465+
t.Errorf("cap list %d contains dropped cap", i)
466+
}
467+
}
468+
}

0 commit comments

Comments
 (0)