runc can be confused to create empty files/directories on the host
Description
runc is a CLI tool for spawning and running containers according to the OCI specification. runc 1.1.13 and earlier, as well as 1.2.0-rc2 and earlier, can be tricked into creating empty files or directories in arbitrary locations in the host filesystem by sharing a volume between two containers and exploiting a race with os.MkdirAll. While this could be used to create empty files, existing files would not be truncated. An attacker must have the ability to start containers using some kind of custom volume configuration. Containers using user namespaces are still affected, but the scope of places an attacker can create inodes can be significantly reduced. Sufficiently strict LSM policies (SELinux/Apparmor) can also in principle block this attack -- we suspect the industry standard SELinux policy may restrict this attack's scope but the exact scope of protection hasn't been analysed. This is exploitable using runc directly as well as through Docker and Kubernetes. The issue is fixed in runc v1.1.14 and v1.2.0-rc3.
Some workarounds are available. Using user namespaces restricts this attack fairly significantly such that the attacker can only create inodes in directories that the remapped root user/group has write access to. Unless the root user is remapped to an actual user on the host (such as with rootless containers that don't use /etc/sub[ug]id), this in practice means that an attacker would only be able to create inodes in world-writable directories. A strict enough SELinux or AppArmor policy could in principle also restrict the scope if a specific label is applied to the runc runtime, though neither the extent to which the standard existing policies block this attack nor what exact policies are needed to sufficiently restrict this attack have been thoroughly tested.
AI Insight
LLM-synthesized narrative grounded in this CVE's description and references.
runc 1.1.13 and earlier can be tricked into creating empty files or directories in the host filesystem via a race condition when sharing volumes between containers.
Vulnerability
Analysis
CVE-2024-45310 affects runc, the CLI tool for spawning and running OCI containers. The vulnerability allows an attacker to create empty files or directories at arbitrary locations on the host filesystem by sharing a volume between two containers and exploiting a race condition within os.MkdirAll. Root cause lies in the mountpoint creation logic, where insufficient synchronization can lead to inodes being created outside the intended container rootfs [1][4].
Exploitation
An attacker must have the ability to start containers with custom volume configurations. The attack is exploitable directly through runc, as well as via Docker and Kubernetes [2]. While containers using user namespaces are affected, the impact is reduced because the attacker can only create inodes in directories where the remapped root user/group has write access (typically world-writable directories). Strict LSM policies (SELinux/AppArmor) may further restrict the attack, though the exact protection scope has not been thoroughly analyzed [4].
Impact
Successful exploitation allows an attacker to create empty files or directories on the host filesystem. Existing files are not truncated, and the attacker cannot modify file contents. This could be leveraged to interfere with host services (e.g., creating placeholder files to trigger unintended behavior) or as a stepping stone for more complex attacks, such as denial of service or privilege escalation in combination with other weaknesses [4].
Mitigation
The issue is fixed in runc v1.1.14 and v1.2.0-rc3 [2][3]. As workarounds, administrators can use user namespaces to restrict write access, or enforce strict SELinux/AppArmor policies. The advisory recommends immediate patching for all affected deployments [4].
- GitHub - opencontainers/runc: CLI tool for spawning and running containers according to the OCI specification
- [1.1] rootfs: consolidate mountpoint creation logic · opencontainers/runc@8781993
- NVD - CVE-2024-45310
- security - CVE-2024-45310: runc can be tricked into creating empty files/directories on host
AI Insight generated on May 20, 2026. Synthesized from this CVE's description and the cited reference URLs; citations are validated against the source bundle.
Affected packages
Versions sourced from the GitHub Security Advisory.
| Package | Affected versions | Patched versions |
|---|---|---|
github.com/opencontainers/runcGo | < 1.1.14 | 1.1.14 |
github.com/opencontainers/runcGo | >= 1.2.0-rc.1, < 1.2.0-rc.3 | 1.2.0-rc.3 |
Affected products
457- osv-coords456 versionspkg:apk/chainguard/buildahpkg:apk/chainguard/cadvisorpkg:apk/chainguard/cadvisor-compatpkg:apk/chainguard/cadvisor-fipspkg:apk/chainguard/cluster-autoscaler-1.31pkg:apk/chainguard/cluster-autoscaler-1.31-compatpkg:apk/chainguard/cluster-autoscaler-fips-1.31pkg:apk/chainguard/cluster-autoscaler-fips-1.31-compatpkg:apk/chainguard/ctoppkg:apk/chainguard/dockerpkg:apk/chainguard/docker-config-mirror-gcrpkg:apk/chainguard/dockerdpkg:apk/chainguard/docker-dindpkg:apk/chainguard/docker-dind-compatpkg:apk/chainguard/dockerd-oci-entrypointpkg:apk/chainguard/dockerd-servicepkg:apk/chainguard/docker-initpkg:apk/chainguard/docker-modprobe-compatpkg:apk/chainguard/docker-oci-entrypointpkg:apk/chainguard/docker-rootlesspkg:apk/chainguard/eks-distro-1.31pkg:apk/chainguard/eks-distro-coredns-1.31pkg:apk/chainguard/eks-distro-coredns-fips-1.31pkg:apk/chainguard/eks-distro-fips-1.31pkg:apk/chainguard/eks-distro-kube-apiserver-1.31pkg:apk/chainguard/eks-distro-kube-apiserver-fips-1.31pkg:apk/chainguard/eks-distro-kube-controller-manager-1.31pkg:apk/chainguard/eks-distro-kube-controller-manager-fips-1.31pkg:apk/chainguard/eks-distro-kube-proxy-1.31pkg:apk/chainguard/eks-distro-kube-proxy-fips-1.31pkg:apk/chainguard/eks-distro-kubernetes-pause-1.31pkg:apk/chainguard/eks-distro-kube-scheduler-1.31pkg:apk/chainguard/eks-distro-kube-scheduler-fips-1.31pkg:apk/chainguard/gosu-1.11pkg:apk/chainguard/gpu-feature-discoverypkg:apk/chainguard/grafana-alloypkg:apk/chainguard/grafana-alloy-compatpkg:apk/chainguard/grafana-alloy-fipspkg:apk/chainguard/grypepkg:apk/chainguard/ingress-nginx-controller-1.10pkg:apk/chainguard/ingress-nginx-controller-1.10-compatpkg:apk/chainguard/ingress-nginx-controller-1.10-kube-webhook-certgenpkg:apk/chainguard/ingress-nginx-controller-1.11pkg:apk/chainguard/ingress-nginx-controller-1.11-compatpkg:apk/chainguard/ingress-nginx-controller-1.11-kube-webhook-certgenpkg:apk/chainguard/ingress-nginx-controller-bitnami-compat-1.10pkg:apk/chainguard/ingress-nginx-controller-bitnami-compat-1.11pkg:apk/chainguard/ingress-nginx-controller-compat-1.10pkg:apk/chainguard/ingress-nginx-controller-compat-1.11pkg:apk/chainguard/ingress-nginx-controller-fips-1.10pkg:apk/chainguard/ingress-nginx-controller-fips-1.11pkg:apk/chainguard/ingress-nginx-controller-fips-bitnami-compat-1.11pkg:apk/chainguard/ingress-nginx-controller-fips-compat-1.11pkg:apk/chainguard/ingress-nginx-controller-fips-iamguarded-compat-1.11pkg:apk/chainguard/ingress-nginx-controller-iamguarded-compat-1.11pkg:apk/chainguard/ingress-nginx-custom-error-pages-1.10pkg:apk/chainguard/ingress-nginx-custom-error-pages-1.11pkg:apk/chainguard/ingress-nginx-custom-error-pages-compat-1.10pkg:apk/chainguard/ingress-nginx-custom-error-pages-compat-1.11pkg:apk/chainguard/ingress-nginx-custom-error-pages-fips-1.10pkg:apk/chainguard/ingress-nginx-custom-error-pages-fips-1.11pkg:apk/chainguard/ingress-nginx-fips-custom-error-pages-1.11pkg:apk/chainguard/ingress-nginx-fips-custom-error-pages-compat-1.11pkg:apk/chainguard/ingress-nginx-fips-opentelemetry-plugin-1.11pkg:apk/chainguard/ingress-nginx-opentelemetry-1.11pkg:apk/chainguard/ingress-nginx-opentelemetry-compat-1.11pkg:apk/chainguard/ingress-nginx-opentelemetry-plugin-1.10pkg:apk/chainguard/ingress-nginx-opentelemetry-plugin-1.11pkg:apk/chainguard/k3spkg:apk/chainguard/k3s-embeddedpkg:apk/chainguard/k3s-imagespkg:apk/chainguard/k3s-multicallpkg:apk/chainguard/k3s-staticpkg:apk/chainguard/kubeadm-1.28pkg:apk/chainguard/kubeadm-1.28-defaultpkg:apk/chainguard/kubeadm-1.29pkg:apk/chainguard/kubeadm-1.29-defaultpkg:apk/chainguard/kubeadm-1.30pkg:apk/chainguard/kubeadm-1.30-defaultpkg:apk/chainguard/kubeadm-1.30-default-compatpkg:apk/chainguard/kubeadm-1.31pkg:apk/chainguard/kubeadm-1.31-defaultpkg:apk/chainguard/kubeadm-1.31-default-compatpkg:apk/chainguard/kubeadm-fips-1.28pkg:apk/chainguard/kubeadm-fips-1.28-defaultpkg:apk/chainguard/kubeadm-fips-1.29pkg:apk/chainguard/kubeadm-fips-1.29-defaultpkg:apk/chainguard/kubeadm-fips-1.30pkg:apk/chainguard/kubeadm-fips-1.30-defaultpkg:apk/chainguard/kubeadm-fips-1.30-default-compatpkg:apk/chainguard/kubeadm-fips-1.31pkg:apk/chainguard/kubeadm-fips-1.31-defaultpkg:apk/chainguard/kubeadm-fips-1.31-default-compatpkg:apk/chainguard/kube-apiserver-1.28pkg:apk/chainguard/kube-apiserver-1.28-defaultpkg:apk/chainguard/kube-apiserver-1.29pkg:apk/chainguard/kube-apiserver-1.29-defaultpkg:apk/chainguard/kube-apiserver-1.30pkg:apk/chainguard/kube-apiserver-1.30-defaultpkg:apk/chainguard/kube-apiserver-1.30-default-compatpkg:apk/chainguard/kube-apiserver-1.31pkg:apk/chainguard/kube-apiserver-1.31-defaultpkg:apk/chainguard/kube-apiserver-1.31-default-compatpkg:apk/chainguard/kube-apiserver-fips-1.28pkg:apk/chainguard/kube-apiserver-fips-1.28-defaultpkg:apk/chainguard/kube-apiserver-fips-1.29pkg:apk/chainguard/kube-apiserver-fips-1.29-defaultpkg:apk/chainguard/kube-apiserver-fips-1.30pkg:apk/chainguard/kube-apiserver-fips-1.30-defaultpkg:apk/chainguard/kube-apiserver-fips-1.30-default-compatpkg:apk/chainguard/kube-apiserver-fips-1.31pkg:apk/chainguard/kube-apiserver-fips-1.31-defaultpkg:apk/chainguard/kube-apiserver-fips-1.31-default-compatpkg:apk/chainguard/kube-controller-manager-1.28pkg:apk/chainguard/kube-controller-manager-1.28-defaultpkg:apk/chainguard/kube-controller-manager-1.29pkg:apk/chainguard/kube-controller-manager-1.29-defaultpkg:apk/chainguard/kube-controller-manager-1.30pkg:apk/chainguard/kube-controller-manager-1.30-defaultpkg:apk/chainguard/kube-controller-manager-1.30-default-compatpkg:apk/chainguard/kube-controller-manager-1.31pkg:apk/chainguard/kube-controller-manager-1.31-defaultpkg:apk/chainguard/kube-controller-manager-1.31-default-compatpkg:apk/chainguard/kube-controller-manager-fips-1.28pkg:apk/chainguard/kube-controller-manager-fips-1.28-defaultpkg:apk/chainguard/kube-controller-manager-fips-1.29pkg:apk/chainguard/kube-controller-manager-fips-1.29-defaultpkg:apk/chainguard/kube-controller-manager-fips-1.30pkg:apk/chainguard/kube-controller-manager-fips-1.30-defaultpkg:apk/chainguard/kube-controller-manager-fips-1.30-default-compatpkg:apk/chainguard/kube-controller-manager-fips-1.31pkg:apk/chainguard/kube-controller-manager-fips-1.31-defaultpkg:apk/chainguard/kube-controller-manager-fips-1.31-default-compatpkg:apk/chainguard/kubectl-1.28pkg:apk/chainguard/kubectl-1.28-bitnami-compatpkg:apk/chainguard/kubectl-1.28-defaultpkg:apk/chainguard/kubectl-1.29pkg:apk/chainguard/kubectl-1.29-bitnami-compatpkg:apk/chainguard/kubectl-1.29-defaultpkg:apk/chainguard/kubectl-1.29-iamguarded-compatpkg:apk/chainguard/kubectl-1.30pkg:apk/chainguard/kubectl-1.30-bitnami-compatpkg:apk/chainguard/kubectl-1.30-defaultpkg:apk/chainguard/kubectl-1.30-default-compatpkg:apk/chainguard/kubectl-1.30-iamguarded-compatpkg:apk/chainguard/kubectl-1.31pkg:apk/chainguard/kubectl-1.31-defaultpkg:apk/chainguard/kubectl-1.31-default-compatpkg:apk/chainguard/kubectl-1.31-iamguarded-compatpkg:apk/chainguard/kubectl-bash-completion-1.28pkg:apk/chainguard/kubectl-bash-completion-1.29pkg:apk/chainguard/kubectl-bash-completion-1.30pkg:apk/chainguard/kubectl-bash-completion-1.31pkg:apk/chainguard/kubectl-bash-completion-fips-1.28pkg:apk/chainguard/kubectl-bash-completion-fips-1.29pkg:apk/chainguard/kubectl-bash-completion-fips-1.30pkg:apk/chainguard/kubectl-bash-completion-fips-1.31pkg:apk/chainguard/kubectl-fips-1.28pkg:apk/chainguard/kubectl-fips-1.28-defaultpkg:apk/chainguard/kubectl-fips-1.29pkg:apk/chainguard/kubectl-fips-1.29-defaultpkg:apk/chainguard/kubectl-fips-1.30pkg:apk/chainguard/kubectl-fips-1.30-defaultpkg:apk/chainguard/kubectl-fips-1.30-default-compatpkg:apk/chainguard/kubectl-fips-1.31pkg:apk/chainguard/kubectl-fips-1.31-defaultpkg:apk/chainguard/kubectl-fips-1.31-default-compatpkg:apk/chainguard/kubelet-1.28pkg:apk/chainguard/kubelet-1.28-defaultpkg:apk/chainguard/kubelet-1.29pkg:apk/chainguard/kubelet-1.29-defaultpkg:apk/chainguard/kubelet-1.30pkg:apk/chainguard/kubelet-1.30-defaultpkg:apk/chainguard/kubelet-1.30-default-compatpkg:apk/chainguard/kubelet-1.31pkg:apk/chainguard/kubelet-1.31-defaultpkg:apk/chainguard/kubelet-1.31-default-compatpkg:apk/chainguard/kubelet-fips-1.28pkg:apk/chainguard/kubelet-fips-1.28-defaultpkg:apk/chainguard/kubelet-fips-1.29pkg:apk/chainguard/kubelet-fips-1.29-defaultpkg:apk/chainguard/kubelet-fips-1.30pkg:apk/chainguard/kubelet-fips-1.30-defaultpkg:apk/chainguard/kubelet-fips-1.30-default-compatpkg:apk/chainguard/kubelet-fips-1.31pkg:apk/chainguard/kubelet-fips-1.31-defaultpkg:apk/chainguard/kubelet-fips-1.31-default-compatpkg:apk/chainguard/kube-proxy-1.28pkg:apk/chainguard/kube-proxy-1.28-defaultpkg:apk/chainguard/kube-proxy-1.28-default-compatpkg:apk/chainguard/kube-proxy-1.29pkg:apk/chainguard/kube-proxy-1.29-defaultpkg:apk/chainguard/kube-proxy-1.29-default-compatpkg:apk/chainguard/kube-proxy-1.30pkg:apk/chainguard/kube-proxy-1.30-defaultpkg:apk/chainguard/kube-proxy-1.30-default-compatpkg:apk/chainguard/kube-proxy-1.31pkg:apk/chainguard/kube-proxy-1.31-defaultpkg:apk/chainguard/kube-proxy-1.31-default-compatpkg:apk/chainguard/kube-proxy-fips-1.28pkg:apk/chainguard/kube-proxy-fips-1.28-defaultpkg:apk/chainguard/kube-proxy-fips-1.29pkg:apk/chainguard/kube-proxy-fips-1.29-defaultpkg:apk/chainguard/kube-proxy-fips-1.30pkg:apk/chainguard/kube-proxy-fips-1.30-defaultpkg:apk/chainguard/kube-proxy-fips-1.30-default-compatpkg:apk/chainguard/kube-proxy-fips-1.31pkg:apk/chainguard/kube-proxy-fips-1.31-defaultpkg:apk/chainguard/kube-proxy-fips-1.31-default-compatpkg:apk/chainguard/kubernetes-1.28pkg:apk/chainguard/kubernetes-1.28-defaultpkg:apk/chainguard/kubernetes-1.29pkg:apk/chainguard/kubernetes-1.29-defaultpkg:apk/chainguard/kubernetes-1.30pkg:apk/chainguard/kubernetes-1.30-defaultpkg:apk/chainguard/kubernetes-1.31pkg:apk/chainguard/kubernetes-1.31-defaultpkg:apk/chainguard/kubernetes-fips-1.28pkg:apk/chainguard/kubernetes-fips-1.28-defaultpkg:apk/chainguard/kubernetes-fips-1.29pkg:apk/chainguard/kubernetes-fips-1.29-defaultpkg:apk/chainguard/kubernetes-fips-1.30pkg:apk/chainguard/kubernetes-fips-1.30-defaultpkg:apk/chainguard/kubernetes-fips-1.31pkg:apk/chainguard/kubernetes-fips-1.31-defaultpkg:apk/chainguard/kubernetes-pause-1.28pkg:apk/chainguard/kubernetes-pause-1.29pkg:apk/chainguard/kubernetes-pause-1.30pkg:apk/chainguard/kubernetes-pause-1.31pkg:apk/chainguard/kubernetes-pause-compat-1.28pkg:apk/chainguard/kubernetes-pause-compat-1.29pkg:apk/chainguard/kubernetes-pause-compat-1.30pkg:apk/chainguard/kubernetes-pause-compat-1.31pkg:apk/chainguard/kubernetes-pause-fips-3.9pkg:apk/chainguard/kube-scheduler-1.28pkg:apk/chainguard/kube-scheduler-1.28-defaultpkg:apk/chainguard/kube-scheduler-1.29pkg:apk/chainguard/kube-scheduler-1.29-defaultpkg:apk/chainguard/kube-scheduler-1.30pkg:apk/chainguard/kube-scheduler-1.30-defaultpkg:apk/chainguard/kube-scheduler-1.30-default-compatpkg:apk/chainguard/kube-scheduler-1.31pkg:apk/chainguard/kube-scheduler-1.31-defaultpkg:apk/chainguard/kube-scheduler-1.31-default-compatpkg:apk/chainguard/kube-scheduler-fips-1.28pkg:apk/chainguard/kube-scheduler-fips-1.28-defaultpkg:apk/chainguard/kube-scheduler-fips-1.29pkg:apk/chainguard/kube-scheduler-fips-1.29-defaultpkg:apk/chainguard/kube-scheduler-fips-1.30pkg:apk/chainguard/kube-scheduler-fips-1.30-defaultpkg:apk/chainguard/kube-scheduler-fips-1.30-default-compatpkg:apk/chainguard/kube-scheduler-fips-1.31pkg:apk/chainguard/kube-scheduler-fips-1.31-defaultpkg:apk/chainguard/kube-scheduler-fips-1.31-default-compatpkg:apk/chainguard/kube-webhook-certgen-1.10pkg:apk/chainguard/kube-webhook-certgen-1.11pkg:apk/chainguard/kube-webhook-certgen-fips-1.10pkg:apk/chainguard/kube-webhook-certgen-fips-1.11pkg:apk/chainguard/neuvectorpkg:apk/chainguard/neuvector-cis-benchmarkspkg:apk/chainguard/neuvector-controllerpkg:apk/chainguard/neuvector-controller-fipspkg:apk/chainguard/neuvector-enforcerpkg:apk/chainguard/neuvector-enforcer-fipspkg:apk/chainguard/neuvector-fipspkg:apk/chainguard/neuvector-monitorpkg:apk/chainguard/neuvector-nstoolspkg:apk/chainguard/neuvector-scannerpkg:apk/chainguard/neuvector-scanner-fipspkg:apk/chainguard/neuvector-scanner-monitorpkg:apk/chainguard/neuvector-scanner-monitor-fipspkg:apk/chainguard/neuvector-scanner-taskpkg:apk/chainguard/neuvector-scanner-task-fipspkg:apk/chainguard/neuvector-upgraderpkg:apk/chainguard/neuvector-upgrader-fipspkg:apk/chainguard/newrelic-infrastructure-agent-1.43pkg:apk/chainguard/node-feature-discovery-0.15pkg:apk/chainguard/node-feature-discovery-0.16pkg:apk/chainguard/opentelemetry-collector-contribpkg:apk/chainguard/opentelemetry-collector-contrib-compatpkg:apk/chainguard/opentelemetry-collector-contrib-fipspkg:apk/chainguard/podmanpkg:apk/chainguard/podman-docpkg:apk/chainguard/runcpkg:apk/chainguard/runc-docpkg:apk/chainguard/syftpkg:apk/wolfi/buildahpkg:apk/wolfi/cadvisorpkg:apk/wolfi/cadvisor-compatpkg:apk/wolfi/cluster-autoscaler-1.31pkg:apk/wolfi/cluster-autoscaler-1.31-compatpkg:apk/wolfi/ctoppkg:apk/wolfi/dockerpkg:apk/wolfi/docker-config-mirror-gcrpkg:apk/wolfi/dockerdpkg:apk/wolfi/docker-dindpkg:apk/wolfi/docker-dind-compatpkg:apk/wolfi/dockerd-oci-entrypointpkg:apk/wolfi/dockerd-servicepkg:apk/wolfi/docker-initpkg:apk/wolfi/docker-modprobe-compatpkg:apk/wolfi/docker-oci-entrypointpkg:apk/wolfi/docker-rootlesspkg:apk/wolfi/gpu-feature-discoverypkg:apk/wolfi/grafana-alloypkg:apk/wolfi/grafana-alloy-compatpkg:apk/wolfi/grypepkg:apk/wolfi/ingress-nginx-controller-1.10pkg:apk/wolfi/ingress-nginx-controller-1.10-compatpkg:apk/wolfi/ingress-nginx-controller-1.10-kube-webhook-certgenpkg:apk/wolfi/ingress-nginx-controller-1.11pkg:apk/wolfi/ingress-nginx-controller-1.11-compatpkg:apk/wolfi/ingress-nginx-controller-1.11-kube-webhook-certgenpkg:apk/wolfi/ingress-nginx-controller-compat-1.11pkg:apk/wolfi/ingress-nginx-opentelemetry-1.11pkg:apk/wolfi/ingress-nginx-opentelemetry-compat-1.11pkg:apk/wolfi/k3spkg:apk/wolfi/k3s-embeddedpkg:apk/wolfi/k3s-imagespkg:apk/wolfi/k3s-multicallpkg:apk/wolfi/k3s-staticpkg:apk/wolfi/kubeadm-1.28pkg:apk/wolfi/kubeadm-1.28-defaultpkg:apk/wolfi/kubeadm-1.29pkg:apk/wolfi/kubeadm-1.29-defaultpkg:apk/wolfi/kubeadm-1.30pkg:apk/wolfi/kubeadm-1.30-defaultpkg:apk/wolfi/kubeadm-1.31pkg:apk/wolfi/kubeadm-1.31-defaultpkg:apk/wolfi/kube-apiserver-1.28pkg:apk/wolfi/kube-apiserver-1.28-defaultpkg:apk/wolfi/kube-apiserver-1.29pkg:apk/wolfi/kube-apiserver-1.29-defaultpkg:apk/wolfi/kube-apiserver-1.30pkg:apk/wolfi/kube-apiserver-1.30-defaultpkg:apk/wolfi/kube-apiserver-1.31pkg:apk/wolfi/kube-apiserver-1.31-defaultpkg:apk/wolfi/kube-controller-manager-1.28pkg:apk/wolfi/kube-controller-manager-1.28-defaultpkg:apk/wolfi/kube-controller-manager-1.29pkg:apk/wolfi/kube-controller-manager-1.29-defaultpkg:apk/wolfi/kube-controller-manager-1.30pkg:apk/wolfi/kube-controller-manager-1.30-defaultpkg:apk/wolfi/kube-controller-manager-1.31pkg:apk/wolfi/kube-controller-manager-1.31-defaultpkg:apk/wolfi/kubectl-1.28pkg:apk/wolfi/kubectl-1.28-defaultpkg:apk/wolfi/kubectl-1.29pkg:apk/wolfi/kubectl-1.29-defaultpkg:apk/wolfi/kubectl-1.30pkg:apk/wolfi/kubectl-1.30-defaultpkg:apk/wolfi/kubectl-1.31pkg:apk/wolfi/kubectl-1.31-defaultpkg:apk/wolfi/kubectl-bash-completion-1.28pkg:apk/wolfi/kubectl-bash-completion-1.29pkg:apk/wolfi/kubectl-bash-completion-1.30pkg:apk/wolfi/kubectl-bash-completion-1.31pkg:apk/wolfi/kubelet-1.28pkg:apk/wolfi/kubelet-1.28-defaultpkg:apk/wolfi/kubelet-1.29pkg:apk/wolfi/kubelet-1.29-defaultpkg:apk/wolfi/kubelet-1.30pkg:apk/wolfi/kubelet-1.30-defaultpkg:apk/wolfi/kubelet-1.31pkg:apk/wolfi/kubelet-1.31-defaultpkg:apk/wolfi/kube-proxy-1.28pkg:apk/wolfi/kube-proxy-1.28-defaultpkg:apk/wolfi/kube-proxy-1.29pkg:apk/wolfi/kube-proxy-1.29-defaultpkg:apk/wolfi/kube-proxy-1.30pkg:apk/wolfi/kube-proxy-1.30-defaultpkg:apk/wolfi/kube-proxy-1.31pkg:apk/wolfi/kube-proxy-1.31-defaultpkg:apk/wolfi/kube-proxy-1.31-default-compatpkg:apk/wolfi/kubernetes-1.28pkg:apk/wolfi/kubernetes-1.28-defaultpkg:apk/wolfi/kubernetes-1.29pkg:apk/wolfi/kubernetes-1.29-defaultpkg:apk/wolfi/kubernetes-1.30pkg:apk/wolfi/kubernetes-1.30-defaultpkg:apk/wolfi/kubernetes-1.31pkg:apk/wolfi/kubernetes-1.31-defaultpkg:apk/wolfi/kubernetes-pause-1.31pkg:apk/wolfi/kubernetes-pause-compat-1.31pkg:apk/wolfi/kube-scheduler-1.28pkg:apk/wolfi/kube-scheduler-1.28-defaultpkg:apk/wolfi/kube-scheduler-1.29pkg:apk/wolfi/kube-scheduler-1.29-defaultpkg:apk/wolfi/kube-scheduler-1.30pkg:apk/wolfi/kube-scheduler-1.30-defaultpkg:apk/wolfi/kube-scheduler-1.31pkg:apk/wolfi/kube-scheduler-1.31-defaultpkg:apk/wolfi/kube-webhook-certgen-1.11pkg:apk/wolfi/neuvectorpkg:apk/wolfi/neuvector-cis-benchmarkspkg:apk/wolfi/neuvector-controllerpkg:apk/wolfi/neuvector-enforcerpkg:apk/wolfi/neuvector-monitorpkg:apk/wolfi/neuvector-nstoolspkg:apk/wolfi/neuvector-scannerpkg:apk/wolfi/neuvector-scanner-monitorpkg:apk/wolfi/neuvector-scanner-taskpkg:apk/wolfi/node-feature-discovery-0.15pkg:apk/wolfi/node-feature-discovery-0.16pkg:apk/wolfi/opentelemetry-collector-contribpkg:apk/wolfi/opentelemetry-collector-contrib-compatpkg:apk/wolfi/podmanpkg:apk/wolfi/podman-docpkg:apk/wolfi/runcpkg:apk/wolfi/runc-docpkg:apk/wolfi/syftpkg:golang/github.com/opencontainers/runcpkg:rpm/opensuse/apptainer&distro=openSUSE%20Leap%2015.6pkg:rpm/opensuse/govulncheck-vulndb&distro=openSUSE%20Tumbleweedpkg:rpm/opensuse/kubevirt&distro=openSUSE%20Leap%2016.0pkg:rpm/opensuse/runc&distro=openSUSE%20Leap%2015.5pkg:rpm/opensuse/runc&distro=openSUSE%20Leap%2015.6pkg:rpm/opensuse/runc&distro=openSUSE%20Leap%20Micro%205.5pkg:rpm/opensuse/runc&distro=openSUSE%20Tumbleweedpkg:rpm/opensuse/squashfuse&distro=openSUSE%20Leap%2015.6pkg:rpm/suse/apptainer&distro=SUSE%20Linux%20Enterprise%20Module%20for%20HPC%2015%20SP7pkg:rpm/suse/apptainer&distro=SUSE%20Linux%20Enterprise%20Server%2015%20SP6-LTSSpkg:rpm/suse/kubevirt&distro=SUSE%20Linux%20Enterprise%20Module%20for%20Containers%2015%20SP7pkg:rpm/suse/kubevirt&distro=SUSE%20Linux%20Enterprise%20Server%2016.0pkg:rpm/suse/kubevirt&distro=SUSE%20Linux%20Enterprise%20Server%20for%20SAP%20applications%2016.0pkg:rpm/suse/kubevirt&distro=SUSE%20Linux%20Micro%206.2pkg:rpm/suse/runc&distro=SUSE%20Enterprise%20Storage%207.1pkg:rpm/suse/runc&distro=SUSE%20Linux%20Enterprise%20High%20Performance%20Computing%2015%20SP2-LTSSpkg:rpm/suse/runc&distro=SUSE%20Linux%20Enterprise%20High%20Performance%20Computing%2015%20SP3-LTSSpkg:rpm/suse/runc&distro=SUSE%20Linux%20Enterprise%20High%20Performance%20Computing%2015%20SP4-ESPOSpkg:rpm/suse/runc&distro=SUSE%20Linux%20Enterprise%20High%20Performance%20Computing%2015%20SP4-LTSSpkg:rpm/suse/runc&distro=SUSE%20Linux%20Enterprise%20High%20Performance%20Computing%2015%20SP5-ESPOSpkg:rpm/suse/runc&distro=SUSE%20Linux%20Enterprise%20High%20Performance%20Computing%2015%20SP5-LTSSpkg:rpm/suse/runc&distro=SUSE%20Linux%20Enterprise%20Micro%205.1pkg:rpm/suse/runc&distro=SUSE%20Linux%20Enterprise%20Micro%205.2pkg:rpm/suse/runc&distro=SUSE%20Linux%20Enterprise%20Micro%205.3pkg:rpm/suse/runc&distro=SUSE%20Linux%20Enterprise%20Micro%205.4pkg:rpm/suse/runc&distro=SUSE%20Linux%20Enterprise%20Micro%205.5pkg:rpm/suse/runc&distro=SUSE%20Linux%20Enterprise%20Module%20for%20Basesystem%2015%20SP7pkg:rpm/suse/runc&distro=SUSE%20Linux%20Enterprise%20Module%20for%20Containers%2012pkg:rpm/suse/runc&distro=SUSE%20Linux%20Enterprise%20Module%20for%20Containers%2015%20SP5pkg:rpm/suse/runc&distro=SUSE%20Linux%20Enterprise%20Module%20for%20Containers%2015%20SP6pkg:rpm/suse/runc&distro=SUSE%20Linux%20Enterprise%20Server%2012%20SP5-LTSSpkg:rpm/suse/runc&distro=SUSE%20Linux%20Enterprise%20Server%2015%20SP2-LTSSpkg:rpm/suse/runc&distro=SUSE%20Linux%20Enterprise%20Server%2015%20SP3-LTSSpkg:rpm/suse/runc&distro=SUSE%20Linux%20Enterprise%20Server%2015%20SP4-LTSSpkg:rpm/suse/runc&distro=SUSE%20Linux%20Enterprise%20Server%2015%20SP5-LTSSpkg:rpm/suse/runc&distro=SUSE%20Linux%20Enterprise%20Server%20for%20SAP%20Applications%2015%20SP2pkg:rpm/suse/runc&distro=SUSE%20Linux%20Enterprise%20Server%20for%20SAP%20Applications%2015%20SP3pkg:rpm/suse/runc&distro=SUSE%20Linux%20Enterprise%20Server%20for%20SAP%20Applications%2015%20SP4pkg:rpm/suse/runc&distro=SUSE%20Linux%20Enterprise%20Server%20for%20SAP%20Applications%2015%20SP5pkg:rpm/suse/runc&distro=SUSE%20Linux%20Enterprise%20Server%20LTSS%20Extended%20Security%2012%20SP5pkg:rpm/suse/runc&distro=SUSE%20Linux%20Micro%206.0pkg:rpm/suse/runc&distro=SUSE%20Linux%20Micro%206.1pkg:rpm/suse/squashfuse&distro=SUSE%20Linux%20Enterprise%20Module%20for%20HPC%2015%20SP7pkg:rpm/suse/squashfuse&distro=SUSE%20Linux%20Enterprise%20Server%2015%20SP6-LTSS
< 1.37.2-r1+ 455 more
- (no CPE)range: < 1.37.2-r1
- (no CPE)range: < 0.50.0-r2
- (no CPE)range: < 0.50.0-r2
- (no CPE)range: < 0.50.0-r2
- (no CPE)range: < 1.31.5-r1
- (no CPE)range: < 1.31.5-r1
- (no CPE)range: < 1.31.2-r0
- (no CPE)range: < 1.31.2-r0
- (no CPE)range: < 0.7.7-r19
- (no CPE)range: < 27.2.0-r1
- (no CPE)range: < 27.2.0-r1
- (no CPE)range: < 27.2.0-r1
- (no CPE)range: < 27.2.0-r1
- (no CPE)range: < 27.2.0-r1
- (no CPE)range: < 27.2.0-r1
- (no CPE)range: < 27.2.0-r1
- (no CPE)range: < 27.2.0-r1
- (no CPE)range: < 27.2.0-r1
- (no CPE)range: < 27.2.0-r1
- (no CPE)range: < 27.2.0-r1
- (no CPE)range: < 1.31.35-r1
- (no CPE)range: < 1.31.35-r1
- (no CPE)range: < 1.31.33-r0
- (no CPE)range: < 1.31.33-r0
- (no CPE)range: < 1.31.35-r1
- (no CPE)range: < 1.31.33-r0
- (no CPE)range: < 1.31.35-r1
- (no CPE)range: < 1.31.33-r0
- (no CPE)range: < 1.31.35-r1
- (no CPE)range: < 1.31.33-r0
- (no CPE)range: < 1.31.35-r1
- (no CPE)range: < 1.31.35-r1
- (no CPE)range: < 1.31.33-r0
- (no CPE)range: < 1.11-r3
- (no CPE)range: < 0.8.2-r5
- (no CPE)range: < 1.3.1-r1
- (no CPE)range: < 1.3.1-r1
- (no CPE)range: < 1.3.1-r1
- (no CPE)range: < 0.80.0-r1
- (no CPE)range: < 1.10.4-r1
- (no CPE)range: < 1.10.4-r1
- (no CPE)range: < 1.10.4-r1
- (no CPE)range: < 1.11.2-r1
- (no CPE)range: < 1.11.2-r1
- (no CPE)range: < 1.11.2-r1
- (no CPE)range: < 1.10.4-r1
- (no CPE)range: < 1.11.2-r1
- (no CPE)range: < 1.10.4-r1
- (no CPE)range: < 1.11.2-r1
- (no CPE)range: < 1.10.4-r1
- (no CPE)range: < 1.11.2-r1
- (no CPE)range: < 1.11.2-r1
- (no CPE)range: < 1.11.2-r1
- (no CPE)range: < 1.11.2-r1
- (no CPE)range: < 1.11.2-r1
- (no CPE)range: < 1.10.4-r1
- (no CPE)range: < 1.11.2-r1
- (no CPE)range: < 1.10.4-r1
- (no CPE)range: < 1.11.2-r1
- (no CPE)range: < 1.10.4-r1
- (no CPE)range: < 1.11.2-r1
- (no CPE)range: < 1.11.2-r1
- (no CPE)range: < 1.11.2-r1
- (no CPE)range: < 1.11.2-r1
- (no CPE)range: < 1.11.2-r1
- (no CPE)range: < 1.11.2-r1
- (no CPE)range: < 1.10.4-r1
- (no CPE)range: < 1.11.2-r1
- (no CPE)range: < 1.31.0.1-r1
- (no CPE)range: < 1.31.0.1-r1
- (no CPE)range: < 1.31.0.1-r1
- (no CPE)range: < 1.31.0.1-r1
- (no CPE)range: < 1.31.0.1-r1
- (no CPE)range: < 1.28.15-r11
- (no CPE)range: < 1.28.15-r11
- (no CPE)range: < 1.29.15-r2
- (no CPE)range: < 1.29.15-r2
- (no CPE)range: < 1.30.11-r2
- (no CPE)range: < 1.30.11-r2
- (no CPE)range: < 1.30.11-r2
- (no CPE)range: < 1.31.14-r0
- (no CPE)range: < 1.31.14-r0
- (no CPE)range: < 1.31.14-r0
- (no CPE)range: < 1.28.15-r1
- (no CPE)range: < 1.28.15-r1
- (no CPE)range: < 1.29.10-r1
- (no CPE)range: < 1.29.10-r1
- (no CPE)range: < 1.30.11-r2
- (no CPE)range: < 1.30.11-r2
- (no CPE)range: < 1.30.11-r2
- (no CPE)range: < 1.31.7-r2
- (no CPE)range: < 1.31.7-r2
- (no CPE)range: < 1.31.7-r2
- (no CPE)range: < 1.28.15-r11
- (no CPE)range: < 1.28.15-r11
- (no CPE)range: < 1.29.15-r2
- (no CPE)range: < 1.29.15-r2
- (no CPE)range: < 1.30.11-r2
- (no CPE)range: < 1.30.11-r2
- (no CPE)range: < 1.30.11-r2
- (no CPE)range: < 1.31.14-r0
- (no CPE)range: < 1.31.14-r0
- (no CPE)range: < 1.31.14-r0
- (no CPE)range: < 1.28.15-r1
- (no CPE)range: < 1.28.15-r1
- (no CPE)range: < 1.29.10-r1
- (no CPE)range: < 1.29.10-r1
- (no CPE)range: < 1.30.11-r2
- (no CPE)range: < 1.30.11-r2
- (no CPE)range: < 1.30.11-r2
- (no CPE)range: < 1.31.7-r2
- (no CPE)range: < 1.31.7-r2
- (no CPE)range: < 1.31.7-r2
- (no CPE)range: < 1.28.15-r11
- (no CPE)range: < 1.28.15-r11
- (no CPE)range: < 1.29.15-r2
- (no CPE)range: < 1.29.15-r2
- (no CPE)range: < 1.30.11-r2
- (no CPE)range: < 1.30.11-r2
- (no CPE)range: < 1.30.11-r2
- (no CPE)range: < 1.31.14-r0
- (no CPE)range: < 1.31.14-r0
- (no CPE)range: < 1.31.14-r0
- (no CPE)range: < 1.28.15-r1
- (no CPE)range: < 1.28.15-r1
- (no CPE)range: < 1.29.10-r1
- (no CPE)range: < 1.29.10-r1
- (no CPE)range: < 1.30.11-r2
- (no CPE)range: < 1.30.11-r2
- (no CPE)range: < 1.30.11-r2
- (no CPE)range: < 1.31.7-r2
- (no CPE)range: < 1.31.7-r2
- (no CPE)range: < 1.31.7-r2
- (no CPE)range: < 1.28.15-r11
- (no CPE)range: < 1.28.15-r11
- (no CPE)range: < 1.28.15-r11
- (no CPE)range: < 1.29.15-r2
- (no CPE)range: < 1.29.15-r2
- (no CPE)range: < 1.29.15-r2
- (no CPE)range: < 1.29.15-r2
- (no CPE)range: < 1.30.11-r2
- (no CPE)range: < 1.30.11-r2
- (no CPE)range: < 1.30.11-r2
- (no CPE)range: < 1.30.11-r2
- (no CPE)range: < 1.30.11-r2
- (no CPE)range: < 1.31.14-r0
- (no CPE)range: < 1.31.14-r0
- (no CPE)range: < 1.31.14-r0
- (no CPE)range: < 1.31.14-r0
- (no CPE)range: < 1.28.15-r11
- (no CPE)range: < 1.29.15-r2
- (no CPE)range: < 1.30.11-r2
- (no CPE)range: < 1.31.14-r0
- (no CPE)range: < 1.28.15-r1
- (no CPE)range: < 1.29.10-r1
- (no CPE)range: < 1.30.11-r2
- (no CPE)range: < 1.31.7-r2
- (no CPE)range: < 1.28.15-r1
- (no CPE)range: < 1.28.15-r1
- (no CPE)range: < 1.29.10-r1
- (no CPE)range: < 1.29.10-r1
- (no CPE)range: < 1.30.11-r2
- (no CPE)range: < 1.30.11-r2
- (no CPE)range: < 1.30.11-r2
- (no CPE)range: < 1.31.7-r2
- (no CPE)range: < 1.31.7-r2
- (no CPE)range: < 1.31.7-r2
- (no CPE)range: < 1.28.15-r11
- (no CPE)range: < 1.28.15-r11
- (no CPE)range: < 1.29.15-r2
- (no CPE)range: < 1.29.15-r2
- (no CPE)range: < 1.30.11-r2
- (no CPE)range: < 1.30.11-r2
- (no CPE)range: < 1.30.11-r2
- (no CPE)range: < 1.31.14-r0
- (no CPE)range: < 1.31.14-r0
- (no CPE)range: < 1.31.14-r0
- (no CPE)range: < 1.28.15-r1
- (no CPE)range: < 1.28.15-r1
- (no CPE)range: < 1.29.10-r1
- (no CPE)range: < 1.29.10-r1
- (no CPE)range: < 1.30.11-r2
- (no CPE)range: < 1.30.11-r2
- (no CPE)range: < 1.30.11-r2
- (no CPE)range: < 1.31.7-r2
- (no CPE)range: < 1.31.7-r2
- (no CPE)range: < 1.31.7-r2
- (no CPE)range: < 1.28.15-r11
- (no CPE)range: < 1.28.15-r11
- (no CPE)range: < 1.28.15-r11
- (no CPE)range: < 1.29.15-r2
- (no CPE)range: < 1.29.15-r2
- (no CPE)range: < 1.29.15-r2
- (no CPE)range: < 1.30.11-r2
- (no CPE)range: < 1.30.11-r2
- (no CPE)range: < 1.30.11-r2
- (no CPE)range: < 1.31.14-r0
- (no CPE)range: < 1.31.14-r0
- (no CPE)range: < 1.31.14-r0
- (no CPE)range: < 1.28.15-r1
- (no CPE)range: < 1.28.15-r1
- (no CPE)range: < 1.29.10-r1
- (no CPE)range: < 1.29.10-r1
- (no CPE)range: < 1.30.11-r2
- (no CPE)range: < 1.30.11-r2
- (no CPE)range: < 1.30.11-r2
- (no CPE)range: < 1.31.7-r2
- (no CPE)range: < 1.31.7-r2
- (no CPE)range: < 1.31.7-r2
- (no CPE)range: < 1.28.15-r11
- (no CPE)range: < 1.28.15-r11
- (no CPE)range: < 1.29.15-r2
- (no CPE)range: < 1.29.15-r2
- (no CPE)range: < 1.30.11-r2
- (no CPE)range: < 1.30.11-r2
- (no CPE)range: < 1.31.14-r0
- (no CPE)range: < 1.31.14-r0
- (no CPE)range: < 1.28.15-r1
- (no CPE)range: < 1.28.15-r1
- (no CPE)range: < 1.29.10-r1
- (no CPE)range: < 1.29.10-r1
- (no CPE)range: < 1.30.11-r2
- (no CPE)range: < 1.30.11-r2
- (no CPE)range: < 1.31.7-r2
- (no CPE)range: < 1.31.7-r2
- (no CPE)range: < 1.28.15-r11
- (no CPE)range: < 1.29.15-r2
- (no CPE)range: < 1.30.11-r2
- (no CPE)range: < 1.31.14-r0
- (no CPE)range: < 1.28.15-r11
- (no CPE)range: < 1.29.15-r2
- (no CPE)range: < 1.30.11-r2
- (no CPE)range: < 1.31.14-r0
- (no CPE)range: < 1.31.7-r2
- (no CPE)range: < 1.28.15-r11
- (no CPE)range: < 1.28.15-r11
- (no CPE)range: < 1.29.15-r2
- (no CPE)range: < 1.29.15-r2
- (no CPE)range: < 1.30.11-r2
- (no CPE)range: < 1.30.11-r2
- (no CPE)range: < 1.30.11-r2
- (no CPE)range: < 1.31.14-r0
- (no CPE)range: < 1.31.14-r0
- (no CPE)range: < 1.31.14-r0
- (no CPE)range: < 1.28.15-r1
- (no CPE)range: < 1.28.15-r1
- (no CPE)range: < 1.29.10-r1
- (no CPE)range: < 1.29.10-r1
- (no CPE)range: < 1.30.11-r2
- (no CPE)range: < 1.30.11-r2
- (no CPE)range: < 1.30.11-r2
- (no CPE)range: < 1.31.7-r2
- (no CPE)range: < 1.31.7-r2
- (no CPE)range: < 1.31.7-r2
- (no CPE)range: < 1.10.4-r1
- (no CPE)range: < 1.11.2-r1
- (no CPE)range: < 1.10.4-r1
- (no CPE)range: < 1.11.2-r1
- (no CPE)range: < 5.3.4-r3
- (no CPE)range: < 5.3.4-r3
- (no CPE)range: < 5.3.4-r3
- (no CPE)range: < 5.4.3-r0
- (no CPE)range: < 5.3.4-r3
- (no CPE)range: < 5.4.3-r0
- (no CPE)range: < 5.4.3-r0
- (no CPE)range: < 5.3.4-r3
- (no CPE)range: < 5.3.4-r3
- (no CPE)range: < 0_git20240528-r8
- (no CPE)range: < 0_git20240528-r5
- (no CPE)range: < 0_git20240528-r8
- (no CPE)range: < 0_git20240528-r5
- (no CPE)range: < 0_git20240528-r8
- (no CPE)range: < 0_git20240528-r5
- (no CPE)range: < 5.3.4-r3
- (no CPE)range: < 5.4.3-r0
- (no CPE)range: < 1.43.2-r13
- (no CPE)range: < 0.15.6-r2
- (no CPE)range: < 0.16.4-r1
- (no CPE)range: < 0.108.0-r1
- (no CPE)range: < 0.108.0-r1
- (no CPE)range: < 0.108.0-r1
- (no CPE)range: < 5.2.2-r1
- (no CPE)range: < 5.2.2-r1
- (no CPE)range: < 1.1.14-r0
- (no CPE)range: < 1.1.14-r0
- (no CPE)range: < 1.11.1-r1
- (no CPE)range: < 1.37.2-r1
- (no CPE)range: < 0.50.0-r2
- (no CPE)range: < 0.50.0-r2
- (no CPE)range: < 1.31.5-r1
- (no CPE)range: < 1.31.5-r1
- (no CPE)range: < 0.7.7-r19
- (no CPE)range: < 27.2.0-r1
- (no CPE)range: < 27.2.0-r1
- (no CPE)range: < 27.2.0-r1
- (no CPE)range: < 27.2.0-r1
- (no CPE)range: < 27.2.0-r1
- (no CPE)range: < 27.2.0-r1
- (no CPE)range: < 27.2.0-r1
- (no CPE)range: < 27.2.0-r1
- (no CPE)range: < 27.2.0-r1
- (no CPE)range: < 27.2.0-r1
- (no CPE)range: < 27.2.0-r1
- (no CPE)range: < 0.8.2-r5
- (no CPE)range: < 1.3.1-r1
- (no CPE)range: < 1.3.1-r1
- (no CPE)range: < 0.80.0-r1
- (no CPE)range: < 1.10.4-r1
- (no CPE)range: < 1.10.4-r1
- (no CPE)range: < 1.10.4-r1
- (no CPE)range: < 1.11.2-r1
- (no CPE)range: < 1.11.2-r1
- (no CPE)range: < 1.11.2-r1
- (no CPE)range: < 1.11.2-r1
- (no CPE)range: < 1.11.2-r1
- (no CPE)range: < 1.11.2-r1
- (no CPE)range: < 1.31.0.1-r1
- (no CPE)range: < 1.31.0.1-r1
- (no CPE)range: < 1.31.0.1-r1
- (no CPE)range: < 1.31.0.1-r1
- (no CPE)range: < 1.31.0.1-r1
- (no CPE)range: < 1.28.15-r11
- (no CPE)range: < 1.28.15-r11
- (no CPE)range: < 1.29.15-r2
- (no CPE)range: < 1.29.15-r2
- (no CPE)range: < 1.30.11-r2
- (no CPE)range: < 1.30.11-r2
- (no CPE)range: < 1.31.14-r0
- (no CPE)range: < 1.31.14-r0
- (no CPE)range: < 1.28.15-r11
- (no CPE)range: < 1.28.15-r11
- (no CPE)range: < 1.29.15-r2
- (no CPE)range: < 1.29.15-r2
- (no CPE)range: < 1.30.11-r2
- (no CPE)range: < 1.30.11-r2
- (no CPE)range: < 1.31.14-r0
- (no CPE)range: < 1.31.14-r0
- (no CPE)range: < 1.28.15-r11
- (no CPE)range: < 1.28.15-r11
- (no CPE)range: < 1.29.15-r2
- (no CPE)range: < 1.29.15-r2
- (no CPE)range: < 1.30.11-r2
- (no CPE)range: < 1.30.11-r2
- (no CPE)range: < 1.31.14-r0
- (no CPE)range: < 1.31.14-r0
- (no CPE)range: < 1.28.15-r11
- (no CPE)range: < 1.28.15-r11
- (no CPE)range: < 1.29.15-r2
- (no CPE)range: < 1.29.15-r2
- (no CPE)range: < 1.30.11-r2
- (no CPE)range: < 1.30.11-r2
- (no CPE)range: < 1.31.14-r0
- (no CPE)range: < 1.31.14-r0
- (no CPE)range: < 1.28.15-r11
- (no CPE)range: < 1.29.15-r2
- (no CPE)range: < 1.30.11-r2
- (no CPE)range: < 1.31.14-r0
- (no CPE)range: < 1.28.15-r11
- (no CPE)range: < 1.28.15-r11
- (no CPE)range: < 1.29.15-r2
- (no CPE)range: < 1.29.15-r2
- (no CPE)range: < 1.30.11-r2
- (no CPE)range: < 1.30.11-r2
- (no CPE)range: < 1.31.14-r0
- (no CPE)range: < 1.31.14-r0
- (no CPE)range: < 1.28.15-r11
- (no CPE)range: < 1.28.15-r11
- (no CPE)range: < 1.29.15-r2
- (no CPE)range: < 1.29.15-r2
- (no CPE)range: < 1.30.11-r2
- (no CPE)range: < 1.30.11-r2
- (no CPE)range: < 1.31.14-r0
- (no CPE)range: < 1.31.14-r0
- (no CPE)range: < 1.31.14-r0
- (no CPE)range: < 1.28.15-r11
- (no CPE)range: < 1.28.15-r11
- (no CPE)range: < 1.29.15-r2
- (no CPE)range: < 1.29.15-r2
- (no CPE)range: < 1.30.11-r2
- (no CPE)range: < 1.30.11-r2
- (no CPE)range: < 1.31.14-r0
- (no CPE)range: < 1.31.14-r0
- (no CPE)range: < 1.31.14-r0
- (no CPE)range: < 1.31.14-r0
- (no CPE)range: < 1.28.15-r11
- (no CPE)range: < 1.28.15-r11
- (no CPE)range: < 1.29.15-r2
- (no CPE)range: < 1.29.15-r2
- (no CPE)range: < 1.30.11-r2
- (no CPE)range: < 1.30.11-r2
- (no CPE)range: < 1.31.14-r0
- (no CPE)range: < 1.31.14-r0
- (no CPE)range: < 1.11.2-r1
- (no CPE)range: < 5.3.4-r3
- (no CPE)range: < 5.3.4-r3
- (no CPE)range: < 5.3.4-r3
- (no CPE)range: < 5.3.4-r3
- (no CPE)range: < 5.3.4-r3
- (no CPE)range: < 5.3.4-r3
- (no CPE)range: < 0_git20240528-r8
- (no CPE)range: < 0_git20240528-r8
- (no CPE)range: < 0_git20240528-r8
- (no CPE)range: < 0.15.6-r2
- (no CPE)range: < 0.16.4-r1
- (no CPE)range: < 0.108.0-r1
- (no CPE)range: < 0.108.0-r1
- (no CPE)range: < 5.2.2-r1
- (no CPE)range: < 5.2.2-r1
- (no CPE)range: < 1.1.14-r0
- (no CPE)range: < 1.1.14-r0
- (no CPE)range: < 1.11.1-r1
- (no CPE)range: < 1.1.14
- (no CPE)range: < 1.4.5-150600.4.12.1
- (no CPE)range: < 0.0.20250807T150727-1.1
- (no CPE)range: < 1.7.0-160000.1.1
- (no CPE)range: < 1.1.14-150000.70.1
- (no CPE)range: < 1.1.14-150000.70.1
- (no CPE)range: < 1.1.14-150000.70.1
- (no CPE)range: < 1.2.0~rc3-1.1
- (no CPE)range: < 0.5.0-150600.3.2.1
- (no CPE)range: < 1.4.5-150600.4.12.1
- (no CPE)range: < 1.4.5-150600.4.12.1
- (no CPE)range: < 1.7.0-150700.3.16.2
- (no CPE)range: < 1.7.0-160000.1.1
- (no CPE)range: < 1.7.0-160000.1.1
- (no CPE)range: < 1.7.0-160000.1.1
- (no CPE)range: < 1.1.14-150000.70.1
- (no CPE)range: < 1.1.14-150000.70.1
- (no CPE)range: < 1.1.14-150000.70.1
- (no CPE)range: < 1.1.14-150000.70.1
- (no CPE)range: < 1.1.14-150000.70.1
- (no CPE)range: < 1.2.6-150000.73.2
- (no CPE)range: < 1.2.6-150000.73.2
- (no CPE)range: < 1.1.14-150000.70.1
- (no CPE)range: < 1.1.14-150000.70.1
- (no CPE)range: < 1.1.14-150000.70.1
- (no CPE)range: < 1.1.14-150000.70.1
- (no CPE)range: < 1.1.14-150000.70.1
- (no CPE)range: < 1.2.6-150000.73.2
- (no CPE)range: < 1.1.14-16.55.1
- (no CPE)range: < 1.1.14-150000.70.1
- (no CPE)range: < 1.1.14-150000.70.1
- (no CPE)range: < 1.2.6-16.60.2
- (no CPE)range: < 1.1.14-150000.70.1
- (no CPE)range: < 1.1.14-150000.70.1
- (no CPE)range: < 1.1.14-150000.70.1
- (no CPE)range: < 1.2.6-150000.73.2
- (no CPE)range: < 1.1.14-150000.70.1
- (no CPE)range: < 1.1.14-150000.70.1
- (no CPE)range: < 1.1.14-150000.70.1
- (no CPE)range: < 1.2.6-150000.73.2
- (no CPE)range: < 1.2.6-16.60.2
- (no CPE)range: < 1.1.14-1.1
- (no CPE)range: < 1.2.6-slfo.1.1_1.1
- (no CPE)range: < 0.5.0-150600.3.2.1
- (no CPE)range: < 0.5.0-150600.3.2.1
- opencontainers/runcv5Range: < 1.1.14
Patches
363c2908164f3rootfs: try to scope MkdirAll to stay inside the rootfs
3 files changed · +174 −10
libcontainer/rootfs_linux.go+21 −10 modified@@ -313,7 +313,7 @@ func mountCgroupV1(m *configs.Mount, c *mountConfig) error { // inside the tmpfs, so we don't want to resolve symlinks). subsystemPath := filepath.Join(c.root, b.Destination) subsystemName := filepath.Base(b.Destination) - if err := os.MkdirAll(subsystemPath, 0o755); err != nil { + if err := utils.MkdirAllInRoot(c.root, subsystemPath, 0o755); err != nil { return err } if err := utils.WithProcfd(c.root, b.Destination, func(dstFd string) error { @@ -505,15 +505,26 @@ func createMountpoint(rootfs string, m mountEntry) (string, error) { return "", fmt.Errorf("%w: file bind mount over rootfs", errRootfsToFile) } // Make the parent directory. - if err := os.MkdirAll(filepath.Dir(dest), 0o755); err != nil { + destDir, destBase := filepath.Split(dest) + destDirFd, err := utils.MkdirAllInRootOpen(rootfs, destDir, 0o755) + if err != nil { return "", fmt.Errorf("make parent dir of file bind-mount: %w", err) } - // Make the target file. - f, err := os.OpenFile(dest, os.O_CREATE, 0o755) - if err != nil { - return "", fmt.Errorf("create target of file bind-mount: %w", err) + defer destDirFd.Close() + // Make the target file. We want to avoid opening any file that is + // already there because it could be a "bad" file like an invalid + // device or hung tty that might cause a DoS, so we use mknodat. + // destBase does not contain any "/" components, and mknodat does + // not follow trailing symlinks, so we can safely just call mknodat + // here. + if err := unix.Mknodat(int(destDirFd.Fd()), destBase, unix.S_IFREG|0o644, 0); err != nil { + // If we get EEXIST, there was already an inode there and + // we can consider that a success. + if !errors.Is(err, unix.EEXIST) { + err = &os.PathError{Op: "mknod regular file", Path: dest, Err: err} + return "", fmt.Errorf("create target of file bind-mount: %w", err) + } } - _ = f.Close() // Nothing left to do. return dest, nil } @@ -532,7 +543,7 @@ func createMountpoint(rootfs string, m mountEntry) (string, error) { } } - if err := os.MkdirAll(dest, 0o755); err != nil { + if err := utils.MkdirAllInRoot(rootfs, dest, 0o755); err != nil { return "", err } return dest, nil @@ -565,7 +576,7 @@ func mountToRootfs(c *mountConfig, m mountEntry) error { } else if !fi.IsDir() { return fmt.Errorf("filesystem %q must be mounted on ordinary directory", m.Device) } - if err := os.MkdirAll(dest, 0o755); err != nil { + if err := utils.MkdirAllInRoot(rootfs, dest, 0o755); err != nil { return err } // Selinux kernels do not support labeling of /proc or /sys. @@ -928,7 +939,7 @@ func createDeviceNode(rootfs string, node *devices.Device, bind bool) error { if dest == rootfs { return fmt.Errorf("%w: mknod over rootfs", errRootfsToFile) } - if err := os.MkdirAll(filepath.Dir(dest), 0o755); err != nil { + if err := utils.MkdirAllInRoot(rootfs, filepath.Dir(dest), 0o755); err != nil { return err } if bind {
libcontainer/system/linux.go+41 −0 modified@@ -6,7 +6,9 @@ import ( "fmt" "io" "os" + "runtime" "strconv" + "strings" "syscall" "unsafe" @@ -214,3 +216,42 @@ func SetLinuxPersonality(personality int) error { } return nil } + +func prepareAt(dir *os.File, path string) (int, string) { + if dir == nil { + return unix.AT_FDCWD, path + } + + // Rather than just filepath.Join-ing path here, do it manually so the + // error and handle correctly indicate cases like path=".." as being + // relative to the correct directory. The handle.Name() might end up being + // wrong but because this is (currently) only used in MkdirAllInRoot, that + // isn't a problem. + dirName := dir.Name() + if !strings.HasSuffix(dirName, "/") { + dirName += "/" + } + fullPath := dirName + path + + return int(dir.Fd()), fullPath +} + +func Openat(dir *os.File, path string, flags int, mode uint32) (*os.File, error) { + dirFd, fullPath := prepareAt(dir, path) + fd, err := unix.Openat(dirFd, path, flags, mode) + if err != nil { + return nil, &os.PathError{Op: "openat", Path: fullPath, Err: err} + } + runtime.KeepAlive(dir) + return os.NewFile(uintptr(fd), fullPath), nil +} + +func Mkdirat(dir *os.File, path string, mode uint32) error { + dirFd, fullPath := prepareAt(dir, path) + err := unix.Mkdirat(dirFd, path, mode) + if err != nil { + err = &os.PathError{Op: "mkdirat", Path: fullPath, Err: err} + } + runtime.KeepAlive(dir) + return err +}
libcontainer/utils/utils_unix.go+112 −0 modified@@ -3,6 +3,7 @@ package utils import ( + "errors" "fmt" "math" "os" @@ -13,6 +14,8 @@ import ( "sync" _ "unsafe" // for go:linkname + "github.com/opencontainers/runc/libcontainer/system" + securejoin "github.com/cyphar/filepath-securejoin" "github.com/sirupsen/logrus" "golang.org/x/sys/unix" @@ -275,3 +278,112 @@ func IsLexicallyInRoot(root, path string) bool { } return strings.HasPrefix(path, root) } + +// MkdirAllInRootOpen attempts to make +// +// path, _ := securejoin.SecureJoin(root, unsafePath) +// os.MkdirAll(path, mode) +// os.Open(path) +// +// safer against attacks where components in the path are changed between +// SecureJoin returning and MkdirAll (or Open) being called. In particular, we +// try to detect any symlink components in the path while we are doing the +// MkdirAll. +// +// NOTE: Unlike os.MkdirAll, mode is not Go's os.FileMode, it is the unix mode +// (the suid/sgid/sticky bits are not the same as for os.FileMode). +// +// NOTE: If unsafePath is a subpath of root, we assume that you have already +// called SecureJoin and so we use the provided path verbatim without resolving +// any symlinks (this is done in a way that avoids symlink-exchange races). +// This means that the path also must not contain ".." elements, otherwise an +// error will occur. +// +// This is a somewhat less safe alternative to +// <https://github.com/cyphar/filepath-securejoin/pull/13>, but it should +// detect attempts to trick us into creating directories outside of the root. +// We should migrate to securejoin.MkdirAll once it is merged. +func MkdirAllInRootOpen(root, unsafePath string, mode uint32) (_ *os.File, Err error) { + // If the path is already "within" the root, use it verbatim. + fullPath := unsafePath + if !IsLexicallyInRoot(root, unsafePath) { + var err error + fullPath, err = securejoin.SecureJoin(root, unsafePath) + if err != nil { + return nil, err + } + } + subPath, err := filepath.Rel(root, fullPath) + if err != nil { + return nil, err + } + + // Check for any silly mode bits. + if mode&^0o7777 != 0 { + return nil, fmt.Errorf("tried to include non-mode bits in MkdirAll mode: 0o%.3o", mode) + } + + currentDir, err := os.OpenFile(root, unix.O_DIRECTORY|unix.O_CLOEXEC, 0) + if err != nil { + return nil, fmt.Errorf("open root handle: %w", err) + } + defer func() { + if Err != nil { + currentDir.Close() + } + }() + + for _, part := range strings.Split(subPath, string(filepath.Separator)) { + switch part { + case "", ".": + // Skip over no-op components. + continue + case "..": + return nil, fmt.Errorf("possible breakout detected: found %q component in SecureJoin subpath %s", part, subPath) + } + + nextDir, err := system.Openat(currentDir, part, unix.O_DIRECTORY|unix.O_NOFOLLOW|unix.O_CLOEXEC, 0) + switch { + case err == nil: + // Update the currentDir. + _ = currentDir.Close() + currentDir = nextDir + + case errors.Is(err, unix.ENOTDIR): + // This might be a symlink or some other random file. Either way, + // error out. + return nil, fmt.Errorf("cannot mkdir in %s/%s: %w", currentDir.Name(), part, unix.ENOTDIR) + + case errors.Is(err, os.ErrNotExist): + // Luckily, mkdirat will not follow trailing symlinks, so this is + // safe to do as-is. + if err := system.Mkdirat(currentDir, part, mode); err != nil { + return nil, err + } + // Open the new directory. There is a race here where an attacker + // could swap the directory with a different directory, but + // MkdirAll's fuzzy semantics mean we don't care about that. + nextDir, err := system.Openat(currentDir, part, unix.O_DIRECTORY|unix.O_NOFOLLOW|unix.O_CLOEXEC, 0) + if err != nil { + return nil, fmt.Errorf("open newly created directory: %w", err) + } + // Update the currentDir. + _ = currentDir.Close() + currentDir = nextDir + + default: + return nil, err + } + } + return currentDir, nil +} + +// MkdirAllInRoot is a wrapper around MkdirAllInRootOpen which closes the +// returned handle, for callers that don't need to use it. +func MkdirAllInRoot(root, unsafePath string, mode uint32) error { + f, err := MkdirAllInRootOpen(root, unsafePath, mode) + if err == nil { + _ = f.Close() + } + return err +}
f0b652ea61ff[1.1] rootfs: try to scope MkdirAll to stay inside the rootfs
3 files changed · +176 −10
libcontainer/rootfs_linux.go+21 −10 modified@@ -253,7 +253,7 @@ func mountCgroupV1(m *configs.Mount, c *mountConfig) error { if c.cgroupns { subsystemPath := filepath.Join(c.root, b.Destination) subsystemName := filepath.Base(b.Destination) - if err := os.MkdirAll(subsystemPath, 0o755); err != nil { + if err := utils.MkdirAllInRoot(c.root, subsystemPath, 0o755); err != nil { return err } if err := utils.WithProcfd(c.root, b.Destination, func(procfd string) error { @@ -406,15 +406,26 @@ func createMountpoint(rootfs string, m *configs.Mount, mountFd *int, source stri return "", fmt.Errorf("%w: file bind mount over rootfs", errRootfsToFile) } // Make the parent directory. - if err := os.MkdirAll(filepath.Dir(dest), 0o755); err != nil { + destDir, destBase := filepath.Split(dest) + destDirFd, err := utils.MkdirAllInRootOpen(rootfs, destDir, 0o755) + if err != nil { return "", fmt.Errorf("make parent dir of file bind-mount: %w", err) } - // Make the target file. - f, err := os.OpenFile(dest, os.O_CREATE, 0o755) - if err != nil { - return "", fmt.Errorf("create target of file bind-mount: %w", err) + defer destDirFd.Close() + // Make the target file. We want to avoid opening any file that is + // already there because it could be a "bad" file like an invalid + // device or hung tty that might cause a DoS, so we use mknodat. + // destBase does not contain any "/" components, and mknodat does + // not follow trailing symlinks, so we can safely just call mknodat + // here. + if err := unix.Mknodat(int(destDirFd.Fd()), destBase, unix.S_IFREG|0o644, 0); err != nil { + // If we get EEXIST, there was already an inode there and + // we can consider that a success. + if !errors.Is(err, unix.EEXIST) { + err = &os.PathError{Op: "mknod regular file", Path: dest, Err: err} + return "", fmt.Errorf("create target of file bind-mount: %w", err) + } } - _ = f.Close() // Nothing left to do. return dest, nil } @@ -433,7 +444,7 @@ func createMountpoint(rootfs string, m *configs.Mount, mountFd *int, source stri } } - if err := os.MkdirAll(dest, 0o755); err != nil { + if err := utils.MkdirAllInRoot(rootfs, dest, 0o755); err != nil { return "", err } return dest, nil @@ -463,7 +474,7 @@ func mountToRootfs(m *configs.Mount, c *mountConfig) error { } else if !fi.IsDir() { return fmt.Errorf("filesystem %q must be mounted on ordinary directory", m.Device) } - if err := os.MkdirAll(dest, 0o755); err != nil { + if err := utils.MkdirAllInRoot(rootfs, dest, 0o755); err != nil { return err } // Selinux kernels do not support labeling of /proc or /sys. @@ -751,7 +762,7 @@ func createDeviceNode(rootfs string, node *devices.Device, bind bool) error { if dest == rootfs { return fmt.Errorf("%w: mknod over rootfs", errRootfsToFile) } - if err := os.MkdirAll(filepath.Dir(dest), 0o755); err != nil { + if err := utils.MkdirAllInRoot(rootfs, filepath.Dir(dest), 0o755); err != nil { return err } if bind {
libcontainer/system/linux.go+41 −0 modified@@ -6,6 +6,8 @@ package system import ( "os" "os/exec" + "runtime" + "strings" "unsafe" "golang.org/x/sys/unix" @@ -102,3 +104,42 @@ func GetSubreaper() (int, error) { return int(i), nil } + +func prepareAt(dir *os.File, path string) (int, string) { + if dir == nil { + return unix.AT_FDCWD, path + } + + // Rather than just filepath.Join-ing path here, do it manually so the + // error and handle correctly indicate cases like path=".." as being + // relative to the correct directory. The handle.Name() might end up being + // wrong but because this is (currently) only used in MkdirAllInRoot, that + // isn't a problem. + dirName := dir.Name() + if !strings.HasSuffix(dirName, "/") { + dirName += "/" + } + fullPath := dirName + path + + return int(dir.Fd()), fullPath +} + +func Openat(dir *os.File, path string, flags int, mode uint32) (*os.File, error) { + dirFd, fullPath := prepareAt(dir, path) + fd, err := unix.Openat(dirFd, path, flags, mode) + if err != nil { + return nil, &os.PathError{Op: "openat", Path: fullPath, Err: err} + } + runtime.KeepAlive(dir) + return os.NewFile(uintptr(fd), fullPath), nil +} + +func Mkdirat(dir *os.File, path string, mode uint32) error { + dirFd, fullPath := prepareAt(dir, path) + err := unix.Mkdirat(dirFd, path, mode) + if err != nil { + err = &os.PathError{Op: "mkdirat", Path: fullPath, Err: err} + } + runtime.KeepAlive(dir) + return err +}
libcontainer/utils/utils_unix.go+114 −0 modified@@ -4,12 +4,17 @@ package utils import ( + "errors" "fmt" "os" + "path/filepath" "strconv" "strings" _ "unsafe" // for go:linkname + "github.com/opencontainers/runc/libcontainer/system" + + securejoin "github.com/cyphar/filepath-securejoin" "golang.org/x/sys/unix" ) @@ -130,3 +135,112 @@ func IsLexicallyInRoot(root, path string) bool { } return strings.HasPrefix(path, root) } + +// MkdirAllInRootOpen attempts to make +// +// path, _ := securejoin.SecureJoin(root, unsafePath) +// os.MkdirAll(path, mode) +// os.Open(path) +// +// safer against attacks where components in the path are changed between +// SecureJoin returning and MkdirAll (or Open) being called. In particular, we +// try to detect any symlink components in the path while we are doing the +// MkdirAll. +// +// NOTE: Unlike os.MkdirAll, mode is not Go's os.FileMode, it is the unix mode +// (the suid/sgid/sticky bits are not the same as for os.FileMode). +// +// NOTE: If unsafePath is a subpath of root, we assume that you have already +// called SecureJoin and so we use the provided path verbatim without resolving +// any symlinks (this is done in a way that avoids symlink-exchange races). +// This means that the path also must not contain ".." elements, otherwise an +// error will occur. +// +// This is a somewhat less safe alternative to +// <https://github.com/cyphar/filepath-securejoin/pull/13>, but it should +// detect attempts to trick us into creating directories outside of the root. +// We should migrate to securejoin.MkdirAll once it is merged. +func MkdirAllInRootOpen(root, unsafePath string, mode uint32) (_ *os.File, Err error) { + // If the path is already "within" the root, use it verbatim. + fullPath := unsafePath + if !IsLexicallyInRoot(root, unsafePath) { + var err error + fullPath, err = securejoin.SecureJoin(root, unsafePath) + if err != nil { + return nil, err + } + } + subPath, err := filepath.Rel(root, fullPath) + if err != nil { + return nil, err + } + + // Check for any silly mode bits. + if mode&^0o7777 != 0 { + return nil, fmt.Errorf("tried to include non-mode bits in MkdirAll mode: 0o%.3o", mode) + } + + currentDir, err := os.OpenFile(root, unix.O_DIRECTORY|unix.O_CLOEXEC, 0) + if err != nil { + return nil, fmt.Errorf("open root handle: %w", err) + } + defer func() { + if Err != nil { + currentDir.Close() + } + }() + + for _, part := range strings.Split(subPath, string(filepath.Separator)) { + switch part { + case "", ".": + // Skip over no-op components. + continue + case "..": + return nil, fmt.Errorf("possible breakout detected: found %q component in SecureJoin subpath %s", part, subPath) + } + + nextDir, err := system.Openat(currentDir, part, unix.O_DIRECTORY|unix.O_NOFOLLOW|unix.O_CLOEXEC, 0) + switch { + case err == nil: + // Update the currentDir. + _ = currentDir.Close() + currentDir = nextDir + + case errors.Is(err, unix.ENOTDIR): + // This might be a symlink or some other random file. Either way, + // error out. + return nil, fmt.Errorf("cannot mkdir in %s/%s: %w", currentDir.Name(), part, unix.ENOTDIR) + + case errors.Is(err, os.ErrNotExist): + // Luckily, mkdirat will not follow trailing symlinks, so this is + // safe to do as-is. + if err := system.Mkdirat(currentDir, part, mode); err != nil { + return nil, err + } + // Open the new directory. There is a race here where an attacker + // could swap the directory with a different directory, but + // MkdirAll's fuzzy semantics mean we don't care about that. + nextDir, err := system.Openat(currentDir, part, unix.O_DIRECTORY|unix.O_NOFOLLOW|unix.O_CLOEXEC, 0) + if err != nil { + return nil, fmt.Errorf("open newly created directory: %w", err) + } + // Update the currentDir. + _ = currentDir.Close() + currentDir = nextDir + + default: + return nil, err + } + } + return currentDir, nil +} + +// MkdirAllInRoot is a wrapper around MkdirAllInRootOpen which closes the +// returned handle, for callers that don't need to use it. +func MkdirAllInRoot(root, unsafePath string, mode uint32) error { + f, err := MkdirAllInRootOpen(root, unsafePath, mode) + if err == nil { + _ = f.Close() + } + return err +}
8781993968fd[1.1] rootfs: consolidate mountpoint creation logic
3 files changed · +94 −109
libcontainer/container_linux.go+6 −22 modified@@ -1276,8 +1276,7 @@ func (c *linuxContainer) restoreNetwork(req *criurpc.CriuReq, criuOpts *CriuOpts // restore using CRIU. This function is inspired from the code in // rootfs_linux.go func (c *linuxContainer) makeCriuRestoreMountpoints(m *configs.Mount) error { - switch m.Device { - case "cgroup": + if m.Device == "cgroup" { // No mount point(s) need to be created: // // * for v1, mount points are saved by CRIU because @@ -1286,26 +1285,11 @@ func (c *linuxContainer) makeCriuRestoreMountpoints(m *configs.Mount) error { // * for v2, /sys/fs/cgroup is a real mount, but // the mountpoint appears as soon as /sys is mounted return nil - case "bind": - // The prepareBindMount() function checks if source - // exists. So it cannot be used for other filesystem types. - // TODO: pass something else than nil? Not sure if criu is - // impacted by issue #2484 - if err := prepareBindMount(m, c.config.Rootfs, nil); err != nil { - return err - } - default: - // for all other filesystems just create the mountpoints - dest, err := securejoin.SecureJoin(c.config.Rootfs, m.Destination) - if err != nil { - return err - } - if err := checkProcMount(c.config.Rootfs, dest, m, ""); err != nil { - return err - } - if err := os.MkdirAll(dest, 0o755); err != nil { - return err - } + } + // TODO: pass something else than nil? Not sure if criu is + // impacted by issue #2484 + if _, err := createMountpoint(c.config.Rootfs, m, nil, ""); err != nil { + return fmt.Errorf("create criu restore mount for %s mount: %w", m.Destination, err) } return nil }
libcontainer/rootfs_linux.go+73 −87 modified@@ -224,36 +224,6 @@ func mountCmd(cmd configs.Command) error { return nil } -func prepareBindMount(m *configs.Mount, rootfs string, mountFd *int) error { - source := m.Source - if mountFd != nil { - source = "/proc/self/fd/" + strconv.Itoa(*mountFd) - } - - stat, err := os.Stat(source) - if err != nil { - // error out if the source of a bind mount does not exist as we will be - // unable to bind anything to it. - return err - } - // ensure that the destination of the bind mount is resolved of symlinks at mount time because - // any previous mounts can invalidate the next mount's destination. - // this can happen when a user specifies mounts within other mounts to cause breakouts or other - // evil stuff to try to escape the container's rootfs. - var dest string - if dest, err = securejoin.SecureJoin(rootfs, m.Destination); err != nil { - return err - } - if err := checkProcMount(rootfs, dest, m, source); err != nil { - return err - } - if err := createIfNotExists(dest, stat.IsDir()); err != nil { - return err - } - - return nil -} - func mountCgroupV1(m *configs.Mount, c *mountConfig) error { binds, err := getCgroupMounts(m) if err != nil { @@ -282,6 +252,7 @@ func mountCgroupV1(m *configs.Mount, c *mountConfig) error { for _, b := range binds { if c.cgroupns { subsystemPath := filepath.Join(c.root, b.Destination) + subsystemName := filepath.Base(b.Destination) if err := os.MkdirAll(subsystemPath, 0o755); err != nil { return err } @@ -292,7 +263,7 @@ func mountCgroupV1(m *configs.Mount, c *mountConfig) error { } var ( source = "cgroup" - data = filepath.Base(subsystemPath) + data = subsystemName ) if data == "systemd" { data = cgroups.CgroupNamePrefix + data @@ -322,14 +293,7 @@ func mountCgroupV1(m *configs.Mount, c *mountConfig) error { } func mountCgroupV2(m *configs.Mount, c *mountConfig) error { - dest, err := securejoin.SecureJoin(c.root, m.Destination) - if err != nil { - return err - } - if err := os.MkdirAll(dest, 0o755); err != nil { - return err - } - err = utils.WithProcfd(c.root, m.Destination, func(procfd string) error { + err := utils.WithProcfd(c.root, m.Destination, func(procfd string) error { return mount(m.Source, m.Destination, procfd, "cgroup2", uintptr(m.Flags), m.Data) }) if err == nil || !(errors.Is(err, unix.EPERM) || errors.Is(err, unix.EBUSY)) { @@ -411,6 +375,70 @@ func doTmpfsCopyUp(m *configs.Mount, rootfs, mountLabel string) (Err error) { }) } +var errRootfsToFile = errors.New("config tries to change rootfs to file") + +func createMountpoint(rootfs string, m *configs.Mount, mountFd *int, source string) (string, error) { + dest, err := securejoin.SecureJoin(rootfs, m.Destination) + if err != nil { + return "", err + } + if err := checkProcMount(rootfs, dest, m, source); err != nil { + return "", fmt.Errorf("check proc-safety of %s mount: %w", m.Destination, err) + } + + switch m.Device { + case "bind": + source := m.Source + if mountFd != nil { + source = "/proc/self/fd/" + strconv.Itoa(*mountFd) + } + + fi, err := os.Stat(source) + if err != nil { + // Error out if the source of a bind mount does not exist as we + // will be unable to bind anything to it. + return "", fmt.Errorf("bind mount source stat: %w", err) + } + // If the original source is not a directory, make the target a file. + if !fi.IsDir() { + // Make sure we aren't tricked into trying to make the root a file. + if rootfs == dest { + return "", fmt.Errorf("%w: file bind mount over rootfs", errRootfsToFile) + } + // Make the parent directory. + if err := os.MkdirAll(filepath.Dir(dest), 0o755); err != nil { + return "", fmt.Errorf("make parent dir of file bind-mount: %w", err) + } + // Make the target file. + f, err := os.OpenFile(dest, os.O_CREATE, 0o755) + if err != nil { + return "", fmt.Errorf("create target of file bind-mount: %w", err) + } + _ = f.Close() + // Nothing left to do. + return dest, nil + } + + case "tmpfs": + // If the original target exists, copy the mode for the tmpfs mount. + if stat, err := os.Stat(dest); err == nil { + dt := fmt.Sprintf("mode=%04o", syscallMode(stat.Mode())) + if m.Data != "" { + dt = dt + "," + m.Data + } + m.Data = dt + + // Nothing left to do. + return dest, nil + } + } + + if err := os.MkdirAll(dest, 0o755); err != nil { + return "", err + } + return dest, nil +} + func mountToRootfs(m *configs.Mount, c *mountConfig) error { rootfs := c.root @@ -442,46 +470,27 @@ func mountToRootfs(m *configs.Mount, c *mountConfig) error { return mountPropagate(m, rootfs, "", nil) } - mountLabel := c.label mountFd := c.fd - dest, err := securejoin.SecureJoin(rootfs, m.Destination) + dest, err := createMountpoint(rootfs, m, mountFd, m.Source) if err != nil { - return err + return fmt.Errorf("create mount destination for %s mount: %w", m.Destination, err) } + mountLabel := c.label switch m.Device { case "mqueue": - if err := os.MkdirAll(dest, 0o755); err != nil { - return err - } if err := mountPropagate(m, rootfs, "", nil); err != nil { return err } return label.SetFileLabel(dest, mountLabel) case "tmpfs": - if stat, err := os.Stat(dest); err != nil { - if err := os.MkdirAll(dest, 0o755); err != nil { - return err - } - } else { - dt := fmt.Sprintf("mode=%04o", syscallMode(stat.Mode())) - if m.Data != "" { - dt = dt + "," + m.Data - } - m.Data = dt - } - if m.Extensions&configs.EXT_COPYUP == configs.EXT_COPYUP { err = doTmpfsCopyUp(m, rootfs, mountLabel) } else { err = mountPropagate(m, rootfs, mountLabel, nil) } - return err case "bind": - if err := prepareBindMount(m, rootfs, mountFd); err != nil { - return err - } if err := mountPropagate(m, rootfs, mountLabel, mountFd); err != nil { return err } @@ -509,12 +518,6 @@ func mountToRootfs(m *configs.Mount, c *mountConfig) error { } return mountCgroupV1(m, c) default: - if err := checkProcMount(rootfs, dest, m, m.Source); err != nil { - return err - } - if err := os.MkdirAll(dest, 0o755); err != nil { - return err - } return mountPropagate(m, rootfs, mountLabel, mountFd) } if err := setRecAttr(m, rootfs); err != nil { @@ -745,6 +748,9 @@ func createDeviceNode(rootfs string, node *devices.Device, bind bool) error { if err != nil { return err } + if dest == rootfs { + return fmt.Errorf("%w: mknod over rootfs", errRootfsToFile) + } if err := os.MkdirAll(filepath.Dir(dest), 0o755); err != nil { return err } @@ -1011,26 +1017,6 @@ func chroot() error { return nil } -// createIfNotExists creates a file or a directory only if it does not already exist. -func createIfNotExists(path string, isDir bool) error { - if _, err := os.Stat(path); err != nil { - if os.IsNotExist(err) { - if isDir { - return os.MkdirAll(path, 0o755) - } - if err := os.MkdirAll(filepath.Dir(path), 0o755); err != nil { - return err - } - f, err := os.OpenFile(path, os.O_CREATE, 0o755) - if err != nil { - return err - } - _ = f.Close() - } - } - return nil -} - // readonlyPath will make a path read only. func readonlyPath(path string) error { if err := mount(path, path, "", "", unix.MS_BIND|unix.MS_REC, ""); err != nil {
libcontainer/utils/utils_unix.go+15 −0 modified@@ -7,6 +7,7 @@ import ( "fmt" "os" "strconv" + "strings" _ "unsafe" // for go:linkname "golang.org/x/sys/unix" @@ -115,3 +116,17 @@ func NewSockPair(name string) (parent *os.File, child *os.File, err error) { } return os.NewFile(uintptr(fds[1]), name+"-p"), os.NewFile(uintptr(fds[0]), name+"-c"), nil } + +// IsLexicallyInRoot is shorthand for strings.HasPrefix(path+"/", root+"/"), +// but properly handling the case where path or root are "/". +// +// NOTE: The return value only make sense if the path doesn't contain "..". +func IsLexicallyInRoot(root, path string) bool { + if root != "/" { + root += "/" + } + if path != "/" { + path += "/" + } + return strings.HasPrefix(path, root) +}
Vulnerability mechanics
Generated on May 9, 2026. Inputs: CWE entries + fix-commit diffs from this CVE's patches. Citations validated against bundle.
References
9- github.com/advisories/GHSA-jfvp-7x6p-h2pvghsaADVISORY
- nvd.nist.gov/vuln/detail/CVE-2024-45310ghsaADVISORY
- www.openwall.com/lists/oss-security/2024/09/03/1ghsaWEB
- github.com/opencontainers/runc/commit/63c2908164f3a1daea455bf5bcd8d363d70328c7ghsax_refsource_MISCWEB
- github.com/opencontainers/runc/commit/8781993968fd964ac723ff5f360b6f259e809a3eghsax_refsource_MISCWEB
- github.com/opencontainers/runc/commit/f0b652ea61ff6750a8fcc69865d45a7abf37accfghsax_refsource_MISCWEB
- github.com/opencontainers/runc/pull/4359ghsax_refsource_MISCWEB
- github.com/opencontainers/runc/security/advisories/GHSA-jfvp-7x6p-h2pvghsax_refsource_CONFIRMWEB
- security.netapp.com/advisory/ntap-20250221-0008ghsaWEB
News mentions
0No linked articles in our index yet.