From 2a9b44aabfa52bb071ff2e3564427da0bb82312e Mon Sep 17 00:00:00 2001 From: Aleksa Sarai Date: Wed, 5 Nov 2025 02:04:02 +1100 Subject: [PATCH 2/2] [1.3] rootfs: re-allow dangling symlinks in mount targets It seems there are a fair few images where dangling symlinks are used as path components for mount targets, which pathrs-lite does not support (and it would be difficult to fully support this in a race-free way). This was actually meant to be blocked by commit 63c2908164f3 ("rootfs: try to scope MkdirAll to stay inside the rootfs"), followed by commit dd827f7b715a ("utils: switch to securejoin.MkdirAllHandle"). However, we still used SecureJoin to construct mountpoint targets, which means that dangling symlinks were "resolved" before reaching pathrs-lite. This patch basically re-adds this hack in order to reduce the breakages we've seen so far. Signed-off-by: Aleksa Sarai Signed-off-by: Kir Kolyshkin --- libcontainer/rootfs_linux.go | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/libcontainer/rootfs_linux.go b/libcontainer/rootfs_linux.go index d85e7321..2fda3c9d 100644 --- a/libcontainer/rootfs_linux.go +++ b/libcontainer/rootfs_linux.go @@ -519,6 +519,17 @@ func (m *mountEntry) createOpenMountpoint(rootfs string) (Err error) { dstIsFile = !fi.IsDir() } + // In previous runc versions, we would tolerate nonsense paths with + // dangling symlinks as path components. pathrs-lite does not support + // this, so instead we have to emulate this behaviour by doing + // SecureJoin *purely to get a semi-reasonable path to use* and then we + // use pathrs-lite to operate on the path safely. + newUnsafePath, err := securejoin.SecureJoin(rootfs, unsafePath) + if err != nil { + return err + } + unsafePath = utils.StripRoot(rootfs, newUnsafePath) + if dstIsFile { dstFile, err = pathrs.CreateInRoot(rootfs, unsafePath, unix.O_CREAT|unix.O_EXCL|unix.O_NOFOLLOW, 0o644) } else { -- 2.51.1