Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add a warning if tmpdir/rundir are not on tmpfs #22141

Closed
wants to merge 1 commit into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions .cirrus.yml
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,8 @@ env:
# Runner statistics log file path/name
STATS_LOGFILE_SFX: 'runner_stats.log'
STATS_LOGFILE: '$GOSRC/${CIRRUS_TASK_NAME}-${STATS_LOGFILE_SFX}'
# Disable Podman warnings about /tmp not being a tmpfs
PODMAN_SUPPRESS_TMPFS_WARNING: 'true'

####
#### Cache-image names to test with (double-quotes around names are critical)
Expand Down
2 changes: 1 addition & 1 deletion contrib/cirrus/lib.sh
Original file line number Diff line number Diff line change
Expand Up @@ -95,7 +95,7 @@ EPOCH_TEST_COMMIT="$CIRRUS_BASE_SHA"
# contexts, such as host->container or root->rootless user
#
# List of envariables which must be EXACT matches
PASSTHROUGH_ENV_EXACT='CGROUP_MANAGER|DEST_BRANCH|DISTRO_NV|GOCACHE|GOPATH|GOSRC|NETWORK_BACKEND|OCI_RUNTIME|PODMAN_IGNORE_CGROUPSV1_WARNING|ROOTLESS_USER|SCRIPT_BASE|SKIP_USERNS|EC2_INST_TYPE|PODMAN_DB|STORAGE_FS'
PASSTHROUGH_ENV_EXACT='CGROUP_MANAGER|DEST_BRANCH|DISTRO_NV|GOCACHE|GOPATH|GOSRC|NETWORK_BACKEND|OCI_RUNTIME|PODMAN_IGNORE_CGROUPSV1_WARNING|ROOTLESS_USER|SCRIPT_BASE|SKIP_USERNS|EC2_INST_TYPE|PODMAN_DB|STORAGE_FS|PODMAN_SUPPRESS_TMPFS_WARNING'

# List of envariable patterns which must match AT THE BEGINNING of the name.
PASSTHROUGH_ENV_ATSTART='CI|LANG|LC_|TEST'
Expand Down
10 changes: 10 additions & 0 deletions libpod/runtime.go
Original file line number Diff line number Diff line change
Expand Up @@ -609,6 +609,16 @@ func makeRuntime(ctx context.Context, runtime *Runtime) (retErr error) {
// refresh runs.
runtime.valid = true

// Is the tmpdir or run root not on a tmpfs?
// If so, throw a very explicit warning that this is not a sane config.
// Allow suppression via an environment variable in case the user is
// very sure (e.g. has configured a service like systemd-tmpfiles to
// clean the dir on reboot).
// Do this very late in init so we can be sure we're not going to turn
// into the rootless userns process (if we did this earlier, we'd print
// this twice).
warnIfNotTmpfs([]string{runtime.config.Engine.TmpDir, runtime.storageConfig.RunRoot})

// If we need to refresh the state, do it now - things are guaranteed to
// be set up by now.
if doRefresh {
Expand Down
6 changes: 6 additions & 0 deletions libpod/runtime_freebsd.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,5 +2,11 @@

package libpod


func checkCgroups2UnifiedMode(runtime *Runtime) {
return
}

func warnIfNotTmpfs(paths []string) {
return
}
34 changes: 34 additions & 0 deletions libpod/runtime_linux.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@ import (
"github.com/sirupsen/logrus"
)

const TmpfsWarningEnvVar = "PODMAN_SUPPRESS_TMPFS_WARNING"

func checkCgroups2UnifiedMode(runtime *Runtime) {
unified, _ := cgroups.IsCgroup2UnifiedMode()
// DELETE ON RHEL9
Expand Down Expand Up @@ -43,3 +45,35 @@ func checkCgroups2UnifiedMode(runtime *Runtime) {
}
}
}

// Print a warning if a path is not on a tmpfs.
func warnIfNotTmpfs(paths []string) {
if os.Getenv(TmpfsWarningEnvVar) != "" {
return
}

notTmpfs := make([]string, 0, len(paths))

for _, path := range paths {
statfs := new(unix.Statfs_t)
if err := unix.Statfs(path, statfs); err != nil {
return
}

if statfs.Type != unix.TMPFS_MAGIC && uint64(statfs.Type) != unix.RAMFS_MAGIC {
notTmpfs = append(notTmpfs, path)
}
}

if len(notTmpfs) == 0 {
return
}

logrus.Warn("The following temporary files directories are not on a tmpfs filesystem:")
for _, path := range notTmpfs {
logrus.Warnf(" %q", path)
}
logrus.Warn("This may cause unpredictable behavior as Podman cannot properly detect and react to system reboots.")
logrus.Warn("It is recommended that you change the path used to one on a tmpfs or mount a tmpfs on the given path.")
logrus.Warnf("If you are certain your configuration is safe and just want to suppress this warning, set the %s environment variable to any non-empty value.", TmpfsWarningEnvVar)
}
21 changes: 21 additions & 0 deletions test/system/005-info.bats
Original file line number Diff line number Diff line change
Expand Up @@ -258,4 +258,25 @@ EOF
run_podman $safe_opts system reset --force
}

@test "podman - warning message on launching Podman with non-tmpfs tmpdir" {
skip_if_remote "Check requires a local Libpod"

# We need a directory that is not tmpfs to put Podman in
OLDTMPFS=$PODMAN_SUPPRESS_TMPFS_WARNING
unset PODMAN_SUPPRESS_TMPFS_WARNING

# Anything that creates a Libpod should trigger the warning.
nottmpfs_tmp=$(mktemp -d /var/tmp)
run_podman --tmpdir=$nottmpfs_tmp/tmp --runroot=$nottmpfs_tmp/runroot --root=$nottmpfs_tmp/root info
assert "$output" =~ "The following temporary files directories are not on a tmpfs filesystem"

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Might I also suggest

    tmpfs_tmp=$(mktemp -d /dev/shm)
    run_podman --tmpdir=$tmpfs_tmp/tmp --runroot=$tmpfs_tmp/runroot --root=$tmpfs_tmp/root info
    assert "$output" !~ "are not on a tmpfs"

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Any reason to not just mktemp and then mount a tmpfs over that directory?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Laziness? And, will that work rootless? I've never seen a system without /dev/shm (at least not in the last 20 years)

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fair point on rootless

# Force a run on tmpfs that should not error
tmpfs_tmp=$(mktemp -d /dev/shm)
run_podman --tmpdir=$tmpfs_tmp/tmp --runroot=$tmpfs_tmp/runroot --root=$tmpfs_tmp/root info
assert "$output" !~ "are not on a tmpfs"
rm -rf $tmpfs_tmp

export PODMAN_SUPPRESS_TMPFS_WARNING=$OLDTMPFS
}

# vim: filetype=sh