CVE-2021-43816: Improper Preservation of Permissions (CWE-281)
value: containerd is an open source container runtime. On installations using SELinux, such as EL8 (CentOS, RHEL), Fedora, or SUSE MicroOS, with containerd since v1.5.0-beta.0 as the backing container runtime interface (CRI), an unprivileged pod scheduled to the node may bind mount, via hostPath volume, any privileged, regular file on disk for complete read/write access (sans delete). Such is achieved by placing the in-container location of the hostPath volume mount at either `/etc/hosts`, `/etc/hostname`, or `/etc/resolv.conf`. These locations are being relabeled indiscriminately to match the container process-label which effectively elevates permissions for savvy containers that would not normally be able to access privileged host files. This issue has been resolved in version 1.5.9. Users are advised to upgrade as soon as possible.
CWE description: The product does not preserve permissions or incorrectly preserves permissions when copying, restoring, or sharing objects, which can cause them to have less restrictive permissions than intended.
CVSS v3 base score: 9.1
Published: 2022-01-05T19:15Z
Repository: https://github.com/dweomer/containerd
Language: Go
Files changed: pkg/cri/opts/spec_linux.go, pkg/cri/server/container_create_linux.go
Commit date: 2021-11-02 12:38:43 -0700
Commit message: Revert "[cri] label etc files for selinux containers"

This reverts commit a731039238c62be081eb8c31525b988415745eea.

Diff: diff --git a/pkg/cri/opts/spec_linux.go b/pkg/cri/opts/spec_linux.go
index c5ec3dfdd..84c16b6f8 100644
--- a/pkg/cri/opts/spec_linux.go
+++ b/pkg/cri/opts/spec_linux.go
@@ -223,34 +223,10 @@ func WithMounts(osi osinterface.OS, config *runtime.ContainerConfig, extra []*ru
 		}
 		return nil
 	}
 }
 
-const (
-	etcHosts       = "/etc/hosts"
-	etcHostname    = "/etc/hostname"
-	resolvConfPath = "/etc/resolv.conf"
-)
-
-// WithRelabeledContainerMounts relabels the default container mounts for files in /etc
-func WithRelabeledContainerMounts(mountLabel string) oci.SpecOpts {
-	return func(ctx context.Context, client oci.Client, _ *containers.Container, s *runtimespec.Spec) (err error) {
-		if mountLabel == "" {
-			return nil
-		}
-		for _, m := range s.Mounts {
-			switch m.Destination {
-			case etcHosts, etcHostname, resolvConfPath:
-				if err := label.Relabel(m.Source, mountLabel, false); err != nil {
-					return err
-				}
-			}
-		}
-		return nil
-	}
-}
-
 // Ensure mount point on which path is mounted, is shared.
 func ensureShared(path string, lookupMount func(string) (mount.Info, error)) error {
 	mountInfo, err := lookupMount(path)
 	if err != nil {
 		return err
diff --git a/pkg/cri/server/container_create_linux.go b/pkg/cri/server/container_create_linux.go
index 1ad2947b8..30989af88 100644
--- a/pkg/cri/server/container_create_linux.go
+++ b/pkg/cri/server/container_create_linux.go
@@ -190,11 +190,11 @@ func (c *criService) containerSpec(
 		if retErr != nil {
 			_ = label.ReleaseLabel(processLabel)
 		}
 	}()
 
-	specOpts = append(specOpts, customopts.WithMounts(c.os, config, extraMounts, mountLabel), customopts.WithRelabeledContainerMounts(mountLabel))
+	specOpts = append(specOpts, customopts.WithMounts(c.os, config, extraMounts, mountLabel))
 
 	if !c.config.DisableProcMount {
 		// Change the default masked/readonly paths to empty slices
 		// See https://github.com/containerd/containerd/issues/5029
 		// TODO: Provide an option to set default paths to the ones in oci.populateDefaultUnixSpec()

Vulnerable code: const (
	etcHosts       = "/etc/hosts"
	etcHostname    = "/etc/hostname"
	resolvConfPath = "/etc/resolv.conf"
)

// WithRelabeledContainerMounts relabels the default container mounts for files in /etc
func WithRelabeledContainerMounts(mountLabel string) oci.SpecOpts {
	return func(ctx context.Context, client oci.Client, _ *containers.Container, s *runtimespec.Spec) (err error) {
		if mountLabel == "" {
			return nil
		}
		for _, m := range s.Mounts {
			switch m.Destination {
			case etcHosts, etcHostname, resolvConfPath:
				if err := label.Relabel(m.Source, mountLabel, false); err != nil {
					return err
				}
			}
		}
		return nil
	}
}

	specOpts = append(specOpts, customopts.WithMounts(c.os, config, extraMounts, mountLabel), customopts.WithRelabeledContainerMounts(mountLabel))
Fixed code: 	specOpts = append(specOpts, customopts.WithMounts(c.os, config, extraMounts, mountLabel))