8
8
"net/rpc"
9
9
"os"
10
10
"os/signal"
11
+ "path"
11
12
"syscall"
12
13
"time"
13
14
@@ -79,14 +80,16 @@ func Run() error {
79
80
80
81
if * address != "" {
81
82
network , addr := parseAddr (* address )
82
- if err := clearAddr (network , addr ); err != nil {
83
- return errors .Wrap (err , "Cannot remove existing unix socket" )
83
+ cleanup , err := checkAddr (network , addr )
84
+ if err != nil {
85
+ return errors .Wrap (err , "cannot remove existing unix socket" )
84
86
}
87
+ defer cleanup ()
88
+
85
89
ln , err := net .Listen (network , addr )
86
90
if err != nil {
87
- return errors .Wrap (err , "Unable to listen" )
91
+ return errors .Wrap (err , "unable to listen" )
88
92
}
89
- defer clearAddr (network , addr )
90
93
91
94
g .Add (func () error {
92
95
for {
@@ -135,16 +138,6 @@ func Run() error {
135
138
return g .Run ()
136
139
}
137
140
138
- func clearAddr (network string , addr string ) error {
139
- if network != "unix" {
140
- return nil
141
- }
142
- if _ , err := os .Stat (addr ); os .IsNotExist (err ) {
143
- return nil
144
- }
145
- return os .Remove (addr )
146
- }
147
-
148
141
// Add an actor (function) to the group. Each actor must be pre-emptable by an
149
142
// interrupt function. That is, if interrupt is invoked, execute should return.
150
143
// Also, it must be safe to call interrupt even after execute has returned.
@@ -154,3 +147,47 @@ func clearAddr(network string, addr string) error {
154
147
func Add (execute func () error , interrupt func (error )) {
155
148
g .Add (execute , interrupt )
156
149
}
150
+
151
+ func checkAddr (network , addr string ) (func (), error ) {
152
+ if network != "unix" {
153
+ return func () {}, nil
154
+ }
155
+ if _ , err := os .Stat (addr ); ! os .IsNotExist (err ) {
156
+ return func () {}, os .Remove (addr )
157
+ }
158
+ if err := os .MkdirAll (path .Dir (addr ), os .ModePerm ); err != nil {
159
+ return func () {}, err
160
+ }
161
+ if ok , err := isWritable (path .Dir (addr )); err != nil || ! ok {
162
+ return func () {}, errors .Wrap (err , "socket directory is not writable" )
163
+ }
164
+ return func () { os .Remove (addr ) }, nil
165
+ }
166
+
167
+ func isWritable (path string ) (isWritable bool , err error ) {
168
+ info , err := os .Stat (path )
169
+ if err != nil {
170
+ return false , err
171
+ }
172
+
173
+ if ! info .IsDir () {
174
+ return false , fmt .Errorf ("%s isn't a directory" , path )
175
+ }
176
+
177
+ // Check if the user bit is enabled in file permission
178
+ if info .Mode ().Perm ()& (1 << (uint (7 ))) == 0 {
179
+ return false , fmt .Errorf ("write permission bit is not set on this %s for user" , path )
180
+ }
181
+
182
+ var stat syscall.Stat_t
183
+ if err = syscall .Stat (path , & stat ); err != nil {
184
+ return false , err
185
+ }
186
+
187
+ err = nil
188
+ if uint32 (os .Geteuid ()) != stat .Uid {
189
+ return false , errors .Errorf ("user doesn't have permission to write to %s" , path )
190
+ }
191
+
192
+ return true , nil
193
+ }
0 commit comments