From fe70d9e0048502addcbeea5399f2da554a14bd78 Mon Sep 17 00:00:00 2001 From: xiadanni Date: Tue, 9 Nov 2021 16:25:09 +0800 Subject: [PATCH] [Backport]containerd:reduce permissions for bundle dir to fix CVE-2021-41103 reduce permissions for bundle dir reduce permissions on plugin directories fix CVE-2021-41103 Conflict:NA Reference:https://github.com/containerd/containerd/commit/6886c6a2ec0c70dde1aa64e77b64a5ad47b983c3 https://github.com/containerd/containerd/commit/7c621e1fcc08bcf5a1a48b837342cc22eada1685 --- runtime/v1/linux/bundle.go | 56 +++++++++++++++++++++++++++++++++++++- snapshots/btrfs/btrfs.go | 8 ++++-- 2 files changed, 61 insertions(+), 3 deletions(-) diff --git a/runtime/v1/linux/bundle.go b/runtime/v1/linux/bundle.go index 0442246f9..90a10862e 100644 --- a/runtime/v1/linux/bundle.go +++ b/runtime/v1/linux/bundle.go @@ -20,6 +20,7 @@ package linux import ( "context" + "encoding/json" "fmt" "io/ioutil" "os" @@ -30,6 +31,7 @@ import ( "github.com/containerd/containerd/runtime/linux/runctypes" "github.com/containerd/containerd/runtime/v1/shim" "github.com/containerd/containerd/runtime/v1/shim/client" + "github.com/opencontainers/runtime-spec/specs-go" "github.com/pkg/errors" "github.com/sirupsen/logrus" ) @@ -63,7 +65,7 @@ func newBundle(id, path, workDir string, spec []byte) (b *bundle, err error) { time.Sleep(waitTime) } - if err := os.Mkdir(path, 0711); err != nil { + if err := os.Mkdir(path, 0700); err != nil { return nil, err } defer func() { @@ -71,6 +73,9 @@ func newBundle(id, path, workDir string, spec []byte) (b *bundle, err error) { os.RemoveAll(path) } }() + if err := prepareBundleDirectoryPermissions(path, spec); err != nil { + return nil, err + } if err := os.MkdirAll(workDir, 0711); err != nil { return nil, err } @@ -90,6 +95,55 @@ func newBundle(id, path, workDir string, spec []byte) (b *bundle, err error) { }, err } +// prepareBundleDirectoryPermissions prepares the permissions of the bundle +// directory. When user namespaces are enabled, the permissions are modified +// to allow the remapped root GID to access the bundle. +func prepareBundleDirectoryPermissions(path string, spec []byte) error { + gid, err := remappedGID(spec) + if err != nil { + return err + } + if gid == 0 { + return nil + } + if err := os.Chown(path, -1, int(gid)); err != nil { + return err + } + return os.Chmod(path, 0710) +} + +// ociSpecUserNS is a subset of specs.Spec used to reduce garbage during +// unmarshal. +type ociSpecUserNS struct { + Linux *linuxSpecUserNS +} + +// linuxSpecUserNS is a subset of specs.Linux used to reduce garbage during +// unmarshal. +type linuxSpecUserNS struct { + GIDMappings []specs.LinuxIDMapping +} + +// remappedGID reads the remapped GID 0 from the OCI spec, if it exists. If +// there is no remapping, remappedGID returns 0. If the spec cannot be parsed, +// remappedGID returns an error. +func remappedGID(spec []byte) (uint32, error) { + var ociSpec ociSpecUserNS + err := json.Unmarshal(spec, &ociSpec) + if err != nil { + return 0, err + } + if ociSpec.Linux == nil || len(ociSpec.Linux.GIDMappings) == 0 { + return 0, nil + } + for _, mapping := range ociSpec.Linux.GIDMappings { + if mapping.ContainerID == 0 { + return mapping.HostID, nil + } + } + return 0, nil +} + type bundle struct { id string path string diff --git a/snapshots/btrfs/btrfs.go b/snapshots/btrfs/btrfs.go index a89b55129..da6f8220e 100644 --- a/snapshots/btrfs/btrfs.go +++ b/snapshots/btrfs/btrfs.go @@ -63,11 +63,15 @@ type snapshotter struct { // root needs to be a mount point of btrfs. func NewSnapshotter(root string) (snapshots.Snapshotter, error) { // If directory does not exist, create it - if _, err := os.Stat(root); err != nil { + if st, err := os.Stat(root); err != nil { if !os.IsNotExist(err) { return nil, err } - if err := os.Mkdir(root, 0755); err != nil { + if err := os.Mkdir(root, 0700); err != nil { + return nil, err + } + } else if st.Mode()&os.ModePerm != 0700 { + if err := os.Chmod(root, 0700); err != nil { return nil, err } } -- 2.27.0