From 9fa8b9de3e74c306db186494187fb789f0fdab4d Mon Sep 17 00:00:00 2001 From: Brian Goff Date: Thu, 22 Jun 2023 21:35:19 +0000 Subject: [PATCH] Fix tmpfs mode opts when dir already exists When a directory already exists (or after a container is restarted) the perms of the directory being mounted to were being used even when a different permission is set on the tmpfs mount options. This prepends the original directory perms to the mount options. If the perms were already set in the mount opts then those perms will win. This eliminates the need to perform a chmod after mount entirely. Signed-off-by: Brian Goff --- libcontainer/rootfs_linux.go | 20 ++++++++------------ tests/integration/run.bats | 34 ++++++++++++++++++++++++++++++++++ 2 files changed, 42 insertions(+), 12 deletions(-) diff --git a/libcontainer/rootfs_linux.go b/libcontainer/rootfs_linux.go index 4c9e90f04..00e84e791 100644 --- a/libcontainer/rootfs_linux.go +++ b/libcontainer/rootfs_linux.go @@ -443,11 +443,16 @@ func mountToRootfs(c *mountConfig, m mountEntry) error { } return label.SetFileLabel(dest, mountLabel) case "tmpfs": - stat, err := os.Stat(dest) - if err != nil { + if stat, err := os.Stat(dest); err != nil { if err := os.MkdirAll(dest, 0o755); err != nil { return err } + } else { + dt := fmt.Sprintf("mode=%04o", stat.Mode()) + if m.Data != "" { + dt = dt + "," + m.Data + } + m.Data = dt } if m.Extensions&configs.EXT_COPYUP == configs.EXT_COPYUP { @@ -456,16 +461,7 @@ func mountToRootfs(c *mountConfig, m mountEntry) error { err = mountPropagate(m, rootfs, mountLabel) } - if err != nil { - return err - } - - if stat != nil { - if err = os.Chmod(dest, stat.Mode()); err != nil { - return err - } - } - return nil + return err case "bind": if err := prepareBindMount(m, rootfs); err != nil { return err diff --git a/tests/integration/run.bats b/tests/integration/run.bats index ae4e0fa59..8afc4bbe8 100644 --- a/tests/integration/run.bats +++ b/tests/integration/run.bats @@ -76,3 +76,37 @@ function teardown() { [ "$status" -eq 0 ] [[ "${lines[0]}" == *'mydomainname'* ]] } + +@test "runc run with tmpfs perms" { + # shellcheck disable=SC2016 + update_config '.process.args = ["sh", "-c", "stat -c %a /tmp/test"]' + update_config '.mounts += [{"destination": "/tmp/test", "type": "tmpfs", "source": "tmpfs", "options": ["mode=0444"]}]' + + # Directory is to be created by runc. + runc run test_tmpfs + [ "$status" -eq 0 ] + [ "$output" = "444" ] + + # Run a 2nd time with the pre-existing directory. + # Ref: https://github.com/opencontainers/runc/issues/3911 + runc run test_tmpfs + [ "$status" -eq 0 ] + [ "$output" = "444" ] + + # Existing directory, custom perms, no mode on the mount, + # so it should use the directory's perms. + update_config '.mounts[-1].options = []' + chmod 0710 rootfs/tmp/test + # shellcheck disable=SC2016 + runc run test_tmpfs + [ "$status" -eq 0 ] + [ "$output" = "710" ] + + # Add back the mode on the mount, and it should use that instead. + # Just for fun, use different perms than was used earlier. + # shellcheck disable=SC2016 + update_config '.mounts[-1].options = ["mode=0410"]' + runc run test_tmpfs + [ "$status" -eq 0 ] + [ "$output" = "410" ] +}