diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-16 16:28:11 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-16 16:28:11 +0000 |
commit | 496cd77eb2f01b34629ee1dfecef1b9bd745a3c5 (patch) | |
tree | 9c5bce932c85822cbd4e88252493173775ab051a /types | |
parent | Releasing progress-linux version 1.51.0+ds1-2~progress7.99u1. (diff) | |
download | golang-github-containers-storage-496cd77eb2f01b34629ee1dfecef1b9bd745a3c5.tar.xz golang-github-containers-storage-496cd77eb2f01b34629ee1dfecef1b9bd745a3c5.zip |
Merging upstream version 1.52.0+ds1.
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'types')
-rw-r--r-- | types/options.go | 86 | ||||
-rw-r--r-- | types/options_test.go | 25 | ||||
-rw-r--r-- | types/utils.go | 151 | ||||
-rw-r--r-- | types/utils_test.go | 271 |
4 files changed, 76 insertions, 457 deletions
diff --git a/types/options.go b/types/options.go index 5ae667a..ad0bfa4 100644 --- a/types/options.go +++ b/types/options.go @@ -11,7 +11,9 @@ import ( "github.com/BurntSushi/toml" cfg "github.com/containers/storage/pkg/config" + "github.com/containers/storage/pkg/homedir" "github.com/containers/storage/pkg/idtools" + "github.com/containers/storage/pkg/unshare" "github.com/sirupsen/logrus" ) @@ -87,7 +89,7 @@ func loadDefaultStoreOptions() { _, err := os.Stat(defaultOverrideConfigFile) if err == nil { - // The DefaultConfigFile(rootless) function returns the path + // The DefaultConfigFile() function returns the path // of the used storage.conf file, by returning defaultConfigFile // If override exists containers/storage uses it by default. defaultConfigFile = defaultOverrideConfigFile @@ -109,21 +111,41 @@ func loadDefaultStoreOptions() { setDefaults() } -// defaultStoreOptionsIsolated is an internal implementation detail of DefaultStoreOptions to allow testing. -// Everyone but the tests this is intended for should only call DefaultStoreOptions, never this function. -func defaultStoreOptionsIsolated(rootless bool, rootlessUID int, storageConf string) (StoreOptions, error) { +// loadStoreOptions returns the default storage ops for containers +func loadStoreOptions() (StoreOptions, error) { + storageConf, err := DefaultConfigFile() + if err != nil { + return defaultStoreOptions, err + } + return loadStoreOptionsFromConfFile(storageConf) +} + +// usePerUserStorage returns whether the user private storage must be used. +// We cannot simply use the unshare.IsRootless() condition, because +// that checks only if the current process needs a user namespace to +// work and it would break cases where the process is already created +// in a user namespace (e.g. nested Podman/Buildah) and the desired +// behavior is to use system paths instead of user private paths. +func usePerUserStorage() bool { + return unshare.IsRootless() && unshare.GetRootlessUID() != 0 +} + +// loadStoreOptionsFromConfFile is an internal implementation detail of DefaultStoreOptions to allow testing. +// Everyone but the tests this is intended for should only call loadStoreOptions, never this function. +func loadStoreOptionsFromConfFile(storageConf string) (StoreOptions, error) { var ( defaultRootlessRunRoot string defaultRootlessGraphRoot string err error ) + defaultStoreOptionsOnce.Do(loadDefaultStoreOptions) if loadDefaultStoreOptionsErr != nil { return StoreOptions{}, loadDefaultStoreOptionsErr } storageOpts := defaultStoreOptions - if rootless && rootlessUID != 0 { - storageOpts, err = getRootlessStorageOpts(rootlessUID, storageOpts) + if usePerUserStorage() { + storageOpts, err = getRootlessStorageOpts(storageOpts) if err != nil { return storageOpts, err } @@ -137,7 +159,7 @@ func defaultStoreOptionsIsolated(rootless bool, rootlessUID int, storageConf str defaultRootlessGraphRoot = storageOpts.GraphRoot storageOpts = StoreOptions{} reloadConfigurationFileIfNeeded(storageConf, &storageOpts) - if rootless && rootlessUID != 0 { + if usePerUserStorage() { // If the file did not specify a graphroot or runroot, // set sane defaults so we don't try and use root-owned // directories @@ -156,6 +178,7 @@ func defaultStoreOptionsIsolated(rootless bool, rootlessUID int, storageConf str if storageOpts.RunRoot == "" { return storageOpts, fmt.Errorf("runroot must be set") } + rootlessUID := unshare.GetRootlessUID() runRoot, err := expandEnvPath(storageOpts.RunRoot, rootlessUID) if err != nil { return storageOpts, err @@ -186,26 +209,17 @@ func defaultStoreOptionsIsolated(rootless bool, rootlessUID int, storageConf str return storageOpts, nil } -// loadStoreOptions returns the default storage ops for containers -func loadStoreOptions(rootless bool, rootlessUID int) (StoreOptions, error) { - storageConf, err := DefaultConfigFile(rootless && rootlessUID != 0) - if err != nil { - return defaultStoreOptions, err - } - return defaultStoreOptionsIsolated(rootless, rootlessUID, storageConf) -} - // UpdateOptions should be called iff container engine received a SIGHUP, // otherwise use DefaultStoreOptions -func UpdateStoreOptions(rootless bool, rootlessUID int) (StoreOptions, error) { - storeOptions, storeError = loadStoreOptions(rootless, rootlessUID) +func UpdateStoreOptions() (StoreOptions, error) { + storeOptions, storeError = loadStoreOptions() return storeOptions, storeError } // DefaultStoreOptions returns the default storage ops for containers -func DefaultStoreOptions(rootless bool, rootlessUID int) (StoreOptions, error) { +func DefaultStoreOptions() (StoreOptions, error) { once.Do(func() { - storeOptions, storeError = loadStoreOptions(rootless, rootlessUID) + storeOptions, storeError = loadStoreOptions() }) return storeOptions, storeError } @@ -270,14 +284,26 @@ func isRootlessDriver(driver string) bool { } // getRootlessStorageOpts returns the storage opts for containers running as non root -func getRootlessStorageOpts(rootlessUID int, systemOpts StoreOptions) (StoreOptions, error) { +func getRootlessStorageOpts(systemOpts StoreOptions) (StoreOptions, error) { var opts StoreOptions - dataDir, rootlessRuntime, err := getRootlessDirInfo(rootlessUID) + rootlessUID := unshare.GetRootlessUID() + + dataDir, err := homedir.GetDataHome() + if err != nil { + return opts, err + } + + rootlessRuntime, err := homedir.GetRuntimeDir() if err != nil { return opts, err } - opts.RunRoot = rootlessRuntime + + opts.RunRoot = filepath.Join(rootlessRuntime, "containers") + if err := os.MkdirAll(opts.RunRoot, 0o700); err != nil { + return opts, fmt.Errorf("unable to make rootless runtime: %w", err) + } + opts.PullOptions = systemOpts.PullOptions if systemOpts.RootlessStoragePath != "" { opts.GraphRoot, err = expandEnvPath(systemOpts.RootlessStoragePath, rootlessUID) @@ -343,12 +369,6 @@ func getRootlessStorageOpts(rootlessUID int, systemOpts StoreOptions) (StoreOpti return opts, nil } -// DefaultStoreOptionsAutoDetectUID returns the default storage ops for containers -func DefaultStoreOptionsAutoDetectUID() (StoreOptions, error) { - uid := getRootlessUID() - return DefaultStoreOptions(uid != 0, uid) -} - var prevReloadConfig = struct { storeOptions *StoreOptions mod time.Time @@ -518,8 +538,8 @@ func Options() (StoreOptions, error) { } // Save overwrites the tomlConfig in storage.conf with the given conf -func Save(conf TomlConfig, rootless bool) error { - configFile, err := DefaultConfigFile(rootless) +func Save(conf TomlConfig) error { + configFile, err := DefaultConfigFile() if err != nil { return err } @@ -537,10 +557,10 @@ func Save(conf TomlConfig, rootless bool) error { } // StorageConfig is used to retrieve the storage.conf toml in order to overwrite it -func StorageConfig(rootless bool) (*TomlConfig, error) { +func StorageConfig() (*TomlConfig, error) { config := new(TomlConfig) - configFile, err := DefaultConfigFile(rootless) + configFile, err := DefaultConfigFile() if err != nil { return nil, err } diff --git a/types/options_test.go b/types/options_test.go index 5201936..bd2d265 100644 --- a/types/options_test.go +++ b/types/options_test.go @@ -10,6 +10,7 @@ import ( "testing" "github.com/containers/storage/pkg/idtools" + "github.com/containers/storage/pkg/unshare" "github.com/sirupsen/logrus" "github.com/stretchr/testify/require" "gotest.tools/assert" @@ -32,7 +33,7 @@ func TestGetRootlessStorageOpts(t *testing.T) { systemOpts.GraphRoot = home systemOpts.RunRoot = runhome - storageOpts, err := getRootlessStorageOpts(os.Geteuid(), systemOpts) + storageOpts, err := getRootlessStorageOpts(systemOpts) assert.NilError(t, err) expectedDriver := vfsDriver @@ -45,7 +46,7 @@ func TestGetRootlessStorageOpts(t *testing.T) { t.Run("systemDriver=btrfs", func(t *testing.T) { systemOpts := StoreOptions{} systemOpts.GraphDriverName = "btrfs" - storageOpts, err := getRootlessStorageOpts(1000, systemOpts) + storageOpts, err := getRootlessStorageOpts(systemOpts) assert.NilError(t, err) assert.Equal(t, storageOpts.GraphDriverName, "btrfs") }) @@ -53,7 +54,7 @@ func TestGetRootlessStorageOpts(t *testing.T) { t.Run("systemDriver=overlay", func(t *testing.T) { systemOpts := StoreOptions{} systemOpts.GraphDriverName = overlayDriver - storageOpts, err := getRootlessStorageOpts(1000, systemOpts) + storageOpts, err := getRootlessStorageOpts(systemOpts) assert.NilError(t, err) assert.Equal(t, storageOpts.GraphDriverName, overlayDriver) }) @@ -61,7 +62,7 @@ func TestGetRootlessStorageOpts(t *testing.T) { t.Run("systemDriver=overlay2", func(t *testing.T) { systemOpts := StoreOptions{} systemOpts.GraphDriverName = "overlay2" - storageOpts, err := getRootlessStorageOpts(1000, systemOpts) + storageOpts, err := getRootlessStorageOpts(systemOpts) assert.NilError(t, err) assert.Equal(t, storageOpts.GraphDriverName, overlayDriver) }) @@ -69,7 +70,7 @@ func TestGetRootlessStorageOpts(t *testing.T) { t.Run("systemDriver=vfs", func(t *testing.T) { systemOpts := StoreOptions{} systemOpts.GraphDriverName = vfsDriver - storageOpts, err := getRootlessStorageOpts(1000, systemOpts) + storageOpts, err := getRootlessStorageOpts(systemOpts) assert.NilError(t, err) assert.Equal(t, storageOpts.GraphDriverName, vfsDriver) }) @@ -77,7 +78,7 @@ func TestGetRootlessStorageOpts(t *testing.T) { t.Run("systemDriver=aufs", func(t *testing.T) { systemOpts := StoreOptions{} systemOpts.GraphDriverName = "aufs" - storageOpts, err := getRootlessStorageOpts(1000, systemOpts) + storageOpts, err := getRootlessStorageOpts(systemOpts) assert.NilError(t, err) assert.Assert(t, storageOpts.GraphDriverName == overlayDriver || storageOpts.GraphDriverName == vfsDriver, fmt.Sprintf("The rootless driver should be set to 'overlay' or 'vfs' not '%v'", storageOpts.GraphDriverName)) }) @@ -85,7 +86,7 @@ func TestGetRootlessStorageOpts(t *testing.T) { t.Run("systemDriver=devmapper", func(t *testing.T) { systemOpts := StoreOptions{} systemOpts.GraphDriverName = "devmapper" - storageOpts, err := getRootlessStorageOpts(1000, systemOpts) + storageOpts, err := getRootlessStorageOpts(systemOpts) assert.NilError(t, err) assert.Assert(t, storageOpts.GraphDriverName == overlayDriver || storageOpts.GraphDriverName == vfsDriver, fmt.Sprintf("The rootless driver should be set to 'overlay' or 'vfs' not '%v'", storageOpts.GraphDriverName)) }) @@ -93,7 +94,7 @@ func TestGetRootlessStorageOpts(t *testing.T) { t.Run("systemDriver=zfs", func(t *testing.T) { systemOpts := StoreOptions{} systemOpts.GraphDriverName = "zfs" - storageOpts, err := getRootlessStorageOpts(1000, systemOpts) + storageOpts, err := getRootlessStorageOpts(systemOpts) assert.NilError(t, err) assert.Assert(t, storageOpts.GraphDriverName == overlayDriver || storageOpts.GraphDriverName == vfsDriver, fmt.Sprintf("The rootless driver should be set to 'overlay' or 'vfs' not '%v'", storageOpts.GraphDriverName)) }) @@ -102,7 +103,7 @@ func TestGetRootlessStorageOpts(t *testing.T) { t.Setenv("STORAGE_DRIVER", "btrfs") systemOpts := StoreOptions{} systemOpts.GraphDriverName = vfsDriver - storageOpts, err := getRootlessStorageOpts(1000, systemOpts) + storageOpts, err := getRootlessStorageOpts(systemOpts) assert.NilError(t, err) assert.Equal(t, storageOpts.GraphDriverName, "btrfs") }) @@ -111,7 +112,7 @@ func TestGetRootlessStorageOpts(t *testing.T) { t.Setenv("STORAGE_DRIVER", "zfs") systemOpts := StoreOptions{} systemOpts.GraphDriverName = vfsDriver - storageOpts, err := getRootlessStorageOpts(1000, systemOpts) + storageOpts, err := getRootlessStorageOpts(systemOpts) assert.NilError(t, err) assert.Equal(t, storageOpts.GraphDriverName, "zfs") }) @@ -127,8 +128,8 @@ func TestGetRootlessStorageOpts2(t *testing.T) { opts := StoreOptions{ RootlessStoragePath: "/$HOME/$UID/containers/storage", } - expectedPath := filepath.Join(os.Getenv("HOME"), "2000", "containers/storage") - storageOpts, err := getRootlessStorageOpts(2000, opts) + expectedPath := filepath.Join(os.Getenv("HOME"), fmt.Sprintf("%d", unshare.GetRootlessUID()), "containers/storage") + storageOpts, err := getRootlessStorageOpts(opts) assert.NilError(t, err) assert.Equal(t, storageOpts.GraphRoot, expectedPath) } diff --git a/types/utils.go b/types/utils.go index 73134f8..5b4b31b 100644 --- a/types/utils.go +++ b/types/utils.go @@ -2,162 +2,15 @@ package types import ( "errors" - "fmt" "os" "path/filepath" "strconv" "strings" "github.com/containers/storage/pkg/homedir" - "github.com/containers/storage/pkg/system" "github.com/sirupsen/logrus" ) -// GetRootlessRuntimeDir returns the runtime directory when running as non root -func GetRootlessRuntimeDir(rootlessUID int) (string, error) { - path, err := getRootlessRuntimeDir(rootlessUID) - if err != nil { - return "", err - } - path = filepath.Join(path, "containers") - if err := os.MkdirAll(path, 0o700); err != nil { - return "", fmt.Errorf("unable to make rootless runtime: %w", err) - } - return path, nil -} - -type rootlessRuntimeDirEnvironment interface { - getProcCommandFile() string - getRunUserDir() string - getTmpPerUserDir() string - - homeDirGetRuntimeDir() (string, error) - systemLstat(string) (*system.StatT, error) - homedirGet() string -} - -type rootlessRuntimeDirEnvironmentImplementation struct { - procCommandFile string - runUserDir string - tmpPerUserDir string -} - -func (env rootlessRuntimeDirEnvironmentImplementation) getProcCommandFile() string { - return env.procCommandFile -} - -func (env rootlessRuntimeDirEnvironmentImplementation) getRunUserDir() string { - return env.runUserDir -} - -func (env rootlessRuntimeDirEnvironmentImplementation) getTmpPerUserDir() string { - return env.tmpPerUserDir -} - -func (rootlessRuntimeDirEnvironmentImplementation) homeDirGetRuntimeDir() (string, error) { - return homedir.GetRuntimeDir() -} - -func (rootlessRuntimeDirEnvironmentImplementation) systemLstat(path string) (*system.StatT, error) { - return system.Lstat(path) -} - -func (rootlessRuntimeDirEnvironmentImplementation) homedirGet() string { - return homedir.Get() -} - -func isRootlessRuntimeDirOwner(dir string, env rootlessRuntimeDirEnvironment) bool { - st, err := env.systemLstat(dir) - return err == nil && int(st.UID()) == os.Getuid() && st.Mode()&0o700 == 0o700 && st.Mode()&0o066 == 0o000 -} - -// getRootlessRuntimeDirIsolated is an internal implementation detail of getRootlessRuntimeDir to allow testing. -// Everyone but the tests this is intended for should only call getRootlessRuntimeDir, never this function. -func getRootlessRuntimeDirIsolated(env rootlessRuntimeDirEnvironment) (string, error) { - runtimeDir, err := env.homeDirGetRuntimeDir() - if err == nil { - return runtimeDir, nil - } - - initCommand, err := os.ReadFile(env.getProcCommandFile()) - if err != nil || string(initCommand) == "systemd" { - runUserDir := env.getRunUserDir() - if isRootlessRuntimeDirOwner(runUserDir, env) { - return runUserDir, nil - } - } - - tmpPerUserDir := env.getTmpPerUserDir() - if tmpPerUserDir != "" { - if _, err := env.systemLstat(tmpPerUserDir); os.IsNotExist(err) { - if err := os.Mkdir(tmpPerUserDir, 0o700); err != nil { - logrus.Errorf("Failed to create temp directory for user: %v", err) - } else { - return tmpPerUserDir, nil - } - } else if isRootlessRuntimeDirOwner(tmpPerUserDir, env) { - return tmpPerUserDir, nil - } - } - - homeDir := env.homedirGet() - if homeDir == "" { - return "", errors.New("neither XDG_RUNTIME_DIR nor temp dir nor HOME was set non-empty") - } - resolvedHomeDir, err := filepath.EvalSymlinks(homeDir) - if err != nil { - return "", err - } - return filepath.Join(resolvedHomeDir, "rundir"), nil -} - -func getRootlessRuntimeDir(rootlessUID int) (string, error) { - return getRootlessRuntimeDirIsolated( - rootlessRuntimeDirEnvironmentImplementation{ - "/proc/1/comm", - fmt.Sprintf("/run/user/%d", rootlessUID), - fmt.Sprintf("%s/containers-user-%d", os.TempDir(), rootlessUID), - }, - ) -} - -// getRootlessDirInfo returns the parent path of where the storage for containers and -// volumes will be in rootless mode -func getRootlessDirInfo(rootlessUID int) (string, string, error) { - rootlessRuntime, err := GetRootlessRuntimeDir(rootlessUID) - if err != nil { - return "", "", err - } - - dataDir, err := homedir.GetDataHome() - if err == nil { - return dataDir, rootlessRuntime, nil - } - - home := homedir.Get() - if home == "" { - return "", "", fmt.Errorf("neither XDG_DATA_HOME nor HOME was set non-empty: %w", err) - } - // runc doesn't like symlinks in the rootfs path, and at least - // on CoreOS /home is a symlink to /var/home, so resolve any symlink. - resolvedHome, err := filepath.EvalSymlinks(home) - if err != nil { - return "", "", err - } - dataDir = filepath.Join(resolvedHome, ".local", "share") - - return dataDir, rootlessRuntime, nil -} - -func getRootlessUID() int { - uidEnv := os.Getenv("_CONTAINERS_ROOTLESS_UID") - if uidEnv != "" { - u, _ := strconv.Atoi(uidEnv) - return u - } - return os.Geteuid() -} - func expandEnvPath(path string, rootlessUID int) (string, error) { var err error path = strings.Replace(path, "$UID", strconv.Itoa(rootlessUID), -1) @@ -169,7 +22,7 @@ func expandEnvPath(path string, rootlessUID int) (string, error) { return newpath, nil } -func DefaultConfigFile(rootless bool) (string, error) { +func DefaultConfigFile() (string, error) { if defaultConfigFileSet { return defaultConfigFile, nil } @@ -177,7 +30,7 @@ func DefaultConfigFile(rootless bool) (string, error) { if path, ok := os.LookupEnv(storageConfEnv); ok { return path, nil } - if !rootless { + if !usePerUserStorage() { if _, err := os.Stat(defaultOverrideConfigFile); err == nil { return defaultOverrideConfigFile, nil } diff --git a/types/utils_test.go b/types/utils_test.go index a6c8d50..124ad87 100644 --- a/types/utils_test.go +++ b/types/utils_test.go @@ -1,276 +1,21 @@ package types import ( - "errors" "fmt" "os" "path/filepath" "testing" - "github.com/containers/storage/pkg/homedir" - "github.com/containers/storage/pkg/system" + "github.com/containers/storage/pkg/unshare" "gotest.tools/assert" ) -type homeRuntimeData struct { - dir string - err error -} - -type rootlessRuntimeDirEnvironmentTest struct { - homeRuntime homeRuntimeData - procCommandFile string - runUserDir string - tmpPerUserDir string - homeDir string - result string -} - -func (env rootlessRuntimeDirEnvironmentTest) getProcCommandFile() string { - return env.procCommandFile -} - -func (env rootlessRuntimeDirEnvironmentTest) getRunUserDir() string { - return env.runUserDir -} - -func (env rootlessRuntimeDirEnvironmentTest) getTmpPerUserDir() string { - return env.tmpPerUserDir -} - -func (env rootlessRuntimeDirEnvironmentTest) homeDirGetRuntimeDir() (string, error) { - return env.homeRuntime.dir, env.homeRuntime.err -} - -func (env rootlessRuntimeDirEnvironmentTest) systemLstat(path string) (*system.StatT, error) { - return system.Lstat(path) -} - -func (env rootlessRuntimeDirEnvironmentTest) homedirGet() string { - return env.homeDir -} - -func TestRootlessRuntimeDir(t *testing.T) { - testDir := t.TempDir() - - homeRuntimeDir := filepath.Join(testDir, "home-rundir") - err := os.Mkdir(homeRuntimeDir, 0o700) - assert.NilError(t, err) - - homeRuntimeDisabled := homeRuntimeData{err: errors.New("homedirGetRuntimeDir is disabled")} - - systemdCommandFile := filepath.Join(testDir, "systemd-command") - err = os.WriteFile(systemdCommandFile, []byte("systemd"), 0o644) - assert.NilError(t, err) - - initCommandFile := filepath.Join(testDir, "init-command") - err = os.WriteFile(initCommandFile, []byte("init"), 0o644) - assert.NilError(t, err) - - dirForOwner := filepath.Join(testDir, "dir-for-owner") - err = os.Mkdir(dirForOwner, 0o700) - assert.NilError(t, err) - - dirForAll := filepath.Join(testDir, "dir-for-all") - err = os.Mkdir(dirForAll, 0o777) - assert.NilError(t, err) - - dirToBeCreated := filepath.Join(testDir, "dir-to-be-created") - - envs := []rootlessRuntimeDirEnvironmentTest{ - { - homeRuntime: homeRuntimeData{dir: homeRuntimeDir}, - result: homeRuntimeDir, - }, - - // Reading proc command file fails - { - homeRuntime: homeRuntimeDisabled, - procCommandFile: "", - runUserDir: dirForOwner, - result: dirForOwner, - }, - { - homeRuntime: homeRuntimeDisabled, - procCommandFile: "", - runUserDir: "", // Accessing run user dir fails - tmpPerUserDir: dirForOwner, - result: dirForOwner, - }, - { - homeRuntime: homeRuntimeDisabled, - procCommandFile: "", - runUserDir: dirForAll, - tmpPerUserDir: dirForOwner, - result: dirForOwner, - }, - { - homeRuntime: homeRuntimeDisabled, - procCommandFile: "", - runUserDir: "", // Accessing run user dir fails - tmpPerUserDir: dirToBeCreated, - result: dirToBeCreated, - }, - { - homeRuntime: homeRuntimeDisabled, - procCommandFile: "", - runUserDir: "", // Accessing run user dir fails - tmpPerUserDir: "", // Accessing tmp per user dir fails - homeDir: dirForOwner, - result: filepath.Join(dirForOwner, "rundir"), - }, - { - homeRuntime: homeRuntimeDisabled, - procCommandFile: "", - runUserDir: "", // Accessing run user dir fails - tmpPerUserDir: dirForAll, - homeDir: dirForOwner, - result: filepath.Join(dirForOwner, "rundir"), - }, - - // systemd - { - homeRuntime: homeRuntimeDisabled, - procCommandFile: systemdCommandFile, - runUserDir: dirForOwner, - result: dirForOwner, - }, - { - homeRuntime: homeRuntimeDisabled, - procCommandFile: systemdCommandFile, - runUserDir: "", // Accessing run user dir fails - tmpPerUserDir: dirForOwner, - result: dirForOwner, - }, - { - homeRuntime: homeRuntimeDisabled, - procCommandFile: systemdCommandFile, - runUserDir: dirForAll, - tmpPerUserDir: dirForOwner, - result: dirForOwner, - }, - { - homeRuntime: homeRuntimeDisabled, - procCommandFile: systemdCommandFile, - runUserDir: "", // Accessing run user dir fails - tmpPerUserDir: dirToBeCreated, - result: dirToBeCreated, - }, - { - homeRuntime: homeRuntimeDisabled, - procCommandFile: systemdCommandFile, - runUserDir: "", // Accessing run user dir fails - tmpPerUserDir: "", // Accessing tmp per user dir fails - homeDir: dirForOwner, - result: filepath.Join(dirForOwner, "rundir"), - }, - { - homeRuntime: homeRuntimeDisabled, - procCommandFile: systemdCommandFile, - runUserDir: "", // Accessing run user dir fails - tmpPerUserDir: dirForAll, - homeDir: dirForOwner, - result: filepath.Join(dirForOwner, "rundir"), - }, - - // init - { - homeRuntime: homeRuntimeDisabled, - procCommandFile: initCommandFile, - tmpPerUserDir: dirForOwner, - result: dirForOwner, - }, - { - homeRuntime: homeRuntimeDisabled, - procCommandFile: initCommandFile, - tmpPerUserDir: dirToBeCreated, - result: dirToBeCreated, - }, - { - homeRuntime: homeRuntimeDisabled, - procCommandFile: initCommandFile, - tmpPerUserDir: "", // Accessing tmp per user dir fails - homeDir: dirForOwner, - result: filepath.Join(dirForOwner, "rundir"), - }, - { - homeRuntime: homeRuntimeDisabled, - procCommandFile: initCommandFile, - tmpPerUserDir: dirForAll, - homeDir: dirForOwner, - result: filepath.Join(dirForOwner, "rundir"), - }, - } - - for i, env := range envs { - t.Run(fmt.Sprintf("%d", i), func(t *testing.T) { - os.Remove(dirToBeCreated) - - resultDir, err := getRootlessRuntimeDirIsolated(env) - assert.NilError(t, err) - assert.Assert(t, resultDir == env.result) - }) - } -} - -type rootlessRuntimeDirEnvironmentRace struct { - procCommandFile string - tmpPerUserDir string -} - -func (env rootlessRuntimeDirEnvironmentRace) getProcCommandFile() string { - return env.procCommandFile -} - -func (rootlessRuntimeDirEnvironmentRace) getRunUserDir() string { - return "" -} - -func (env rootlessRuntimeDirEnvironmentRace) getTmpPerUserDir() string { - return env.tmpPerUserDir -} - -func (rootlessRuntimeDirEnvironmentRace) homeDirGetRuntimeDir() (string, error) { - return "", errors.New("homedirGetRuntimeDir is disabled") -} - -func (env rootlessRuntimeDirEnvironmentRace) systemLstat(path string) (*system.StatT, error) { - if path == env.tmpPerUserDir { - st, err := system.Lstat(path) - // We can simulate that race directory was created immediately after system.Lstat call. - if err := os.Mkdir(path, 0o700); err != nil { - return nil, err - } - return st, err - } - return system.Lstat(path) -} - -func (rootlessRuntimeDirEnvironmentRace) homedirGet() string { - return homedir.Get() -} - -func TestRootlessRuntimeDirRace(t *testing.T) { - raceDir := t.TempDir() - - procCommandFile := filepath.Join(raceDir, "command") - err := os.WriteFile(procCommandFile, []byte("init"), 0o644) - assert.NilError(t, err) - - tmpPerUserDir := filepath.Join(raceDir, "tmp") - - resultDir, err := getRootlessRuntimeDirIsolated(rootlessRuntimeDirEnvironmentRace{ - procCommandFile, - tmpPerUserDir, - }) - assert.NilError(t, err) - assert.Assert(t, resultDir != tmpPerUserDir, "Rootless runtime dir shouldn't follow race dir.") -} - func TestDefaultStoreOpts(t *testing.T) { - storageOpts, err := defaultStoreOptionsIsolated(true, 1000, "./storage_test.conf") - - expectedPath := filepath.Join(os.Getenv("HOME"), "1000", "containers/storage") + if !usePerUserStorage() { + t.Skip() + } + storageOpts, err := loadStoreOptionsFromConfFile("./storage_test.conf") + expectedPath := filepath.Join(os.Getenv("HOME"), fmt.Sprintf("%d", unshare.GetRootlessUID()), "containers/storage") assert.NilError(t, err) assert.Equal(t, storageOpts.RunRoot, expectedPath) @@ -280,7 +25,7 @@ func TestDefaultStoreOpts(t *testing.T) { func TestStorageConfOverrideEnvironmentDefaultConfigFileRootless(t *testing.T) { t.Setenv("CONTAINERS_STORAGE_CONF", "default_override_test.conf") - defaultFile, err := DefaultConfigFile(true) + defaultFile, err := DefaultConfigFile() expectedPath := "default_override_test.conf" @@ -290,7 +35,7 @@ func TestStorageConfOverrideEnvironmentDefaultConfigFileRootless(t *testing.T) { func TestStorageConfOverrideEnvironmentDefaultConfigFileRoot(t *testing.T) { t.Setenv("CONTAINERS_STORAGE_CONF", "default_override_test.conf") - defaultFile, err := DefaultConfigFile(false) + defaultFile, err := DefaultConfigFile() expectedPath := "default_override_test.conf" |