From 0b3ad66a78662bf7355a526fa18337ac7eed331b Mon Sep 17 00:00:00 2001 From: Ygal Blum Date: Tue, 10 Dec 2024 15:33:10 -0500 Subject: [PATCH] Quadlet - make sure the /etc/containers/systemd/users is traversed in rootless Signed-off-by: Ygal Blum --- cmd/quadlet/main.go | 8 ++++++-- cmd/quadlet/main_test.go | 44 ++++++++++++++++++++++++---------------- 2 files changed, 33 insertions(+), 19 deletions(-) diff --git a/cmd/quadlet/main.go b/cmd/quadlet/main.go index 77e522f672..61c78cd95b 100644 --- a/cmd/quadlet/main.go +++ b/cmd/quadlet/main.go @@ -186,9 +186,9 @@ func getRootlessDirs(paths *searchPaths, nonNumericFilter, userLevelFilter func( appendSubPaths(paths, filepath.Join(quadlet.UnitDirAdmin, "users", u.Uid), true, userLevelFilter) } else { fmt.Fprintf(os.Stderr, "Warning: %v", err) + // Add the base directory even if the UID was not found + paths.Add(filepath.Join(quadlet.UnitDirAdmin, "users")) } - - paths.Add(filepath.Join(quadlet.UnitDirAdmin, "users")) } func getRootDirs(paths *searchPaths, userLevelFilter func(string, bool) bool) { @@ -279,6 +279,10 @@ func getNonNumericFilter(resolvedUnitDirAdminUser string, systemUserDirLevel int // ignore sub dirs under the `users` directory which correspond to a user id if strings.HasPrefix(path, resolvedUnitDirAdminUser) { listDirUserPathLevels := strings.Split(path, string(os.PathSeparator)) + // Make sure to add the base directory + if len(listDirUserPathLevels) == systemUserDirLevel { + return true + } if len(listDirUserPathLevels) > systemUserDirLevel { if !(regexp.MustCompile(`^[0-9]*$`).MatchString(listDirUserPathLevels[systemUserDirLevel])) { return true diff --git a/cmd/quadlet/main_test.go b/cmd/quadlet/main_test.go index e2340ac021..2c84d7021b 100644 --- a/cmd/quadlet/main_test.go +++ b/cmd/quadlet/main_test.go @@ -85,7 +85,6 @@ func TestUnitDirs(t *testing.T) { appendSubPaths(rootlessPaths, path.Join(configDir, "containers/systemd"), false, nil) appendSubPaths(rootlessPaths, filepath.Join(quadlet.UnitDirAdmin, "users"), true, nonNumericFilter) appendSubPaths(rootlessPaths, filepath.Join(quadlet.UnitDirAdmin, "users", u.Uid), true, userLevelFilter) - rootlessPaths.Add(filepath.Join(quadlet.UnitDirAdmin, "users")) unitDirs = getUnitDirs(true) assert.Equal(t, rootlessPaths.sorted, unitDirs, "rootless unit dirs should match") @@ -222,28 +221,39 @@ func TestUnitDirs(t *testing.T) { err = os.RemoveAll(quadlet.UnitDirAdmin) assert.Nil(t, err) - systemdDir := filepath.Join("/", "systemd") - userDir := filepath.Join("/", "users") - err = os.Mkdir(systemdDir, 0755) - assert.Nil(t, err) - err = os.Mkdir(userDir, 0755) - assert.Nil(t, err) - err = os.Symlink(userDir, filepath.Join(systemdDir, "users")) - assert.Nil(t, err) - err = os.Symlink(systemdDir, quadlet.UnitDirAdmin) - assert.Nil(t, err) + createDir := func(path, name string) string { + dirName := filepath.Join(path, name) + err = os.Mkdir(dirName, 0755) + assert.Nil(t, err) + return dirName + } - uidDir := filepath.Join(userDir, u.Uid) - err = os.Mkdir(uidDir, 0755) - assert.Nil(t, err) - uidDir2 := filepath.Join(userDir, strconv.Itoa(uidInt+1)) - err = os.Mkdir(uidDir2, 0755) - assert.Nil(t, err) + linkDir := func(path, name, target string) { + linkName := filepath.Join(path, name) + err = os.Symlink(target, linkName) + assert.Nil(t, err) + } + systemdDir := createDir("/", "systemd") + userDir := createDir("/", "users") + linkDir(systemdDir, "users", userDir) + linkDir(quadlet.UnitDirAdmin, "", systemdDir) + + uidDir := createDir(userDir, u.Uid) + uidDir2 := createDir(userDir, strconv.Itoa(uidInt+1)) + userInternalDir := createDir(userDir, "internal") + + // Make sure QUADLET_UNIT_DIRS is not set t.Setenv("QUADLET_UNIT_DIRS", "") + // Test Rootful unitDirs := getUnitDirs(false) assert.NotContains(t, unitDirs, userDir, "rootful should not contain rootless") + assert.NotContains(t, unitDirs, userInternalDir, "rootful should not contain rootless") + + // Test Rootless unitDirs = getUnitDirs(true) assert.NotContains(t, unitDirs, uidDir2, "rootless should not contain other users'") + assert.Contains(t, unitDirs, userInternalDir, "rootless should contain sub-directories of users dir") + assert.Contains(t, unitDirs, uidDir, "rootless should contain the directory for its UID") } }