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" ] +}