From 9af462e4a7ffde09db8db38d32cc3d746692042a 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 (cherry picked from commit 9fa8b9de3e74c306db186494187fb789f0fdab4d) Resolved conflicts: tests/integration/run.bats Signed-off-by: Bjorn Neergaard --- 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 c3f88fc7038..54520ad01d1 100644 --- a/libcontainer/rootfs_linux.go +++ b/libcontainer/rootfs_linux.go @@ -459,11 +459,16 @@ func mountToRootfs(m *configs.Mount, c *mountConfig) 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 { @@ -472,16 +477,7 @@ func mountToRootfs(m *configs.Mount, c *mountConfig) error { err = mountPropagate(m, rootfs, mountLabel, nil) } - 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, mountFd); err != nil { return err diff --git a/tests/integration/run.bats b/tests/integration/run.bats index 420040a52ed..d2eae2a0865 100644 --- a/tests/integration/run.bats +++ b/tests/integration/run.bats @@ -58,3 +58,37 @@ function teardown() { runc state test_run_keep [ "$status" -ne 0 ] } + +@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" ] +}