Skip to content

Commit

Permalink
[backport 1.4] oci.WithPrivileged: set current caps (#17)
Browse files Browse the repository at this point in the history
Backport of containerd#5017

Signed-off-by: Jacob Blain Christen <[email protected]>
  • Loading branch information
dweomer authored and brandond committed Oct 4, 2021
1 parent 2ecb406 commit 500cbff
Show file tree
Hide file tree
Showing 13 changed files with 935 additions and 307 deletions.
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

0 comments on commit 500cbff

Please sign in to comment.