commit 0b0fbfb04caeff8a19c0ab76effbe4245df74806 Author: John Arbash Meinel Date: Wed May 17 09:02:20 2017 +0400 Handle bug #1682411 by using a temp dir to get permissions correct before the socket is in place. diff --git a/juju/sockets/sockets_nix.go b/juju/sockets/sockets_nix.go index dc0ac5f..dd8fd33 100644 --- a/juju/sockets/sockets_nix.go +++ b/juju/sockets/sockets_nix.go @@ -7,9 +7,11 @@ package sockets import ( + "io/ioutil" "net" "net/rpc" "os" + "path/filepath" "github.com/juju/errors" ) @@ -23,6 +25,32 @@ func Listen(socketPath string) (net.Listener, error) { if err := os.Remove(socketPath); err != nil { logger.Tracef("ignoring error on removing %q: %v", socketPath, err) } - listener, err := net.Listen("unix", socketPath) - return listener, errors.Trace(err) + // We first create the socket in a temporary directory as a subdirectory of + // the target dir so we know we can get the permissions correct and still + // rename the socket into the correct place. + // ioutil.TempDir creates the temporary directory as 0700 so it starts with + // the right perms as well. + socketDir, socketName := filepath.Split(socketPath) + // socketName here is just the prefix for the temporary dir name, + // so it won't collide + tempdir, err := ioutil.TempDir(socketDir, socketName) + if err != nil { + return nil, errors.Trace(err) + } + defer os.RemoveAll(tempdir) + tempSocketPath := filepath.Join(tempdir, socketName) + listener, err := net.Listen("unix", tempSocketPath) + if err != nil { + logger.Errorf("failed to listen on unix:%s: %v", socketPath, err) + return nil, errors.Trace(err) + } + if err := os.Chmod(tempSocketPath, 0700); err != nil { + listener.Close() + return nil, errors.Trace(err) + } + if err := os.Rename(tempSocketPath, socketPath); err != nil { + listener.Close() + return nil, errors.Trace(err) + } + return listener, nil }