@@ -2,162 +2,15 @@ package types
2
2
3
3
import (
4
4
"errors"
5
- "fmt"
6
5
"os"
7
6
"path/filepath"
8
7
"strconv"
9
8
"strings"
10
9
11
10
"github.com/containers/storage/pkg/homedir"
12
- "github.com/containers/storage/pkg/system"
13
11
"github.com/sirupsen/logrus"
14
12
)
15
13
16
- // GetRootlessRuntimeDir returns the runtime directory when running as non root
17
- func GetRootlessRuntimeDir (rootlessUID int ) (string , error ) {
18
- path , err := getRootlessRuntimeDir (rootlessUID )
19
- if err != nil {
20
- return "" , err
21
- }
22
- path = filepath .Join (path , "containers" )
23
- if err := os .MkdirAll (path , 0o700 ); err != nil {
24
- return "" , fmt .Errorf ("unable to make rootless runtime: %w" , err )
25
- }
26
- return path , nil
27
- }
28
-
29
- type rootlessRuntimeDirEnvironment interface {
30
- getProcCommandFile () string
31
- getRunUserDir () string
32
- getTmpPerUserDir () string
33
-
34
- homeDirGetRuntimeDir () (string , error )
35
- systemLstat (string ) (* system.StatT , error )
36
- homedirGet () string
37
- }
38
-
39
- type rootlessRuntimeDirEnvironmentImplementation struct {
40
- procCommandFile string
41
- runUserDir string
42
- tmpPerUserDir string
43
- }
44
-
45
- func (env rootlessRuntimeDirEnvironmentImplementation ) getProcCommandFile () string {
46
- return env .procCommandFile
47
- }
48
-
49
- func (env rootlessRuntimeDirEnvironmentImplementation ) getRunUserDir () string {
50
- return env .runUserDir
51
- }
52
-
53
- func (env rootlessRuntimeDirEnvironmentImplementation ) getTmpPerUserDir () string {
54
- return env .tmpPerUserDir
55
- }
56
-
57
- func (rootlessRuntimeDirEnvironmentImplementation ) homeDirGetRuntimeDir () (string , error ) {
58
- return homedir .GetRuntimeDir ()
59
- }
60
-
61
- func (rootlessRuntimeDirEnvironmentImplementation ) systemLstat (path string ) (* system.StatT , error ) {
62
- return system .Lstat (path )
63
- }
64
-
65
- func (rootlessRuntimeDirEnvironmentImplementation ) homedirGet () string {
66
- return homedir .Get ()
67
- }
68
-
69
- func isRootlessRuntimeDirOwner (dir string , env rootlessRuntimeDirEnvironment ) bool {
70
- st , err := env .systemLstat (dir )
71
- return err == nil && int (st .UID ()) == os .Getuid () && st .Mode ()& 0o700 == 0o700 && st .Mode ()& 0o066 == 0o000
72
- }
73
-
74
- // getRootlessRuntimeDirIsolated is an internal implementation detail of getRootlessRuntimeDir to allow testing.
75
- // Everyone but the tests this is intended for should only call getRootlessRuntimeDir, never this function.
76
- func getRootlessRuntimeDirIsolated (env rootlessRuntimeDirEnvironment ) (string , error ) {
77
- runtimeDir , err := env .homeDirGetRuntimeDir ()
78
- if err == nil {
79
- return runtimeDir , nil
80
- }
81
-
82
- initCommand , err := os .ReadFile (env .getProcCommandFile ())
83
- if err != nil || string (initCommand ) == "systemd" {
84
- runUserDir := env .getRunUserDir ()
85
- if isRootlessRuntimeDirOwner (runUserDir , env ) {
86
- return runUserDir , nil
87
- }
88
- }
89
-
90
- tmpPerUserDir := env .getTmpPerUserDir ()
91
- if tmpPerUserDir != "" {
92
- if _ , err := env .systemLstat (tmpPerUserDir ); os .IsNotExist (err ) {
93
- if err := os .Mkdir (tmpPerUserDir , 0o700 ); err != nil {
94
- logrus .Errorf ("Failed to create temp directory for user: %v" , err )
95
- } else {
96
- return tmpPerUserDir , nil
97
- }
98
- } else if isRootlessRuntimeDirOwner (tmpPerUserDir , env ) {
99
- return tmpPerUserDir , nil
100
- }
101
- }
102
-
103
- homeDir := env .homedirGet ()
104
- if homeDir == "" {
105
- return "" , errors .New ("neither XDG_RUNTIME_DIR nor temp dir nor HOME was set non-empty" )
106
- }
107
- resolvedHomeDir , err := filepath .EvalSymlinks (homeDir )
108
- if err != nil {
109
- return "" , err
110
- }
111
- return filepath .Join (resolvedHomeDir , "rundir" ), nil
112
- }
113
-
114
- func getRootlessRuntimeDir (rootlessUID int ) (string , error ) {
115
- return getRootlessRuntimeDirIsolated (
116
- rootlessRuntimeDirEnvironmentImplementation {
117
- "/proc/1/comm" ,
118
- fmt .Sprintf ("/run/user/%d" , rootlessUID ),
119
- fmt .Sprintf ("%s/containers-user-%d" , os .TempDir (), rootlessUID ),
120
- },
121
- )
122
- }
123
-
124
- // getRootlessDirInfo returns the parent path of where the storage for containers and
125
- // volumes will be in rootless mode
126
- func getRootlessDirInfo (rootlessUID int ) (string , string , error ) {
127
- rootlessRuntime , err := GetRootlessRuntimeDir (rootlessUID )
128
- if err != nil {
129
- return "" , "" , err
130
- }
131
-
132
- dataDir , err := homedir .GetDataHome ()
133
- if err == nil {
134
- return dataDir , rootlessRuntime , nil
135
- }
136
-
137
- home := homedir .Get ()
138
- if home == "" {
139
- return "" , "" , fmt .Errorf ("neither XDG_DATA_HOME nor HOME was set non-empty: %w" , err )
140
- }
141
- // runc doesn't like symlinks in the rootfs path, and at least
142
- // on CoreOS /home is a symlink to /var/home, so resolve any symlink.
143
- resolvedHome , err := filepath .EvalSymlinks (home )
144
- if err != nil {
145
- return "" , "" , err
146
- }
147
- dataDir = filepath .Join (resolvedHome , ".local" , "share" )
148
-
149
- return dataDir , rootlessRuntime , nil
150
- }
151
-
152
- func getRootlessUID () int {
153
- uidEnv := os .Getenv ("_CONTAINERS_ROOTLESS_UID" )
154
- if uidEnv != "" {
155
- u , _ := strconv .Atoi (uidEnv )
156
- return u
157
- }
158
- return os .Geteuid ()
159
- }
160
-
161
14
func expandEnvPath (path string , rootlessUID int ) (string , error ) {
162
15
var err error
163
16
path = strings .Replace (path , "$UID" , strconv .Itoa (rootlessUID ), - 1 )
0 commit comments