Skip to content

Commit 61c1ece

Browse files
committed
pkg/homedir: enhance GetConfigHome()
copy the version from Podman that checks if the user owns the directory. [NO NEW TESTS NEEDED] moved from Podman Signed-off-by: Giuseppe Scrivano <[email protected]>
1 parent a56f2b2 commit 61c1ece

File tree

3 files changed

+62
-15
lines changed

3 files changed

+62
-15
lines changed

pkg/homedir/homedir.go

Lines changed: 0 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -6,21 +6,6 @@ import (
66
"path/filepath"
77
)
88

9-
// GetConfigHome returns XDG_CONFIG_HOME.
10-
// GetConfigHome returns $HOME/.config and nil error if XDG_CONFIG_HOME is not set.
11-
//
12-
// See also https://standards.freedesktop.org/basedir-spec/latest/ar01s03.html
13-
func GetConfigHome() (string, error) {
14-
if xdgConfigHome := os.Getenv("XDG_CONFIG_HOME"); xdgConfigHome != "" {
15-
return xdgConfigHome, nil
16-
}
17-
home := Get()
18-
if home == "" {
19-
return "", errors.New("could not get either XDG_CONFIG_HOME or HOME")
20-
}
21-
return filepath.Join(home, ".config"), nil
22-
}
23-
249
// GetDataHome returns XDG_DATA_HOME.
2510
// GetDataHome returns $HOME/.local/share and nil error if XDG_DATA_HOME is not set.
2611
//

pkg/homedir/homedir_others.go

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,8 @@ package homedir
88

99
import (
1010
"errors"
11+
"os"
12+
"path/filepath"
1113
)
1214

1315
// GetRuntimeDir is unsupported on non-linux system.
@@ -19,3 +21,18 @@ func GetRuntimeDir() (string, error) {
1921
func StickRuntimeDirContents(files []string) ([]string, error) {
2022
return nil, errors.New("homedir.StickRuntimeDirContents() is not supported on this system")
2123
}
24+
25+
// GetConfigHome returns XDG_CONFIG_HOME.
26+
// GetConfigHome returns $HOME/.config and nil error if XDG_CONFIG_HOME is not set.
27+
//
28+
// See also https://standards.freedesktop.org/basedir-spec/latest/ar01s03.html
29+
func GetConfigHome() (string, error) {
30+
if xdgConfigHome := os.Getenv("XDG_CONFIG_HOME"); xdgConfigHome != "" {
31+
return xdgConfigHome, nil
32+
}
33+
home := Get()
34+
if home == "" {
35+
return "", errors.New("could not get either XDG_CONFIG_HOME or HOME")
36+
}
37+
return filepath.Join(home, ".config"), nil
38+
}

pkg/homedir/homedir_unix.go

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,9 +8,12 @@ package homedir
88

99
import (
1010
"errors"
11+
"fmt"
1112
"os"
1213
"path/filepath"
1314
"strings"
15+
"sync"
16+
"syscall"
1417

1518
"github.com/containers/storage/pkg/unshare"
1619
)
@@ -94,3 +97,45 @@ func stick(f string) error {
9497
m |= os.ModeSticky
9598
return os.Chmod(f, m)
9699
}
100+
101+
var (
102+
rootlessConfigHomeDirError error
103+
rootlessConfigHomeDirOnce sync.Once
104+
rootlessConfigHomeDir string
105+
)
106+
107+
// isWriteableOnlyByOwner checks that the specified permission mask allows write
108+
// access only to the owner.
109+
func isWriteableOnlyByOwner(perm os.FileMode) bool {
110+
return (perm & 0o722) == 0o700
111+
}
112+
113+
// GetConfigHome returns XDG_CONFIG_HOME.
114+
// GetConfigHome returns $HOME/.config and nil error if XDG_CONFIG_HOME is not set.
115+
//
116+
// See also https://standards.freedesktop.org/basedir-spec/latest/ar01s03.html
117+
func GetConfigHome() (string, error) {
118+
rootlessConfigHomeDirOnce.Do(func() {
119+
cfgHomeDir := os.Getenv("XDG_CONFIG_HOME")
120+
if cfgHomeDir == "" {
121+
home := Get()
122+
resolvedHome, err := filepath.EvalSymlinks(home)
123+
if err != nil {
124+
rootlessConfigHomeDirError = fmt.Errorf("cannot resolve %s: %w", home, err)
125+
return
126+
}
127+
tmpDir := filepath.Join(resolvedHome, ".config")
128+
_ = os.MkdirAll(tmpDir, 0o700)
129+
st, err := os.Stat(tmpDir)
130+
if err == nil && int(st.Sys().(*syscall.Stat_t).Uid) == os.Geteuid() && isWriteableOnlyByOwner(st.Mode().Perm()) {
131+
cfgHomeDir = tmpDir
132+
} else {
133+
rootlessConfigHomeDirError = fmt.Errorf("path %q exists and it is not writeable only by the current user", tmpDir)
134+
return
135+
}
136+
}
137+
rootlessConfigHomeDir = cfgHomeDir
138+
})
139+
140+
return rootlessConfigHomeDir, rootlessConfigHomeDirError
141+
}

0 commit comments

Comments
 (0)