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

[backport 1.4] oci.WithPrivileged set current caps #17

Merged
merged 1 commit into from
May 20, 2021
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
4 changes: 2 additions & 2 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ go 1.14

replace (
github.com/containerd/continuity => github.com/k3s-io/continuity v0.0.0-20210309170710-f93269e0d5c1
github.com/containerd/cri => github.com/k3s-io/cri v1.4.0-k3s.5 // k3s-release/1.4
github.com/containerd/cri => github.com/k3s-io/cri v1.4.0-k3s.6 // k3s-release/1.4
github.com/golang/protobuf => github.com/golang/protobuf v1.3.5
google.golang.org/genproto => google.golang.org/genproto v0.0.0-20200224152610-e50cd9704f63
k8s.io/api => k8s.io/api v0.19.5
Expand Down Expand Up @@ -73,7 +73,7 @@ require (
github.com/pkg/errors v0.9.1
github.com/prometheus/client_golang v1.7.1
github.com/sirupsen/logrus v1.7.0
github.com/syndtr/gocapability v0.0.0-20180916011248-d98352740cb2
github.com/stretchr/testify v1.4.0
github.com/tchap/go-patricia v2.2.6+incompatible // indirect
github.com/urfave/cli v1.22.2
go.etcd.io/bbolt v1.3.5
Expand Down
4 changes: 2 additions & 2 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -402,8 +402,8 @@ github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7V
github.com/jung-kurt/gofpdf v1.0.3-0.20190309125859-24315acbbda5/go.mod h1:7Id9E/uU8ce6rXgefFLlgrJj/GYY22cpxn+r32jIOes=
github.com/k3s-io/continuity v0.0.0-20210309170710-f93269e0d5c1 h1:KEz2rd9IDbrQT8w6RibEYlwfTXiu0P6hQDE+6O4IJdI=
github.com/k3s-io/continuity v0.0.0-20210309170710-f93269e0d5c1/go.mod h1:EXlVlkqNba9rJe3j7w3Xa924itAMLgZH4UD/Q4PExuQ=
github.com/k3s-io/cri v1.4.0-k3s.5 h1:Uh7QkRKibPJqSBbtCtgpjYsdNVcx3Tx+7HHlhxKBtu8=
github.com/k3s-io/cri v1.4.0-k3s.5/go.mod h1:fGPUUHMKQik/vIegSe05DtX/m4miovdtvVLqRUFAkK0=
github.com/k3s-io/cri v1.4.0-k3s.6 h1:Hn/0KRtv62B/KNT8oULl1hWnViyuJ+RB0x9y9zZsmCw=
github.com/k3s-io/cri v1.4.0-k3s.6/go.mod h1:fGPUUHMKQik/vIegSe05DtX/m4miovdtvVLqRUFAkK0=
github.com/karrick/godirwalk v1.7.5/go.mod h1:2c9FRhkDxdIbgkOnCEvnSWs71Bhugbl46shStcFDJ34=
github.com/kisielk/errcheck v1.1.0/go.mod h1:EZBBE59ingxPouuu3KfxchcWSUPOHkagtvWXihfKN4Q=
github.com/kisielk/errcheck v1.2.0/go.mod h1:/BMXB+zMLi60iA8Vv6Ksmxu/1UDYcXs4uQLJ+jE2L00=
Expand Down
113 changes: 53 additions & 60 deletions oci/spec_opts.go
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,6 @@ import (
"github.com/opencontainers/runc/libcontainer/user"
specs "github.com/opencontainers/runtime-spec/specs-go"
"github.com/pkg/errors"
"github.com/syndtr/gocapability/capability"
)

// SpecOpts sets spec specific information to a newly generated OCI spec
Expand Down Expand Up @@ -274,6 +273,28 @@ func WithMounts(mounts []specs.Mount) SpecOpts {
}
}

// WithoutMounts removes mounts
func WithoutMounts(dests ...string) SpecOpts {
return func(_ context.Context, _ Client, _ *containers.Container, s *Spec) error {
var (
mounts []specs.Mount
current = s.Mounts
)
mLoop:
for _, m := range current {
mDestination := filepath.Clean(m.Destination)
for _, dest := range dests {
if mDestination == dest {
continue mLoop
}
}
mounts = append(mounts, m)
}
s.Mounts = mounts
return nil
}
}

// WithHostNamespace allows a task to run inside the host's linux namespace
func WithHostNamespace(ns specs.LinuxNamespaceType) SpecOpts {
return func(_ context.Context, _ Client, _ *containers.Container, s *Spec) error {
Expand All @@ -295,10 +316,7 @@ func WithLinuxNamespace(ns specs.LinuxNamespace) SpecOpts {
setLinux(s)
for i, n := range s.Linux.Namespaces {
if n.Type == ns.Type {
before := s.Linux.Namespaces[:i]
after := s.Linux.Namespaces[i+1:]
s.Linux.Namespaces = append(before, ns)
s.Linux.Namespaces = append(s.Linux.Namespaces, after...)
s.Linux.Namespaces[i] = ns
return nil
}
}
Expand Down Expand Up @@ -536,7 +554,7 @@ func WithUser(userstr string) SpecOpts {
}
f := func(root string) error {
if username != "" {
user, err := getUserFromPath(root, func(u user.User) bool {
user, err := UserFromPath(root, func(u user.User) bool {
return u.Name == username
})
if err != nil {
Expand All @@ -545,7 +563,7 @@ func WithUser(userstr string) SpecOpts {
uid = uint32(user.Uid)
}
if groupname != "" {
gid, err = getGIDFromPath(root, func(g user.Group) bool {
gid, err = GIDFromPath(root, func(g user.Group) bool {
return g.Name == groupname
})
if err != nil {
Expand Down Expand Up @@ -600,11 +618,11 @@ func WithUserID(uid uint32) SpecOpts {
if !isRootfsAbs(s.Root.Path) {
return errors.Errorf("rootfs absolute path is required")
}
user, err := getUserFromPath(s.Root.Path, func(u user.User) bool {
user, err := UserFromPath(s.Root.Path, func(u user.User) bool {
return u.Uid == int(uid)
})
if err != nil {
if os.IsNotExist(err) || err == errNoUsersFound {
if os.IsNotExist(err) || err == ErrNoUsersFound {
s.Process.User.UID, s.Process.User.GID = uid, 0
return nil
}
Expand All @@ -626,11 +644,11 @@ func WithUserID(uid uint32) SpecOpts {
return err
}
return mount.WithTempMount(ctx, mounts, func(root string) error {
user, err := getUserFromPath(root, func(u user.User) bool {
user, err := UserFromPath(root, func(u user.User) bool {
return u.Uid == int(uid)
})
if err != nil {
if os.IsNotExist(err) || err == errNoUsersFound {
if os.IsNotExist(err) || err == ErrNoUsersFound {
s.Process.User.UID, s.Process.User.GID = uid, 0
return nil
}
Expand All @@ -654,7 +672,7 @@ func WithUsername(username string) SpecOpts {
if !isRootfsAbs(s.Root.Path) {
return errors.Errorf("rootfs absolute path is required")
}
user, err := getUserFromPath(s.Root.Path, func(u user.User) bool {
user, err := UserFromPath(s.Root.Path, func(u user.User) bool {
return u.Name == username
})
if err != nil {
Expand All @@ -675,7 +693,7 @@ func WithUsername(username string) SpecOpts {
return err
}
return mount.WithTempMount(ctx, mounts, func(root string) error {
user, err := getUserFromPath(root, func(u user.User) bool {
user, err := UserFromPath(root, func(u user.User) bool {
return u.Name == username
})
if err != nil {
Expand Down Expand Up @@ -707,11 +725,11 @@ func WithAdditionalGIDs(userstr string) SpecOpts {
var username string
uid, err := strconv.Atoi(userstr)
if err == nil {
user, err := getUserFromPath(root, func(u user.User) bool {
user, err := UserFromPath(root, func(u user.User) bool {
return u.Uid == uid
})
if err != nil {
if os.IsNotExist(err) || err == errNoUsersFound {
if os.IsNotExist(err) || err == ErrNoUsersFound {
return nil
}
return err
Expand Down Expand Up @@ -776,29 +794,6 @@ func WithCapabilities(caps []string) SpecOpts {
}
}

// WithAllCapabilities sets all linux capabilities for the process
var WithAllCapabilities = func(ctx context.Context, client Client, c *containers.Container, s *Spec) error {
return WithCapabilities(GetAllCapabilities())(ctx, client, c, s)
}

// GetAllCapabilities returns all caps up to CAP_LAST_CAP
// or CAP_BLOCK_SUSPEND on RHEL6
func GetAllCapabilities() []string {
last := capability.CAP_LAST_CAP
// hack for RHEL6 which has no /proc/sys/kernel/cap_last_cap
if last == capability.Cap(63) {
last = capability.CAP_BLOCK_SUSPEND
}
var caps []string
for _, cap := range capability.List() {
if cap > last {
continue
}
caps = append(caps, "CAP_"+strings.ToUpper(cap.String()))
}
return caps
}

func capsContain(caps []string, s string) bool {
for _, c := range caps {
if c == s {
Expand Down Expand Up @@ -869,9 +864,12 @@ func WithAmbientCapabilities(caps []string) SpecOpts {
}
}

var errNoUsersFound = errors.New("no users found")
// ErrNoUsersFound can be returned from UserFromPath
var ErrNoUsersFound = errors.New("no users found")

func getUserFromPath(root string, filter func(user.User) bool) (user.User, error) {
// UserFromPath inspects the user object using /etc/passwd in the specified rootfs.
// filter can be nil.
func UserFromPath(root string, filter func(user.User) bool) (user.User, error) {
ppath, err := fs.RootPath(root, "/etc/passwd")
if err != nil {
return user.User{}, err
Expand All @@ -881,14 +879,17 @@ func getUserFromPath(root string, filter func(user.User) bool) (user.User, error
return user.User{}, err
}
if len(users) == 0 {
return user.User{}, errNoUsersFound
return user.User{}, ErrNoUsersFound
}
return users[0], nil
}

var errNoGroupsFound = errors.New("no groups found")
// ErrNoGroupsFound can be returned from GIDFromPath
var ErrNoGroupsFound = errors.New("no groups found")

func getGIDFromPath(root string, filter func(user.Group) bool) (gid uint32, err error) {
// GIDFromPath inspects the GID using /etc/passwd in the specified rootfs.
// filter can be nil.
func GIDFromPath(root string, filter func(user.Group) bool) (gid uint32, err error) {
gpath, err := fs.RootPath(root, "/etc/group")
if err != nil {
return 0, err
Expand All @@ -898,7 +899,7 @@ func getGIDFromPath(root string, filter func(user.Group) bool) (gid uint32, err
return 0, err
}
if len(groups) == 0 {
return 0, errNoGroupsFound
return 0, ErrNoGroupsFound
}
g := groups[0]
return uint32(g.Gid), nil
Expand Down Expand Up @@ -948,33 +949,27 @@ func WithReadonlyPaths(paths []string) SpecOpts {

// WithWriteableSysfs makes any sysfs mounts writeable
func WithWriteableSysfs(_ context.Context, _ Client, _ *containers.Container, s *Spec) error {
for i, m := range s.Mounts {
for _, m := range s.Mounts {
if m.Type == "sysfs" {
var options []string
for _, o := range m.Options {
for i, o := range m.Options {
if o == "ro" {
o = "rw"
m.Options[i] = "rw"
}
options = append(options, o)
}
s.Mounts[i].Options = options
}
}
return nil
}

// WithWriteableCgroupfs makes any cgroup mounts writeable
func WithWriteableCgroupfs(_ context.Context, _ Client, _ *containers.Container, s *Spec) error {
for i, m := range s.Mounts {
for _, m := range s.Mounts {
if m.Type == "cgroup" {
var options []string
for _, o := range m.Options {
for i, o := range m.Options {
if o == "ro" {
o = "rw"
m.Options[i] = "rw"
}
options = append(options, o)
}
s.Mounts[i].Options = options
}
}
return nil
Expand Down Expand Up @@ -1126,7 +1121,7 @@ func WithDefaultUnixDevices(_ context.Context, _ Client, _ *containers.Container

// WithPrivileged sets up options for a privileged container
var WithPrivileged = Compose(
WithAllCapabilities,
WithAllCurrentCapabilities,
WithMaskedPaths(nil),
WithReadonlyPaths(nil),
WithWriteableSysfs,
Expand Down Expand Up @@ -1199,15 +1194,13 @@ func WithLinuxDevices(devices []specs.LinuxDevice) SpecOpts {
}
}

var ErrNotADevice = errors.New("not a device node")

// WithLinuxDevice adds the device specified by path to the spec
func WithLinuxDevice(path, permissions string) SpecOpts {
return func(_ context.Context, _ Client, _ *containers.Container, s *Spec) error {
setLinux(s)
setResources(s)

dev, err := deviceFromPath(path, permissions)
dev, err := deviceFromPath(path)
if err != nil {
return err
}
Expand Down
Loading