mirror of
https://github.com/containers/podman.git
synced 2025-05-17 06:59:07 +08:00

Podman needs to be able to detect when a system reboot occurs to do certain types of cleanup operation (for example, reset container states, clean up IPAM allocations, etc). our current method for this is a sentinel file on a tmpfs filesystem. The problem emerges that there is no directory that is guaranteed to be a tmpfs and is also guaranteed to be accessible to rootless users in the FHS. If the user has a systemd user session, we can depend on /run/user/$UID, but we can't reliably say that they do. This code will detect the no-tmpfs-but-reboot-occurred case by writing the current system boot ID to our tmpfs sentinel file when it is created, and checking that file every time Podman starts to make sure that the current boot ID matches the cached one in the sentinel file. If they don't match, a reboot occurred and the sentinel file was not on a tmpfs and thus survived. In that case, throw an error telling the user to remove certain directories (the ones that are supposed to be tmpfs), so we can proceed as expected. Signed-off-by: Matt Heon <mheon@redhat.com>
68 lines
2.4 KiB
Go
68 lines
2.4 KiB
Go
//go:build !remote
|
|
|
|
package libpod
|
|
|
|
import (
|
|
"errors"
|
|
"fmt"
|
|
"os"
|
|
|
|
"golang.org/x/sys/unix"
|
|
|
|
"github.com/containers/common/pkg/cgroups"
|
|
"github.com/containers/podman/v5/pkg/rootless"
|
|
"github.com/containers/podman/v5/pkg/systemd"
|
|
"github.com/sirupsen/logrus"
|
|
)
|
|
|
|
func checkCgroups2UnifiedMode(runtime *Runtime) {
|
|
unified, _ := cgroups.IsCgroup2UnifiedMode()
|
|
// DELETE ON RHEL9
|
|
if !unified {
|
|
_, ok := os.LookupEnv("PODMAN_IGNORE_CGROUPSV1_WARNING")
|
|
if !ok {
|
|
logrus.Warn("Using cgroups-v1 which is deprecated in favor of cgroups-v2 with Podman v5 and will be removed in a future version. Set environment variable `PODMAN_IGNORE_CGROUPSV1_WARNING` to hide this warning.")
|
|
}
|
|
}
|
|
// DELETE ON RHEL9
|
|
|
|
if unified && rootless.IsRootless() && !systemd.IsSystemdSessionValid(rootless.GetRootlessUID()) {
|
|
// If user is rootless and XDG_RUNTIME_DIR is found, podman will not proceed with /tmp directory
|
|
// it will try to use existing XDG_RUNTIME_DIR
|
|
// if current user has no write access to XDG_RUNTIME_DIR we will fail later
|
|
if err := unix.Access(runtime.storageConfig.RunRoot, unix.W_OK); err != nil {
|
|
msg := fmt.Sprintf("RunRoot is pointing to a path (%s) which is not writable. Most likely podman will fail.", runtime.storageConfig.RunRoot)
|
|
if errors.Is(err, os.ErrNotExist) {
|
|
// if dir does not exist, try to create it
|
|
if err := os.MkdirAll(runtime.storageConfig.RunRoot, 0700); err != nil {
|
|
logrus.Warn(msg)
|
|
}
|
|
} else {
|
|
logrus.Warnf("%s: %v", msg, err)
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
// Check the current boot ID against the ID cached in the runtime alive file.
|
|
func (r *Runtime) checkBootID(runtimeAliveFile string) error {
|
|
systemBootID, err := os.ReadFile("/proc/sys/kernel/random/boot_id")
|
|
if err == nil {
|
|
podmanBootID, err := os.ReadFile(runtimeAliveFile)
|
|
if err != nil {
|
|
return fmt.Errorf("reading boot ID from runtime alive file: %w", err)
|
|
}
|
|
if len(podmanBootID) != 0 {
|
|
if string(systemBootID) != string(podmanBootID) {
|
|
return fmt.Errorf("current system boot ID differs from cached boot ID; an unhandled reboot has occurred. Please delete directories %q and %q and re-run Podman", r.storageConfig.RunRoot, r.config.Engine.TmpDir)
|
|
}
|
|
} else {
|
|
// Write the current boot ID to the alive file.
|
|
if err := os.WriteFile(runtimeAliveFile, systemBootID, 0644); err != nil {
|
|
return fmt.Errorf("writing boot ID to runtime alive file: %w", err)
|
|
}
|
|
}
|
|
}
|
|
return nil
|
|
}
|