diff --git a/libcontainer/rootfs_linux.go b/libcontainer/rootfs_linux.go index f9902e85b18..2ad61df9704 100644 --- a/libcontainer/rootfs_linux.go +++ b/libcontainer/rootfs_linux.go @@ -340,6 +340,13 @@ func mountToRootfs(m *configs.Mount, rootfs, mountLabel string, enableCgroupns b case "tmpfs": copyUp := m.Extensions&configs.EXT_COPYUP == configs.EXT_COPYUP tmpDir := "" + // dest might be an absolute symlink, so it needs + // to be resolved under rootfs. + dest, err := securejoin.SecureJoin(rootfs, m.Destination) + if err != nil { + return err + } + m.Destination = dest stat, err := os.Stat(dest) if err != nil { if err := os.MkdirAll(dest, 0755); err != nil { diff --git a/tests/integration/mounts.bats b/tests/integration/mounts.bats index 4be19f50e2c..a4b9f296e8d 100644 --- a/tests/integration/mounts.bats +++ b/tests/integration/mounts.bats @@ -37,3 +37,19 @@ function teardown() { [ "$status" -eq 0 ] [[ "${lines[0]}" == *'ro,'* ]] } + +# https://github.com/opencontainers/runc/issues/2683 +@test "runc run [tmpfs mount with absolute symlink]" { + # in container, /conf -> /real/conf + mkdir -p rootfs/real/conf + ln -s /real/conf rootfs/conf + update_config ' .mounts += [{ + type: "tmpfs", + source: "tmpfs", + destination: "/conf/stack", + options: ["ro", "nodev", "nosuid"] + }] + | .process.args |= ["true"]' + runc run test_busybox + [ "$status" -eq 0 ] +}